/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/NamespaceConfig.java,v 1.37 2004/11/24 16:20:42 luetzkendorf Exp $
 * $Revision: 1.37 $
 * $Date: 2004/11/24 16:20:42 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed under the Apache 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.apache.org/licenses/LICENSE-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.
 *
 */

package org.apache.slide.common;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.apache.slide.content.ContentInterceptor;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.structure.ActionNode;
import org.apache.slide.structure.LinkNode;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.Messages;
import org.apache.slide.util.conf.Configuration;
import org.apache.slide.util.conf.ConfigurationException;
import org.apache.slide.util.logger.Logger;

/**
 * Configuration of the Namespace.
 *
 * @version $Revision: 1.37 $
 */
public final class NamespaceConfig {
    
    
    // -------------------------------------------------------------- Constants
    
    
    /**
     * Base role names.
     */
    public static final String NOBODY = "nobody";
    public static final String NOBODY_ROLE = ObjectNode.class.getName();
    public static final String BASE_ROLE = SubjectNode.class.getName();
    public static final String ACTION_ROLE = ActionNode.class.getName();
    public static final String LINK_ROLE = LinkNode.class.getName();
    
    
    private final static String
        ACL_INHERIT_TYPE       = "acl_inheritance_type",
        NESTED_ROLES_MAXDEPTH  = "nested_roles_maxdepth";
    
    private final static int
        NESTED_ROLES_MAXDEPTH_DEFAULT = 0;
    
    public final static int
        ACL_INHERIT_TYPE_NONE  = 0,
        ACL_INHERIT_TYPE_ROOT  = 1,
        ACL_INHERIT_TYPE_PATH  = 2,
        ACL_INHERIT_TYPE_FULL  = 3;
    
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Namespace name.
     */
    protected String name;
    
    
    /**
     * Read object action.
     */
    protected ActionNode readObjectAction;
    
    
    /**
     * Create object action. Equivalent to createChildAction.
     */
    protected ActionNode createObjectAction;
    
    
    /**
     * Remove object action.
     */
    protected ActionNode removeObjectAction;
    
    
    /**
     * Grant permission action.
     */
    protected ActionNode grantPermissionAction;
    
    
    /**
     * Revoke permission action.
     */
    protected ActionNode revokePermissionAction;
    
    
    /**
     * Read permissions action.
     */
    protected ActionNode readPermissionsAction;
    protected ActionNode readOwnPermissionsAction;
    
    
    /**
     * Lock object action.
     */
    protected ActionNode lockObjectAction;
    
    
    /**
     * Kill lock action.
     */
    protected ActionNode killLockAction;
    
    
    /**
     * Read locks action.
     */
    protected ActionNode readLocksAction;
    
    
    /**
     * Create revision metadata action.
     */
    protected ActionNode createRevisionMetadataAction;
    
    
    /**
     * Modify revision metadata action.
     */
    protected ActionNode modifyRevisionMetadataAction;
    
    
    /**
     * Remove revision metadata action.
     */
    protected ActionNode removeRevisionMetadataAction;
    
    
    /**
     * Read revision metadata action.
     */
    protected ActionNode readRevisionMetadataAction;
    
    
    /**
     * Read revision content action.
     */
    protected ActionNode readRevisionContentAction;
    
    
    /**
     * Create revision content action.
     */
    protected ActionNode createRevisionContentAction;
    
    
    /**
     * Modify revision content action.
     */
    protected ActionNode modifyRevisionContentAction;
    
    
    /**
     * Remove revision content action.
     */
    protected ActionNode removeRevisionContentAction;
    
    
    /**
     * Bind/unbind actions
     */
    protected ActionNode bindMemberAction;
    protected ActionNode unbindMemberAction;
    
    
    /**
     * Users path.
     */
    protected String usersPath = null;
    protected String groupsPath = null;
    protected String rolesPath = null;
    
