package common; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; /** * Abstract implementation of the generic <code>Environment</code> * interface. * * @author Benedikt Meurer * @version $Id$ */ public abstract class AbstractEnvironment<S, E> implements Environment<S, E> { // // Inner classes // /** * The store mappings, mapping locations to values. */ protected static class Mapping<S, E> { private S symbol; private E entry; public Mapping(S symbol, E entry) { this.symbol = symbol; this.entry = entry; } public S getSymbol() { return this.symbol; } public E getEntry() { return this.entry; } } // // Attributes // /** * The mappings, the symbol/entry pairs, within * this environment. */ protected LinkedList<Mapping<S, E>> mappings; // // Constructors // /** * Default constructor, creates a new empty environment * with no mappings. */ protected AbstractEnvironment() { // start with an empty mapping this.mappings = new LinkedList<Mapping<S, E>>(); } /** * Creates a new environment, based on the mappings from the * specified <code>environment</code>. * * @param environment another <code>AbstractEnvironment</code> * to inherit the mappings from. * * @throws NullPointerException if the <code>environment</code> * is <code>null</code>. */ protected AbstractEnvironment(AbstractEnvironment<S, E> environment) { if (environment == null) { throw new NullPointerException("environment is null"); } // copy-on-write for the mappings this.mappings = environment.mappings; } // // Primitives // /** * {@inheritDoc} * * @see common.Environment#containsSymbol(S) */ public boolean containsSymbol(S symbol) { if (symbol == null) { throw new NullPointerException("symbol is null"); } for (Mapping<S, E> mapping : this.mappings) { if (mapping.getSymbol().equals(symbol)) { return true; } } return false; } /** * {@inheritDoc} * * @see common.Environment#get(S) */ public E get(S symbol) { if (symbol == null) { throw new NullPointerException("symbol is null"); } for (Mapping<S, E> mapping : this.mappings) { if (mapping.getSymbol().equals(symbol)) { return mapping.getEntry(); } } throw new IllegalArgumentException("symbol is invalid"); } /** * {@inheritDoc} * * @see common.Environment#symbols() */ public Enumeration<S> symbols() { return new Enumeration<S>() { private Iterator<Mapping<S, E>> iterator = AbstractEnvironment.this.mappings.iterator(); public boolean hasMoreElements() { return this.iterator.hasNext(); } public S nextElement() { return this.iterator.next().getSymbol(); } }; } // // Overwritten methods // /** * Returns the string representation for the mutable * store. Should be used for debugging purpose only. * * @return the string representation. * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append('['); for (Mapping<S, E> mapping : this.mappings) { if (builder.length() > 1) builder.append(", "); builder.append(mapping.getSymbol()); builder.append(": "); builder.append(mapping.getEntry()); } builder.append(']'); return builder.toString(); } }