/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/security/admin/URMActionsGate.java,v 1.3 2004/07/30 06:52:01 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:01 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 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.store.tamino.security.admin;

import org.apache.slide.urm.URMException;
import org.apache.slide.urm.URMForbiddenException;
import org.apache.slide.urm.accesscontroler.URMAction;
import org.apache.slide.urm.accesscontroler.URMActionIdNotUniqueException;
import org.apache.slide.urm.accesscontroler.URMActionInUseException;
import org.apache.slide.urm.common.URMDeleteException;
import org.apache.slide.urm.common.URMInsertException;
import org.apache.slide.urm.common.URMInternalServerException;
import org.apache.slide.urm.common.URMPrincipal;
import org.apache.slide.store.tamino.common.XForbiddenException;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.tools.stores.ActionDeclaration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.macro.ConflictException;
import org.apache.slide.macro.ForbiddenException;


/**
 ** URMActionsGate serves the URMActionsStore using URM API. It represents an action
 **
 ** @author    josef.haiduk@softwareag.com
 ** @version   $Revision: 1.3 $
 **
 **/

public class URMActionsGate extends URMGate
{
    
    String action = null;
    URMAction urmAction = null;
    private boolean actionExists = false;
    private boolean isHome = false;
    private boolean isParentHome = false;
    
    
    /**
     * Creates a new gate to the URM API for serving action requests
     *
     * @param    parent              an URMUserDBStore
     * @param    uriStr              a  String
     * @param    principal           an URMPrincipal
     *
     * @throws   ServiceAccessException
     *
     */
    public URMActionsGate(URMUserDBStore parent, String uriStr, URMPrincipal principal)
        throws ServiceAccessException
    {
        super(parent, uriStr, principal);
        init();
    }
    
    /**
     * Creates a new gate to the URM API for serving action requests
     *
     * @param    parent              an URMUserDBStore
     * @param    uriStr              a  String
     *
     * @throws   ServiceAccessException
     *
     */
    public URMActionsGate(URMUserDBStore parent, String uriStr)
        throws ServiceAccessException
    {
        super(parent, uriStr);
        init();
    }
    
    /**
     * Method init
     *
     * @throws   ServiceAccessException
     *
     */
    private void init()
        throws ServiceAccessException
    {
        String path = ActionDeclaration.SCOPE;
        if ( uriStr.equals(path)) {
            isHome = true;
            return;
        }
        
        if ( uri.getParent().toString().equals(path) )
            isParentHome = true;
        
        String lastToken = uriStr.substring(path.length()+1);
        if ( lastToken.indexOf("/") != -1 )
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uriStr,
                            new XForbiddenException( "Operations below an action are forbidden!!!" )));
        
        try {
            action = new String(lastToken);
            urmAction = urmAclAdm.getAction(action);
            if ( urmAction != null ) {
                actionExists = true;
            }
        }

        catch (URMInternalServerException e) {
            throw new ServiceAccessException(parent, e);
        }
    }

    /**
     * Returns true if the uri passed to the constructor equals <code>../administartion/security/actions</code>
     *
     * @return   a boolean
     *
     */
    public boolean isHome()
    {
        return isHome;
    }
    
    /**
     * Returns true if the parent uri of the uri passed to the constructor is
     * ../administartion/security/actions
     *
     * @return   a boolean
     *
     */
    public boolean isParentHome()
    {
        return isParentHome;
    }
    
    
    /**
     * objectExists returns true if the action referenced by uri passed to the constructor exists.
     *
     * @return   a boolean
     *
     */
    public boolean objectExists()
    {
        return actionExists;
    }
    
    /**
     * getId returns the the name of the action
     *
     * @return   a String
     *
     */
    public String getId()
    {
        return action;
    }

    /**
     * getObject returns the URMAction referenced by the uri passed to the constructor
     *
     * @return   an URMAction
     *
     */
    public URMAction getObject()
    {
        return urmAction;
    }
    
    /**
     * createObject creates the action referenced by the uri passed to the constructor
     *
     * @throws   ServiceAccessException
     *
     */
    public void createObject()
        throws ServiceAccessException
    {
        try {
            urmAction = urmAclAdm.createAction(action);
            actionExists = true;
        }
        catch (URMActionIdNotUniqueException e) {
            throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(), e));
        }
        
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }

    /**
     * deleteObject deletes the action referenced by the uri passed to the constructor
     *
     * @throws   ServiceAccessException
     *
     */
    public void deleteObject()
        throws ServiceAccessException
    {
        try {
            urmAclAdm.deleteAction(action);
            actionExists = false;
        }
        catch (URMActionInUseException e) {
            throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    /**
     * getActions returns the base actions of this action
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    public Set getActions()
        throws ServiceAccessException
    {
        return urmAction.getBaseActions();
    }
    
    /**
     * getAllActions returns all existing actions
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    private Set getAllActions()
        throws ServiceAccessException
    {
        try {
            return urmAclAdm.getAllActions();
        }
        catch (URMInternalServerException e) {
            throw new ServiceAccessException(parent,e);
        }
    }
    
    /**
     * enumerateActions puts all existing actions in to the vector
     *
     * @param    v                   a  Vector
     *
     * @throws   ServiceAccessException
     *
     */
    public void enumerateActions(Vector v)
        throws ServiceAccessException
    {
        enumerateActions(getAllActions(), v);
    }
    
    /**
     * updateMembers updates the action set of this action. It looks in the NodeRevisionDescriptor for
     * parameter referenced by URMUserDBStore.PRIVILEGE_MEMBER_SET. existing actions which are not
     * in this parameter are deleted.
     *
     * @param    nrd                 a  NodeRevisionDescriptor
     *
     * @throws   ServiceAccessException
     *
     */
    public void updateMembers(NodeRevisionDescriptor nrd)
        throws ServiceAccessException
    {
        try {
            HashSet newMembrs = getNewMembers(nrd,URMUserDBStore.PRIVILEGE_MEMBER_SET,XGlobals.TAMINO_NAMESPACE_URI);

            // build a delta using the existing and required member set
            // process actions
            HashSet liveSet = (HashSet)getActions();
            HashSet actionsSet = new HashSet(liveSet.size());
            actionsSet.addAll(liveSet);
            
            megreStrings(newMembrs, actionsSet, ActionDeclaration.SCOPE);
            
            // add new groups and users
            Iterator i = newMembrs.iterator();
            HashSet newActions = new HashSet();
            
            // check if they exist
            while ( i.hasNext() ) {
                String subjectUri = (String)i.next();
                if ( subjectUri.startsWith(ActionDeclaration.SCOPE)) {
                    URMActionsGate rg = new URMActionsGate(parent, subjectUri);
                    if ( rg.objectExists() )
                        newActions.add(rg.getId());
                    else
                        throw new ConflictException(subjectUri, new XForbiddenException( "An action must exist before it can be added to another action" ));
                }
                else
                    throw new ConflictException(subjectUri, new XForbiddenException( "The URL is invalid" ));
            }
            
            URMAction admin = urmAclAdm.getAction(action);
            // add actions
            i = newActions.iterator();
            while ( i.hasNext() ) {
                admin.addAction((String)i.next());
            }
            
            i = actionsSet.iterator();
            while ( i.hasNext() ) {
                String action = (String)i.next();
                admin.removeAction(action);
            }
        
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMDeleteException e) {
            throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(), e));
        }
        catch (URMInsertException e) {
            throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(), e));
        }
        catch (Exception e) {
            throw new ServiceAccessException(parent, e);
        }
        
    }
}





