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

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.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.ServiceInitializationFailedException;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeRevisionContent;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionAlreadyExistException;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.content.RevisionNotFoundException;
import org.apache.slide.macro.ForbiddenException;
import org.apache.slide.store.tamino.common.XForbiddenException;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.tools.stores.XDomainFileHandler;
import org.apache.slide.store.tamino.tools.stores.XStoreGroup;
import org.apache.slide.structure.ObjectAlreadyExistsException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.util.ClassName;
import org.apache.slide.util.XException;
import org.apache.slide.util.XUri;


/**
 ** Memory store. This non-persistent store serves as base for several store
 ** implementations of the administration scope.
 **
 ** @author    peter.nevermann@softwareag.com
 ** @version   0.1
 **
 **/
public class XDefaultStore extends XMemoryStore implements XGlobals {
    
    private static final String LOGNAME = LoggerUtil.getThisClassName();
    private static final String CLASSNAME = new ClassName(LOGNAME).getPlainName();
    private static Logger logger = LoggerFactory.getLogger(LOGNAME);
    

    private final Set validURIs;
    
    /**
     ** Default constructor.
     **/
    public XDefaultStore() {
        if( logger.isLoggable(Level.FINE) )
            logger.entering( CLASSNAME, "<init>" );
        
        if( logger.isLoggable(Level.FINE) )
            logger.exiting( CLASSNAME, "<init>" );
        
        validURIs = new HashSet();
    }
    

    public synchronized void initialize( NamespaceAccessToken token )
        throws ServiceInitializationFailedException
    {
        super.initialize(token);
        
        Iterator iter;
        XStoreGroup group;
        
        validURIs.add(XUri.SEP);
        validURIs.add(XUri.SEP + "administration");
        validURIs.add(XUri.SEP + "tempaction");
        try {
            iter = XDomainFileHandler.get().getNamespace(token.getName()).getPublicStoreGroups().iterator();
        } catch (XException e) {
            throw new ServiceInitializationFailedException(this, e);
        }
        while (iter.hasNext()) {
            group = (XStoreGroup) iter.next();
            group.addPrefixes(validURIs);
        }
    }

    // ------------------------------------------------------------------------
    // ContentStore interface
    // ------------------------------------------------------------------------
    
    /**
     * Create a new revision
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @param revisionContent Node revision content
     * @exception ServiceAccessException service access error
     * @exception RevisionAlreadyExistException revision already exists
     */
    public void createRevisionContent( Uri uri, NodeRevisionDescriptor revisionDescriptor,
                                      NodeRevisionContent revisionContent )
        throws ServiceAccessException, RevisionAlreadyExistException {
        if( logger.isLoggable(Level.FINE) )
            logger.entering( CLASSNAME, "createRevisionContent", new Object[] {uri,
                            (revisionDescriptor!=null
                                 ? revisionDescriptor.getRevisionNumber()+"@"+revisionDescriptor.getBranchName()
                                 : null), revisionContent} );
        
        String uriStr = uri.toString();
        
        if( logger.isLoggable(Level.FINE) )
            logger.exiting( CLASSNAME, "createRevisionContent" );
        
        throw new ServiceAccessException( this,
                                         new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    /**
     * Modify the latest revision of an object.
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @param revisionContent Node revision content
     * @exception ServiceAccessException service access error
     * @exception RevisionNotFoundException revision was not found
     */
    public void storeRevisionContent( Uri uri, NodeRevisionDescriptor revisionDescriptor,
                                     NodeRevisionContent revisionContent)
        throws ServiceAccessException, RevisionNotFoundException {
        if( logger.isLoggable(Level.FINE) )
            logger.entering( CLASSNAME, "storeRevisionContent", new Object[] {uri,
                            (revisionDescriptor!=null
                                 ? revisionDescriptor.getRevisionNumber()+"@"+revisionDescriptor.getBranchName()
                                 : null), revisionContent} );
        
        String uriStr = uri.toString();
        
        if (logger.isLoggable(Level.FINE))
            logger.exiting( CLASSNAME, "storeRevisionContent" );
        
        throw new ServiceAccessException( this,
                                         new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    /**
     * Remove revision.
     *
     * @param uri Uri
     * @param revisionDescriptor revision descriptor
     * @exception ServiceAccessException service access error
     */
    public void removeRevisionContent( Uri uri, NodeRevisionDescriptor revisionDescriptor )
        throws ServiceAccessException {
        if( logger.isLoggable(Level.FINE) )
            logger.entering( CLASSNAME, "removeRevisionContent", new Object[] {uri,
                            (revisionDescriptor!=null
                                 ? revisionDescriptor.getRevisionNumber()+"@"+revisionDescriptor.getBranchName()
                                 : null)} );
        
        String uriStr = uri.toString();
        
        if( logger.isLoggable(Level.FINE) )
            logger.exiting( CLASSNAME, "removeRevisionContent" );
        
        throw new ServiceAccessException( this,
                                         new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    // ------------------------------------------------------------------------
    // NodeStore interface
    // ------------------------------------------------------------------------
    
    /**
     * Store an object in the Descriptors Store.
     *
     * @param uri Uri of the object we want to update
     * @param object Object to update
     * @exception ServiceAccessException Error accessing the Descriptors Store
     * @exception ObjectNotFoundException The object to update was not found
     */
    public void storeObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, "storeObject",
                                                            new Object[] {uri, (object!=null ? object.getUri() : null)} );
        
        validate(uri);
        super.storeObject( uri, object );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME, "storeObject" );
    }
    
    /**
     * Create a new object in the Descriptors Store.
     *
     * @param uri Uri of the object we want to create
     * @param object SlideObject
     * @exception ServiceAccessException Error accessing the Descriptors Store
     * @exception ObjectAlreadyExistsException An object already exists
     * at this Uri
     */
    public void createObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectAlreadyExistsException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, "createObject",
                                                            new Object[] {uri, (object!=null ? object.getUri() : null)} );
        
        validate(uri);
        super.createObject( uri, object );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME, "createObject" );
    }
    
