package javax.wvcm;

import java.util.Iterator;
import java.util.List;


/**
 * NOT YET STANDARD
 * <p>
 * <b>Access Control List (ACL):</b>
 * An "ACL" is a list of access control elements that define access control to a
 * particular resource.
 * </p><p>
 * <b>Access Control Element (ACE):</b>
 * An "ACE" either grants or denies a particular set of (non-abstract) privileges
 * for a particular principal.
 * </p><p>
 * <b>Inherited ACE:</b>
 * An "inherited ACE" is an ACE that is dynamically shared from the ACL of another
 * resource. When a shared ACE changes on the primary resource, it is also changed
 * on inheriting resources.
 * </p>
 */

public class AccessControlElement {
    
    // the principal
    private Principal principal;
    
    // the list of Privilege objects
    private List privileges;
    
    // if true, the all privileges of the ACE are granted; otherwise, all are denied
    private boolean grant;
    
    // the resource from which this ACE was inherited
    private Resource inheritedFrom;
    
    public AccessControlElement(Principal principal, List privileges, boolean grant) {
        this.principal = principal;
        this.privileges = privileges;
        this.grant = grant;
    }
    
    /**
     * Set the principal of this ACE
     *
     * @param    principal a Principal object
     */
    public void setPrincipal(Principal principal) {
        this.principal = principal;
    }
    
    /**
     * Get the principal of this ACE
     *
     * @return   a Principal object
     */
    public Principal getPrincipal() {
        return principal;
    }
    
    /**
     * Set the List of Privilege objects to be granted or denied by this ACE
     *
     * @param    privileges a List of Privilege objects
     */
    public void setPrivileges(List privileges) {
        this.privileges = privileges;
    }
    
    /**
     * Set the List of Privilege objects which are granted or denied by this ACE
     *
     * @return   a List of Privilege objects
     *
     */
    public List getPrivileges() {
        return privileges;
    }
    
    /**
     * Set whether the privileges of this ACE are granted (grant=true) or denied
     * (grant=false)
     *
     * @param    grant true to grant, false to deny
     *
     */
    public void setGrant(boolean grant) {
        this.grant = grant;
    }
    
    /**
     * Returns true, if the privileges of this ACE are all granted, and false
     * if the privileges of this ACE are all denied.
     *
     * @return   true, if all privileges of this resource are granted
     *           false, if all privileges of this resource are denied
     *
     */
    public boolean isGrant() {
        return grant;
    }
    
    /**
     * Set the resource this ACE is inherited from.
     *
     * @param    inheritedFrom       a  Resource
     */
    public void setInheritedFrom(Resource inheritedFrom) {
        this.inheritedFrom = inheritedFrom;
    }
    
    /**
     * Get the resource from which this ACE is inherited from.
     *
     * @return   a Resource
     */
    public Resource getInheritedFrom() {
        return inheritedFrom;
    }
    
    public String toString() {
        StringBuffer b = new StringBuffer("ACE: principal=");
        try {
            //            b.append(principal.getDisplayName()).append(" [").append(principal.location().string()).append("], ");
            b.append(principal.location().lastSegment());
            b.append(", ");
            b.append(grant ? "grant=" : "deny=");
            b.append("[");
            Iterator i = privileges.iterator();
            for (int n=0; i.hasNext(); n++) {
                b.append(n > 0 ? "," : "");
                b.append(((Privilege)i.next()).location().lastSegment());
            }
            b.append("]");
            if (inheritedFrom != null) {
                b.append(", inheritedFrom=");
                b.append(inheritedFrom.location().string());
            }
        }
        catch (Exception e) {}
        //        catch (WvcmException e) {}
        return b.toString();
    }
    
    
    public boolean equals(Object that) {
        if (!(that instanceof AccessControlElement)) return false;
        AccessControlElement other = (AccessControlElement) that;
        boolean result =
            (this.isGrant() == other.isGrant()) &&
            (this.getPrincipal().equals(other.getPrincipal())) &&
            //            (this.getInheritedFrom().equals(other.getInheritedFrom())) &&
            (this.getPrivileges().equals(other.getPrivileges())) ;
        return result;
    }
    
    
    
    public int hashCode() {
        return getPrincipal().hashCode();
    }
    
    
    
    /**
     * NOT YET STANDARD
     * <p>
     * <b>Privilege:</b>
     * A "privilege" controls access to a particular set of HTTP operations on a resource.
     * </p><p>
     * <b>Aggregate Privilege:</b>
     * An "aggregate privilege" is a privilege that contains a set of other privileges.
     * </p><p>
     * <b>Abstract Privilege</b>
     * The modifier "abstract", when applied to a privilege on a resource, means the
     * privilege cannot be set in an access control element (ACE) on that resource .
     * </p>
     */
    public static interface Privilege extends Resource {
        
        public Privilege ALL = new GenericPrivilegeImpl(Location.ALL);
        
        /**
         * Create a Privilege on the server.
         *
         * @throws WvcmException Preconditions:
         * <br>(resource-must-be-null): A resource MUST NOT exist at the location of this Resource.
         * <br>(location-ok): The location of this Privilege MUST identify a valid location to create this Resource.
         *   A client can determine the location of folders that can contain Privileges
         *  from the PrivilegeFolderList property.
         * @throws WvcmException Postconditions:
         * <br>(initialize-resource): A new Privilege resource exists at the location of this Resource.
         */
        public void doCreateResource() throws WvcmException;
        
        
        /**
         * NOT YET STANDARD
         * Implementation of a generic Privilege.
         *
         * @author <a href="mailto:peter.nevermann@softwareag.com">Peter Nevermann</a>
         * @version $Revision: 1.5 $
         */
        public class GenericPrivilegeImpl extends GenericResourceImpl implements Privilege {
            
            /**
             * Constructor
             *
             * @param    location            a  Location
             */
            public GenericPrivilegeImpl(Location location) {
                super(location);
            }
            
            /**
             * Create a Privilege on the server.
             *
             * @throws WvcmException Preconditions:
             * <br>(resource-must-be-null): A resource MUST NOT exist at the location of this Resource.
             * <br>(location-ok): The location of this Privilege MUST identify a valid location to create this Resource.
             *   A client can determine the location of folders that can contain Privileges
             *  from the PrivilegeFolderList property.
             * @throws WvcmException Postconditions:
             * <br>(initialize-resource): A new Privilege resource exists at the location of this Resource.
             */
            public void doCreateResource() throws WvcmException {
                throw new UnsupportedOperationException("Not supported for generic resources");
            }
            
            public String toString() {
                return location().lastSegment();
            }
        }
    }
}

