/**************************************************************
 * 
 * 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_sw.hxx"


#include <xmloff/xmlnmspe.hxx>
#include "xmlimp.hxx"

using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;

// ---------------------------------------------------------------------


class SwXMLBodyContentContext_Impl : public SvXMLImportContext
{
	SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }

public:

	SwXMLBodyContentContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx,
					   	  const OUString& rLName );
	virtual ~SwXMLBodyContentContext_Impl();

	virtual SvXMLImportContext *CreateChildContext(
			sal_uInt16 nPrefix, const OUString& rLocalName,
			const Reference< xml::sax::XAttributeList > & xAttrList );

	// The body element's text:global attribute can be ignored, because
	// we must have the correct object shell already.
	virtual void EndElement();
};

SwXMLBodyContentContext_Impl::SwXMLBodyContentContext_Impl( SwXMLImport& rImport,
											  sal_uInt16 nPrfx,
				   	  						  const OUString& rLName ) :
	SvXMLImportContext( rImport, nPrfx, rLName )
{
}

SwXMLBodyContentContext_Impl::~SwXMLBodyContentContext_Impl()
{
}

SvXMLImportContext *SwXMLBodyContentContext_Impl::CreateChildContext(
		sal_uInt16 nPrefix, const OUString& rLocalName,
		const Reference< xml::sax::XAttributeList > & xAttrList )
{
	SvXMLImportContext *pContext = 0;

	pContext = GetSwImport().GetTextImport()->CreateTextChildContext(
			GetImport(), nPrefix, rLocalName, xAttrList,
		   	XML_TEXT_TYPE_BODY );
	if( !pContext )
		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

	return pContext;
}

void SwXMLBodyContentContext_Impl::EndElement()
{
    /* #108146# Code moved to SwXMLOmport::endDocument */
	GetImport().GetTextImport()->SetOutlineStyles( sal_False );
}

SvXMLImportContext *SwXMLImport::CreateBodyContentContext(
									   const OUString& rLocalName )
{
	SvXMLImportContext *pContext = 0;

	if( !IsStylesOnlyMode() )
 		pContext = new SwXMLBodyContentContext_Impl( *this, XML_NAMESPACE_OFFICE,
											  rLocalName );
	else
		pContext = new SvXMLImportContext( *this, XML_NAMESPACE_OFFICE,
										   rLocalName );

	return pContext;
}