    private UriPath
        usersUriPath,
        groupsUriPath,
        rolesUriPath;
    
    
    /**
     * Guest user path.
     */
    protected String guestPath;
    
    
    /**
     * File path.
     */
    protected String filesPath = null;
    
    
    /**
     * File path.
     */
    protected String actionsPath = null;
    
    
    /**
     * Additional parameters.
     */
    protected Hashtable parameters;
    
    
    /**
     * Role name -> role interface mappings.
     * Note : One name is associated to only one interface.
     */
    protected Hashtable roleMappings = new Hashtable();
    
    
    /**
     * Role interface -> role name mappings.
     * Note : One interface can be associated to multiple names, in which case
     * only one is stored here.
     */
    protected Hashtable roleClassMappings = new Hashtable();
    
    
    /**
     * List of default properties.
     * Role name -> Vector[NodeProperty].
     */
    protected Hashtable defaultProperties;
    
    
    /**
     * Empty vector. Don't add stuff there.
     */
    protected static Vector emptyVector = new Vector();
    
    
    /**
     * Content interceptors.
     */
    protected ContentInterceptor[] contentInterceptors
        = new ContentInterceptor[0];
    
    /**
     * Automatically create users.
     */
    protected boolean autoCreateUsers = false;
    
    
    /**
     * Roles implementation to be used for automatically created users.
     */
    protected String autoCreateUsersRole = "slideroles.basic.UserRoleImpl";
    
    
    // ------------------------------------------------------------- Properties
    
    
    /**
     * Default action accessor.
     *
     * @return ActionNode Default action
     */
    public ActionNode getDefaultAction() {
        return ActionNode.DEFAULT;
    }
    
    
    /**
     * Read object action accessor.
     *
     * @return ActionNode Read object action
     */
    public ActionNode getReadObjectAction() {
        return readObjectAction;
    }
    
    
    /**
     * Create object action accessor.
     *
     * @return ActionNode Create object action
     */
    public ActionNode getCreateObjectAction() {
        return createObjectAction;
    }
    
    
    /**
     * Remove object accessor.
     *
     * @return ActionNode Remove object action
     */
    public ActionNode getRemoveObjectAction() {
        return removeObjectAction;
    }
    
    
    /**
     * Grant permission accessor.
     *
     * @return ActionNode Grant permission action
     */
    public ActionNode getGrantPermissionAction() {
        return grantPermissionAction;
    }
    
    
    /**
     * Revoke permission accessor.
     *
     * @return ActionNode Revoke permission action
     */
    public ActionNode getRevokePermissionAction() {
        return revokePermissionAction;
    }
    
    
    /**
     * Read permissions accessor.
     *
     * @return ActionNode Read permissions action
     */
    public ActionNode getReadPermissionsAction() {
        return readPermissionsAction;
    }
    public ActionNode getReadOwnPermissionsAction() {
        return readOwnPermissionsAction;
    }
    
    
    /**
     * Lock object accessor.
     *
     * @return ActionNode Lock object action
     */
    public ActionNode getLockObjectAction() {
        return lockObjectAction;
    }
    
    
    /**
     * Kill lock accessor.
     *
     * @return ActionNode Kill lock action
     */
    public ActionNode getKillLockAction() {
        return killLockAction;
    }
    
    
    /**
     * Read locks accessor.
     *
     * @return ActionNode Read locks action
     */
    public ActionNode getReadLocksAction() {
        return readLocksAction;
    }
    
    
    /**
     * Create revision metadata accessor.
     *
     * @return ActionNode Create revision metadata action
     */
    public ActionNode getCreateRevisionMetadataAction() {
        return createRevisionMetadataAction;
    }
    
    
    /**
     * Read revision metadata accessor.
     *
     * @return ActionNode Read revision metadata action
     */
    public ActionNode getReadRevisionMetadataAction() {
        return readRevisionMetadataAction;
    }
    
    
    /**
     * Modify revision metadata accessor.
     *
     * @return ActionNode Modify revision metadata action
     */
    public ActionNode getModifyRevisionMetadataAction() {
        return modifyRevisionMetadataAction;
    }
    
    
    /**
     * Remove revision metadata accessor.
     *
     * @return ActionNode Remove revision metadata action
     */
    public ActionNode getRemoveRevisionMetadataAction() {
        return removeRevisionMetadataAction;
    }
    
    
    /**
     * Read revision content accessor.
     *
     * @return ActionNode Read revision content action
     */
    public ActionNode getReadRevisionContentAction() {
        return readRevisionContentAction;
    }
    
    
    /**
     * Create revision content accessor.
     *
     * @return ActionNode Create revision content action
     */
    public ActionNode getCreateRevisionContentAction() {
        return createRevisionContentAction;
    }
    
    
    /**
     * Modify revision content accessor.
     *
     * @return ActionNode Modify revision content action
     */
    public ActionNode getModifyRevisionContentAction() {
        return modifyRevisionContentAction;
    }
    
    
    /**
     * Remove revision content accessor.
     *
     * @return ActionNode Remove revision content action
     */
    public ActionNode getRemoveRevisionContentAction() {
        return removeRevisionContentAction;
    }
    
    
    /**
     * Method getBindAction
     *
     * @return   an ActionNode
     */
    public ActionNode getBindMemberAction() {
        return bindMemberAction;
    }
    
    
    public ActionNode getUnbindMemberAction() {
        return unbindMemberAction;
    }
    
