/*
* Copyright 2003-2010 Tufts University  Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 * 
 * http://www.osedu.org/licenses/ECL-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

/*
 * VueAuthorizationManager.java
 *
 * Created on December 15, 2003, 11:02 AM
 */
package tufts.oki.authorization;
import java.util.*;
import osid.shared.*;

/**
 *  The authorization manager maintains three lists of object related to authorizating
 *  operations in the VUE system.  These objects are VueAuthorization, VueFunction, and
 *  VueQualifier.  As stated by the OKI OSID documentation on authorization, these objects
 *  can be viewed as the subject, verb, and direct object.  The VueAuthorization indictes
 *  who has this authorization, the VueFunction defines what operation is allowed, and the
 *  VueQualifier places restrictions (if any) on the operation.
 *  <p>
 *  The AuthZMgr queries take two forms: Explicit 
 *  and Implicit. The documentation indicates that explicit authorizations may be modified. 
 *  It is assumed that explicit authorization have a function Id and 
 *  qualifier id physically present in the Authorization instance (which allows them to be 
 *  modified). This is opposed to authorizations which are valid due to inheritied qualifiers 
 *  (ancestors of the instance), which is the implicit form of authorization.
 *  <p>
 *  This implementation of the AuthorizationManager does not include persistance of any kind.
 *  This means that all authorizations, functions, and qualifiers must be defined at run time
 *  by an application which uses it.  Note also, that funtion types and qualifier types are
 *  not defined either.
 *
 * @author  Mark Norton
 */
public class AuthorizationManager extends tufts.oki.OsidManager implements osid.authorization.AuthorizationManager {
    private Vector auths = null;            //  The list of authorizations.
    private Vector functions = null;        //  The list of known functions.
    private Vector qualifiers = null;       //  The list of known qualifiers.
    private Vector rootQualifiers = null;   //  The list of qualifier hierarchies.
    private osid.shared.Agent user = null;  //  The default user of this authorization manager.
    
    static public osid.shared.SharedManager sharedMgr = null;   //  SharedManager is cached.
    
    /** 
     *  Creates a new instance of VueAuthorizationManager.  The OsidOwner provides a context
     *  which can be shared between OSID managers.  The user-agent should be an authenticated
     *  agent who is (presumably) the user of this application session.  SharedManager is cached
     *  due to the need of resolving agent instances versus their Id's.
     */
    public AuthorizationManager() {
        super();
        this.auths = new Vector(100);
        this.functions = new Vector(100);
        this.qualifiers = new Vector(100);
        this.rootQualifiers = new Vector(100);
    }
    
    /** 
     *  Creates a new instance of VueAuthorizationManager.  The OsidOwner provides a context
     *  which can be shared between OSID managers.  The user-agent should be an authenticated
     *  agent who is (presumably) the user of this application session.  SharedManager is cached
     *  due to the need of resolving agent instances versus their Id's.
     */
    public AuthorizationManager(osid.OsidOwner owner, osid.shared.Agent user, osid.shared.SharedManager sharedMgr) {
        super(owner);
        this.user = user;
        this.auths = new Vector(100);
        this.functions = new Vector(100);
        this.qualifiers = new Vector(100);
        this.rootQualifiers = new Vector(100);
        this.sharedMgr = sharedMgr;
    }
    
    /**
     *  Initialize the authorization manager.  This should be called if the Authorization
     *  Manager is loaded by OsidLoader.  It causes the default user to be initialized and
     *  the Shared Manager to be cached locally.
     *
     *  @author Mark Norton
     */
    public void initManager (osid.shared.Agent user, osid.shared.SharedManager sharedMgr) {
        this.user = user;
        this.sharedMgr = sharedMgr;
    }
    
    /**
     *  The documentation indicates that this check doesn't determine if the agent is
     *  referenced by the AZMgr, or is present in the shared manager.  The MIT implementation
     *  checks for an agent of the Id in a database table.  It returns true if the agent
     *  is "known" to the authorization manager.  This implementation returns true if
     *  an agent of the Id given is present in the list of authorizations.
     *
     *  @author Mark Norton
     */
    public boolean agentExists(osid.shared.Id agentId) {
        for (int i = 0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            try {
                if (agentId.isEqual(az.getAgent().getId()))
                    return true;
            }
            catch (osid.shared.SharedException ex) {
                return false;
            }
            catch (osid.authorization.AuthorizationException ex2) {
                return false;
            }
        }
        return false;
    }
    
