/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

package com.sun.star.xml.security.uno;

import org.w3c.dom.Node;
import com.sun.star.xml.sax.XDocumentHandler;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;

/*
 * this class is used to parse a document into SAX events
 */
class ParsingThread
{
	/*
	 * the Node which will be handled with in the next step
	 */
	private Node m_node;
	
	/*
	 * the event to be handled in the next step.
	 * true means endElement event, false otherwise.
	 */
	private boolean m_bIsEndEvent;
	
	/*
	 * the document handler which receives generated SAX events
	 */
	private XDocumentHandler m_xDocumentHandler;
	
	/*
	 * the TestTool which receives UI feedbacks
	 */
	private TestTool m_testTool;
	
         
        ParsingThread(Node node, XDocumentHandler xDocumentHandler, TestTool testTool) 
        {
        	m_node = node;
        	m_xDocumentHandler = xDocumentHandler;
        	m_testTool = testTool;
        	
        	m_bIsEndEvent = false;
        }
        
        /*
         * changes the document handler.
         */
        protected void setHandler(XDocumentHandler xDocumentHandler)
        {
        	this.m_xDocumentHandler = xDocumentHandler;
        }
 
        /*
         * sends the next SAX event.
         * when there is no further step, then false is returned,
         * otherwise, true returned.
         */
        protected boolean nextStep()
        {
        	boolean rc = true;
        	
        	try
        	{
	        	String message;
			int type = m_node.getNodeType();
			if (!m_bIsEndEvent)
			/*
			 * the next event is not a endElement event.
			 */
			{
				switch (type)
				{
				case Node.DOCUMENT_NODE: /* startDocument */
					m_testTool.updatesCurrentSAXEventInformation("startDocument");
					m_xDocumentHandler.startDocument();
					m_testTool.updatesUIs();
					break;
				case Node.ELEMENT_NODE: /* startElement */
					String nodeName = m_node.getNodeName();
					message = "startElement:"+nodeName;			
					NamedNodeMap attrs = m_node.getAttributes();
					
					AttributeListHelper attributeListHelper = new AttributeListHelper();
					
					int length = attrs.getLength();
					for (int i=0; i<length; ++i)
					{
						Attr attr = (Attr)attrs.item(i);
						attributeListHelper.setAttribute(attr.getName(), "CDATA", attr.getValue());
						message += " "+attr.getName()+"='"+attr.getValue()+"'";
					}
					
					m_testTool.updatesCurrentSAXEventInformation(message);
					m_xDocumentHandler.startElement(m_node.getNodeName(), attributeListHelper);
					
					m_testTool.updatesUIs();
					break;
				case Node.TEXT_NODE: /* characters */
					message = m_node.getNodeValue();
					if (message != null)
					{
						m_testTool.updatesCurrentSAXEventInformation("characters:"+message);
						m_xDocumentHandler.characters(message);
						m_testTool.updatesUIs();
					}
					break;
				case Node.COMMENT_NODE: /* comment */
					break;
				case Node.PROCESSING_INSTRUCTION_NODE: /* PI */
					m_testTool.updatesCurrentSAXEventInformation("processingInstruction:"+m_node.getNodeName()+" "+m_node.getNodeValue());
					m_xDocumentHandler.processingInstruction(m_node.getNodeName(), m_node.getNodeValue());
					m_testTool.updatesUIs();
					break;
				}
				
				/*
				 * figures out the event for the next step.
				 */
				switch (type) 
				{
					case Node.DOCUMENT_NODE: 
					case Node.ELEMENT_NODE:
						if (m_node.hasChildNodes()) 
						/* 
						 * for a Document node or an Element node,
						 * if the node has children, then the next event will be for its
						 * first child node.
						 */
						{
							m_node = m_node.getFirstChild();
						}
						else 
						/*
						 * otherwise, the next event will be endElement.
						 */
						{
							m_bIsEndEvent = true; 
						}
						break; 
					case Node.TEXT_NODE:
					case Node.PROCESSING_INSTRUCTION_NODE:
					case Node.COMMENT_NODE: 
						Node nextNode = m_node.getNextSibling();
						if (nextNode != null) 
						/*
						 * for other kinds of node,
						 * if it has a next sibling, then the next event will be for that
						 * sibling.
						 */
						{
							m_node = nextNode; 
						} 
						else
						/*
						 * otherwise, the next event will be the endElement for the node's
						 * parent node.
						 */
						{
							m_node = m_node.getParentNode();
							m_bIsEndEvent = true; 
						}
						break; 
				}
			}
			else
			/*
			 * the next event is an endElement event.
			 */
			{
				switch (type)
				{
					case Node.DOCUMENT_NODE: /* endDocument */
						m_testTool.updatesCurrentSAXEventInformation("endDocument"); 
						m_xDocumentHandler.endDocument(); 
						m_testTool.updatesUIs();
						
						/*
						 * no further steps.
						 */
						rc = false;
						break;
					case Node.ELEMENT_NODE: /* endElement */
						m_testTool.updatesCurrentSAXEventInformation("endElement:"+m_node.getNodeName()); 
						m_xDocumentHandler.endElement(m_node.getNodeName()); 
						m_testTool.updatesUIs();
							
						Node nextNode = m_node.getNextSibling();
						if (nextNode != null)
						/*
						 * if the node has a next sibling, then the next event will be the
						 * start event for that sibling node.
						 */
						{
							m_node = nextNode;
							m_bIsEndEvent = false;
						}
						else
						/*
						 * otherwise, the next event will be the endElement for the node's
						 * parent node.
						 */
						{
							m_node = m_node.getParentNode();
						}
						break;
				}
			}
		}
		catch(  com.sun.star.xml.sax.SAXException e)
		{
			e.printStackTrace();
			
			/*
			 * forces to end.
			 */
			rc = false;
		}
		
		return rc;
	}
}