/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.bebop;
import com.arsdigita.util.*;
import com.arsdigita.xml.Document;
import java.util.StringTokenizer;
import javax.servlet.ServletException;

/**
 *  This utility class takes a Bebop Component and generates the XML for
 *  that component type. If the type is a general component, it will
 *  be inserted into a Page object for XML generation.
 *return p
 *  If the Component is of type Page, it will not be further nested.
 *
 * @version $Revision: #9 $ $Date: 2004/04/07 $
 */
public class ComponentToXML {

    public static final String versionId = "$Id: //core-platform/dev/test/src/com/arsdigita/bebop/ComponentToXML.java#9 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";

    /**
     *  This method places the given component into a page, generates XML, and returns
     *  a <code>String</code> representation of the XML
     *
     *  @return The XML document as a String
     */
    static public String getXMLString( Component c ) throws ServletException
    {
        return docToString( getDocument(c) );
    }

    /**
     *  This method generates XML for the page, and returns
     *  a <code>String</code> representation of the XML
     *
     *  @return The XML document as a String
     *
     *  @pre p.isLocked()
     */
    static public String getXMLString( Page p ) throws ServletException
    {
        return docToString( getDocument(p) );
    }

    /**
     *  This method places the given Component into a Page, *
     *  generates XML, and returns the <code>Document</code> *
     *  representation of the XML. If this method is called for a *
     *  Component reference ot a Page type, it will not be inserted *
     *  into a Page.  Assumes debugging.
     *
     *  @return The XML document */
    static public Document getDocument(Component c)
        throws ServletException {
        return getDocument(c, true);
    }

    /**
     * Generate XML from a Component.  Like
     * {@link#getDocument(Component)}, but it allows specifying wheter
     * debug mode is enabled */
    static public Document getDocument(Component c, boolean isDebug)
        throws ServletException {

        // Just in case...
        if( c instanceof Page ) {
            return getDocument((Page)c, isDebug);
        }

        Page page = new Page();
        page.add( c );
        page.lock();

        return getDocument(page, isDebug);
    }

    /**
     *  This method generates XML for the page, and returns
     *  the <code>Document</code> representation of the XML
     *
     *  @return The XML document
     *
     *  @pre p.isLocked()
     */
    static public Document getDocument(Page p, boolean isDebug)
        throws ServletException {
        Assert.assertTrue( p.isLocked() );
        HttpServletDummyRequest request = new HttpServletDummyRequest(isDebug);
        HttpServletDummyResponse response = new HttpServletDummyResponse();

        return p.buildDocument( request, response );
    }

    /**
     *  Function converts the Document object into a String.
     *
     *  As a quick & dirty aid to human reading, it tokenizes the
     *  document based on the > end of XML tags, inserting a
     *  newline after each. This will make any errors discovered
     *  in regression testing easier to diagnose.
     *
     *  Could probably do something more clever here involving
     *  parsing the DOM tree.
     *
     *  @param doc The XML document to convert to a readable string sequence.
     *
     * @return The XML document as a String.  */
    private static String docToString(Document doc)
    {
        String docStr = doc.toString();
        StringTokenizer st = new StringTokenizer(docStr, ">");
        StringBuffer buf = new StringBuffer(docStr.length());
        while(st.hasMoreTokens())
            {
                String token = st.nextToken() + ">\n";
                buf.append( token );
            }
        return buf.toString();

    }

}
