/**************************************************************
 *
 * 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 "FrameOOoTContext.hxx"
#include "IgnoreTContext.hxx"
#include "MutableAttrList.hxx"
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/nmspmap.hxx>
#include "ActionMapTypesOOo.hxx"
#include "AttrTransformerAction.hxx"
#include "ElemTransformerAction.hxx"
#include "TransformerActions.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;
using namespace ::xmloff::token;

TYPEINIT1( XMLFrameOOoTransformerContext, XMLPersElemContentTContext );

XMLFrameOOoTransformerContext::XMLFrameOOoTransformerContext(
		XMLTransformerBase& rImp,
		const OUString& rQName ) :
	XMLPersElemContentTContext( rImp, rQName ),
	m_aElemQName( rImp.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_DRAW,
							::xmloff::token::GetXMLToken( XML_FRAME ) ) )
{
}

XMLFrameOOoTransformerContext::~XMLFrameOOoTransformerContext()
{
}

void XMLFrameOOoTransformerContext::StartElement(
	const Reference< XAttributeList >& rAttrList )
{

	XMLTransformerActions *pActions =
		GetTransformer().GetUserDefinedActions( OOO_FRAME_ATTR_ACTIONS );
	OSL_ENSURE( pActions, "go no actions" );

	Reference< XAttributeList > xAttrList( rAttrList );
	XMLMutableAttributeList *pMutableAttrList =
		GetTransformer().ProcessAttrList( xAttrList, OOO_SHAPE_ACTIONS,
										  sal_True );
	if( !pMutableAttrList )
		pMutableAttrList = new XMLMutableAttributeList( rAttrList );
	xAttrList = pMutableAttrList;

	XMLMutableAttributeList *pFrameMutableAttrList =
		new XMLMutableAttributeList;
	Reference< XAttributeList > xFrameAttrList( pFrameMutableAttrList );

	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		const OUString& rAttrName = xAttrList->getNameByIndex( i );
		OUString aLocalName;
		sal_uInt16 nPrefix =
			GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
																 &aLocalName );
		XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
		XMLTransformerActions::const_iterator aIter =
			pActions->find( aKey );
		if( !(aIter == pActions->end() ) )
		{
			const OUString& rAttrValue = xAttrList->getValueByIndex( i );
			switch( (*aIter).second.m_nActionType )
			{
			case XML_ATACTION_MOVE_TO_ELEM:
				pFrameMutableAttrList->AddAttribute( rAttrName, rAttrValue );
				pMutableAttrList->RemoveAttributeByIndex( i );
				--i;
				--nAttrCount;
				break;
			default:
				OSL_ENSURE( sal_False, "unknown action" );
				break;
			}
		}
	}

	GetTransformer().GetDocHandler()->startElement( m_aElemQName,
													xFrameAttrList );
	XMLTransformerContext::StartElement( xAttrList );
}

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

	XMLTransformerActions *pActions =
		GetTransformer().GetUserDefinedActions( OOO_FRAME_ELEM_ACTIONS );
	OSL_ENSURE( pActions, "go no actions" );
	XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
	XMLTransformerActions::const_iterator aIter = pActions->find( aKey );

	if( !(aIter == pActions->end()) )
	{
		switch( (*aIter).second.m_nActionType )
		{
		case XML_ETACTION_COPY:
		case XML_ETACTION_COPY_TEXT:
		case XML_ETACTION_RENAME_ELEM:
			// the ones in the list have to be persistent

			pContext = XMLPersElemContentTContext::CreateChildContext(
				   		nPrefix, rLocalName, rQName, rAttrList );
			break;
		default:
			OSL_ENSURE( sal_False, "unknown action" );
			break;
		}
	}

	// default is copying
	if( !pContext )
		pContext = XMLTransformerContext::CreateChildContext(
					nPrefix, rLocalName, rQName, rAttrList );

	return pContext;
}

void XMLFrameOOoTransformerContext::EndElement()
{
	XMLTransformerContext::EndElement();
	ExportContent();
	GetTransformer().GetDocHandler()->endElement( m_aElemQName );
}

void XMLFrameOOoTransformerContext::Characters( const OUString& rChars )
{
	XMLTransformerContext::Characters( rChars );
}

sal_Bool XMLFrameOOoTransformerContext::IsPersistent() const
{
	// this context stores some of its child elements, but is not persistent
	// itself.
	return sal_False;
}