    /**
     * Users path accessor.
     *
     * @return String Users path
     */
    public String getUsersPath() {
        return usersPath;
    }
    
    /**
     * Groups path accessor.
     *
     * @return String Groups path
     */
    public String getGroupsPath() {
        return groupsPath;
    }
    
    /**
     * Roles path accessor.
     *
     * @return String Roles path
     */
    public String getRolesPath() {
        return rolesPath;
    }
    
    
    /**
     * Guest path accessor.
     *
     * @return String Guest path
     * @deprecated There is now a generic SubjectNode for "guest"
     */
    public String getGuestPath() {
        return guestPath;
    }
    
    
    /**
     * Files path accessor.
     *
     * @return String Files path
     */
    public String getFilesPath() {
        return filesPath;
    }
    
    
    /**
     * Actions path accessor.
     *
     * @return String Action path
     */
    public String getActionsPath() {
        return actionsPath;
    }
    
    
    /**
     * Get default properties for a given role.
     *
     * @return Enumeration of properties
     */
    public Enumeration getDefaultProperties(String role) {
        Vector result = (Vector) defaultProperties.get(role);
        if (result == null)
            return emptyVector.elements();
        else
            return result.elements();
    }
    
    
    /**
     * Get content interceptors.
     */
    ContentInterceptor[] getContentInterceptors() {
        return contentInterceptors;
    }
    
    
    // --------------------------------------------------------- Public Methods
    
    
    /**
     * Get parameter value.
     *
     * @param name Parameter name
     * @return String Parameter value
     */
    public String getParameter(String name) {
        Object result = parameters.get(name);
        if (result==null) {
            return null;
        } else {
            return (String) result;
        }
    }
    
    
    /**
     * Get role mapping. If the interface name is given, one of the names is
     * returned. If the name is given, the interface name is returned.
     *
     * @param name Role name (or interface name)
     * @return String Role interface name (or name)
     */
    public String getRoleMapping(String name) {
        Object result = roleMappings.get(name);
        if (result == null) {
            return (String) roleClassMappings.get(name);
        } else {
            return (String) result;
        }
    }
    
    
    /**
     * Is automcatic user creation active ?
     */
    public boolean isAutoCreateUsers() {
        return autoCreateUsers;
    }

    public boolean isPrincipal(String uri) {
        return (usersUriPath != null && usersUriPath.isParentOf(uri) ||
                rolesUriPath != null && rolesUriPath.isParentOf(uri) ||
                groupsUriPath != null && groupsUriPath.isParentOf(uri));
    }

    public boolean isRole(String uri) {
        return (rolesUriPath != null && rolesUriPath.isParentOf(uri));
    }