    /**
     * Remove an object from the Descriptors Store.
     *
     * @param uri Uri of the object we want to remove
     * @param object Object to remove **IGNORED**
     * @exception ServiceAccessException Error accessing the Descriptors Store
     * @exception ObjectNotFoundException The object to remove was not found
     */
    public void removeObject(Uri uri, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME, "removeObject",
                                                            new Object[] {uri, (object!=null ? object.getUri() : null)} );
        
        String uriStr = uri.toString();
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME, "removeObject" );
        
        if( !TEMPACTION_URI.equals(uriStr) )
            throw new ServiceAccessException( this,
                                             new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    // ------------------------------------------------------------------------
    // RevisionDescriptorsStore interface
    // ------------------------------------------------------------------------
    
    /**
     * Create new revision descriptors.
     *
     * @param uri Uri
     * @param revisionDescriptors Node revision descriptors
     * @exception ServiceAccessException Service access error
     */
    public void createRevisionDescriptors
        (Uri uri, NodeRevisionDescriptors revisionDescriptors)
        throws ServiceAccessException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "createRevisionDescriptors", new Object[] {uri,
                            (revisionDescriptors!=null ? revisionDescriptors.getUri() : null)} );
        
        validate(uri);
        super.createRevisionDescriptors( uri, revisionDescriptors );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "createRevisionDescriptors" );
    }
    
    /**
     * Update revision descriptors.
     *
     * @param uri Uri
     * @param revisionDescriptors Node revision descriptors
     * @exception ServiceAccessException Service access error
     * @exception RevisionDescriptorNotFoundException Revision descriptor
     * was not found
     */
    public void storeRevisionDescriptors
        (Uri uri, NodeRevisionDescriptors revisionDescriptors)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "storeRevisionDescriptors", new Object[] {uri,
                            (revisionDescriptors!=null ? revisionDescriptors.getUri() : null)} );
        
        validate(uri);
        
        super.storeRevisionDescriptors( uri, revisionDescriptors );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "storeRevisionDescriptors" );
    }
    
    /**
     * Remove revision descriptors.
     *
     * @param uri Uri
     * @exception ServiceAccessException Service access error
     */
    public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "removeRevisionDescriptors", new Object[] {uri} );
        
        String uriStr = uri.toString();
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "removeRevisionDescriptors" );
        
        throw new ServiceAccessException( this,
                                         new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    // ------------------------------------------------------------------------
    // RevisionDescriptorStore interface
    // ------------------------------------------------------------------------
    
    /**
     * Create new revision descriptor.
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @exception ServiceAccessException Service access error
     */
    public void createRevisionDescriptor
        (Uri uri, NodeRevisionDescriptor revisionDescriptor) throws ServiceAccessException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "createRevisionDescriptor", new Object[] {uri, (revisionDescriptor!=null
                                                                                                                ? revisionDescriptor.getRevisionNumber()+"@"+revisionDescriptor.getBranchName()
                                                                                                                : null)} );
        
        validate(uri);
        super.createRevisionDescriptor( uri, revisionDescriptor );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "createRevisionDescriptor" );
    }
    
    /**
     * Update revision descriptor.
     *
     * @param uri Uri
     * @param revisionDescriptor Node revision descriptor
     * @exception ServiceAccessException Service access error
     * @exception RevisionDescriptorNotFoundException Revision descriptor
     * was not found
     */
    public void storeRevisionDescriptor
        (Uri uri, NodeRevisionDescriptor revisionDescriptor)
        throws ServiceAccessException, RevisionDescriptorNotFoundException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "storeRevisionDescriptor", new Object[] {uri, (revisionDescriptor!=null
                                                                                                               ? revisionDescriptor.getRevisionNumber()+"@"+revisionDescriptor.getBranchName()
                                                                                                               : null)} );
        
        super.storeRevisionDescriptor( uri, revisionDescriptor );
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "storeRevisionDescriptor" );
    }
    
    /**
     * Remove revision descriptor.
     *
     * @param uri Uri
     * @param number Revision number
     * @exception ServiceAccessException Service access error
     */
    public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber number)
        throws ServiceAccessException {
        if( logger.isLoggable(Level.FINE) ) logger.entering( CLASSNAME,
                                                            "removeRevisionDescriptor", new Object[] {uri, number} );
        
        String uriStr = uri.toString();
        
        if( logger.isLoggable(Level.FINE) ) logger.exiting( CLASSNAME,
                                                           "removeRevisionDescriptor" );
        
        throw new ServiceAccessException( this,
                                         new ForbiddenException(uriStr, new XForbiddenException( "Invalid uri: "+uriStr )) );
    }
    
    private void validate(Uri uri) throws ServiceAccessException {
        String str;
        String rel;
            
        rel = uri.getRelative();
        if( rel == null ) {
            rel = XUri.SEP;
        } else if (!rel.startsWith(XUri.SEP)) {
            rel = XUri.SEP + rel;
        }
        if( !validURIs.contains(rel)) {
            str = uri.toString();
            throw new ServiceAccessException( this,
                                             new ForbiddenException(str, new XForbiddenException( "Invalid uri: "+str )) );
        }
    }
}

