/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/security/admin/URMRolesStore.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 com.softwareag.common.instrumentation.logging.Level;
import com.softwareag.common.instrumentation.logging.Logger;
import com.softwareag.common.instrumentation.logging.LoggerFactory;
import com.softwareag.common.instrumentation.logging.LoggerUtil;
import java.util.Vector;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.jdomobjects.XFactory;
import org.apache.slide.store.tamino.tools.stores.ActionDeclaration;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.ClassName;
import org.apache.slide.util.XMLValue;
import org.jdom.Element;


/**
 ** @author    josef.haiduk@softwareag.com
 ** @version   $Revision: 1.3 $
 **
 **/
public class URMRolesStore extends URMUserDBStore {
    
    private static final String LOGNAME = LoggerUtil.getThisClassName();
    private static final String CLASSNAME = new ClassName(LOGNAME).getPlainName();
    private static Logger logger = LoggerFactory.getLogger(LOGNAME);
    static String ROLE = "role";
    /**
     ** Default constructor.
     **/
    public URMRolesStore() {
        super();
    }
    
    public synchronized ObjectNode retrieveObject(Uri uri)
        throws ServiceAccessException, ObjectNotFoundException {
        
        logEnter("retrieveObject",uri);
        String uriStr = uri.toString();
        Vector children = new Vector(0);
        ObjectNode result = new SubjectNode(uriStr, children, new Vector(0));
        
        if ( getPrincipal() == null )
            return result;
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        
        if ( urmRolesGate.isHome() ) {
            urmRolesGate.enumerateObjects(children);
            return new SubjectNode(uriStr, children ,new Vector(0));
        }
        
        if ( urmRolesGate.objectExists() && urmRolesGate.isParentHome() ) {
            //urmRolesGate.enumerateMembers(children);
            return new SubjectNode(uriStr, children ,new Vector(0));
        }
        
        logExit("retrieveObject FAILED",uri);
        throw new ObjectNotFoundException(uriStr);
    }
    
    public synchronized void createObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectAlreadyExistsException {
        
        logEnter("createObject",uri);
        String uriStr = uri.toString();
        
        if ( getPrincipal() == null ) {
            return;
        }
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        if ( urmRolesGate.isParentHome() && urmRolesGate.objectExists())
            throw new ObjectAlreadyExistsException(uriStr);
        
        if ( urmRolesGate.isParentHome() && !urmRolesGate.objectExists()) {
            StoreInfo storeInfo = getStoredInfo();
            storeInfo.storeRoleBeingCreated(urmRolesGate);
            return;
        }
        
    }
    
    public synchronized void storeObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException {
        logEnter("storeObject",uri);
        String uriStr = uri.toString();
        
        // store
        if ( uriStr.equals(rolesPath) ) {
            StoreInfo storeInfo = getStoredInfo();
            Vector rolesGates = storeInfo.getRolesBeingCreated();
            storeInfo.clearRolesBeingCreated();
            for (int i=0; i<rolesGates.size();i++) {
                URMRolesGate urmGate = (URMRolesGate)rolesGates.elementAt(i);
                urmGate.createObject();
            }
            return;
        }
    }
    
    public synchronized void removeObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException {
        logEnter("removeObject",uri);
        String uriStr = uri.toString();
        
        if ( getPrincipal() == null ) {
            return;
        }
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        
        if (!urmRolesGate.objectExists() || !urmRolesGate.isParentHome()) {
            logExit("removeObject FAILED",uri);
            throw new ObjectNotFoundException(uriStr);
        }
        
        urmRolesGate.deleteObject();
        return;
        
    }
    
    
    // inherit docu from RevisionDescriptorStore interface
    public synchronized NodeRevisionDescriptor retrieveRevisionDescriptor
        (Uri uri, NodeRevisionNumber revisionNumber)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        
        logEnter("retrieveRevisionDescriptor",uri);
        String uriStr = uri.toString();
        NodeRevisionDescriptor result = XFactory.createNRD(uriStr, COLLECTION);
        
        if ( getPrincipal() == null )
            return result;
        
