/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/urm/org/apache/slide/urm/authenticator/userdb/impl/URMUserAdminImpl.java,v 1.4 2005/03/02 10:53:34 eckehard Exp $
 * $Revision: 1.4 $
 * $Date: 2005/03/02 10:53:34 $
 *
 * ====================================================================
 *
 * 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.urm.authenticator.userdb.impl;

import java.util.Iterator;
import java.util.Set;
import java.util.Properties;
import java.util.HashSet;

import org.apache.slide.urm.authenticator.URMSubject;
import org.apache.slide.urm.authenticator.rolemanager.URMRoleManagerSpi;
import org.apache.slide.urm.authenticator.rolemanager.impl.URMRoleAdminImpl;
import org.apache.slide.urm.authenticator.userdb.URMMetadataPropsSpi;
import org.apache.slide.urm.authenticator.userdb.URMUserDBManagerSpi;
import org.apache.slide.urm.URMNotImplementedException;
import org.apache.slide.urm.URMForbiddenException;
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.URMUpdateException;
import org.apache.slide.urm.utils.messagelogger.MessageLogger;
import org.apache.slide.urm.utils.validatorcache.URMListener;

/**
 * Represents an userdb user.
 *
 * @author eckehard.hermann@softwareag.com
 * @author dieter.kessler@softwareag.com
 * @author zsolt.sasvarie@softwareag.com
 */
public class URMUserAdminImpl extends URMUserImpl  {
    
    private static org.apache.log4j.Logger msLogger =
        org.apache.log4j.Logger.getLogger(URMUserAdminImpl.class.getName());
    
    // get event listeners
    private URMListener aclListenerSet = URMListener.getAclListenerSet();
        
    
    /*
     * Constructor: create new URMUser instance
     *
     * @param user name
     * @param domain name
     * @param URMUserDBManagerSpi
     */
    public URMUserAdminImpl(String username, String domain,
                        URMUserDBManagerSpi userDbManagerSpi,
                        URMMetadataPropsSpi metadataPropsSpi,
                        URMRoleManagerSpi roleManagerSpi) {
        super(username, domain, userDbManagerSpi, metadataPropsSpi, roleManagerSpi);
    }
    
    public static Set getURMUserObjectSetFromStringSet(Set usernames, String domain,
                                                    URMUserDBManagerSpi userDbManagerSpi,
                                                    URMMetadataPropsSpi metadataPropsSpi,
                                                    URMRoleManagerSpi roleManagerSpi) {
        if (usernames == null)
            return null;
        Iterator iter = usernames.iterator();
        HashSet retusrs = new HashSet();
        while (iter.hasNext())
            retusrs.add(new URMUserAdminImpl((String)iter.next(), domain,
                                        userDbManagerSpi, metadataPropsSpi, roleManagerSpi));
        return retusrs;
    }
    
    public static Set getURMUserObjectSetFromSubjectSet(Set subjects,
                                                    URMUserDBManagerSpi userDbManagerSpi,
                                                    URMMetadataPropsSpi metadataPropsSpi,
                                                    URMRoleManagerSpi roleManagerSpi) {
        if (subjects == null)
            return null;
        Iterator iter = subjects.iterator();
        HashSet retusrs = new HashSet();
        while (iter.hasNext()) {
            URMSubject subj = (URMSubject)iter.next();
            retusrs.add(new URMUserAdminImpl(subj.getName(), subj.getDomain(),
                                        userDbManagerSpi, metadataPropsSpi, roleManagerSpi));
        }
        return retusrs;
    }
    
    public Set getGroups()
            throws URMNotImplementedException, URMForbiddenException,
                URMInternalServerException{
        return URMGroupAdminImpl.getURMGroupObjectSetFromStringSet(
                mUserDBManagerSpi.getGroupsOfUser(mUserName, mDomain),
                mDomain, mUserDBManagerSpi, mMetadataPropsSpi, mRoleManagerSpi);
    }
    
    public Set getRoleMapping()
            throws URMNotImplementedException, URMForbiddenException,
                URMInternalServerException {
        return URMRoleAdminImpl.getURMRoleObjectSetFromSubjectSet(
                mRoleManagerSpi.getRoleMappingOfUser(mUserName, mDomain), mRoleManagerSpi,
                                    mUserDBManagerSpi, mMetadataPropsSpi);
    }