    public boolean isGroup(String uri) {
        return (groupsUriPath != null && groupsUriPath.isParentOf(uri));
    }
    
    
    /**
     * Get the class name of the role which will be used to create nodes which
     * are automatically created when isAutoCreateUsers() returns true.
     */
    public String getAutoCreateUsersRole() {
        return autoCreateUsersRole;
    }
    
    public int getAclInheritanceType() {
        String aclInheritanceTypeStr = getParameter(ACL_INHERIT_TYPE);
        if ("none".equalsIgnoreCase(aclInheritanceTypeStr)) {
            return ACL_INHERIT_TYPE_NONE;
        }
        else if ("root".equalsIgnoreCase(aclInheritanceTypeStr)) {
            return ACL_INHERIT_TYPE_ROOT;
        }
        else if ("path".equalsIgnoreCase(aclInheritanceTypeStr)) {
            return ACL_INHERIT_TYPE_PATH;
        }
        else if ("full".equalsIgnoreCase(aclInheritanceTypeStr)) {
            return ACL_INHERIT_TYPE_FULL;
        }
        else {
            return ACL_INHERIT_TYPE_PATH;
        }
    }
    
    public int getNestedRolesMaxDepth() {
        int result = NESTED_ROLES_MAXDEPTH_DEFAULT;
        String nestedRolesMaxDepthStr = getParameter(NESTED_ROLES_MAXDEPTH);
        try {
            result = Integer.parseInt(nestedRolesMaxDepthStr);
        }
        catch (NumberFormatException e) {}
        return result;
    }
    
    // -------------------------------------------------------- Package Methods
    
    
    /**
     * Initialize the Namespace configuration using the given Configuration
     * object.
     *
     * @param namespace Namespace on which we are trying to load the config
     * @param config Castor Config object
     * @exception InvalidNamespaceConfigurationException Namespace
     * configuration is invalid
     * @exception SlideException One of the action nodes doesn't exist
     */
    void initializeNamespaceConfig(Namespace namespace, Configuration config)
        throws InvalidNamespaceConfigurationException, SlideException {
        
        name = namespace.getName();
        
        readObjectAction = getConfiguredNode(namespace, config, "read-object");
        createObjectAction = getConfiguredNode(namespace, config, "create-object");
        removeObjectAction = getConfiguredNode(namespace, config, "remove-object");
        grantPermissionAction = getConfiguredNode(namespace, config, "grant-permission");
        revokePermissionAction = getConfiguredNode(namespace, config, "revoke-permission");
        readPermissionsAction = getConfiguredNode(namespace, config, "read-permissions");
        readOwnPermissionsAction = getConfiguredNode(namespace, config, "read-own-permissions");
        lockObjectAction = getConfiguredNode(namespace, config, "lock-object");
        killLockAction = getConfiguredNode(namespace, config, "kill-lock");
        readLocksAction = getConfiguredNode(namespace, config, "read-locks");
        readRevisionMetadataAction = getConfiguredNode(namespace, config, "read-revision-metadata");
        createRevisionMetadataAction = getConfiguredNode(namespace, config, "create-revision-metadata");
        modifyRevisionMetadataAction = getConfiguredNode(namespace, config, "modify-revision-metadata");
        removeRevisionMetadataAction = getConfiguredNode(namespace, config, "remove-revision-metadata");
        readRevisionContentAction = getConfiguredNode(namespace, config, "read-revision-content");
        createRevisionContentAction = getConfiguredNode(namespace, config, "create-revision-content");
        modifyRevisionContentAction = getConfiguredNode(namespace, config, "modify-revision-content");
        removeRevisionContentAction = getConfiguredNode(namespace, config, "remove-revision-content");
        
        bindMemberAction = getConfiguredNode(namespace, config, "bind-member");
        unbindMemberAction = getConfiguredNode(namespace, config, "unbind-member");
        
        
        setPathsAndConfigValues(config);
        
        setParameters(config, namespace);
        
        setRoles(config, namespace);
        
        setDefaultProperties(config, namespace);
        
        Enumeration contentInteceptorsDef =
            config.getConfigurations("content-interceptor");
        try {
            while (contentInteceptorsDef.hasMoreElements()) {
                Configuration contentInterceptorDef =
                    (Configuration) contentInteceptorsDef.nextElement();
                String classname = contentInterceptorDef.getAttribute("class");
                
                // Load contentInterceptor parameters
                Enumeration contentInterceptorParametersDef =
                    contentInterceptorDef.getConfigurations("parameter");
                Hashtable contentInterceptorParameters = new Hashtable();
                while (contentInterceptorParametersDef.hasMoreElements()) {
                    Configuration parameterDefinition = (Configuration)
                        contentInterceptorParametersDef.nextElement();
                    String parameterName =
                        parameterDefinition.getAttribute("name");
                    String parameterValue = parameterDefinition.getValue();
                    contentInterceptorParameters.put(parameterName,
                                                     parameterValue);
                }
                
                try {
                    Class contentInterceptorClass =
                        Class.forName(classname);
                    ContentInterceptor contentInterceptor =
                        (ContentInterceptor)
                        contentInterceptorClass.newInstance();
                    contentInterceptor.setParameters(contentInterceptorParameters);
                    ContentInterceptor[] tempArray =
                        new ContentInterceptor[contentInterceptors.length + 1];
                    for (int i = 0; i < contentInterceptors.length; i++) {
                        tempArray[i] = contentInterceptors[i];
                    }
                    tempArray[contentInterceptors.length] = contentInterceptor;
                    contentInterceptors = tempArray;
                } catch (Exception e) {
                    namespace.getLogger().log
                        (Messages.format
                             ("org.apache.slide.common.InvalidContentInterceptor",
                              classname, e.getMessage()), Logger.WARNING);
                }
            }
            
            // Initialize the content interceptors with the
            // NamespaceAccessToken
            NamespaceAccessToken nat = new NamespaceAccessTokenImpl(namespace);
            ContentInterceptor[] contentInterceptors =
                namespace.getContentInterceptors();
            for (int i = 0; i < contentInterceptors.length; i++) {
                contentInterceptors[i].setNamespace(nat);
            }
        } catch (ConfigurationException e) {
            throw new InvalidNamespaceConfigurationException
                (namespace, e.getMessage());
        }
        
    }
    