        if ( uriStr.equals(rolesPath) )  {
            insertDisplayname(result, roleCollection);
            return result;
        }
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        if ( urmRolesGate.objectExists() && urmRolesGate.isParentHome() ) {
            result = XFactory.createMemberNRD(uriStr);
            insertResourceType(result);
            String role = urmRolesGate.getId();
            insertPrincipalUrl(result, rolesPath + "/" + role);
            insertAlternateUriSet(result, ""); // TODO: put somesthing senseful here, e.g. an LDAP scheme URL (RFC2255)
            urmRolesGate.insertMappedProperties(result);
            insertSubjectProperties(result, urmRolesGate.getUnmappedProperties());
            insertGroupmemberSet(result, usersPath, urmRolesGate.getUsers());
            insertGroupmemberSet(result, groupsPath, urmRolesGate.getGroups());
            insertGroupmemberSet(result, rolesPath, urmRolesGate.getRoles());
            insertGroupmemberShip(result, rolesPath, urmRolesGate.getParents() );
            insertSubjectProperties(result, urmRolesGate.getProperties(),urmRolesGate.getAvailableProperties());
            insertActionmemberSet(result, ActionDeclaration.SCOPE, urmRolesGate.getActions());
            
            return result;
        }
        
        logExit("retrieveRevisionDescriptor FAILED",uri);
        throw new RevisionDescriptorNotFoundException(uriStr);
    }
    
    private void insertResourceType(NodeRevisionDescriptor nrd) {
        XMLValue xmlVal = new XMLValue();
        xmlVal.add( new Element("principal") );
        xmlVal.add( new Element(ROLE, XGlobals.TAMINO_NAMESPACE_PREFIX, XGlobals.TAMINO_NAMESPACE_URI) );
        NodeProperty resourcetypeProp = new NodeProperty(RESOURCETYPE, xmlVal, true);
        nrd.setProperty( resourcetypeProp );
    }
    
    public synchronized void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        
        logEnter("storeRevisionDescriptor",uri);
        String uriStr = uri.toString();
        
        if ( getPrincipal() == null )
            return;
        
        if ( uriStr.equals(rolesPath) )  {
            return;
        }
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        if ( !urmRolesGate.objectExists() ) {
            throw new RevisionDescriptorNotFoundException(uriStr);
        }
        else {
            urmRolesGate.updateParents(revisionDescriptor);
            urmRolesGate.updateActions(revisionDescriptor);
            urmRolesGate.updateMembers(revisionDescriptor);
            urmRolesGate.setProperties(revisionDescriptor);
        }
        
    }
    
    // inherit docu from securityStore interface
    public synchronized NodeRevisionContent retrieveRevisionContent(
        Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException, RevisionNotFoundException {
        
        logEnter("retrieveRevisionContent",uri);
        String uriStr = uri.toString();
        
        NodeRevisionContent result = new NodeRevisionContent();
        if ( uriStr.equals(rolesPath) )  {
            result.setContent(uriStr.toCharArray());
            return result;
        }
        
        if ( getPrincipal() == null ) {
            result.setContent(uriStr.toCharArray());
            return result;
        }
        
        URMRolesGate urmRolesGate = new URMRolesGate(this, uriStr);
        if ( urmRolesGate.isParentHome() && urmRolesGate.objectExists()) {
            result.setContent(urmRolesGate.getPropertiesAsBytes());
            return result;
        }
        
        logExit("retrieveRevisionContent FAILED",uri);
        throw new RevisionNotFoundException (uriStr,revisionDescriptor.getRevisionNumber());
    }
    
    private void logEnter(String method) {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, method);
    }
    
    private void logEnter(String method, Uri uri) {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, method, new Object[] {uri} );
    }
    
    private void logEnter(String method, Uri uri, String s1) {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, method,
                                                            new Object[] {uri, (s1!=null ? s1 : null)} );
        
    }
    private void logExit(String method, String text) {
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME, method ,text);
    }
    private void logExit(String method, Uri uri) {
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME, method ,uri.toString());
    }
}