    /**
     * Retrieves user specific properties
     *
     * @param inProps properties to set them
     *
     * @exception URMNotImplementedException if the method is not
     *            implemented by the user database.
     * @exception URMForbiddenException if the user has not the permission
     *            to invoke the method.
     * @exception URMException if an unpredictable internal error occurs
     */
    public void setProperties(Properties inProps)
            throws URMNotImplementedException, URMForbiddenException, URMUpdateException, URMDeleteException, URMInternalServerException {
        if (inProps == null)
            return;
        if (mMetadataPropsSpi != null) {
            Properties udbprops  = new Properties();
            Properties metaprops = new Properties();
            Set availablemetaprops = mMetadataPropsSpi.getAvailableUserPropKeys();
            Set writeablemetaprops = mMetadataPropsSpi.getWriteableUserPropKeys();
            Set availableuserdbprops = mUserDBManagerSpi.getAvailablePropKeys(true);
            Set writeableuserdbprops = mUserDBManagerSpi.getWriteablePropKeys(true);
            for (Iterator keys = inProps.keySet().iterator(); keys.hasNext();) {
                String key = (String)keys.next();
                if (availablemetaprops.contains(key)) {
                    if (writeablemetaprops.contains(key))
                        metaprops.setProperty(key, (String)inProps.getProperty(key));
                    else
                        throw new URMUpdateException(MessageLogger.getAndLogMessage(msLogger, "URMMPE0001", key));
                }
                else
                if (availableuserdbprops.contains(key)) {
                    if (writeableuserdbprops.contains(key))
                        udbprops.setProperty(key, (String)inProps.getProperty(key));
                    else
                        throw new URMUpdateException(MessageLogger.getAndLogMessage(msLogger, "URMSUE0006", key));
                }
            }
            if (udbprops.size() > 0)
                mUserDBManagerSpi.setUserProperties(mUserName, mDomain, udbprops);
            if (metaprops.size() > 0)
                mMetadataPropsSpi.setProperties(mUserName, mDomain, metaprops, true);
        }
        else
            mUserDBManagerSpi.setUserProperties(mUserName, mDomain, inProps);
    }
    
    /**
     * Changes the password of a user in the user database
     *
     * @param oldpassword the user's current password
     *
     * @param newpassword the desired password of the userd
     *
     * @exception URMNotImplementedException if the method is not
     *            implemented by the user database.
     * @exception URMForbiddenException if the user has not the permission
     *            to invoke the method.
     * @exception URMException if an unpredictable internal error occurs
     */
    public void setPassword(char[] oldpassword, char[] newpassword)
            throws URMNotImplementedException, URMForbiddenException, URMUpdateException {
        mUserDBManagerSpi.changeUserPassword(mUserName, mDomain,
                                             oldpassword, newpassword);
    }

    /** Mapps this subject to a role, so that the subject can take this role
     *
     * @param role name of the role.
     *
     * @exception URMNotImplementedException if the method is not
     *            implemented by the user database.
     * @exception URMForbiddenException if the user has not the permission
     *            to invoke the method.
     * @exception URMException if an unpredictable internal error occurs
     */
    public void linkToRole(String role)
            throws URMNotImplementedException, URMForbiddenException, URMInsertException, URMInternalServerException {
        if (!mRoleManagerSpi.isRole(role))
            throw new URMInternalServerException(MessageLogger.getAndLogMessage(msLogger, "URMCOE0055", role));

        mRoleManagerSpi.addUserLink(role, mDomain, mUserName);
        aclListenerSet.resetEvent();
    }

    /** Delets a role link to the subject. The subject is no longer able to take this role
     *
     * @param role name the ancestor that should be removed from the role
     *
     * @exception URMNotImplementedException if the method is not
     *            implemented by the user database.
     * @exception URMForbiddenException if the user has not the permission
     *            to invoke the method.
     * @exception URMException if an unpredictable internal error occurs
     */
    public void deleteRoleLink(String role)
            throws URMNotImplementedException, URMForbiddenException, URMDeleteException, URMInternalServerException {
        mRoleManagerSpi.deleteUserLink(role, mUserName, mDomain);
        aclListenerSet.resetEvent();
    }


    /**
     * Sets new subject specific properties
     *
     * @param key property key
     * @param prop property value
     *
     * @exception URMNotImplementedException if the method is not
     *            implemented by the user database.
     * @exception URMForbiddenException if the user has not the permission
     *            to invoke the method.
     * @exception URMException if an unpredictable internal error occurs
     */
    public void setProperty(String key, Object prop) throws URMNotImplementedException, URMForbiddenException, URMUpdateException, URMDeleteException, URMInternalServerException{
        //Properties props = mUserDBManagerSpi.getUserProperties(mUserName, mDomain);
        Properties props = new Properties();
        props.setProperty(key, (String) prop);
        setProperties(props);
                
    }

}
