Index: fedd/abac-src/rtml/src/edu/stanford/rt/credential/OrderedMap.java
===================================================================
--- fedd/abac-src/rtml/src/edu/stanford/rt/credential/OrderedMap.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
+++ fedd/abac-src/rtml/src/edu/stanford/rt/credential/OrderedMap.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
@@ -0,0 +1,224 @@
+package edu.stanford.rt.credential;
+
+import java.util.*;
+
+/**
+ * @author Ninghui Li, Sandra Qiu<br>
+ * 
+ *  OrderedMap maintains a map from key to values and the ordering 
+ *  of the keys.
+ * 
+ */
+public class OrderedMap
+{
+	/** key type */
+	private Class keyClass;
+	/** value type */
+	private Class valueClass;
+	/**  map for the key-value pairs */
+	private HashMap dataMap;
+	/** also stores the keys as they are added to the list, 
+	 * so that we can remember the ordering of the keys.
+	 */
+	private ArrayList keyList;
+	/** whether this map is editable   */
+	private boolean editable;
+	/** defualt map capacity */
+	private static final int DEFAULT_SIZE = 10;
+
+	/**
+	 * Constructor for OrderedMap.
+	 * 
+	 *   Constructs a OrderedMap object with size default to 10.
+	 *   Both key and value are of Object type.
+	 */
+	public OrderedMap()
+	{
+		this(DEFAULT_SIZE, Object.class, Object.class);
+	}
+
+	/**
+	 * Constructor for OrderedMap.
+	 *   Constructs a OrderedMap object with given size.
+	 *   Both key and value are of Object type.
+	 */
+	public OrderedMap(int size)
+	{
+		this(size, Object.class, Object.class);
+	}
+
+	/**
+	 * Constructor for OrderedMap.
+	 *  Constructs a OrderedMap object with size default to 10.
+	 *  The key and value type are specified by the given keyClass and 
+	 *   valueClass, respectively.
+	 */
+	public OrderedMap(Class keyClass, Class valueClass)
+	{
+		this(DEFAULT_SIZE, keyClass, valueClass);
+	}
+
+	/**
+	 * Constructor for OrderedMap.
+	 *   Constructs a OrderedMap object with given size.
+	 *   The key and value type are specified by the given keyClass and 
+	 *   valueClass, respectively.
+	 */
+	public OrderedMap(int size, Class keyClass, Class valueClass)
+	{
+		this.keyClass = keyClass;
+		this.valueClass = valueClass;
+		this.dataMap = new HashMap(size);
+		this.keyList = new ArrayList(size);
+		this.editable = true;
+	}
+
+	/**
+	 * Method constainsKey.
+	 *   Returns true if there is a mapping for the given key.
+	 * @param key
+	 * @return boolean
+	 */
+	public synchronized boolean constainsKey(Object key)
+	{
+		return dataMap.containsKey(key);
+	}
+
+	/**
+	 * Method put.
+     *   Add a new key-value mapping entry to the map.
+     *   Exception is thrown if the map is not editable, the key is null,
+     *   or the given key or value's type does not match the specified 
+     *   key type or value type.  Exception will also be thrown if trying
+     *   to add duplicated key-value pair.
+	 * @param key
+	 * @param value
+	 * @throws DomainSpecException
+	 */
+	public synchronized void put(Object key, Object value)
+		throws DomainSpecException
+	{
+		if (!editable)
+			throw new DomainSpecException("Adding to unmodifiable map");
+
+		if (key == null)
+			throw new DomainSpecException("Wrong key value: null.");
+
+		if (!keyClass.isInstance(key))
+			throw new DomainSpecException("Wrong key type");
+
+		if (value != null && !valueClass.isInstance(value))
+			throw new DomainSpecException("Wrong value type");
+
+		myPut(key, value);
+	}
+
+	private void myPut(Object key, Object value)
+		throws DomainSpecException
+	{
+		//RTUtil.debugInfo("myPut() > key  = " + key.toString());
+
+		if (dataMap.get(key) != null)
+		{
+			//RTUtil.debugInfo("myPut() > " + dataMap.get(key).toString());
+			throw new DomainSpecException("Duplicate mapping");
+		}
+		dataMap.put(key, value);
+		keyList.add(key);
+	}
+
+	/**
+	    Copies all the mapping entries to this map, perserving the 
+	    original ordering of the entries.
+	    
+	    Exception is thrown when the key type or value type of the given 
+	    map does not match that of this map, or when duplicated entries 
+	    are detected.
+	*/
+	public synchronized void putAll(OrderedMap map)
+		throws DomainSpecException
+	{
+		if (!this.keyClass.equals(map.getKeyClass())
+			|| !this.valueClass.equals(map.getValueClass()))
+		{
+			throw new DomainSpecException("Illegal key/value type.");
+		}
+		Iterator it = map.keyIterator();
+		while (it.hasNext())
+		{
+			Object key = it.next();
+			Object value = map.get(key);
+			myPut(key, value);
+		}
+		// Do not call setUneditable mothod here!
+	}
+
+	/**
+	    marks this map as uneditable.
+	*/
+	public synchronized void setUneditable()
+	{
+		editable = false;
+	}
+
+	/**
+	    Returns true if the map is editable.
+	*/
+	public boolean isEditable()
+	{
+		return editable;
+	}
+
+	/** Returns the size of this map */
+	public synchronized int size()
+	{
+		return keyList.size();
+	}
+
+	/** Returns iterator to the list of keys in the map.*/
+	public synchronized Iterator keyIterator()
+	{
+		return keyList.iterator();
+	}
+
+	/**
+	    Returns the value for the given key and returns null if there is 
+	    no mapping for the given key .
+	    
+	    Exception is thrown when the type of given key does not match the 
+	    specified key type of this map. 
+	*/
+	public Object get(Object key) throws DomainSpecException
+	{
+		if (!keyClass.isInstance(key))
+			throw new DomainSpecException("Wrong key type");
+
+		return dataMap.get(key);
+	}
+
+	/** Returns an unmodifiable view of all the keys. */
+	public synchronized List keyList()
+	{
+		// returns a unmodifiable version of the keys
+		return Collections.unmodifiableList(keyList);
+	}
+
+	/** Returns an unmodifiable view of this map. */
+	public synchronized Map valueMap()
+	{
+		return Collections.unmodifiableMap(dataMap);
+	}
+
+	/** Returns the key type. */
+	public Class getKeyClass()
+	{
+		return keyClass;
+	}
+
+	/** Returns the value type */
+	public Class getValueClass()
+	{
+		return valueClass;
+	}
+
+}
