/*
 * $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PollMethod.java,v 1.12 2005/02/25 17:03:52 luetzkendorf Exp $
 * $Revision: 1.12 $
 * $Date: 2005/02/25 17:03:52 $
 *
 * ====================================================================
 *
 * Copyright 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.webdav.method;

import java.util.EventObject;
import java.util.Iterator;
import java.util.List;

import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.event.EventDispatcher;
import org.apache.slide.event.RemoteInformation;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.event.NotificationTrigger;
import org.apache.slide.webdav.event.Subscriber;
import org.apache.slide.webdav.event.WebdavEvent;
import org.apache.slide.webdav.util.NotificationConstants;
import org.apache.slide.webdav.util.WebdavStatus;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * Poll Method.
 *
 */
public class PollMethod extends AbstractWebdavMethod implements NotificationConstants {
    protected final static String LOG_CHANNEL = PollMethod.class.getName();
    protected final static Namespace NNSP = Namespace.getNamespace(N_PREFIX, N_URI);

    private XMLOutputter xmlOut;


    /**
     * Constructor.
     *
     * @param token     the token for accessing the namespace
     * @param config    configuration of the WebDAV servlet
     */
    public PollMethod(NamespaceAccessToken token, WebdavServletConfig config) {
        super(token, config);
        Format format = org.jdom.output.Format.getPrettyFormat();
        format.setIndent(XML_RESPONSE_INDENT);
        xmlOut = new XMLOutputter(format);
    }
    
    protected void parseRequest() throws WebdavException {
    }
    
    protected void executeRequest() throws WebdavException {
        try {
            if ( WebdavEvent.POLL.isEnabled() ) EventDispatcher.getInstance().fireVetoableEvent(WebdavEvent.POLL, new WebdavEvent(this));
            int []subscriptionID = requestHeaders.getSubscriptionId();
            // includes subscription id's that are not valid any more but requested in the poll-request
            resp.setContentType( TEXT_XML_UTF_8 );
            resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
            Element multistatus = new Element(E_MULTISTATUS, DNSP);
            boolean content = false;
            boolean noContent = false;
            Element contentResponse = new Element(E_RESPONSE, DNSP);
            int statusCode = WebdavStatus.SC_OK;
            generateStatusText(contentResponse, requestUri, statusCode);
            Element noContentResponse = new Element(E_RESPONSE, DNSP);
            statusCode = WebdavStatus.SC_NO_CONTENT;
            generateStatusText(noContentResponse, requestUri, statusCode);
            Element subscriptionIdContent = new Element(E_SUBSCRIPTION_ID, NNSP);
            Element subscriptionIdNoContent = new Element(E_SUBSCRIPTION_ID, NNSP);
            contentResponse.addContent(subscriptionIdContent);
            noContentResponse.addContent(subscriptionIdNoContent);
            for ( int i = 0; i < subscriptionID.length; i++ ) {
                // sort subscribers by the occurance of events
                Subscriber subscriber = NotificationTrigger.getInstance().getSubscriber(subscriptionID[i]);
                if ( subscriber != null ) {
                    NotificationTrigger.getInstance().refreshSubscriber(subscriber, true);
                    List events = subscriber.getEvents();
                    if ( events.size() == 0 ) {
                        noContent = true;
                        Element listener = new Element(E_LISTENER);
                        listener.addContent(String.valueOf(subscriber.getId()));
                        subscriptionIdNoContent.addContent(listener);
                    } else {
                        content = true;
                        Element listener = new Element(E_LISTENER);
                        listener.addContent(String.valueOf(subscriber.getId()));
                        subscriptionIdContent.addContent(listener);
                        for ( Iterator j = events.iterator(); j.hasNext(); ) {
                            EventObject event = (EventObject)j.next();
                            if ( event instanceof RemoteInformation ) {
                                Element eventElement = new Element(E_EVENT, NNSP);
                                String[][] information = ((RemoteInformation)event).getInformation();
                                for ( int k = 0; k < information.length; k++ ) {
                                    Element entry = new Element(E_INFORMATION, NNSP);
                                    entry.setAttribute(A_INFORMATION_KEY, information[k][0]);
                                    // FIXME: if the information value is a Slide URI, we
                                    // have to add the slideContext
                                    // FIXME: this should be generalized
                                    if ("uri".equals(information[k][0])) {
                                       entry.addContent(
                                             getSlideContextPath() + 
                                             String.valueOf(information[k][1]));
                                    } else {
                                       entry.addContent(String.valueOf(information[k][1]));
                                    }
                                    eventElement.addContent(entry);
                                }
                                subscriptionIdContent.addContent(eventElement);
                            }
                        }
                        subscriber.clearEvents();
                    }
                }
            }
            if ( content ) {
                multistatus.addContent(contentResponse);
            }
            if ( noContent ) {
                multistatus.addContent(noContentResponse);
            }
            xmlOut.output(new Document(multistatus), resp.getWriter());
        } catch (Exception e) {
            int statusCode = getErrorCode(e);
            sendError( statusCode, e );
            throw new WebdavException( statusCode );
        }
    }
}