Index: fedd/abac-src/rtml/src/edu/stanford/rt/credential/RoleDeclaration.java
===================================================================
--- fedd/abac-src/rtml/src/edu/stanford/rt/credential/RoleDeclaration.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
+++ fedd/abac-src/rtml/src/edu/stanford/rt/credential/RoleDeclaration.java	(revision 8780cbecc6db2bdc2b9ef31eec6e5209ad3bff15)
@@ -0,0 +1,565 @@
+package edu.stanford.rt.credential;
+import java.util.*;
+import edu.stanford.rt.util.*;
+import edu.stanford.rt.datatype.*;
+/**
+ * @author Ninghui Li, Sandra Qiu<br>
+ * 
+ *  All the information about a declared role.  In RTML, this is 
+ *  represented by a <code>RoleDeclaration</code> element in a 
+ *  <code>ApplicationDomainSpecification</code> document.
+ * 
+ *	Issue: Do not support identity yet.
+ */
+public class RoleDeclaration
+	implements Constants, java.io.Serializable
+{
+    /**
+     * Issuer traces types
+     */
+	static public HashMap issuerTracesTypes;
+    /**
+     * Subject traces types
+     */
+	static public HashMap subjectTracesTypes;
+	static {
+		issuerTracesTypes = new HashMap(4);
+		issuerTracesTypes.put("all", new Integer(ISSUER_TRACES_ALL));
+		issuerTracesTypes.put("def", new Integer(ISSUER_TRACES_DEF));
+		issuerTracesTypes.put(
+			"rule",
+			new Integer(ISSUER_TRACES_RULE));
+		issuerTracesTypes.put(
+			"none",
+			new Integer(ISSUER_TRACES_NONE));
+		subjectTracesTypes = new HashMap(3);
+		subjectTracesTypes.put(
+			"all",
+			new Integer(SUBJECT_TRACES_ALL));
+		subjectTracesTypes.put(
+			"fact",
+			new Integer(SUBJECT_TRACES_FACT));
+		subjectTracesTypes.put(
+			"none",
+			new Integer(SUBJECT_TRACES_NONE));
+	}
+    /**
+     * Default issuer traces type: rule
+     */
+	static public int DEFAULT_ISSUER_TYPE = ISSUER_TRACES_RULE;
+    /**
+     * Defualt issuer traces type: fact.
+     */
+	static public int DEFAULT_SUBJECT_TYPE = SUBJECT_TRACES_FACT;
+	/**
+	 * Role declaration context. 
+	 * <br>
+	 * The <code>DomainSpecification</code> in which the current role
+	 * is declared.
+	 */
+	private DomainSpecification context;
+	/** Role name. <br>
+	 * In RTML: attribute <code>name</code>.
+	 */
+	private String name;
+	/** Default is DEFAULT_ISSUER_TYPE <br>
+	 *  In RTML: attribute <code>issuerTracesType</code>.
+	 */
+	private int issuerTracesType = DEFAULT_ISSUER_TYPE;
+	/** Default is DEFAULT_SUBJECT_TYPE <br>
+	 *  In RTML: attribute <code>subjectTracesType</code>.
+	 */
+	private int subjectTracesType = DEFAULT_SUBJECT_TYPE;
+	/**  Default is 1 <br>
+	 * In RTML: attribute <code>dimension</code>.
+	 */
+	private int dimension = 1;
+	/** Default is false. <br>
+	 * In RTML: attribute <code>isIdentity</code>.
+	 */
+	private boolean isIdentity = false;
+	/** Maps String (parameter name) to DataType (parameter type). */
+	private OrderedMap parameterDeclarations;
+	/** Declaration type: Restriction, Extension, Projection or Plain. */
+	private int declarationType;
+	/** BaseRole Element for Restriction, Extension, Projection. */
+	private RoleDeclaration baseRole;
+	/** This map keeps track of the ordersing of the flattend name-prefixes.
+	 A name-prefix is colon-separated name concatenation.*/
+	private HashMap prefixToPositions;
+	private HashMap positionToPrefixes;
+    
+    // Role declaration types
+	static private final int RESTRICTION = 1;
+	static private final int EXTENSION = 2;
+	static private final int PROJECTION = 3;
+	static private final int PLAIN = 4;
+	/**
+	 *  Private contructor ensures that no one else can contruct a RoleDeclaration
+	 *  object and the state of a RoleDeclaration object is complete (unmodifiable)
+	 *  once it is created. <br>
+	 * 	And the newly created RoleDeclaration's parameter-postion mapping is also
+	 * 	calculated.
+	 * @param context
+	 * @param name
+	 * @param issuerTracesType
+	 * @param subjectTracesType
+	 * @param dimension
+	 * @param isIdentity
+	 * @param declarationType
+	 * @param baseRole
+	 * @param parameterDeclarations
+	 * @throws DomainSpecException
+	 */
+	private RoleDeclaration(
+		DomainSpecification context,
+		String name,
+		int issuerTracesType,
+		int subjectTracesType,
+		int dimension,
+		boolean isIdentity,
+		int declarationType,
+		RoleDeclaration baseRole,
+		OrderedMap parameterDeclarations)
+		throws DomainSpecException
+	{
+		this.context = context;
+		this.name = name;
+		this.issuerTracesType = issuerTracesType;
+		this.subjectTracesType = subjectTracesType;
+		this.dimension = dimension;
+		this.isIdentity = isIdentity;
+		this.declarationType = declarationType;
+		this.baseRole = baseRole;
+		this.parameterDeclarations = parameterDeclarations;
+		this.parameterDeclarations.setUneditable();
+		this.prefixToPositions = new HashMap();
+		this.positionToPrefixes = new HashMap();
+		// Compute parameters, which includes all parameters of base role plus 
+		// those in "this" role.
+		calculatePrefixPositions(
+			new StringBuffer(name),
+			0,
+			this.parameterDeclarations,
+			this.prefixToPositions,
+			this.positionToPrefixes);
+	}
+	/**
+	 * Method createRestrictionRole.
+	 * 		Public interface to construct a <code>Restriction</code> type 
+	 * 		<code>RoleDeclaration</code> object.
+	 * @param name
+	 * @param isIdentity
+	 * @param baseRole
+	 * @param newParameters
+	 * @return RoleDeclaration
+	 * @throws DomainSpecException
+	 */
+	public static RoleDeclaration createRestrictionRole(
+		DomainSpecification context,
+		String name,
+		boolean isIdentity,
+		RoleDeclaration baseRole,
+		OrderedMap newParameters)
+		throws DomainSpecException
+	{
+		if (baseRole == null)
+			throw new DomainSpecException("");
+		int issuerTracesType = baseRole.getIssuerTracesType();
+		int subjectTracesType = baseRole.getSubjectTracesType();
+		int dimension = baseRole.getDimension();
+		OrderedMap parameterDeclarations =
+			new OrderedMap(String.class, DataType.class);
+		parameterDeclarations.putAll(
+			baseRole.getParameterDeclarations());
+		parameterDeclarations.putAll(parameterDeclarations);
+		return new RoleDeclaration(
+			context,
+			name,
+			issuerTracesType,
+			subjectTracesType,
+			dimension,
+			isIdentity,
+			RESTRICTION,
+			baseRole,
+			parameterDeclarations);
+	}
+	/**
+	 * Method createExtensionRole.
+	 * 		Public interface to construct an <code>Extension</code> type 
+	 * 		<code>RoleDeclaration</code> object.
+	 * @param name
+	 * @param isIdentity
+	 * @param baseRole
+	 * @param newParameters
+	 * @return RoleDeclaration
+	 * @throws DomainSpecException
+	 */
+	public static RoleDeclaration createExtensionRole(
+		DomainSpecification context,
+		String name,
+		boolean isIdentity,
+		RoleDeclaration baseRole,
+		OrderedMap newParameters)
+		throws DomainSpecException
+	{
+		if (baseRole == null)
+			throw new DomainSpecException("");
+		int issuerTracesType = baseRole.getIssuerTracesType();
+		int subjectTracesType = baseRole.getSubjectTracesType();
+		int dimension = baseRole.getDimension();
+		OrderedMap parameterDeclarations =
+			new OrderedMap(String.class, DataType.class);
+		parameterDeclarations.putAll(
+			baseRole.getParameterDeclarations());
+		parameterDeclarations.putAll(parameterDeclarations);
+		return new RoleDeclaration(
+			context,
+			name,
+			issuerTracesType,
+			subjectTracesType,
+			dimension,
+			isIdentity,
+			EXTENSION,
+			baseRole,
+			parameterDeclarations);
+	}
+	/**
+	 * Method createProjectionRole.
+	 * 		Public interface to construct a <code>Projection</code> type 
+	 * 		<code>RoleDeclaration</code> object.
+	 * @param name
+	 * @param isIdentity
+	 * @param baseRole
+	 * @param parameterNames
+	 * @return RoleDeclaration
+	 * @throws DomainSpecException
+	 */
+	public static RoleDeclaration createProjectionRole(
+		DomainSpecification context,
+		String name,
+		boolean isIdentity,
+		RoleDeclaration baseRole,
+		String[] parameterNames)
+		throws DomainSpecException
+	{
+		if (baseRole == null)
+			throw new DomainSpecException("");
+		int issuerTracesType = baseRole.getIssuerTracesType();
+		int subjectTracesType = baseRole.getSubjectTracesType();
+		int dimension = baseRole.getDimension();
+		OrderedMap parameterDeclarations =
+			new OrderedMap(String.class, DataType.class);
+		OrderedMap baseRoleParameters =
+			baseRole.getParameterDeclarations();
+		for (int i = 0; i < parameterNames.length; i++)
+		{
+			DataType type =
+				baseRole.getParameterType(parameterNames[i]);
+			parameterDeclarations.put(parameterNames[i], type);
+		}
+		return new RoleDeclaration(
+			context,
+			name,
+			issuerTracesType,
+			subjectTracesType,
+			dimension,
+			isIdentity,
+			PROJECTION,
+			baseRole,
+			parameterDeclarations);
+	}
+	/**
+	 * Method createPlainRole.
+	 * Public interface to construct a <code>Plain</code> type of 
+     * <code>RoleDeclaration</code> object. <code>Identity</code> is not supported.
+	 * @param name
+	 * @param issuerTracesType
+	 * @param subjectTracesType
+	 * @param dimension
+	 * @param isIdentity
+	 * @param newParameters
+	 * @return RoleDeclaration
+	 * @throws DomainSpecException
+	 */
+	public static RoleDeclaration createPlainRole(
+		DomainSpecification context,
+		String name,
+		int issuerTracesType,
+		int subjectTracesType,
+		int dimension,
+		boolean isIdentity,
+		OrderedMap newParameters)
+		throws DomainSpecException
+	{
+		return new RoleDeclaration(
+			context,
+			name,
+			issuerTracesType,
+			subjectTracesType,
+			dimension,
+			isIdentity,
+			PLAIN,
+			null,
+			newParameters);
+	}
+	/** Returns the role declaration context. */
+	public DomainSpecification getContext()
+	{
+		return context;
+	}
+	/** Returns the role name. */
+	public String getName()
+	{
+		return name;
+	}
+	/** Returns the value for <code>issuerTracesType</code>. */
+	public int getIssuerTracesType()
+	{
+		return issuerTracesType;
+	}
+	/** Returns the value for <code>subjectTracesType</code>. */
+	public int getSubjectTracesType()
+	{
+		return subjectTracesType;
+	}
+	/**
+	 * Returns the value for <code>dimension</code>.
+	 */
+	public int getDimension()
+	{
+		return dimension;
+	}
+	/** Returns the base role object. */
+	public RoleDeclaration getBaseRole()
+	{
+		return baseRole;
+	}
+	/** Checks whether this role is an identity-based role. */
+	public boolean isIdentity()
+	{
+		return isIdentity;
+	}
+	/**
+	 * Method getParameterDeclarations.
+	 * @return OrderedMap
+	 *	 	Returns an OrderedMap of parameter declarations in 
+	 *  this role declaration object. <br>
+	 *  For Restriction or Extension type <code>RoleDeclaration</code>, 
+	 *  the map contains parameters declared both in base role and this role.
+	 *  For Projection type <code>RoleDeclaration</code>, 
+	 *  the map contains only those paraeters declared in base role with 
+	 *  matching names with this role's declared parameters.
+	 * 
+	 * @throws DomainSpecException
+	 */
+	public synchronized OrderedMap getParameterDeclarations()
+		throws DomainSpecException
+	{
+		if (parameterDeclarations.isEditable())
+			throw new IllegalStateException("Parameter declarations are not finalized.");
+		return parameterDeclarations;
+	}
+	/**
+	 * Method getParameterType.
+	 * @param paramName name of the declared parameter.
+	 * @return DataType type of the declared parameter.
+	 * @throws DomainSpecException 
+	 */
+	public DataType getParameterType(String paramName)
+		throws DomainSpecException
+	{
+		return (DataType) parameterDeclarations.get(paramName);
+	}
+	/** Returns a unmodifiable view of prefix-to-position map.*/
+	public synchronized Map getPrefixToPositions()
+	{
+		return Collections.unmodifiableMap(prefixToPositions);
+	}
+	/** Returns a unmodifiable view of position-to-prefix map.*/
+	public synchronized Map getPositionToPrefixes()
+	{
+		return Collections.unmodifiableMap(positionToPrefixes);
+	}
+	/** Returns the total number of the prefixes in the map.*/
+	public int getTotalPrefixes()
+	{
+		return prefixToPositions.size();
+	}
+	/**
+	 * Method getPosition.
+	 * @param prefix 
+	 * 		the prefix to get the position with.
+	 * @return int
+	 * 		the postition of the given prefix.
+	 */
+	public int getPosition(String prefix)
+	{
+		Integer pos = (Integer) prefixToPositions.get(prefix);
+		return pos.intValue();
+	}
+	/**
+	 * Method getPrefix.
+	 * @param position 
+	 * 		the position to get prefix with.
+	 * @return String
+	 * 		the prefix at the given position.
+	 */
+	public String getPrefix(int position)
+	{
+		return (String) positionToPrefixes.get(new Integer(position));
+	}
+	/**
+	 * Method toString.
+	 * @param indent
+	 * @return String
+	 */
+	public String toString(String indent)
+	{
+		String thisIndent = indent + "  ";
+		StringBuffer sb = new StringBuffer();
+
+		sb.append(thisIndent).append("RoleDeclaration: ").append(
+			name).append(
+			"\n");
+		sb
+			.append(thisIndent + "  ")
+			.append("issuerTracesType = ")
+			.append(getIssuerTracesTypeString(issuerTracesType))
+			.append("\n");
+		sb
+			.append(thisIndent + "  ")
+			.append("subjectTracesType = ")
+			.append(getSubjectTracesTypeString(subjectTracesType))
+			.append("\n");
+
+		sb.append(thisIndent + "  ").append("Parameters: \n");
+		Iterator it = parameterDeclarations.keyIterator();
+		while (it.hasNext())
+		{
+			String key = (String) it.next();
+			sb.append(thisIndent + "    ").append(key);
+			try
+			{
+				DataType value =
+					(DataType) parameterDeclarations.get(key);
+				sb.append("    ").append(value.getName()).append(
+					"\n");
+			}
+			catch (DomainSpecException e)
+			{
+				e.printStackTrace();
+			}
+		}
+		return sb.toString();
+	}
+
+    /**
+     * Method calculatePrefixPositions.
+     * @param prefix        
+     *      current prefix. Prefix is a lolon-saparated string, which 
+     *      is the concatenation of role name and parameter names.
+     * @param position  
+     *      the current position of the prefix.
+     * @param paramDeclarations 
+     *      all parameters declared in this role.
+     * @param prefixToPositionMap
+     *      a HashMap which maps a prefix to its position.
+     * @param positionToPrefixMap
+     *      a HashMap which maps a position to its prefix
+     * @throws DomainSpecException
+     *      
+     */
+    private synchronized void calculatePrefixPositions(
+        StringBuffer prefix,
+        int position,
+        OrderedMap paramDeclarations,
+        HashMap prefixToPositionMap,
+        HashMap positionToPrefixMap)
+        throws DomainSpecException
+    {
+        RTUtil.debugInfo(
+            "RoleDeclaration.calculatePrefixPositions(, ,  , , ) ....");
+        //        RTUtil.debugInfo("prefix = " + prefix);   
+        Iterator paramNameIt = paramDeclarations.keyIterator();
+        StringBuffer newPrefix = new StringBuffer(prefix.toString());
+        while (paramNameIt.hasNext())
+        {
+            newPrefix.append(COLON);
+            String paramName = (String) paramNameIt.next();
+            newPrefix.append(paramName);
+            RTUtil.debugInfo("newPrefix = " + newPrefix.toString());
+            DataType paramType = getParameterType(paramName);
+            if (paramType instanceof RecordType)
+            {
+                OrderedMap fieldDeclarations =
+                    ((RecordType) paramType).getFieldDeclarations();
+                calculatePrefixPositions(
+                    newPrefix,
+                    position++,
+                    fieldDeclarations,
+                    prefixToPositionMap,
+                    positionToPrefixMap);
+                position++;
+            }
+            else
+            {
+                position++;
+                RTUtil.debugInfo("position = " + position);
+                prefixToPositionMap.put(
+                    newPrefix.toString(),
+                    new Integer(position));
+                positionToPrefixMap.put(
+                    new Integer(position),
+                    newPrefix.toString());
+            }
+            //RTUtil.debugInfo("**** prefix = " + prefix.toString());
+            newPrefix = new StringBuffer(prefix.toString());
+            //RTUtil.debugInfo("newPrefix 2 = " + newPrefix.toString());
+        }
+    }
+
+	private String getIssuerTracesTypeString(int issuerTracesType)
+	{
+		String res = null;
+		switch (issuerTracesType)
+		{
+			case ISSUER_TRACES_ALL :
+				res = "all";
+				break;
+			case ISSUER_TRACES_DEF :
+				res = "def";
+				break;
+			case ISSUER_TRACES_RULE :
+				res = "rule";
+				break;
+			case ISSUER_TRACES_NONE :
+				res = "none";
+				break;
+			default :
+				res = "rule";
+				break;
+		}
+		return res;
+	}
+	private String getSubjectTracesTypeString(int subjectTracesType)
+	{
+		String res = null;
+		switch (subjectTracesType)
+		{
+			case SUBJECT_TRACES_ALL :
+				res = "all";
+				break;
+			case SUBJECT_TRACES_FACT :
+				res = "fact";
+				break;
+			case SUBJECT_TRACES_NONE :
+				res = "none";
+				break;
+			default :
+				res = "fact";
+				break;
+		}
+		return res;
+	}
+}