    /**
     *  Return a new authorization given an agent, function, and qualifier.  Use this version
     *  if the authorization doesn't have date bounds.  Creates explicit authorizations.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Authorization createAuthorization(osid.shared.Id agentId, osid.shared.Id functionId, osid.shared.Id qualifierId) {
        return createDatedAuthorization (agentId, functionId, qualifierId, null, null);
    }
    
    /**
     *  Return a new authorization given an agent, function, and qualifier.  Use this version if
     *  the authorization has date bounds.  Creates explicit authorizations.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Authorization createDatedAuthorization(osid.shared.Id agentId, osid.shared.Id functionId, osid.shared.Id qualifierId, java.util.Calendar effectiveDate, java.util.Calendar expirationDate) {
        //System.out.println ("createDatedAuthorization - functionID:  "+functionId);
        osid.shared.Id authId = null;
        try {
            authId = sharedMgr.createId();
        }
        catch (osid.shared.SharedException ex) {}
        osid.authorization.Function ftn = getFunction (functionId);
        osid.authorization.Qualifier qual = getQualifier (qualifierId);
        VueAuthorization az = new VueAuthorization (authId, agentId, ftn, qual, effectiveDate, expirationDate, true);
        auths.add (az);
        return (osid.authorization.Authorization) az;
    }
    
    /**
     *  Create a new function given a functionId, display name, description, function type, and hierarchy id.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Function createFunction(osid.shared.Id functionId, String displayName, String description, osid.shared.Type functionType, osid.shared.Id qualifierHierarchyId) {
        VueFunction ftn = new VueFunction (displayName, description, functionType, functionId, qualifierHierarchyId);
        functions.add (ftn);
        return (osid.authorization.Function) ftn;
    }
    
    /**
     *  Create a new qualifier given a Id, dislay name, description, qualifier type, and parent.
     *  The parent may be null, if there is no inheritance relationships.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Qualifier createQualifier(osid.shared.Id qualifierId, String displayName, String description, osid.shared.Type qualifierType, osid.shared.Id parentId) {
        VueQualifier parent = (VueQualifier) this.getQualifier(parentId);
        VueQualifier qual = new VueQualifier (displayName, description, qualifierId, qualifierType, this, parent);
        qualifiers.add (qual);
        return qual;
    }
    
    /**
     *  Create a qualifier node and enter it as the root of a qualifier hierarchy.  Since osid.hierarchy is not being
     *  used in this implementation, the qualifier node created is added to the list of root nodes.  The qualifier
     *  hierarchy Id is not used and may be passed as null.  Qualifier roots do not have parents.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Qualifier createRootQualifier(osid.shared.Id qualifierId, String displayName, String description, osid.shared.Type qualifierType, osid.shared.Id qualifierHierarchyId) {
        VueQualifier qual = new VueQualifier (displayName, description, qualifierId, qualifierType, null);
        qualifiers.add (qual);
        rootQualifiers.add (qual);
        return qual;
    }
    
    /**
     *  Delete the authorization given by the identifier passed.
     *
     *  @author Mark Norton
     */
    public void deleteAuthorization(osid.shared.Id authorizationId) {
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            try {
                if (authorizationId.isEqual(az.getId())) {
                    auths.remove(i);
                }
            }
            catch (osid.shared.SharedException ex) {}
        }
    }
    
    /**
     *  Delete the function given by its identifier.  All authorizations based on this
     *  function are also deleted.
     *
     *  @author Mark Norton
     */
    public void deleteFunction(osid.shared.Id functionId) {
        //  Search for all authorizations based on this function and delete them.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            VueFunction ftn = (VueFunction) az.getFunction();
            try {
                if (functionId.isEqual (ftn.getId()))
                    auths.remove (i);
            }
            catch (osid.shared.SharedException ex) {}
        }
        
        //  Search for the function and remove it from the list of known functions.
        for (int j=0; j < functions.size(); j++) {
            VueFunction ftn = (VueFunction) functions.elementAt(j);
            try {
                if (functionId.isEqual(ftn.getId()))
                    functions.remove(j);
            }
            catch (osid.shared.SharedException ex2) {}
        }
    }
    
    /**
     *  Since deleting qualifiers has a serious impact on the trees that they are included
     *  in, deletion is not supported in this implementation.
     *
     *  @author Mark Norton
     */
    public void deleteQualifier(osid.shared.Id qualifierId) throws osid.authorization.AuthorizationException {
        //  Trees need to be repaired if qualifiers are deleted.
        throw new osid.authorization.AuthorizationException (osid.authorization.AuthorizationException.UNIMPLEMENTED);
    }
    
    /**
     *  Returns all authorizations with the agent id, function id and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  agent-id, funtion-id, qualifier-id, active
    public osid.authorization.AuthorizationIterator getAllAZs(osid.shared.Id agentId, osid.shared.Id functionId, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the agent, function and qualifier, and is active, then add it to our final list.
            if (az.hasAgent(agentId) && az.hasFunction(functionId) && az.hasQualifierOrAncestor(qualifierId)) {
                if (isActiveNow && az.isActiveNow()) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (azCopy);
                }
                else if (isActiveNow == false) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (az);
                }
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all authorizations with the agent id, function type and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  agent-id, function-type, qualifier-id, active
    public osid.authorization.AuthorizationIterator getAllAZsByFuncType(osid.shared.Id agentId, osid.shared.Type functionType, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the agent, function and qualifier, and is active, then add it to our final list.
            if (az.hasAgent(agentId) && az.hasFunctionType(functionType) && az.hasQualifierOrAncestor(qualifierId)) {
                if (isActiveNow && az.isActiveNow()) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (azCopy);
                }
                else if (isActiveNow == false) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (az);
                }
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all authorizations with the function id and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  function-id, qualifier-id, active
    public osid.authorization.AuthorizationIterator getAllUserAZs(osid.shared.Id functionId, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the function and qualifier, and is active, then add it to our final list.
            if (az.hasFunction(functionId) && az.hasQualifierOrAncestor(qualifierId)) {
                if (isActiveNow && az.isActiveNow()) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (azCopy);
                }
                else if (isActiveNow == false) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (az);
                }
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all authorizations with the function type and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  agent-id, funtion-type, qualifier-id, active
    public osid.authorization.AuthorizationIterator getAllUserAZsByFuncType(osid.shared.Type functionType, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the function and qualifier, and is active, then add it to our final list.
            if (az.hasFunctionType(functionType) && az.hasQualifierOrAncestor(qualifierId)) {
                if (isActiveNow && az.isActiveNow()) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (azCopy);
                }
                else if (isActiveNow == false) {
                    VueAuthorization azCopy = (VueAuthorization) az.clone();
                    authz.add (az);
                }
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all explicit authorizations with the agent id, function id and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  agent-id, function-id, qualifier-id, active
    public osid.authorization.AuthorizationIterator getExplicitAZs(osid.shared.Id agentId, osid.shared.Id functionId, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the agent, function and qualifier, and is active, then add it to our final list.
            if (az.hasAgent(agentId) && az.hasFunction(functionId) && az.hasQualifier(qualifierId)) {
                if (isActiveNow && az.isActiveNow())
                    authz.add (az);
                else if (isActiveNow == false)
                    authz.add (az);
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all explicit authorizations with the agent id, function type and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  agent-id, function-type, qualifier-id, active
    public osid.authorization.AuthorizationIterator getExplicitAZsByFuncType(osid.shared.Id agentId, osid.shared.Type functionType, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the agent, function and qualifier, and is active, then add it to our final list.
            if (az.hasAgent(agentId) && az.hasFunctionType(functionType) && az.hasQualifier(qualifierId)) {
                if (isActiveNow && az.isActiveNow())
                    authz.add (az);
                else if (isActiveNow == false)
                    authz.add (az);
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all explicit authorizations with the function id and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  funtion-id, qualifier-id, active
    public osid.authorization.AuthorizationIterator getExplicitUserAZs(osid.shared.Id functionId, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the function and qualifier, and is active, then add it to our final list.
            if (az.hasFunction(functionId) && az.hasQualifier(qualifierId)) {
                if (isActiveNow && az.isActiveNow())
                    authz.add (az);
                else if (isActiveNow == false)
                    authz.add (az);
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Returns all explicit authorizations with the function type and qualifier id given.
     *  If the active flag is true, the authorizations must be within the activation dates.
     *
     *  @author Mark Norton
     */
    //  function-type, qualifier-id, active
    public osid.authorization.AuthorizationIterator getExplicitUserAZsByFuncType(osid.shared.Type functionType, osid.shared.Id qualifierId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the function and qualifier, and is active, then add it to our final list.
            if (az.hasFunctionType(functionType) && az.hasQualifier(qualifierId)) {
                if (isActiveNow && az.isActiveNow())
                    authz.add (az);
                else if (isActiveNow == false)
                    authz.add (az);
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }
    
    /**
     *  Get all the authorizations for a specified user agent.
     *  <p>
     *  Note that this method is an extension to osid.authorization.
     *
     *  @author Mark Norton
     */
    public osid.authorization.AuthorizationIterator getAllExplicitAZs(osid.shared.Id agentId, boolean isActiveNow) {
        Vector authz = new Vector(100);
        
        //  Iterate over all known authorizations.
        System.out.println ("getAllExplicitAZs:  Authorization count: " + auths.size());
        for (int i=0; i < auths.size(); i++) {
            VueAuthorization az = (VueAuthorization) auths.elementAt(i);
            
            //  If the authorization has the agent and is active, then add it to our final list.
            if (az.hasAgent(agentId)) {
                if (isActiveNow && az.isActiveNow())
                    authz.add (az);
                else if (isActiveNow == false)
                    authz.add (az);
            }
        }
        return (osid.authorization.AuthorizationIterator) new VueAuthorizationIterator (authz);
    }

    /**
     *  Return the Function given an function Id.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Function getFunction(osid.shared.Id functionId) {
        osid.authorization.Function foundFtn = null;
        VueFunctionIterator it = new VueFunctionIterator (functions);
        while (it.hasNext()) {
            osid.authorization.Function ftn = it.next();
            osid.shared.Id id = ((VueFunction)ftn).getId();
            try {
                if (id.isEqual(functionId)) {
                    foundFtn = ftn;
                    break;
                }
           }
           catch (osid.shared.SharedException ex) {}
        }
        return foundFtn;
    }
    
    /**
     *  Return an iterator which lists the known function types.
     *
     *  @author Mark Norton
     */
    public osid.shared.TypeIterator getFunctionTypes() {
        return new tufts.oki.shared.TypeIterator (tufts.oki.authorization.VueFunctionType.functionTypes);
    }
    
    /**
     *  Return an iterator which lists the currently defined functions.
     *
     *  @author Mark Norton
     */
    public osid.authorization.FunctionIterator getFunctions(osid.shared.Type functionType) {
        return new VueFunctionIterator (functions);
    }
    
    /**
     *  Return the qualifier who's id is given.
     *
     *  @author Mark Norton
     */
    public osid.authorization.Qualifier getQualifier(osid.shared.Id qualifierId) {
        osid.authorization.Qualifier foundQual = null;
        VueQualifierIterator it = new VueQualifierIterator (qualifiers);
        while (it.hasNext()) {
            osid.authorization.Qualifier qual = it.next();
            osid.shared.Id id = ((VueQualifier)qual).getId();
            try {
                if (id.isEqual(qualifierId)) {
                    foundQual = qual;
                    break;
                }
            }
            catch (osid.shared.SharedException ex) {}
        }
        return foundQual;
    }
    
    /**
     *  Return an interator for the children of the qualfier given by it's Id.
     *
     *  @author Mark Norton
     */
    public osid.authorization.QualifierIterator getQualifierChildren(osid.shared.Id qualifierId) {
        Vector children = new Vector(10);
        for (int i = 0; i < this.qualifiers.size(); i++) {
            VueQualifier qual = (VueQualifier) qualifiers.elementAt(i);
            if (qual.isChildOf (qualifierId)) {
                children.add (qual);
            }
        }
        return (osid.authorization.QualifierIterator) new VueQualifierIterator (children);
    }
    
    /**
     *  Return an iterator for all descendants of the qualfier given by it's Id.
     *
     *  @author Mark Norton
     */
    public osid.authorization.QualifierIterator getQualifierDescendants(osid.shared.Id qualifierId) {
        Vector children = new Vector(10);
        for (int i = 0; i < this.qualifiers.size(); i++) {
            VueQualifier qual = (VueQualifier) qualifiers.elementAt(i);
            if (qual.isDescendantOf (qualifierId)) {
                children.add (qual);
            }
        }
        return (osid.authorization.QualifierIterator) new VueQualifierIterator (children);
    }
    
    /**
     *  Return an iterator for the list of root qualifier hierarchy Ids.
     *
     *  @author Mark Norton
     */
    public osid.shared.IdIterator getQualifierHierarchies() {
        Vector roots = new Vector (rootQualifiers.size());
        for (int i=0; i < rootQualifiers.size(); i++) {
            VueQualifier rt = (VueQualifier) rootQualifiers.elementAt(i);
            roots.add (rt.getId());
        }
        return new tufts.oki.shared.IdIterator (roots);
    }
    
    /**
     *  Return an iterator for the list of known qualifier types.
     *
     *  @author Mark Norton
     */
    public osid.shared.TypeIterator getQualifierTypes() {
        return new tufts.oki.shared.TypeIterator (tufts.oki.authorization.VueQualifierType.qualifierTypes);
    }
    
    /**
     *  This method is intended to return the roots associated with a particular hiearchy.  Since
     *  this implementation doesn't use osid.hierarchy, it returns an iterator for the known
     *  qualifier roots.  The qualifierHierarchyId is ignored and may be passed as null.
     *
     *  @author Mark Norton
     */
    public osid.authorization.QualifierIterator getRootQualifiers(osid.shared.Id qualifierHierarchyId) {
        return (osid.authorization.QualifierIterator) new VueQualifierIterator (this.rootQualifiers);
    }
    
    /**
     *  Return an iterator which lists all agents who are authorized to perform the function on the qualifier
     *  given.  The isActive flag is used to determine if all authorizations or only those which are active
     *  should be included.
     *
     *  @author Mark Norton
     */
    public osid.shared.AgentIterator getWhoCanDo(osid.shared.Id functionId, osid.shared.Id qualifierId, boolean isActiveNow) throws osid.authorization.AuthorizationException {
        //  Get all authorizations for this function, and qualifier.
        VueAuthorizationIterator it = (VueAuthorizationIterator) this.getAllUserAZs (functionId, qualifierId, isActiveNow);

        //  Iterate over those authorizations and extract a unique list of agents.
        Vector agents = new Vector(100);
        while (it.hasNext()) {
            VueAuthorization az = (VueAuthorization) it.next();
            osid.shared.Agent ag = az.getAgent();
            if (agents.indexOf (ag) == -1)
                agents.add(ag);
        }
        return new tufts.oki.shared.AgentIterator(agents);
    }
    
    /**
     *  Return true if the agent provided is currently authorized to perform the function on
     *  the qualifer provided.
     *
     *  @author Mark Norton
     */
    public boolean isAuthorized(osid.shared.Id agentId, osid.shared.Id functionId, osid.shared.Id qualifierId) {
        //  Get all authorizations for this agent, function, and qualifier currently active.
        VueAuthorizationIterator it = (VueAuthorizationIterator) this.getAllAZs(agentId, functionId, qualifierId, true);
        
        //  If there is one or more, then the agent is authorized.
        if (it.hasNext())
            return true;
        else
            return false;
    }
    
    /**
     *  Return true if the default user is currently authorized to perform the function on
     *  the qualifer provided.
     *
     *  @author Mark Norton
     */
    public boolean isUserAuthorized(osid.shared.Id functionId, osid.shared.Id qualifierId) throws osid.authorization.AuthorizationException {
        osid.shared.Id userId = null;
        
        //  Check to see that there is a valid default user agent.
        if (this.user == null)
            throw new osid.authorization.AuthorizationException ("Unknown default user.");
        
        //  If so, use it to see if that agent is authorized to perform the function on the qualifier.
        else {
            try {
                userId = this.user.getId();
            }
            catch (osid.shared.SharedException ex) {}
            return isAuthorized (userId, functionId, qualifierId);
        }
    }

}
