/*
 * $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/util/UnlockListenerImpl.java,v 1.6 2005/02/25 17:07:59 luetzkendorf Exp $
 * $Revision: 1.6 $
 * $Date: 2005/02/25 17:07:59 $
 *
 * ====================================================================
 *
 * 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.webdav.util;

import java.util.Enumeration;
import java.util.HashSet;

import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.SlideException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.content.Content;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionDescriptors;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.lock.UnlockListener;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
import org.apache.slide.util.Configuration;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.CheckedOutVersionControlled;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;

/**
 * Implements UnlockListener
 */
public class UnlockListenerImpl implements UnlockListener {
    private SlideToken slideToken;
    private NamespaceAccessToken token;
    private VersioningHelper versioningHelper;
    // counts the locks this listner is called for
    private int unlockCount = 0;
    // set ot uris that are Lock-Null resources anre removed by this listener
    private HashSet removedLockNullResources = new HashSet();
    
    /**
     * Constructor
     */
    public UnlockListenerImpl( SlideToken slideToken, NamespaceAccessToken token,
            VersioningHelper versioningHelper) {
        this.slideToken = slideToken;
        this.token = token;
        this.versioningHelper = versioningHelper;
    }
    
    /**
     * This method is called before unlocking the resource.
     *
     * @param      uri the uri of the resource that will be unlocked.
     * @throws     SlideException
     */
    public void beforeUnlock(String uri) throws SlideException {
    }
    
    /**
     * This method is called after unlocking the resource.
     *
     * @param      uri the uri of the resource that has been unlocked.
     * @throws     SlideException
     */
    public void afterUnlock(String uri) throws SlideException {
        unlockCount++;
        
        // Check whether the resource must be checked-in due to auto-versioning semantics.
        Content content = token.getContentHelper();
        Structure structure = token.getStructureHelper();
        NodeRevisionDescriptors revisionDescriptors =
            content.retrieve(slideToken, uri);
        NodeRevisionDescriptor revisionDescriptor =
            content.retrieve(slideToken, revisionDescriptors);
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(token, uri, revisionDescriptor);
        if( Configuration.useVersionControl() &&
               (resourceKind instanceof CheckedOutVersionControlled) ) {
            NodeProperty checkinLocktokenProperty =
                revisionDescriptor.getProperty(DeltavConstants.PN_CHECKIN_LOCKTOKEN);
            if (checkinLocktokenProperty == null) {
                // retry with default (DAV:) namespace which was the
                // former namespace of this property
                checkinLocktokenProperty =
                    revisionDescriptor.getProperty(DeltavConstants.PN_CHECKIN_LOCKTOKEN_COMP);
            }
            if ( (checkinLocktokenProperty != null) && (checkinLocktokenProperty.getValue() != null)
                // && slideToken.checkLockToken(checkinLocktokenProperty.getValue().toString())
               ) {
                try {
                    versioningHelper.checkin(revisionDescriptors, revisionDescriptor, false, false, true);
                }
                catch (java.io.IOException e) {}
                catch (org.jdom.JDOMException e) {}
            }
        }
        
        // if the URI has no more locks associated to it and is
        // a lock-null resource, we must attempt to delete it
        try {
            Enumeration locks = token.getLockHelper().enumerateLocks(slideToken, uri);
            if (!locks.hasMoreElements() && isLockNull(revisionDescriptor)) {
                this.removedLockNullResources.add(uri);
                content.remove(slideToken, uri, revisionDescriptor);
                content.remove(slideToken, revisionDescriptors);
                structure.remove(slideToken, structure.retrieve(slideToken, uri));
            }
        } catch (ObjectNotFoundException onfe) {
        } catch (RevisionDescriptorNotFoundException e) {
           // this happens e.g. if some one tries to create a resource
           // in the history that looks like a version 
           // e.g. PUT /history/221/7.1 (cf VcPutVHR)
        }
    }
    
    /**
     * Returns the number on unlocks processed be this listener.
     */ 
    public int getUnlockCount() {
        return this.unlockCount;
    }
    public boolean isRemovedLockResource(String uri) {
        return this.removedLockNullResources.contains(uri);
    }
    
    private boolean isLockNull( NodeRevisionDescriptor nrd ) {
        return nrd.propertyValueContains(WebdavConstants.P_RESOURCETYPE, 
                WebdavConstants.E_LOCKNULL);
    }
}

