package edu.stanford.rt.credential;
import java.util.*;
import edu.stanford.rt.datatype.*;
import edu.stanford.rt.credential.*;
import edu.stanford.rt.util.*;
/**
* @author Ninghui Li, Sandra Qiu
*
* This class stores the common information about an ApplicationDomain
or
* a CredentialDomain
. The info includes the following:
* principal type, imported application domains, type declarations,
* role declarations, hash id, RTML context, and the parsing status.
*
*/
public class DomainSpecification
{
/**
* Principal type
*/
private SimpleType principalType;
/**
* Stores all imported domains in this domain,
* mapping string (domain name) to ApplicationDomain object.
*/
private OrderedMap importedDomains;
/**
* Stores all type decalarations in this domain,
* mapping string(type name) to type declaration object.
*/
private OrderedMap typeDeclarations;
/**
* Stores all role declarations in this domain,
* mapping string(role name) to role declaration object.
*/
private OrderedMap roleDeclarations;
/**
* A flag indicates the parsing status of the domain.
*/
private boolean completeState;
/** The hash value of the domain. */
private HashID hashID;
/**
* RTML Context
*/
private RTContext context;
/**
* Constuctor for DomainSpecification.
Contructs a DomainSpecification object with the specific uri.
Include System DomainSpecification for non-system DomainSpecification
object.
* @param uri
* @param isSystemDomain
* @param context
* @throws DomainSpecException
*/
DomainSpecification(RTContext context) throws DomainSpecException
{
this.completeState = false;
this.importedDomains =
new OrderedMap(String.class, DomainSpecification.class);
this.typeDeclarations =
new OrderedMap(String.class, DataType.class);
this.roleDeclarations =
new OrderedMap(String.class, RoleDeclaration.class);
this.context = context;
}
// /**
// Copies over the type declarations and role declarations from the
// included domain specification objects.
// */
// private void includeDomain(DomainSpecification ds)
// throws DomainSpecException
// {
// SimpleType prinType = ds.getPrincipalType();
// if (prinType != null)
// {
// if (this.principalType == null)
// {
// this.principalType = prinType;
// }
// else if (!prinType.equals(this.principalType))
// {
// throw new DomainSpecException("Pincipal Type Conflict!");
// }
// }
// typeDeclarations.putAll(ds.getTypeDeclarations());
// roleDeclarations.putAll(ds.getRoleDeclarations());
// }
/**
* Method importDomain.
* Add a newly imported domain map.
* @param name
* the short name to refer to spec with the domain.
* @param spec
* @throws DomainSpecException
*/
public synchronized void importDomain(
String name,
ApplicationDomain spec)
throws DomainSpecException
{
importedDomains.put(name, spec);
}
/**
* Method addType.
* Add a new type declaration to the domain.
* @param type
* @throws DomainSpecException
* DomainSpecException when a duplicated type declaration,
* i.e. a type declaration with the same name and same data
* type, is added.
*/
public synchronized void addType(DataType type)
throws DomainSpecException
{
String typeName = type.getName();
if (typeExistsInSystemDomain(typeName))
throw new DomainSpecException(
"Type '"
+ typeName
+ "' already declared in system domain");
typeDeclarations.put(typeName, type);
}
/**
* Method addType.
* Add XML built-in type.
* @param typeName
* @throws DomainSpecException
*/
public synchronized void addType(String typeName)
throws DomainSpecException
{
if (typeExistsInSystemDomain(typeName))
throw new DomainSpecException(
"Type '"
+ typeName
+ "' already declared in system domain");
typeDeclarations.put(typeName, null);
}
/**
* Method addRole.
* Add a new role declaration to the domain.
* @param role
* @throws DomainSpecException
*/
public synchronized void addRole(RoleDeclaration role)
throws DomainSpecException
{
RTUtil.debugInfo(
"DomainSpecification(id="
+ getHashID().toString()
+ ") adding role '"
+ role.getName()
+ "'");
String roleName = role.getName();
if (roleExistsInSystemDomain(roleName))
throw new DomainSpecException(
"Role '"
+ roleName
+ "' already declared in system domain");
roleDeclarations.put(roleName, role);
}
/**
* Method setPrincipalType.
* @param prinType
* @throws DomainSpecException
*/
public synchronized void setPrincipalType(SimpleType prinType)
throws DomainSpecException
{
if (this.principalType == null)
this.principalType = prinType;
else if (!prinType.equals(this.principalType))
throw new DomainSpecException("Pincipal Type Conflict!");
}
/**
* Method isComplete.
* checks whether the parsing is completed.
* @return boolean
*/
public boolean isComplete()
{
return completeState;
}
/**
* Method setComplete.
* marks the parsing status as complete, so no modification
* is allowed for imported domains, type declarations , and
* role declarations maps.
*/
public synchronized void setComplete()
{
completeState = true;
importedDomains.setUneditable();
typeDeclarations.setUneditable();
roleDeclarations.setUneditable();
}
/**
* Method lookupImportedDomain.
* Lookup an imported domain by the given domainRef
* in the currnt domain.
* @param domainRef
* @return DomainSpecification
* @throws DomainSpecException
* if cannot find one
*/
public DomainSpecification lookupImportedDomain(String domainRef)
throws DomainSpecException
{
DomainSpecification spec =
(DomainSpecification) importedDomains.get(domainRef);
if (spec == null)
{
throw new DomainSpecException(
"Domain '" + domainRef + "' not found.");
}
return spec;
}
/**
* Method lookupType.
* Look up the DataType declaration by given typeName
* in the current domain.
* @param typeName
* @return DataType
* returns null if cannot find one.
* @throws DomainSpecException
* if cannot find a DataType declaration by the given name.
*/
public DataType lookupType(String typeName)
throws DomainSpecException
{
return (DataType) typeDeclarations.get(typeName);
}
/**
* Method lookupType.
* Look up the DataType declaration by given typeName in the given domain.
* @param domainRef
* specifies which domain to look up in. If domainRef is null or an
* empty string, then look up in the current domain.
* @param typeName
* @return DataType
* @throws DomainSpecException
* if cannot find a DataType with given name.
*/
public DataType lookupType(String domainRef, String typeName)
throws DomainSpecException
{
DataType type;
if (domainRef == null || domainRef.length() == 0)
{
type = this.lookupType(typeName);
}
else
{
DomainSpecification importedSpec =
this.lookupImportedDomain(domainRef);
type = importedSpec.lookupType(typeName);
}
return type;
}
/**
* Method lookupRoleDeclaration.
* Look up the role declaration by given roleName in the current domain.
* @param roleName
* @return RoleDeclaration
* returns null if cannot find one.
* @throws DomainSpecException
* if cannot find one.
*/
public RoleDeclaration lookupRoleDeclaration(String roleName)
throws DomainSpecException
{
return (RoleDeclaration) roleDeclarations.get(roleName);
}
/**
* Method lookupRoleDeclaration.
* looks up a role declaration by given roleName in the given domain.
* @param domainRef
* specifies which domain to look up in. If domainRef is null or an
* empty string, then look up in the current domain.
* @param roleName
* @return RoleDeclaration
* @throws DomainSpecException
* if cannot find a one.
*/
public RoleDeclaration lookupRoleDeclaration(
String domainRef,
String roleName)
throws DomainSpecException
{
RoleDeclaration role;
if (domainRef == null || domainRef.length() == 0)
{
role = this.lookupRoleDeclaration(roleName);
}
else
{
DomainSpecification importedSpec =
this.lookupImportedDomain(domainRef);
role = importedSpec.lookupRoleDeclaration(roleName);
}
return role;
}
/**
* Method getContext.
* @return RTContext
*/
public RTContext getContext()
{
return context;
}
/**
* Method getTypeDeclarations.
* @return OrderedMap
* @throws DomainSpecException
* when parsing is not completed.
*/
public OrderedMap getTypeDeclarations()
throws DomainSpecException
{
if (!isComplete())
throw new DomainSpecException("Still parsing current domain specification");
return typeDeclarations;
}
/**
* Method getRoleDeclarations.
* @return OrderedMap
* @throws DomainSpecException
* when parsing is not completed.
*/
public OrderedMap getRoleDeclarations()
throws DomainSpecException
{
if (!isComplete())
throw new DomainSpecException("Still parsing current domain specification");
return roleDeclarations;
}
/**
* Method getImportedDomains.
* @return OrderedMap
* @throws DomainSpecException
* when parsing is not completed.
*/
public OrderedMap getImportedDomains() throws DomainSpecException
{
if (!isComplete())
throw new DomainSpecException("Still parsing current domain specification");
return importedDomains;
}
/**
* Method getPrincipalType.
* @return SimpleType
*/
public SimpleType getPrincipalType()
{
return this.principalType;
}
/**
* Returns the hashID.
* @return ApplicationDomainHashID
*/
public HashID getHashID()
{
return this.hashID;
}
/**
* Sets the hashID.
* @param hashID The hashID to set
*/
public synchronized void setHashID(HashID hashID)
throws DomainSpecException
{
this.hashID = hashID;
}
/**
* Method typeExistsInSystemDomain.
* checks whether a DataType with given typeName is already
* declcared in system domain.
* @param typeName
* @return boolean
*/
private boolean typeExistsInSystemDomain(String typeName)
{
if (context == null)
return false;
try
{
DataType t =
context.getSystemDomain().lookupType(typeName);
return true;
}
catch (DomainSpecException e)
{
return false;
}
}
/**
* Method roleExistsInSystemDomain.
* checks whether a RoleDeclaration with given roleName is already
* declcared in system domain.
* @param roleName
* @return boolean
*/
private boolean roleExistsInSystemDomain(String roleName)
{
if (context == null)
return false;
try
{
RoleDeclaration r =
context.getSystemDomain().lookupRoleDeclaration(
roleName);
return true;
}
catch (DomainSpecException e)
{
return false;
}
}
}