/**************************************************************
 *
 * 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();
	}
}
