import java.io.*;
import java.util.Enumeration;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.*;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xalan.xpath.xdom.XercesLiaison;
import org.apache.xalan.xslt.*;

/* 
 * Linus Sphinx's New Xml Servlet - attempts to create new xml file with contents of request parameters
 * Copyright Linus Sphinx 1999 (c) all rights reserved
 */

public class nxml extends HttpServlet
{ 
public String XDocRoot; // location of doc root in initArgs from zone.properties
public String XDocName; // name on xml file to work on in XDocRoot
public String XItem; // main item to create, root tag in doc ie. <html>
public String Title = "Linus' Xml Wizard"; // title of html pages


// ------------------
// doGet - handle get requests
// ------------------
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        createXml( request, response );
    }

// ------------------
// doPost - handle post requests
// ------------------
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        createXml( request, response );
    }

// ------------------
// createXml - create a file and fill with tags based on
// ------------------
    public void createXml (HttpServletRequest request, HttpServletResponse response) throws IOException, NoSuchElementException
    {
        int level = 0;
        PrintWriter out;
        String title = "Linus' XML Wizard";
        Document doc;
        org.w3c.dom.Element root = null;
        org.w3c.dom.Element xkid = null;
        org.w3c.dom.Element xitem = null;
        String myArgs = "xdoc xitem xdata xdir xmap xptag xstyle";
        ArrayList<String> nestedItem = new ArrayList<String>(); // storage for nested branches
        ArrayList<String> nestedValue = new ArrayList<String>();
	ServletContext context = this.getServletContext();

        XDocRoot = context.getInitParameter( "docroot" );
        XDocName = request.getParameter( "xdoc" );
        XItem = request.getParameter( "xitem" );

        response.setContentType( "text/html" );
        out = response.getWriter();
        out.println( "<HTML><HEAD><TITLE>" );
        out.println( title );
        out.println( "</TITLE></HEAD><BODY bgcolor=\"#FFFFFF\">" );
        out.println( "<H4>" + title + "</H4>" );

        Enumeration e = request.getParameterNames();

		try
		{
			doc = new DocumentImpl();
			root = doc.createElement( XItem );

			// build flat nodes and add to root, saving nested branches in two arraylists, name and value
			while( e.hasMoreElements())
			{
				String s = (String)e.nextElement(); // tag name
				if ( myArgs.indexOf( s ) < 0 ) // it's not one of ours
				{
					String v = (String)request.getParameter( s ); // tag contents
					if ( s.indexOf( '/' ) > 0 ) // it's nested so save it
					{
						nestedItem.add( s ); // param
						nestedValue.add( v ); // param
					}
					else // no children
					{
						xitem = doc.createElement( s ); // param
						xitem.appendChild( doc.createTextNode( v )); // value
						root.appendChild( xitem );
					}
				}
			}

			// now build the nested branches
        	org.w3c.dom.Element nestedroot = null;
			String nestedroottag = new String();
			for ( int i = 0; i < nestedItem.size(); i ++ )
			{
				String str = (String)nestedItem.get( i );
				String val = (String)nestedValue.get( i );
				StringTokenizer st = new StringTokenizer( str, "/" );
				String token = st.nextToken();
				int toknum = st.countTokens(); 
				int g = findTagNode( root, token, out ); // already done?

				if ( g == -1 ) // not found, haven't done this one yet
				{
					nestedroot = doc.createElement( token );
					nestedroottag = token;
//					out.print( "<br />Nestedroot: " + token );
					for ( int ni = 0; ni < nestedItem.size(); ni ++ ) // now do all it's children
					{
						String nstr = (String)nestedItem.get( ni );
						if ( nstr.startsWith( nestedroottag + "/" ))
						{
//							out.print( "<br />#" + ni + " adding: " + nstr );
							String nval = (String)nestedValue.get( ni );

							StringTokenizer nst = new StringTokenizer( nstr, "/" );
							String ntoken = nst.nextToken();
							int ntoknum = nst.countTokens(); 
//							out.print( "<br />ntoken" + ntoken + " ntoknum: " + ntoknum );

							for ( int j = 0; j < ntoknum; j++ )
							{
								ntoken = nst.nextToken();
								xitem = doc.createElement( ntoken ); 
								nestedroot.appendChild( xitem );
								if ( j == ntoknum - 1)
								{
									xitem.appendChild( doc.createTextNode( nval )); // value
								}
							}
						}	
					}
					// add to doc
					root.appendChild( nestedroot );
				}				
			}

			StringTokenizer xst = new StringTokenizer( XDocName, "/" );
			int xtoknum = xst.countTokens(); 
			if ( xtoknum > 2 )
			{
				String x1token = xst.nextToken();
				String x2token = xst.nextToken();
            	File file = new File( XDocRoot + x1token + "/" + x2token );
				boolean duh = file.mkdirs();
				if ( duh == false )
				{
   	         	out.println("<br />Dir " + x2token + " already exists." );
				}
				else
				{
   		         	out.println("<br />Created dir " + x2token + "." );
				}
			}
			out.println( "<br />Created file: " + XDocName + "." );

            // write out our tree
            FileWriter xFile = new FileWriter( XDocRoot + XDocName, false);
            PrintWriter newFile = new PrintWriter(xFile);
            printTree( root, newFile, level );
            newFile.close();
            Date now = new Date();
            out.println("<br />at " + now.toString());
            out.println("<p /><a href=\"/emonster/index.xml\">Home</a>");
            out.println("</BODY></HTML>");
            out.close();

        } catch (IOException ioe) {
           // I/O error
           ioe.printStackTrace();
           return;
        } catch (NoSuchElementException nste) {
           // stringtokenizer error
           nste.printStackTrace();
           return;
        }
    } // eo createXml