    private void setDefaultProperties(Configuration config, Namespace namespace) throws InvalidNamespaceConfigurationException {
        defaultProperties = new Hashtable();
        Enumeration defaultPropertiesDef =
            config.getConfigurations("default-property");
        try {
            while (defaultPropertiesDef.hasMoreElements()) {
                Configuration defaultProperty =
                    (Configuration) defaultPropertiesDef.nextElement();
                String name = defaultProperty.getAttribute("name");
                String value = defaultProperty.getAttribute("value", "");
                String propertyNamespace = defaultProperty.getAttribute
                    ("namespace", NodeProperty.DEFAULT_NAMESPACE);
                String role = defaultProperty.getAttribute("role");
                addDefaultProperty(role, name, value, propertyNamespace);
            }
        } catch (ConfigurationException e) {
            throw new InvalidNamespaceConfigurationException
                (namespace, e.getMessage());
        }
    }
    
    private void setParameters(Configuration config, Namespace namespace) throws InvalidNamespaceConfigurationException {
        parameters = new Hashtable();
        Enumeration parametersDef = config.getConfigurations("parameter");
        try {
            while (parametersDef.hasMoreElements()) {
                Configuration parameter =
                    (Configuration) parametersDef.nextElement();
                addParameter(parameter.getAttribute("name"),
                             parameter.getValue());
            }
        } catch (ConfigurationException e) {
            throw new InvalidNamespaceConfigurationException
                (namespace, e.getMessage());
        }
    }
    
    private ActionNode getConfiguredNode(Namespace namespace, Configuration config, String nodeName) throws SlideException {
        ActionNode result = null;
        try {
            result = getActionNode(namespace, config.getConfiguration( nodeName).getValue());
        } catch (ConfigurationException e) {
            result = getDefaultAction();
        }
        return result;
    }
    
