/*
 * $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/util/ComputedPropertyProvider.java,v 1.13 2005/01/10 18:13:25 luetzkendorf Exp $
 * $Revision: 1.13 $
 * $Date: 2005/01/10 18:13:25 $
 *
 * ====================================================================
 *
 * Copyright 1999 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 list
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.PropertyName;
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.search.PropertyProvider;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;
import org.jdom.JDOMException;

/**
 *
 *
 * @version $Revision: 1.13 $
 *
 **/
public class ComputedPropertyProvider implements PropertyProvider {
    
    /**
     * The context path of the request, the prefix of all slide uri in the
     * WebDAV view.
     */
   protected String slideContextPath = null;
    
    /**
     * The Content helper to use.
     */
    protected Content contentHelper = null;
    
    /**
     * The NamespaceAccessToken to use.
     */
    protected NamespaceAccessToken nsaToken= null;
    
    /**
     * The SlideToken to use.
     */
    protected SlideToken slideToken= null;
    
    /**
     * The PropertyHelper to use to access the computed properties.
     */
    protected PropertyHelper propertyHelper = null;
    
    /**
     * The NodeRevisionDescriptors of the current resource.
     */
    protected NodeRevisionDescriptors revisionDescriptors = null;
    
    /**
     * The NodeRevisionDescriptor of the current resource.
     */
    protected NodeRevisionDescriptor revisionDescriptor = null;
    
    /**
     * The URI of the last accessed resource.
     */
    protected String lastResourceUri = null;
    
    
    /**
     * Creates a ComputedPropertyProvider.
     *
     * @param      nsaToken        the NamespaceAccessToken to use.
     * @param      slideToken      the SlideToken to use.
     * @param      slideContextPath the context + servlet path of the request.
     */
    public ComputedPropertyProvider(NamespaceAccessToken nsaToken, SlideToken slideToken, String slideContextPath, WebdavServletConfig sConf) {
       this(nsaToken, slideToken, 
             PropertyHelper.getPropertyHelper(slideToken, nsaToken, sConf), 
             slideContextPath);
    }
    /** 
     * @deprecated use {@link #ComputedPropertyProvider(NamespaceAccessToken, SlideToken, String, WebdavServletConfig)}  
     */
    public ComputedPropertyProvider(NamespaceAccessToken nsaToken, SlideToken slideToken, String contextPath, String servletPath, WebdavServletConfig sConf) {
        this(nsaToken, slideToken, PropertyHelper.getPropertyHelper(slideToken, nsaToken, sConf), contextPath, servletPath);
    }

    /** 
     * @deprecated 
     */
    public ComputedPropertyProvider(NamespaceAccessToken nsaToken, SlideToken slideToken, String contextPath, String servletPath) {
        this(nsaToken, slideToken, PropertyHelper.getPropertyHelper(slideToken, nsaToken, (WebdavServletConfig)null), contextPath, servletPath);
    }
    
    /**
     * Creates a ComputedPropertyProvider.
     *
     * @param      nsaToken         the NamespaceAccessToken to use.
     * @param      slideToken       the SlideToken to use.
     * @param      propertyHelper   the PropertyHelper to use to access the computed properties.
     * @param      slideContextPath the context + servlet path of the request.
     */
    public ComputedPropertyProvider(NamespaceAccessToken nsaToken, 
          SlideToken slideToken, PropertyHelper propertyHelper, 
          String slideContextPath) 
    {
       this.nsaToken = nsaToken;
       this.slideToken = slideToken;
       this.propertyHelper = propertyHelper;
       this.slideContextPath = slideContextPath;
       
       contentHelper = nsaToken.getContentHelper();
    }
    
    /**
     * @deprecated use {@link #ComputedPropertyProvider(NamespaceAccessToken, SlideToken, PropertyHelper, String)}
     */
    public ComputedPropertyProvider(NamespaceAccessToken nsaToken, SlideToken slideToken, PropertyHelper propertyHelper, String contextPath, String servletPath) {
        
        this.nsaToken = nsaToken;
        this.slideToken = slideToken;
        this.propertyHelper = propertyHelper;
        //this.contextPath = contextPath;
        //this.servletPath = servletPath;
        this.slideContextPath = contextPath + servletPath;
        
        contentHelper = nsaToken.getContentHelper();
    }
    
    /**
     * Returns <code>true</code> if this PropertyProvider can provide the NodeProperty
     * specified by <code>propertyNamespace</code> and <code>propertyName</code>
     * for the resource with the given <code>resourceUri</code>.
     *
     * @param      resourceUri        the URI of the resource.
     * @param      propertyName       the name of the property.
     * @param      propertyNamespace  the namespace of the property.
     *
     * @return     <code>true</code> if this PropertyProvider can provide the NodeProperty.
     *
     * @throws     SlideException
     */
    public boolean isSupportedProperty(String resourceUri, String propertyName, 
            String propertyNamespace) throws SlideException {
        
        updateDescriptors(resourceUri);
        
        return getComputedPropertiesNames().contains(
                PropertyName.getPropertyName(propertyName, propertyNamespace));
    }
    
