/*************************************************************************
 *
 *  $RCSfile: db_xml.cxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000/09/18 17:14:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/


#ifdef PRECOMPILED
#include "filt_pch.hxx"
#endif

#pragma hdrstop


#include "fltini.hxx"
#include "swerror.h"
#include "doc.hxx"
#include "pam.hxx"
#include "ndtxt.hxx"
#ifndef _DONDOC_HXX
#include <svtools/domdoc.hxx>
#endif

class SwDbgDOMDoc : public DOMDocument
{
	SwDoc *pDoc;
	SwPaM *pPam;

	void DumpNode( const DOMNode *pNode, USHORT nLevel );
protected:

	virtual void NotifyNodeStarted( const DOMNode *pNode );
	virtual DOMNotifyAction NotifyNodeFinished( const DOMNode *pNode );

public:

	SwDbgDOMDoc( SwDoc *pD, SwPaM *pP ) :
		pDoc( pD ), pPam( pP ) {}

	void Dump();
};

void SwDbgDOMDoc::NotifyNodeStarted( const DOMNode *pNode )
{
	String aTxt;
	USHORT i;
	switch( pNode->GetNodeType() )
	{
	case DOM_NT_ELEMENT:
	{
		const XMLAttributes& rAttrs = ((DOMElement*)pNode)->GetStrAttrList();
		(aTxt = '<')
		 += ((DOMElement*)pNode)->GetTagName();
			for( i=0; i<rAttrs.Count(); i++ )
				((((aTxt += ' ')
					+= rAttrs.GetName(i))
					+= "=\"")
					+= rAttrs.GetValue(i))
					+= '\"';
			aTxt += '>';
		break;
		}
	default:
		aTxt = "[unbekannter Node-Typ]";
		break;
	}
	pDoc->Insert( *pPam, aTxt );
	pDoc->AppendTxtNode( *pPam->GetPoint() );
}

DOMNotifyAction SwDbgDOMDoc::NotifyNodeFinished( const DOMNode *pNode )
{
	DOMNotifyAction eAction = DOM_NA_KEEP;

	String aTxt;
	switch( pNode->GetNodeType() )
	{
	case DOM_NT_PI:
		((((aTxt = "<?")
			 += ((DOMPI*)pNode)->GetName())
			 += ' ')
			 += ((DOMPI*)pNode)->GetData())
			 += "?>";
		eAction = DOM_NA_DELETE;
		break;
	case DOM_NT_ELEMENT:
		((aTxt = "</")
		 += ((DOMElement*)pNode)->GetTagName())
		 += '>';
		break;
	case DOM_NT_TEXT:
		aTxt = ((DOMText*)pNode)->GetData();
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0a", "\\n" ) );
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0d", "\\r" ) );
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x09", "\\t" ) );
		break;
	case DOM_NT_COMMENT:
		((aTxt = "<!--")
		 += ((DOMText*)pNode)->GetData())
		 += "-->";
		eAction = DOM_NA_DELETE;
		break;
	default:
		aTxt = "[unbekannter Node-Typ]";
		break;
	}
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0a", "\\n" ) );
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0d", "\\r" ) );
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x09", "\\t" ) );
	pDoc->Insert( *pPam, aTxt );
	pDoc->AppendTxtNode( *pPam->GetPoint() );

	return eAction;
}

void SwDbgDOMDoc::DumpNode( const DOMNode *pNode, USHORT nLevel )
{
	String aTxt;
	for( USHORT i=0; i < nLevel; i++ )
		aTxt += "  ";


	switch( pNode->GetNodeType() )
	{
	case DOM_NT_PI:
		((((aTxt += "<?")
			 += ((DOMPI*)pNode)->GetName())
			 += ' ')
			 += ((DOMPI*)pNode)->GetData())
			 += "?>";
		if( pNode->HasChildren() )
			aTxt += "\n[Node has Children]";
		break;
	case DOM_NT_ELEMENT:
	{
		const XMLAttributes& rAttrs = ((DOMElement*)pNode)->GetStrAttrList();
		aTxt += '<';
		aTxt += ((DOMElement*)pNode)->GetTagName();
		for( i=0; i<rAttrs.Count(); i++ )
			((((aTxt += ' ')
				+= rAttrs.GetName(i))
				+= "=\"")
				+= rAttrs.GetValue(i))
				+= '\"';
		if( !pNode->HasChildren() )
			aTxt += '/';
		aTxt += '>';

		if( pNode->HasChildren() )
		{
			pDoc->Insert( *pPam, aTxt );
			pDoc->AppendTxtNode( *pPam->GetPoint() );
			const DOMNode *pChild = pNode->GetFirstChild();
			while( pChild )
			{
				DumpNode( pChild, nLevel + 1 );
				pChild = pChild->GetNextSibling();
			}

			aTxt.Erase( 2*nLevel );
			((aTxt += "</")
				+= ((DOMElement*)pNode)->GetTagName())
				+= '>';
		}
	}
		break;
	case DOM_NT_TEXT:
		aTxt += ((DOMText*)pNode)->GetData();
		if( pNode->HasChildren() )
			aTxt += "\n[Node has Children]";
		break;
	case DOM_NT_COMMENT:
		((aTxt += "<!--")
		 += ((DOMText*)pNode)->GetData())
		 += "-->";
		if( pNode->HasChildren() )
			aTxt += "\n[Node has Children]";
		break;
	default:
		aTxt = "[unbekannter Node-Typ]";
		break;
	}
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0a", "\\n" ) );
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0d", "\\r" ) );
	while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x09", "\\t" ) );

	pDoc->Insert( *pPam, aTxt );
	pDoc->AppendTxtNode( *pPam->GetPoint() );
}

void SwDbgDOMDoc::Dump()
{
	pDoc->AppendTxtNode( *pPam->GetPoint() );
	pDoc->AppendTxtNode( *pPam->GetPoint() );
	pDoc->Insert( *pPam, "[Start of Dumped Document]" );
	pDoc->AppendTxtNode( *pPam->GetPoint() );

	const DOMNode *pChild = GetFirstChild();
	while( pChild )
	{
		DumpNode( pChild,  0 );
		pChild = pChild->GetNextSibling();
	}
	pDoc->Insert( *pPam, "[End of Dumped Document]" );
}

// Aufruf fuer die allg. Reader-Schnittstelle
ULONG XMLReader::Read( SwDoc &rDoc,SwPaM &rPam, const String & rName )
{
	if( !pStrm )
	{
		ASSERT( pStrm, "XML-Read ohne Stream" );
		return ERR_SWG_READ_ERROR;
	}

	if( !bInsertMode )
	{
		Reader::SetNoOutlineNum( rDoc );
		Reader::ResetFrmFmts( rDoc );
	}

#if 0
	XMLScanner aScanner( *pStrm );
	String aTxt;
	BOOL bDone = FALSE;
	do
	{
		XMLToken eToken = aScanner.GetNextToken();
		USHORT i;
		switch( eToken )
		{
		case XML_XML_DECL:
			aTxt = "<?xml";
			for( i=0; i<aScanner.GetAttrs().Count(); i++ )
				((((aTxt += ' ')
					+= aScanner.GetAttrs().GetName(i))
					+= "=\"")
					+= aScanner.GetAttrs().GetValue(i))
					+= '\"';
			aTxt += "?>";
			break;
		case XML_DOCTYPE_DECL:
		case XML_DOCTYPE_DECL_START:
			((aTxt = "<!DOCTYPE")
				+= ' ')
				+= aScanner.GetElement();
			for( i=0; i<aScanner.GetAttrs().Count(); i++ )
				((((aTxt += ' ')
					+= aScanner.GetAttrs().GetName(i))
					+= "=\"")
					+= aScanner.GetAttrs().GetValue(i))
					+= '\"';
			if( XML_DOCTYPE_DECL == eToken )
				aTxt += '>';
			else
				aTxt += " [";
			break;
		case XML_DOCTYPE_DECL_END:
			aTxt = "]>";
			break;
		case XML_ELEMENT_DECL:
			aTxt = "<!ELEMENT>";
			break;
		case XML_ATTLIST_DECL:
			aTxt = "<!ATTLIST>";
			break;
		case XML_ENTITY_DECL:
			aTxt = "<!ENTITY>";
			break;
		case XML_NOTATION_DECL:
			aTxt = "<!NOTATION>";
			break;
		case XML_PROC_INS:
			((((aTxt = "<?")
			 += aScanner.GetElement())
			 += ' ')
			 += aScanner.GetCharData())
			 += "?>";
			break;
		case XML_START_TAG:
			(aTxt = '<')
			 += aScanner.GetElement();
			for( i=0; i<aScanner.GetAttrs().Count(); i++ )
				((((aTxt += ' ')
					+= aScanner.GetAttrs().GetName(i))
					+= "=\"")
					+= aScanner.GetAttrs().GetValue(i))
					+= '\"';
			aTxt += '>';
			break;
		case XML_END_TAG:
			((aTxt = "</")
			 += aScanner.GetElement())
			 += '>';
			break;
		case XML_EMPTY_TAG:
			(aTxt = '<')
			 += aScanner.GetElement();
			for( i=0; i<aScanner.GetAttrs().Count(); i++ )
				((((aTxt += ' ')
					+= aScanner.GetAttrs().GetName(i))
					+= "=\"")
					+= aScanner.GetAttrs().GetValue(i))
					+= '\"';
			aTxt += "/>";
			break;
		case XML_CHAR_DATA:
			aTxt = aScanner.GetCharData();
			break;
		case XML_COMMENT:
			((aTxt = "<!--")
			 += aScanner.GetCharData())
			 += "-->";
			break;
		case XML_PARSE_ERROR:
			aTxt = "[Fatal Parse Error]";
			bDone = TRUE;
			break;
		case XML_EOF:
			bDone = TRUE;
			break;
		default:
			aTxt = "[unknwon token]";
			break;
		}
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0a", "\\n" ) );
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x0d", "\\r" ) );
		while( STRING_NOTFOUND != aTxt.SearchAndReplace( "\x09", "\\t" ) );
		rDoc.Insert( rPam, aTxt );
		rDoc.AppendTxtNode( *rPam.GetPoint() );
	}
	while( !bDone );

	if( aScanner.HasError() )
		((aTxt = "[Error: ") += aScanner.GetError()) += ']';
	else
		aTxt = "[No Error]";
	rDoc.Insert( rPam, aTxt );
#endif

	SwDbgDOMDoc aDOMDoc( &rDoc, &rPam );
	USHORT nFlags = 0;
	if( rName.Len() > 5 &&
		COMPARE_EQUAL == rName.Copy( rName.Len()-5 ).ICompare( ".MXML" ) )
	{
		// CDF-Files sind keine echten XML-Files
		nFlags |= DOM_LOAD_CDF;
	}

	USHORT nErr = aDOMDoc.Load( *pStrm, nFlags );

	String aTxt;
	if( nErr )
		((aTxt = "[Error: ") += nErr) += ']';
	else
		aTxt = "[No Error]";

	rDoc.Insert( rPam, aTxt );

	if( XML_ERR_NONE == nErr || XML_ERR_NONFATAL <= nErr )
		aDOMDoc.Dump();

	return 0;
}

/*************************************************************************

	  $Log: db_xml.cxx,v $
	  Revision 1.1.1.1  2000/09/18 17:14:54  hr
	  initial import
	
	  Revision 1.3  2000/09/18 16:04:41  willem.vandorp
	  OpenOffice header added.
	
	  Revision 1.2  1998/07/23 09:11:28  JP
	  Task #52654#: Einfuegen Doc nicht mit einer CrsrShell sondern mit einen PaM
	

	  Rev 1.1   23 Jul 1998 11:11:28   JP
   Task #52654#: Einfuegen Doc nicht mit einer CrsrShell sondern mit einen PaM

	  Rev 1.0   19 Mar 1998 18:16:32   MIB
   Initial revision.


*************************************************************************/