    private void setPathsAndConfigValues(Configuration config) {
        try {
            usersPath = config.getConfiguration("userspath").getValue();
            usersUriPath = new UriPath(usersPath);
        } catch (ConfigurationException e) {
            usersPath = "";
        }
        
        try {
            groupsPath = config.getConfiguration("groupspath").getValue();
            groupsUriPath = new UriPath(groupsPath);
        } catch (ConfigurationException e) {
            groupsPath = "";
        }
        
        try {
            rolesPath = config.getConfiguration("rolespath").getValue();
            rolesUriPath = new UriPath(rolesPath);
        } catch (ConfigurationException e) {
            rolesPath = "";
        }
        
        try {
            guestPath = config.getConfiguration("guestpath").getValue();
        } catch (ConfigurationException e) {
            guestPath = "";
        }
        
        try {
            filesPath = config.getConfiguration("filespath").getValue();
        } catch (ConfigurationException e) {
            filesPath = "";
        }
        
        try {
            actionsPath = config.getConfiguration("actionspath").getValue();
        } catch (ConfigurationException e) {
            actionsPath = "";
        }
        
        try {
            autoCreateUsers = Boolean.valueOf
                (config.getConfiguration("auto-create-users").getValue())
                .booleanValue();
        } catch (ConfigurationException e) {
            autoCreateUsers = false;
        }
        
        try {
            autoCreateUsersRole =
                config.getConfiguration("auto-create-users-role").getValue();
        } catch (ConfigurationException e) {
        }
    }
    
    
    /**
     * Initialize the Namespace configuration using the given Configuration
     * object.
     *
     * @param namespace Namespace on which we are trying to load the config
     * @param config Castor Config object
     * @exception InvalidNamespaceConfigurationException Namespace
     * configuration is invalid
     * @exception SlideException One of the action nodes doesn't exist
     */
    void initializeNamespaceParameters
        (Namespace namespace, Configuration config)
        throws InvalidNamespaceConfigurationException, SlideException {
        
        
        setParameters(config, namespace);
        
        setPathsAndConfigValues(config);
        
        setRoles(config, namespace);
        
        setDefaultProperties(config, namespace);
        
    }
    