// ------------------
// print a tree in xml code by calling printBranches on every type 1 node
// ------------------
    void printTree( org.w3c.dom.Node rootNode, PrintWriter Out, int level )
    {
        int type = rootNode.getNodeType();
        String name = rootNode.getNodeName();
        Out.println("<?xml version=\"1.0\"?>"); 
        if ( type == 1 )
            Out.println("<" + name + ">"); 
        printBranches( rootNode, Out, level );
        if ( type == 1 )
            Out.println("</" + name + ">"); 
    }

// ------------------
// print a branch in xml code
// ------------------
    void printBranches( org.w3c.dom.Node rootNode, PrintWriter Out, int level )
    {
        int j;

        org.w3c.dom.NodeList nodes = rootNode.getChildNodes();
        for (int i=0; i<nodes.getLength(); i++) {
            org.w3c.dom.Node node = nodes.item(i);
            int type = node.getNodeType();
            if ( type == 1 )
            {
                Out.print("<" + node.getNodeName() + ">"); 
            }
            if ( type == 3 )
            {
                String s = node.getNodeValue();
                if ( s.trim().compareTo( "" ) != 0 )
                {
                    Out.print( s ); 
                }
            }
            if ( node.hasChildNodes() )
            {
               printBranches( node, Out, level + 1 );
            } 
            if ( type == 1 )
            {
                Out.println("</" + node.getNodeName() + ">"); 
            }
        }
    } // eo printTree

// ------------------
// return true if a child Node of rootNode has the same name as str
// ------------------
	public int findTagNode( org.w3c.dom.Node rootNode, String str, PrintWriter Out ) 
	{	
		int type;
		String name;
		org.w3c.dom.Node nodei;

		name = rootNode.getNodeName();
		type = rootNode.getNodeType();

		if ( name.equals( str ) && type == 1 ) return( 0 );
		if ( rootNode.hasChildNodes() )
		{
			org.w3c.dom.NodeList nodeListi = rootNode.getChildNodes();
			for ( int i = 0; i < nodeListi.getLength(); i++ )
			{
				nodei = nodeListi.item( i );
				type = nodei.getNodeType();
				name = nodei.getNodeName();

				if ( type == 1 && name.equals( str ) ) // it's a tag and matches our item
				{
					return( i ); // success
				}
			 }
		}
        return( -1 ); // not found
    } 
// ------------------
// eoclass
// ------------------
}