    public boolean isSupportedProperty(String resourceUri, PropertyName propertyName) 
        throws SlideException {
        
        updateDescriptors(resourceUri);
        
        return getComputedPropertiesNames().contains(propertyName);
    }
    
    /**
     * Returns the names of the computed properties.
     *
     * @return  the {@link PropertyName}s of the computed properties.
     */
    protected Set getComputedPropertiesNames() {
        
        ResourceKind resourceKind =
            AbstractResourceKind.determineResourceKind(nsaToken,
                                                       revisionDescriptors,
                                                       revisionDescriptor);
        Set computedLivePropertyNames =
            resourceKind.getSupportedLivePropertyNames(DeltavConstants.Q_COMPUTED_ONLY);
        return computedLivePropertyNames;
    }
    
    /**
     * Returns an Iterator of PropertyName of all properties supported by this
     * PropertyProvider.
     *
     * @param      resourceUri        the URI of the resource for which to return
     *                                the suppored PropertyNames.
     *
     * @return     an Iterator of PropertyName.
     *
     * @throws     SlideException
     */
    public Iterator getSupportedPropertiesNames(String resourceUri) throws SlideException {
        
        updateDescriptors(resourceUri);
        
//        Set computedLivePropertyNames = getComputedPropertiesNames();
//        List propertiesNamesList = new ArrayList(computedLivePropertyNames.size());
//        propertiesNamesList.addAll(computedLivePropertyNames);
        
        return getComputedPropertiesNames().iterator();
    }
    
    
    /**
     * If the property specified by <code>propertyNamespace</code> and
     * <code>propertyName</code> is {@link #isSupportedProperty supported
     * by this PropertyProvider}, the NodeProperty of the resource located
     * at the given <code>resourceUri</code> will be returned. Otherwise
     * <code>null</code> is returned.
     *
     * @param      resourceUri        the URI of the resource for which to return
     *                                the NodeProperty.
     * @param      propertyName       the name of the property to return.
     * @param      propertyNamespace  the namespace of the property to return.
     *
     * @return     the requested NodeProperty if it is supported, otherwise
     *             <code>null</code>.
     *
     * @throws     SlideException
     */
    public NodeProperty getProperty(String resourceUri, String propertyName, String propertyNamespace) throws SlideException {
        
        updateDescriptors(resourceUri);
        try {
            return propertyHelper.getProperty(
                    PropertyName.getPropertyName(propertyName, propertyNamespace), 
                    revisionDescriptors, revisionDescriptor, slideContextPath);
        }
        catch (JDOMException e) {
            throw new SlideException("ComputedPropertyProvider.getProperty(): " + e.getMessage());
        }
    }
    
    public NodeProperty getProperty(String resourceUri, PropertyName propertyName) 
        throws SlideException 
    {
        updateDescriptors(resourceUri);
        
        try {
            return propertyHelper.getProperty(propertyName, revisionDescriptors, 
                    revisionDescriptor, slideContextPath);
        }
        catch (JDOMException e) {
            throw new SlideException("ComputedPropertyProvider.getProperty(): " + e.getMessage());
        }
    }
    
    /**
     * Returns an Iterator of all NodeProperties supported by this PropertyProvider.
     *
     * @param      resourceUri        the URI of the resource for which to return
     *                                the supported properties.
     *
     * @return     all NodeProperties supported by this provider.
     *
     * @throws     SlideException
     */
    public Iterator getSupportedProperties(String resourceUri) throws SlideException {
        
        updateDescriptors(resourceUri);
        
        Set propertyNames = getComputedPropertiesNames();
        List supportedProperties = new ArrayList(propertyNames.size());
        Iterator iterator = propertyNames.iterator();
        while (iterator.hasNext()) {
            supportedProperties.add(
                    getProperty(resourceUri, (PropertyName)iterator.next()));
        }
        return supportedProperties.iterator();
    }
    
    /**
     * Updates the {@link #revisionDescriptors revisionDescriptors} and
     * {@link #revisionDescriptor revisionDescriptor} if the given
     * <code>resourceUri</code> is different from the {@link #lastResourceUri
     * last accessed resource URI}.
     *
     * @param      resourceUri  the URI of the resource to access next.
     *
     * @throws     SlideException
     */
    protected void updateDescriptors(String resourceUri) throws SlideException {
        
        if ( (lastResourceUri == null) || ( ! lastResourceUri.equals(resourceUri) ) ) {
            revisionDescriptors = contentHelper.retrieve(slideToken, resourceUri);
            revisionDescriptor = contentHelper.retrieve(slideToken, revisionDescriptors);
            lastResourceUri = resourceUri;
        }
    }
}