    private void setRoles(Configuration config, Namespace namespace) throws InvalidNamespaceConfigurationException {
        // Add basic role mappings
        addRoleMapping(NOBODY, NOBODY_ROLE);
        addRoleMapping(NOBODY, LINK_ROLE);
        addRoleMapping(NOBODY, ACTION_ROLE);
        // Note : the base role should be the last one.
        addRoleMapping(NOBODY, BASE_ROLE);
        Enumeration roleMappingsDef = config.getConfigurations("role");
        try {
            while (roleMappingsDef.hasMoreElements()) {
                Configuration roleMappingDef =
                    (Configuration) roleMappingsDef.nextElement();
                addRoleMapping(roleMappingDef.getAttribute("name"),
                               roleMappingDef.getValue());
            }
        } catch (ConfigurationException e) {
            throw new InvalidNamespaceConfigurationException
                (namespace, e.getMessage());
        }
    }
    
    
    /**
     * Create a dummy config, used to create the base namespace data.
     *
     * @param namespace Namespace
     * @exception InvalidNamespaceConfigurationException Namespace
     * configuration is invalid
     */
    void initializeAsDummyConfig(Namespace namespace)
        throws InvalidNamespaceConfigurationException {
        
        name = namespace.getName();
        
        try {
            readObjectAction = getDefaultAction();
            createObjectAction = getDefaultAction();
            removeObjectAction = getDefaultAction();
            grantPermissionAction = getDefaultAction();
            revokePermissionAction = getDefaultAction();
            readPermissionsAction = getDefaultAction();
            readOwnPermissionsAction = getDefaultAction();
            lockObjectAction = getDefaultAction();
            killLockAction = getDefaultAction();
            readLocksAction = getDefaultAction();
            readRevisionMetadataAction = getDefaultAction();
            createRevisionMetadataAction = getDefaultAction();
            modifyRevisionMetadataAction = getDefaultAction();
            removeRevisionMetadataAction = getDefaultAction();
            readRevisionContentAction = getDefaultAction();
            createRevisionContentAction = getDefaultAction();
            modifyRevisionContentAction = getDefaultAction();
            removeRevisionContentAction = getDefaultAction();
            bindMemberAction = getDefaultAction();
            unbindMemberAction = getDefaultAction();
        } catch (Exception e) {
            throw new InvalidNamespaceConfigurationException
                (namespace, e.getMessage());
        }
    }
    
    
    /**
     * TEST PURPOSES ONLY.
     */
    public void initializeForTestPurposesOnly()
        throws InvalidNamespaceConfigurationException {
        
        name = "slide";
        
        try {
            readObjectAction = getDefaultAction();
            createObjectAction = getDefaultAction();
            removeObjectAction = getDefaultAction();
            grantPermissionAction = getDefaultAction();
            revokePermissionAction = getDefaultAction();
            readPermissionsAction = getDefaultAction();
            readOwnPermissionsAction = getDefaultAction();
            lockObjectAction = getDefaultAction();
            killLockAction = getDefaultAction();
            readLocksAction = getDefaultAction();
            readRevisionMetadataAction = getDefaultAction();
            createRevisionMetadataAction = getDefaultAction();
            modifyRevisionMetadataAction = getDefaultAction();
            removeRevisionMetadataAction = getDefaultAction();
            readRevisionContentAction = getDefaultAction();
            createRevisionContentAction = getDefaultAction();
            modifyRevisionContentAction = getDefaultAction();
            removeRevisionContentAction = getDefaultAction();
            bindMemberAction = getDefaultAction();
            unbindMemberAction = getDefaultAction();
        } catch (Exception e) {
            throw new InvalidNamespaceConfigurationException
                (null, e.getMessage());
        }
    }
    
    
    // ------------------------------------------------------ Protected Methods
    
    
    /**
     * Add a new parameter.
     *
     * @param name Parameter name
     * @param value Parameter value
     */
    protected void addParameter(String name, String value) {
        if ((name!=null) && (value!=null)) {
            parameters.put(name, value);
        }
    }
    
    
    /**
     * Add a new default property.
     *
     * @param role Role
     * @param name Property name
     * @param value Property value
     * @param namespace Property namespace
     */
    protected void addDefaultProperty(String role, String name, String value,
                                      String namespace) {
        if ((role!=null) && (name!=null) && (value!=null)) {
            Vector currentDefaultProperties =
                (Vector) defaultProperties.get(role);
            if (currentDefaultProperties == null) {
                currentDefaultProperties = new Vector();
                defaultProperties.put(role, currentDefaultProperties);
            }
            currentDefaultProperties.addElement
                (new NodeProperty(name, value, namespace));
        }
    }
    
    
    /**
     * Add a new role mapping.
     *
     * @param name Role mapping name
     * @param value Role mapping value
     */
    protected void addRoleMapping(String name, String value) {
        if ((name!=null) && (value!=null)) {
            roleMappings.put(name, value);
            roleClassMappings.put(value, name);
        }
    }
    
    
    /**
     * Retrieve an action node.
     *
     * @param namespace The namespace, that contains the action node
     * @param actionPath Path of the action
     */
    protected ActionNode getActionNode(Namespace namespace, String actionPath)
        throws InvalidNamespaceConfigurationException, SlideException {
        
        ActionNode result = null;
        
        if (actionPath != null) {
            Uri actionUri = namespace.getUri(actionPath);
            result = (ActionNode) actionUri.getStore()
                .retrieveObject(actionUri);
        }
        else {
            result = getDefaultAction();
        }
        
        return result;
        
    }
    
    
    // --------------------------------------------------------- Object Methods
    
    
    /**
     * Get a String representation of this domain.
     */
    public String toString() {
        return name;
    }
    
    
}
