/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "DeepTContext.hxx"
#ifndef _XMLOFF_FLATTTCONTEXT_HXX
#include "FlatTContext.hxx"
#endif
#include "EventOOoTContext.hxx"
#include "TransformerActions.hxx"
#include "ElemTransformerAction.hxx"
#include "PersMixedContentTContext.hxx"
#ifndef _XMLOFF_TRANSFORMERBASE_HXX
#include "TransformerBase.hxx"
#endif

using ::rtl::OUString;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;

TYPEINIT1( XMLPersElemContentTContext, XMLPersAttrListTContext );

void XMLPersElemContentTContext::AddContent( XMLTransformerContext *pContext )
{
	OSL_ENSURE( pContext && pContext->IsPersistent(), 
				"non-persistent context" );
	XMLTransformerContextVector::value_type aVal( pContext );
	m_aChildContexts.push_back( aVal );
}

XMLPersElemContentTContext::XMLPersElemContentTContext( 
		XMLTransformerBase& rImp, 
		const OUString& rQName ) :
	XMLPersAttrListTContext( rImp, rQName )
{
}

XMLPersElemContentTContext::XMLPersElemContentTContext( 
		XMLTransformerBase& rImp, 
		const OUString& rQName,
	   sal_uInt16 nActionMap ) :
	XMLPersAttrListTContext( rImp, rQName, nActionMap )
{
}

XMLPersElemContentTContext::XMLPersElemContentTContext( 
		XMLTransformerBase& rImp, 
		const OUString& rQName,
	    sal_uInt16 nPrefix,
		::xmloff::token::XMLTokenEnum eToken ) :
	XMLPersAttrListTContext( rImp, rQName, nPrefix, eToken )
{
}

XMLPersElemContentTContext::XMLPersElemContentTContext( 
		XMLTransformerBase& rImp, 
		const OUString& rQName,
	    sal_uInt16 nPrefix,
		::xmloff::token::XMLTokenEnum eToken,
	   sal_uInt16 nActionMap ) :
	XMLPersAttrListTContext( rImp, rQName, nPrefix, eToken, nActionMap )
{
}

XMLPersElemContentTContext::~XMLPersElemContentTContext()
{
}

XMLTransformerContext *XMLPersElemContentTContext::CreateChildContext(
		sal_uInt16 nPrefix,
		const OUString& rLocalName,
		const OUString& rQName,
		const Reference< XAttributeList >& )
{
	XMLTransformerContext *pContext = 0;

	XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
	XMLTransformerActions::const_iterator aIter =
		GetTransformer().GetElemActions().find( aKey );

	if( !(aIter == GetTransformer().GetElemActions().end()) )
	{
		switch( (*aIter).second.m_nActionType )
		{
		case XML_ETACTION_COPY:
			pContext = new XMLPersMixedContentTContext( GetTransformer(), 
													   rQName );
			break;
		case XML_ETACTION_COPY_TEXT:
			pContext = new XMLPersMixedContentTContext( GetTransformer(), 
													   rQName );
			break;
		case XML_ETACTION_RENAME_ELEM:
			pContext = new XMLPersMixedContentTContext( GetTransformer(), rQName,
					(*aIter).second.GetQNamePrefixFromParam1(),
					(*aIter).second.GetQNameTokenFromParam1() );
			break;
		case XML_ETACTION_RENAME_ELEM_PROC_ATTRS:
			pContext = new XMLPersMixedContentTContext( GetTransformer(), rQName,
					(*aIter).second.GetQNamePrefixFromParam1(),
					(*aIter).second.GetQNameTokenFromParam1(),
				   	static_cast< sal_uInt16 >( (*aIter).second.m_nParam2 ) );
			break;
		case XML_ETACTION_RENAME_ELEM_ADD_PROC_ATTR:
			{
				XMLPersMixedContentTContext *pMC = 
					new XMLPersMixedContentTContext( GetTransformer(), rQName,
						(*aIter).second.GetQNamePrefixFromParam1(),
						(*aIter).second.GetQNameTokenFromParam1(),
						static_cast< sal_uInt16 >( 
							(*aIter).second.m_nParam3  >> 16 ) );
				pMC->AddAttribute( 
					(*aIter).second.GetQNamePrefixFromParam2(),
					(*aIter).second.GetQNameTokenFromParam2(),
				   	static_cast< ::xmloff::token::XMLTokenEnum >( 
						(*aIter).second.m_nParam3 & 0xffff ) );
				pContext = pMC;
			}
			break;
		case XML_ETACTION_PROC_ATTRS:
			pContext = new XMLPersMixedContentTContext( GetTransformer(), rQName,
				   	static_cast< sal_uInt16 >( (*aIter).second.m_nParam1 ) );
			break;
		default:
			pContext = GetTransformer().CreateUserDefinedContext( 
							(*aIter).second, rQName, sal_True );
			OSL_ENSURE( pContext && pContext->IsPersistent(), 
						"unknown or not persistent action" );
			if( pContext && !pContext->IsPersistent() )
			{
				delete pContext;
				pContext = 0;
			}		
			break;
		}
	}

	// default is copying
	if( !pContext )
		pContext = new XMLPersMixedContentTContext( GetTransformer(), rQName );
	XMLTransformerContextVector::value_type aVal( pContext );
	m_aChildContexts.push_back( aVal );

	return pContext;
}

void XMLPersElemContentTContext::ExportContent()
{
	XMLTransformerContextVector::iterator aIter = m_aChildContexts.begin();

	for( ; aIter != m_aChildContexts.end(); ++aIter )
	{
		(*aIter)->Export();
	}
}

