/**************************************************************
 *
 * 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 <com/sun/star/beans/XPropertySetInfo.hpp>
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <osl/mutex.hxx>
#include <rtl/uuid.h>
#include <rtl/memory.h>
#include <svl/svarray.hxx>
#include "unointerfacetouniqueidentifiermapper.hxx"
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmluconv.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmltoken.hxx>
#include <xmloff/XMLFontStylesContext.hxx>
#include <xmloff/xmlictxt.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmlnumfi.hxx>
#include "XMLEventImportHelper.hxx"
#include "XMLStarBasicContextFactory.hxx"
#include "XMLScriptContextFactory.hxx"
#include "StyleMap.hxx"
#include <xmloff/ProgressBarHelper.hxx>
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlerror.hxx"
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/document/XBinaryStreamResolver.hpp>
#include <com/sun/star/document/XStorageBasedDocument.hpp>
#include <com/sun/star/xml/sax/XLocator.hpp>
#include <com/sun/star/packages/zip/ZipIOException.hpp>
#include <comphelper/namecontainer.hxx>
#include <rtl/logfile.hxx>
#include <tools/string.hxx> // used in StartElement for logging
#include <cppuhelper/implbase1.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/documentconstants.hxx>
#include <comphelper/storagehelper.hxx>
#include <unotools/fontcvt.hxx>

#include <com/sun/star/rdf/XMetadatable.hpp>
#include <com/sun/star/rdf/XRepositorySupplier.hpp>
#include "RDFaImportHelper.hxx"

#define LOGFILE_AUTHOR "unknown"

using ::com::sun::star::beans::XPropertySetInfo;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;

using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::document;
using namespace ::xmloff::token;

sal_Char __READONLY_DATA sXML_np__office[] = "_office";
sal_Char __READONLY_DATA sXML_np__office_ext[] = "_office_ooo";
sal_Char __READONLY_DATA sXML_np__ooo[] = "_ooo";
sal_Char __READONLY_DATA sXML_np__ooow[] = "_ooow";
sal_Char __READONLY_DATA sXML_np__oooc[] = "_oooc";
sal_Char __READONLY_DATA sXML_np__of[] = "_of";
sal_Char __READONLY_DATA sXML_np__style[] = "_style";
sal_Char __READONLY_DATA sXML_np__text[] = "_text";
sal_Char __READONLY_DATA sXML_np__text_ext[] = "_text_ooo";
sal_Char __READONLY_DATA sXML_np__table[] = "_table";
sal_Char __READONLY_DATA sXML_np__table_ext[] = "_table_ooo";
sal_Char __READONLY_DATA sXML_np__draw[] = "_draw";
sal_Char __READONLY_DATA sXML_np__draw_ext[] = "_draw_ooo";
sal_Char __READONLY_DATA sXML_np__dr3d[] = "_dr3d";
sal_Char __READONLY_DATA sXML_np__fo[] = "_fo";
sal_Char __READONLY_DATA sXML_np__xlink[] = "_xlink";
sal_Char __READONLY_DATA sXML_np__dc[] = "_dc";
sal_Char __READONLY_DATA sXML_np__dom[] = "_dom";
sal_Char __READONLY_DATA sXML_np__meta[] = "_meta";
sal_Char __READONLY_DATA sXML_np__number[] = "_number";
sal_Char __READONLY_DATA sXML_np__svg[] = "_svg";
sal_Char __READONLY_DATA sXML_np__chart[] = "_chart";
sal_Char __READONLY_DATA sXML_np__math[] = "_math";
sal_Char __READONLY_DATA sXML_np__form[] = "_form";
sal_Char __READONLY_DATA sXML_np__script[] = "_script";
sal_Char __READONLY_DATA sXML_np__config[] = "_config";
sal_Char __READONLY_DATA sXML_np__db[] = "_db";
sal_Char __READONLY_DATA sXML_np__xforms[] = "_xforms";
sal_Char __READONLY_DATA sXML_np__xsd[] = "_xsd";
sal_Char __READONLY_DATA sXML_np__xsi[] = "_xsi";
sal_Char __READONLY_DATA sXML_np__field[] = "_field";
sal_Char __READONLY_DATA sXML_np__xhtml[] = "_xhtml";

sal_Char __READONLY_DATA sXML_np__fo_old[] = "__fo";
sal_Char __READONLY_DATA sXML_np__xlink_old[] = "__xlink";
sal_Char __READONLY_DATA sXML_np__office_old[] = "__office";
sal_Char __READONLY_DATA sXML_np__style_old[] = "__style";
sal_Char __READONLY_DATA sXML_np__text_old[] = "__text";
sal_Char __READONLY_DATA sXML_np__table_old[] = "__table";
sal_Char __READONLY_DATA sXML_np__meta_old[] = "__meta";



class SvXMLImportEventListener : public cppu::WeakImplHelper1<
							com::sun::star::lang::XEventListener >
{
private:
	SvXMLImport*	pImport;

public:
							SvXMLImportEventListener(SvXMLImport* pImport);
	virtual					~SvXMLImportEventListener();

							// XEventListener
	virtual void SAL_CALL disposing(const lang::EventObject& rEventObject) throw(::com::sun::star::uno::RuntimeException);
};

SvXMLImportEventListener::SvXMLImportEventListener(SvXMLImport* pTempImport)
	: pImport(pTempImport)
{
}

SvXMLImportEventListener::~SvXMLImportEventListener()
{
}

// XEventListener
void SAL_CALL SvXMLImportEventListener::disposing( const lang::EventObject& )
	throw(uno::RuntimeException)
{
	if (pImport)
	{
		pImport->DisposingModel();
		pImport = NULL;
	}
}

//==============================================================================
// --> ORW
namespace
{
    class DocumentInfo
    {
        private:
            sal_uInt16 mnGeneratorVersion;

        public:
            DocumentInfo( const SvXMLImport& rImport )
                : mnGeneratorVersion( SvXMLImport::ProductVersionUnknown )
            {
                sal_Int32 nUPD, nBuild;
                if ( rImport.getBuildIds( nUPD, nBuild ) )
                {
                    if ( nUPD >= 640 && nUPD <= 645 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_1x;
                    }
                    else if ( nUPD == 680 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_2x;
                    }
                    else if ( nUPD == 300 && nBuild <= 9379 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_30x;
                    }
                    else if ( nUPD == 310 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_31x;
                    }
                    else if ( nUPD == 320 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_32x;
                    }
                    else if ( nUPD == 330 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_33x;
                    }
                    else if ( nUPD == 340 )
                    {
                        mnGeneratorVersion = SvXMLImport::OOo_34x;
                    }
                }
            }

            ~DocumentInfo()
            {}

            sal_uInt16 getGeneratorVersion() const
            {
                return mnGeneratorVersion;
            }
    };
}
// <--

class SvXMLImport_Impl
{
public:
	FontToSubsFontConverter hBatsFontConv;
	FontToSubsFontConverter hMathFontConv;

	bool mbOwnGraphicResolver;
	bool mbOwnEmbeddedResolver;
	INetURLObject aBaseURL;
    INetURLObject aDocBase;

    // name of stream in package, e.g., "content.xml"
    ::rtl::OUString mStreamName;

    ::rtl::OUString aODFVersion;

    // --> OD 2004-08-10 #i28749# - boolean, indicating that position attributes
    // of shapes are given in horizontal left-to-right layout. This is the case
    // for the OpenOffice.org file format.
    sal_Bool mbShapePositionInHoriL2R;
    // <--
    // --> OD 2007-12-19 #152540#
    sal_Bool mbTextDocInOOoFileFormat;
    // <--

    const uno::Reference< uno::XComponentContext > mxComponentContext;

    std::auto_ptr< xmloff::RDFaImportHelper > mpRDFaHelper;

    // --> ORW
    std::auto_ptr< DocumentInfo > mpDocumentInfo;
    // <--

    SvXMLImport_Impl()
        : hBatsFontConv( 0 )
        , hMathFontConv( 0 )
        , mbOwnGraphicResolver( false )
        , mbOwnEmbeddedResolver( false )
        , mStreamName()
        , mbShapePositionInHoriL2R( sal_False )
        , mbTextDocInOOoFileFormat( sal_False )
        , mxComponentContext( ::comphelper::getProcessComponentContext() )
        , mpRDFaHelper() // lazy
        // --> ORW
        , mpDocumentInfo() // lazy
        // <--
    {
        OSL_ENSURE(mxComponentContext.is(), "SvXMLImport: no ComponentContext");
        if (!mxComponentContext.is()) throw uno::RuntimeException();
    }

	~SvXMLImport_Impl()
	{
		if( hBatsFontConv )
			DestroyFontToSubsFontConverter( hBatsFontConv );
		if( hMathFontConv )
			DestroyFontToSubsFontConverter( hMathFontConv );
	}

    // --> ORW
    sal_uInt16 getGeneratorVersion( const SvXMLImport& rImport )
    {
        if ( !mpDocumentInfo.get() )
        {
            mpDocumentInfo.reset( new DocumentInfo( rImport ) );
        }

        return mpDocumentInfo->getGeneratorVersion();
    }
    // <--

	::comphelper::UnoInterfaceToUniqueIdentifierMapper	maInterfaceToIdentifierMapper;
};

typedef SvXMLImportContext *SvXMLImportContextPtr;
SV_DECL_PTRARR( SvXMLImportContexts_Impl, SvXMLImportContextPtr, 20, 5 )
SV_IMPL_PTRARR( SvXMLImportContexts_Impl, SvXMLImportContextPtr )

SvXMLImportContext *SvXMLImport::CreateContext( sal_uInt16 nPrefix,
										 const OUString& rLocalName,
										 const uno::Reference< xml::sax::XAttributeList >& )
{
	return new SvXMLImportContext( *this, nPrefix, rLocalName );
}

void SvXMLImport::_InitCtor()
{
	if( mnImportFlags != 0 )
	{
		// implicit "xml" namespace prefix
		mpNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office ) ),
							GetXMLToken(XML_N_OFFICE),
							XML_NAMESPACE_OFFICE );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office_ext ) ),
							GetXMLToken(XML_N_OFFICE_EXT),
							XML_NAMESPACE_OFFICE_EXT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__ooo ) ), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__style) ),
							GetXMLToken(XML_N_STYLE),
							XML_NAMESPACE_STYLE );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__text) ),
							GetXMLToken(XML_N_TEXT),
							XML_NAMESPACE_TEXT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__text_ext ) ),
							GetXMLToken(XML_N_TEXT_EXT),
							XML_NAMESPACE_TEXT_EXT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__table ) ),
							GetXMLToken(XML_N_TABLE),
							XML_NAMESPACE_TABLE );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__table_ext ) ),
							GetXMLToken(XML_N_TABLE_EXT),
							XML_NAMESPACE_TABLE_EXT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__draw ) ),
							GetXMLToken(XML_N_DRAW),
							XML_NAMESPACE_DRAW );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__draw_ext ) ),
							GetXMLToken(XML_N_DRAW_EXT),
							XML_NAMESPACE_DRAW_EXT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM (sXML_np__dr3d ) ),
							GetXMLToken(XML_N_DR3D),
							XML_NAMESPACE_DR3D );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__fo) ),
							GetXMLToken(XML_N_FO_COMPAT),
							XML_NAMESPACE_FO );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xlink) ),
							GetXMLToken(XML_N_XLINK),
							XML_NAMESPACE_XLINK );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__dc) ),
							GetXMLToken(XML_N_DC),
							XML_NAMESPACE_DC );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__dom ) ),
							GetXMLToken(XML_N_DOM),
							XML_NAMESPACE_DOM );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__meta) ),
							GetXMLToken(XML_N_META),
							XML_NAMESPACE_META );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__number) ),
							GetXMLToken(XML_N_NUMBER),
							XML_NAMESPACE_NUMBER );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__svg) ),
							GetXMLToken(XML_N_SVG_COMPAT),
							XML_NAMESPACE_SVG );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__chart) ),
							GetXMLToken(XML_N_CHART),
							XML_NAMESPACE_CHART );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__math) ),
							GetXMLToken(XML_N_MATH),
							XML_NAMESPACE_MATH );
		mpNamespaceMap->Add(OUString(RTL_CONSTASCII_USTRINGPARAM( sXML_np__form )),
							GetXMLToken(XML_N_FORM),
							XML_NAMESPACE_FORM );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__script) ),
							GetXMLToken(XML_N_SCRIPT),
							XML_NAMESPACE_SCRIPT );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__config) ),
							GetXMLToken(XML_N_CONFIG),
							XML_NAMESPACE_CONFIG );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xforms) ),
							GetXMLToken(XML_N_XFORMS_1_0),
							XML_NAMESPACE_XFORMS );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xsd) ),
							GetXMLToken(XML_N_XSD),
							XML_NAMESPACE_XSD );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xsi) ),
							GetXMLToken(XML_N_XSI),
							XML_NAMESPACE_XFORMS );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__ooow ) ), GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__oooc ) ), GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__field ) ), GetXMLToken(XML_N_FIELD), XML_NAMESPACE_FIELD );
		mpNamespaceMap->Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__of ) ),
							GetXMLToken(XML_N_OF), XML_NAMESPACE_OF );
		mpNamespaceMap->Add(
			OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xhtml ) ),
			GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
	}

	msPackageProtocol = OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package:" ) );

	if (mxNumberFormatsSupplier.is())
		mpNumImport = new SvXMLNumFmtHelper(mxNumberFormatsSupplier, getServiceFactory());

	if (mxModel.is() && !mxEventListener.is())
	{
		mxEventListener.set(new SvXMLImportEventListener(this));
		mxModel->addEventListener(mxEventListener);
	}

	::comphelper::UnoInterfaceToUniqueIdentifierMapper	maInterfaceToIdentifierMapper;

}

// #110680#
SvXMLImport::SvXMLImport(
	const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
	sal_uInt16 nImportFlags ) throw ()
:	mpImpl( new SvXMLImport_Impl() ),
	mpNamespaceMap( new SvXMLNamespaceMap ),

	// #110680#
	// pUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM ) ),
	mpUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM, xServiceFactory ) ),

	mpContexts( new SvXMLImportContexts_Impl ),
	mpNumImport( NULL ),
	mpProgressBarHelper( NULL ),
	mpEventImportHelper( NULL ),
	mpXMLErrors( NULL ),
	mpStyleMap(0),
	mnImportFlags( nImportFlags ),
	mnErrorFlags(0),
	// #110680#
	mxServiceFactory(xServiceFactory),
	mbIsFormsSupported( sal_True ),
	mbIsTableShapeSupported( false ),
	mbIsGraphicLoadOnDemandSupported( true )
{
	DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
	_InitCtor();
}

// #110680#
SvXMLImport::SvXMLImport(
	const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
	const Reference< XModel > & rModel ) throw ()
:	mxModel( rModel ),
	mxNumberFormatsSupplier (rModel, uno::UNO_QUERY),
	mpImpl( new SvXMLImport_Impl() ),
	mpNamespaceMap( new SvXMLNamespaceMap ),
	// #110680#
	// pUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM ) ),
	mpUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM, xServiceFactory ) ),
	mpContexts( new SvXMLImportContexts_Impl ),
	mpNumImport( NULL ),
	mpProgressBarHelper( NULL ),
	mpEventImportHelper( NULL ),
	mpXMLErrors( NULL ),
	mpStyleMap(0),
	mnImportFlags( IMPORT_ALL ),
	mnErrorFlags(0),
	// #110680#
	mxServiceFactory(xServiceFactory),
	mbIsFormsSupported( sal_True ),
	mbIsTableShapeSupported( false ),
	mbIsGraphicLoadOnDemandSupported( true )
{
	DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
	_InitCtor();
}

// #110680#
SvXMLImport::SvXMLImport(
	const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
	const Reference< XModel > & rModel,
	const ::com::sun::star::uno::Reference< ::com::sun::star::document::XGraphicObjectResolver > & rGraphicObjects ) throw ()
:	mxModel( rModel ),
	mxNumberFormatsSupplier (rModel, uno::UNO_QUERY),
	mxGraphicResolver( rGraphicObjects ),
	mpImpl( new SvXMLImport_Impl() ),
	mpNamespaceMap( new SvXMLNamespaceMap ),
	// #110680#
	// pUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM ) ),
	mpUnitConv( new SvXMLUnitConverter( MAP_100TH_MM, MAP_100TH_MM, xServiceFactory ) ),
	mpContexts( new SvXMLImportContexts_Impl ),
	mpNumImport( NULL ),
	mpProgressBarHelper( NULL ),
	mpEventImportHelper( NULL ),
	mpXMLErrors( NULL ),
	mpStyleMap(0),
	mnImportFlags( IMPORT_ALL ),
	mnErrorFlags(0),
	// #110680#
	mxServiceFactory(xServiceFactory),
	mbIsFormsSupported( sal_True ),
	mbIsGraphicLoadOnDemandSupported( true )
{
	DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
	_InitCtor();
}

SvXMLImport::~SvXMLImport() throw ()
{
	delete mpXMLErrors;
	delete mpNamespaceMap;
	delete mpUnitConv;
	delete mpEventImportHelper;
	if( mpContexts )
	{
		while( mpContexts->Count() )
		{
			sal_uInt16 n = mpContexts->Count() - 1;
			SvXMLImportContext *pContext = (*mpContexts)[n];
			mpContexts->Remove( n, 1 );
			if( pContext )
				pContext->ReleaseRef();
		}
		delete mpContexts;
	}

	// delete pImageMapImportHelper;

	// #i9518# the import component might not be deleted until after the document has been closed,
	// so the stuff that accesses the document has been moved to endDocument.

	// pNumImport is allocated in the ctor, so it must also be deleted here in case the component
	// is created and deleted without actually importing.
	delete mpNumImport;
	delete mpProgressBarHelper;

	xmloff::token::ResetTokens();

	if( mpImpl )
		delete mpImpl;

	if (mxEventListener.is() && mxModel.is())
		mxModel->removeEventListener(mxEventListener);
}

// XUnoTunnel & co
const uno::Sequence< sal_Int8 > & SvXMLImport::getUnoTunnelId() throw()
{
	static uno::Sequence< sal_Int8 > * pSeq = 0;
	if( !pSeq )
	{
		Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
		if( !pSeq )
		{
			static uno::Sequence< sal_Int8 > aSeq( 16 );
			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
			pSeq = &aSeq;
		}
	}
	return *pSeq;
}

SvXMLImport* SvXMLImport::getImplementation( uno::Reference< uno::XInterface > xInt ) throw()
{
	uno::Reference< lang::XUnoTunnel > xUT( xInt, uno::UNO_QUERY );
	if( xUT.is() )
	{
		return
			reinterpret_cast<SvXMLImport*>(
				sal::static_int_cast<sal_IntPtr>(
					xUT->getSomething( SvXMLImport::getUnoTunnelId())));
	}
	else
		return NULL;
}

// XUnoTunnel
sal_Int64 SAL_CALL SvXMLImport::getSomething( const uno::Sequence< sal_Int8 >& rId )
	throw( uno::RuntimeException )
{
	if( rId.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
														 rId.getConstArray(), 16 ) )
	{
		return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this));
	}
	return 0;
}

void SAL_CALL SvXMLImport::startDocument( void )
	throw( xml::sax::SAXException, uno::RuntimeException )
{
	RTL_LOGFILE_TRACE_AUTHOR( "xmloff", LOGFILE_AUTHOR, "{ SvXMLImport::startDocument" );

	if( !mxGraphicResolver.is() || !mxEmbeddedResolver.is() )
	{
		Reference< lang::XMultiServiceFactory > xFactory( mxModel,	UNO_QUERY );
		if( xFactory.is() )
		{
			try
			{
				if( !mxGraphicResolver.is() )
				{
					mxGraphicResolver = Reference< XGraphicObjectResolver >::query(
						xFactory->createInstance(
							OUString(RTL_CONSTASCII_USTRINGPARAM(
								// #99870# Import... instead of Export...
								"com.sun.star.document.ImportGraphicObjectResolver"))));
					mpImpl->mbOwnGraphicResolver = mxGraphicResolver.is();
				}

				if( !mxEmbeddedResolver.is() )
				{
					mxEmbeddedResolver = Reference< XEmbeddedObjectResolver >::query(
						xFactory->createInstance(
							OUString(RTL_CONSTASCII_USTRINGPARAM(
								// #99870# Import... instead of Export...
								"com.sun.star.document.ImportEmbeddedObjectResolver"))));
					mpImpl->mbOwnEmbeddedResolver = mxEmbeddedResolver.is();
				}
			}
			catch( com::sun::star::uno::Exception& )
			{
			}
		}
	}
}

void SAL_CALL SvXMLImport::endDocument( void )
	throw( xml::sax::SAXException, uno::RuntimeException)
{
	RTL_LOGFILE_TRACE_AUTHOR( "xmloff", LOGFILE_AUTHOR, "} SvXMLImport::startDocument" );

	// #i9518# All the stuff that accesses the document has to be done here, not in the dtor,
	// because the SvXMLImport dtor might not be called until after the document has been closed.

    if (mpImpl->mpRDFaHelper.get())
    {
        const uno::Reference<rdf::XRepositorySupplier> xRS(mxModel,
            uno::UNO_QUERY);
        if (xRS.is())
        {
            mpImpl->mpRDFaHelper->InsertRDFa( xRS );
        }
    }

	if (mpNumImport)
	{
		delete mpNumImport;
		mpNumImport = NULL;
	}
	if (mxImportInfo.is())
	{
		uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo();
		if (xPropertySetInfo.is())
		{
			if (mpProgressBarHelper)
			{
				OUString sProgressMax(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSMAX));
				OUString sProgressCurrent(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSCURRENT));
                OUString sRepeat(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSREPEAT));
				if (xPropertySetInfo->hasPropertyByName(sProgressMax) &&
					xPropertySetInfo->hasPropertyByName(sProgressCurrent))
				{
					sal_Int32 nProgressMax(mpProgressBarHelper->GetReference());
					sal_Int32 nProgressCurrent(mpProgressBarHelper->GetValue());
					uno::Any aAny;
					aAny <<= nProgressMax;
					mxImportInfo->setPropertyValue(sProgressMax, aAny);
					aAny <<= nProgressCurrent;
					mxImportInfo->setPropertyValue(sProgressCurrent, aAny);
				}
                if (xPropertySetInfo->hasPropertyByName(sRepeat))
                    mxImportInfo->setPropertyValue(sRepeat, cppu::bool2any(mpProgressBarHelper->GetRepeat()));
                // pProgressBarHelper is deleted in dtor
			}
			OUString sNumberStyles(RTL_CONSTASCII_USTRINGPARAM(XML_NUMBERSTYLES));
			if (mxNumberStyles.is() && xPropertySetInfo->hasPropertyByName(sNumberStyles))
			{
				uno::Any aAny;
				aAny <<= mxNumberStyles;
				mxImportInfo->setPropertyValue(sNumberStyles, aAny);
			}
		}
	}

	if( mxFontDecls.Is() )
		((SvXMLStylesContext *)&mxFontDecls)->Clear();
	if( mxStyles.Is() )
		((SvXMLStylesContext *)&mxStyles)->Clear();
	if( mxAutoStyles.Is() )
		((SvXMLStylesContext *)&mxAutoStyles)->Clear();
	if( mxMasterStyles.Is() )
		((SvXMLStylesContext *)&mxMasterStyles)->Clear();

	// possible form-layer related knittings which can only be done when
	// the whole document exists
	if ( mxFormImport.is() )
		mxFormImport->documentDone();

	// The shape import helper does the z-order sorting in the dtor,
	// so it must be deleted here, too.
	mxShapeImport = NULL;

	if( mpImpl->mbOwnGraphicResolver )
	{
		Reference< lang::XComponent > xComp( mxGraphicResolver, UNO_QUERY );
		xComp->dispose();
	}

	if( mpImpl->mbOwnEmbeddedResolver )
	{
		Reference< lang::XComponent > xComp( mxEmbeddedResolver, UNO_QUERY );
		xComp->dispose();
	}
	if( mpStyleMap )
	{
		mpStyleMap->release();
		mpStyleMap = 0;
	}

	if ( mpXMLErrors != NULL )
	{
		mpXMLErrors->ThrowErrorAsSAXException( XMLERROR_FLAG_SEVERE );
	}
}

void SAL_CALL SvXMLImport::startElement( const OUString& rName,
										 const uno::Reference< xml::sax::XAttributeList >& xAttrList )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
	SvXMLNamespaceMap *pRewindMap = 0;

	// Process namespace attributes. This must happen before creating the
	// context, because namespace declaration apply to the element name itself.
	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		const OUString& rAttrName = xAttrList->getNameByIndex( i );
		if ( rAttrName.equalsAscii("office:version") )
		{
			mpImpl->aODFVersion = xAttrList->getValueByIndex( i );

            // the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2
            if ( mpImpl->mStreamName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) )
              && !IsODFVersionConsistent( mpImpl->aODFVersion ) )
            {
                throw xml::sax::SAXException(
                        ::rtl::OUString(
                            RTL_CONSTASCII_USTRINGPARAM( "Inconsistent ODF versions in content.xml and manifest.xml!" ) ),
                        uno::Reference< uno::XInterface >(),
                        uno::makeAny(
                            packages::zip::ZipIOException(
                                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
                                    "Inconsistent ODF versions in content.xml and manifest.xml!" ) ),
							    Reference< XInterface >() ) ) );
            }
        }
        else if( ( rAttrName.getLength() >= 5 ) &&
            ( rAttrName.compareTo( GetXMLToken(XML_XMLNS), 5 ) == 0 ) &&
			( rAttrName.getLength() == 5 || ':' == rAttrName[5] ) )
		{
			if( !pRewindMap )
			{
				pRewindMap = mpNamespaceMap;
				mpNamespaceMap = new SvXMLNamespaceMap( *mpNamespaceMap );
			}
			const OUString& rAttrValue = xAttrList->getValueByIndex( i );

            OUString aPrefix( ( rAttrName.getLength() == 5 )
                                 ? OUString()
                                 : rAttrName.copy( 6 ) );
			// Add namespace, but only if it is known.
			sal_uInt16 nKey = mpNamespaceMap->AddIfKnown( aPrefix, rAttrValue );
			// If namespace is unknown, try to match a name with similar
			// TC Id an version
			if( XML_NAMESPACE_UNKNOWN == nKey )
			{
				OUString aTestName( rAttrValue );
				if( SvXMLNamespaceMap::NormalizeURI( aTestName ) )
					nKey = mpNamespaceMap->AddIfKnown( aPrefix, aTestName );
			}
			// If that namespace is not known, too, add it as unknown
			if( XML_NAMESPACE_UNKNOWN == nKey )
				mpNamespaceMap->Add( aPrefix, rAttrValue );

		}
	}

	// Get element's namespace and local name.
	OUString aLocalName;
	sal_uInt16 nPrefix =
		mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName );

	// If there are contexts already, call a CreateChildContext at the topmost
	// context. Otherwise, create a default context.
	SvXMLImportContext *pContext;
	sal_uInt16 nCount = mpContexts->Count();
	if( nCount > 0 )
	{
		pContext = (*mpContexts)[nCount - 1]->CreateChildContext( nPrefix,
																 aLocalName,
																 xAttrList );
		DBG_ASSERT( pContext && pContext->GetPrefix() == nPrefix,
				"SvXMLImport::startElement: created context has wrong prefix" );
	}
	else
	{
#ifdef TIMELOG
        // If we do profiling, we want a trace message for the first element
        // in order to identify the stream.
        ByteString aString( (String)rName, RTL_TEXTENCODING_ASCII_US );
        RTL_LOGFILE_TRACE_AUTHOR1( "xmloff", LOGFILE_AUTHOR,
                                   "SvXMLImport::StartElement( \"%s\", ... )",
                                   aString.GetBuffer() );
#endif

		pContext = CreateContext( nPrefix, aLocalName, xAttrList );
		if( (nPrefix & XML_NAMESPACE_UNKNOWN_FLAG) != 0 &&
			IS_TYPE( SvXMLImportContext, pContext ) )
		{
			OUString aMsg( RTL_CONSTASCII_USTRINGPARAM( "Root element unknown" ) );
			Reference<xml::sax::XLocator> xDummyLocator;
			Sequence < OUString > aParams(1);
			aParams.getArray()[0] = rName;

			SetError( XMLERROR_FLAG_SEVERE|XMLERROR_UNKNOWN_ROOT,
					  aParams, aMsg, xDummyLocator );
		}
	}

	DBG_ASSERT( pContext, "SvXMLImport::startElement: missing context" );
	if( !pContext )
		pContext = new SvXMLImportContext( *this, nPrefix, aLocalName );

	pContext->AddRef();

	// Remember old namespace map.
	if( pRewindMap )
		pContext->SetRewindMap( pRewindMap );

	// Call a startElement at the new context.
	pContext->StartElement( xAttrList );

	// Push context on stack.
	mpContexts->Insert( pContext, nCount );
}

void SAL_CALL SvXMLImport::endElement( const OUString&
#ifdef DBG_UTIL
rName
#endif
)
	throw(xml::sax::SAXException, uno::RuntimeException)
{
	sal_uInt16 nCount = mpContexts->Count();
	DBG_ASSERT( nCount, "SvXMLImport::endElement: no context left" );
	if( nCount > 0 )
	{
		// Get topmost context and remove it from the stack.
		SvXMLImportContext *pContext = (*mpContexts)[nCount-1];
		mpContexts->Remove( nCount-1, 1 );

#ifdef DBG_UTIL
		// Non product only: check if endElement call matches startELement call.
		OUString aLocalName;
		sal_uInt16 nPrefix =
			mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
		DBG_ASSERT( pContext->GetPrefix() == nPrefix,
				"SvXMLImport::endElement: popped context has wrong prefix" );
		DBG_ASSERT( pContext->GetLocalName() == aLocalName,
				"SvXMLImport::endElement: popped context has wrong lname" );
#endif

		// Call a EndElement at the current context.
		pContext->EndElement();

		// Get a namespace map to rewind.
		SvXMLNamespaceMap *pRewindMap = pContext->GetRewindMap();

		// Delete the current context.
		pContext->ReleaseRef();
		pContext = 0;

		// Rewind a namespace map.
		if( pRewindMap )
		{
			delete mpNamespaceMap;
			mpNamespaceMap = pRewindMap;
		}
	}
}

void SAL_CALL SvXMLImport::characters( const OUString& rChars )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
	sal_uInt16 nCount = mpContexts->Count();
	if( nCount > 0 )
	{
		(*mpContexts)[nCount - 1]->Characters( rChars );
	}
}

void SAL_CALL SvXMLImport::ignorableWhitespace( const OUString& )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::processingInstruction( const OUString&,
									   const OUString& )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& rLocator )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
	mxLocator = rLocator;
}

// XExtendedDocumentHandler
void SAL_CALL SvXMLImport::startCDATA( void ) throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::endCDATA( void ) throw(uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::comment( const OUString& )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::allowLineBreak( void )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SAL_CALL SvXMLImport::unknown( const OUString& )
	throw(xml::sax::SAXException, uno::RuntimeException)
{
}

void SvXMLImport::SetStatistics(const uno::Sequence< beans::NamedValue> &)
{
	GetProgressBarHelper()->SetRepeat(sal_False);
	GetProgressBarHelper()->SetReference(0);
}

///////////////////////////////////////////////////////////////////////

// XImporter
void SAL_CALL SvXMLImport::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc )
	throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	mxModel = uno::Reference< frame::XModel >::query( xDoc );
	if( !mxModel.is() )
		throw lang::IllegalArgumentException();
	if (mxModel.is() && !mxEventListener.is())
	{
		mxEventListener.set(new SvXMLImportEventListener(this));
		mxModel->addEventListener(mxEventListener);
	}

	DBG_ASSERT( !mpNumImport, "number format import already exists." );
	if( mpNumImport )
	{
		delete mpNumImport;
		mpNumImport = 0;
	}
}

// XFilter
sal_Bool SAL_CALL SvXMLImport::filter( const uno::Sequence< beans::PropertyValue >& )
	throw (uno::RuntimeException)
{
	return sal_False;
}

void SAL_CALL SvXMLImport::cancel(  )
	throw (uno::RuntimeException)
{
}

// XInitialize
void SAL_CALL SvXMLImport::initialize( const uno::Sequence< uno::Any >& aArguments )
	throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
{
	const sal_Int32 nAnyCount = aArguments.getLength();
	const uno::Any* pAny = aArguments.getConstArray();

	for( sal_Int32 nIndex = 0; nIndex < nAnyCount; nIndex++, pAny++ )
	{
        Reference<XInterface> xValue;
        *pAny >>= xValue;

        uno::Reference<task::XStatusIndicator> xTmpStatusIndicator(
            xValue, UNO_QUERY );
		if( xTmpStatusIndicator.is() )
			mxStatusIndicator = xTmpStatusIndicator;

        uno::Reference<document::XGraphicObjectResolver> xTmpGraphicResolver(
            xValue, UNO_QUERY );
		if( xTmpGraphicResolver.is() )
			mxGraphicResolver = xTmpGraphicResolver;

        uno::Reference<document::XEmbeddedObjectResolver> xTmpObjectResolver(
            xValue, UNO_QUERY );
        if( xTmpObjectResolver.is() )
            mxEmbeddedResolver = xTmpObjectResolver;

        uno::Reference<beans::XPropertySet> xTmpPropSet( xValue, UNO_QUERY );
        if( xTmpPropSet.is() )
        {
            mxImportInfo = xTmpPropSet;
            uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo();
            if (xPropertySetInfo.is())
			{
                OUString sPropName(RTL_CONSTASCII_USTRINGPARAM(XML_NUMBERSTYLES));
                if (xPropertySetInfo->hasPropertyByName(sPropName))
				{
                    uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
                    aAny >>= mxNumberStyles;
				}

				sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("PrivateData" ) );
                if (xPropertySetInfo->hasPropertyByName(sPropName))
				{
					Reference < XInterface > xIfc;
                    uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
                    aAny >>= xIfc;

					StyleMap *pSMap = StyleMap::getImplementation( xIfc );
					if( pSMap )
					{
						mpStyleMap = pSMap;
						mpStyleMap->acquire();
					}
				}
				OUString sBaseURI;
				sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("BaseURI" ) );
                if (xPropertySetInfo->hasPropertyByName(sPropName))
				{
                    uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
                    aAny >>= sBaseURI;
					mpImpl->aBaseURL.SetURL( sBaseURI );
                    mpImpl->aDocBase.SetURL( sBaseURI );
				}
				OUString sRelPath;
				sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("StreamRelPath" ) );
				if( xPropertySetInfo->hasPropertyByName(sPropName) )
				{
					uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
					aAny >>= sRelPath;
				}
				OUString sName;
				sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("StreamName" ) );
				if( xPropertySetInfo->hasPropertyByName(sPropName) )
				{
					uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
					aAny >>= sName;
				}
				if( sBaseURI.getLength() && sName.getLength() )
				{
					if( sRelPath.getLength() )
						mpImpl->aBaseURL.insertName( sRelPath );
					mpImpl->aBaseURL.insertName( sName );
				}
                mpImpl->mStreamName = sName; // Note: may be empty (XSLT)
                // --> OD 2004-08-10 #i28749# - retrieve property <ShapePositionInHoriL2R>
                sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("ShapePositionInHoriL2R" ) );
                if( xPropertySetInfo->hasPropertyByName(sPropName) )
                {
                    uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
                    aAny >>= (mpImpl->mbShapePositionInHoriL2R);
                }
                // <--
                // --> OD 2007-12-19 #152540#
                sPropName = OUString( RTL_CONSTASCII_USTRINGPARAM("TextDocInOOoFileFormat" ) );
                if( xPropertySetInfo->hasPropertyByName(sPropName) )
                {
                    uno::Any aAny = mxImportInfo->getPropertyValue(sPropName);
                    aAny >>= (mpImpl->mbTextDocInOOoFileFormat);
                }
                // <--
            }
		}
	}
}

// XServiceInfo
OUString SAL_CALL SvXMLImport::getImplementationName()
	throw(uno::RuntimeException)
{
	OUString aStr;
	return aStr;
}

sal_Bool SAL_CALL SvXMLImport::supportsService( const OUString& rServiceName )
	throw(::com::sun::star::uno::RuntimeException)
{
    return
        rServiceName.equalsAsciiL(
            "com.sun.star.document.ImportFilter",
            sizeof("com.sun.star.document.ImportFilter")-1 ) ||
        rServiceName.equalsAsciiL(
            "com.sun.star.xml.XMLImportFilter",
            sizeof("com.sun.star.xml.XMLImportFilter")-1);
}

uno::Sequence< OUString > SAL_CALL SvXMLImport::getSupportedServiceNames(  )
	throw(uno::RuntimeException)
{
    uno::Sequence<OUString> aSeq(2);
    aSeq[0] = OUString(
        RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.ImportFilter"));
    aSeq[1] = OUString(
        RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLImportFilter"));
    return aSeq;
}

///////////////////////////////////////////////////////////////////////

XMLTextImportHelper* SvXMLImport::CreateTextImport()
{
	return new XMLTextImportHelper( mxModel, *this );
}

XMLShapeImportHelper* SvXMLImport::CreateShapeImport()
{
	return new XMLShapeImportHelper( *this, mxModel );
}

#ifndef SVX_LIGHT
SchXMLImportHelper* SvXMLImport::CreateChartImport()
{
	return new SchXMLImportHelper();
}
#endif

#ifndef SVX_LIGHT
::xmloff::OFormLayerXMLImport* SvXMLImport::CreateFormImport()
{
	return new ::xmloff::OFormLayerXMLImport(*this);
}
#endif // #ifndef SVX_LIGHT


///////////////////////////////////////////////////////////////////////////////
//
// Get or create fill/line/lineend-style-helper
//

const Reference< container::XNameContainer > & SvXMLImport::GetGradientHelper()
{
	if( !mxGradientHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxGradientHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GradientTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxGradientHelper;
}

const Reference< container::XNameContainer > & SvXMLImport::GetHatchHelper()
{
	if( !mxHatchHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxHatchHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.HatchTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxHatchHelper;
}

const Reference< container::XNameContainer > & SvXMLImport::GetBitmapHelper()
{
	if( !mxBitmapHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxBitmapHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.BitmapTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxBitmapHelper;
}

const Reference< container::XNameContainer > & SvXMLImport::GetTransGradientHelper()
{
	if( !mxTransGradientHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxTransGradientHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.TransparencyGradientTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxTransGradientHelper;
}

const Reference< container::XNameContainer > & SvXMLImport::GetMarkerHelper()
{
	if( !mxMarkerHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxMarkerHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.MarkerTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxMarkerHelper;
}

const Reference< container::XNameContainer > & SvXMLImport::GetDashHelper()
{
	if( !mxDashHelper.is() )
	{
		if( mxModel.is() )
		{
			Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY);
			if( xServiceFact.is() )
			{
				try
				{
					mxDashHelper =  Reference< container::XNameContainer >( xServiceFact->createInstance(
						OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DashTable" ) ) ), UNO_QUERY);
				}
				catch( lang::ServiceNotRegisteredException& )
				{}
			}
		}
	}

	return mxDashHelper;
}

sal_Bool SvXMLImport::IsPackageURL( const ::rtl::OUString& rURL ) const
{

	// if, and only if, only parts are imported, then we're in a package
	const sal_uInt32 nTest = IMPORT_META|IMPORT_STYLES|IMPORT_CONTENT|IMPORT_SETTINGS;
	if( (mnImportFlags & nTest) == nTest )
		return sal_False;

	// Some quick tests: Some may rely on the package structure!
	sal_Int32 nLen = rURL.getLength();
	if( (nLen > 0 && '/' == rURL[0]) )
		// RFC2396 net_path or abs_path
		return sal_False;
	else if( nLen > 1 && '.' == rURL[0] )
	{
		if( '.' == rURL[1] )
			// ../: We are never going up one level, so we know
			// it's not an external URI
			return sal_False;
		else if( '/' == rURL[1] )
			// we are remaining on a level, so it's an package URI
			return sal_True;
	}

	// Now check for a RFC2396 schema
	sal_Int32 nPos = 1;
	while( nPos < nLen )
	{
		switch( rURL[nPos] )
		{
		case '/':
			// a relative path segment
			return sal_True;
		case ':':
			// a schema
			return sal_False;
		default:
			break;
			// we don't care about any other characters
		}
		++nPos;
	}

	return sal_True;
}

::rtl::OUString SvXMLImport::ResolveGraphicObjectURL( const ::rtl::OUString& rURL,
													  sal_Bool bLoadOnDemand )
{
	::rtl::OUString sRet;

	if( IsPackageURL( rURL ) )
	{
		if( !bLoadOnDemand && mxGraphicResolver.is() )
		{
			::rtl::OUString		aTmp( msPackageProtocol );
			aTmp += rURL;
			sRet = mxGraphicResolver->resolveGraphicObjectURL( aTmp );
		}

		if( !sRet.getLength() )
		{
			sRet = msPackageProtocol;
			sRet += rURL;
		}
	}

	if( !sRet.getLength() )
		sRet = GetAbsoluteReference( rURL );

	return sRet;
}

Reference< XOutputStream > SvXMLImport::GetStreamForGraphicObjectURLFromBase64()
{
	Reference< XOutputStream > xOStm;
	Reference< document::XBinaryStreamResolver > xStmResolver( mxGraphicResolver, UNO_QUERY );

	if( xStmResolver.is() )
		xOStm = xStmResolver->createOutputStream();

	return xOStm;
}

::rtl::OUString SvXMLImport::ResolveGraphicObjectURLFromBase64(
								 const Reference < XOutputStream >& rOut )
{
	OUString sURL;
	Reference< document::XBinaryStreamResolver > xStmResolver( mxGraphicResolver, UNO_QUERY );
	if( xStmResolver.is() )
		sURL = xStmResolver->resolveOutputStream( rOut );

	return sURL;
}

::rtl::OUString SvXMLImport::ResolveEmbeddedObjectURL(
									const ::rtl::OUString& rURL,
									const ::rtl::OUString& rClassId )
{
	::rtl::OUString sRet;

	if( IsPackageURL( rURL ) )
	{
		if ( mxEmbeddedResolver.is() )
		{
			OUString sURL( rURL );
			if( rClassId.getLength() )
			{
				sURL += OUString( sal_Unicode('!') );
				sURL += rClassId;
			}
			sRet = mxEmbeddedResolver->resolveEmbeddedObjectURL( sURL );
		}
	}
	else
		sRet = GetAbsoluteReference( rURL );

	return sRet;
}

Reference < XOutputStream >
		SvXMLImport::GetStreamForEmbeddedObjectURLFromBase64()
{
	Reference < XOutputStream > xOLEStream;

	if( mxEmbeddedResolver.is() )
	{
		Reference< XNameAccess > xNA( mxEmbeddedResolver, UNO_QUERY );
		if( xNA.is() )
		{
			OUString aURL( RTL_CONSTASCII_USTRINGPARAM( "Obj12345678" ) );
			Any aAny = xNA->getByName( aURL );
			aAny >>= xOLEStream;
		}
	}

	return xOLEStream;
}

::rtl::OUString SvXMLImport::ResolveEmbeddedObjectURLFromBase64()
{
	::rtl::OUString sRet;

	if( mxEmbeddedResolver.is() )
	{
		OUString aURL( RTL_CONSTASCII_USTRINGPARAM( "Obj12345678" ) );
		sRet = mxEmbeddedResolver->resolveEmbeddedObjectURL( aURL );
	}

	return sRet;
}

void SvXMLImport::AddStyleDisplayName( sal_uInt16 nFamily,
									   const OUString& rName,
									   const OUString& rDisplayName )
{
	if( !mpStyleMap )
	{
		mpStyleMap = new StyleMap;
		mpStyleMap->acquire();
		if( mxImportInfo.is() )
		{
			OUString sPrivateData(
					RTL_CONSTASCII_USTRINGPARAM("PrivateData" ) );
			Reference< beans::XPropertySetInfo > xPropertySetInfo =
				mxImportInfo->getPropertySetInfo();
			if( xPropertySetInfo.is() &&
				xPropertySetInfo->hasPropertyByName(sPrivateData) )
			{
				Reference < XInterface > xIfc(
						static_cast< XUnoTunnel *>( mpStyleMap ) );
				Any aAny;
				aAny <<= xIfc;
				mxImportInfo->setPropertyValue( sPrivateData, aAny );
			}
		}
	}

	StyleMap::key_type aKey( nFamily, rName );
	StyleMap::value_type aValue( aKey, rDisplayName );
	::std::pair<StyleMap::iterator,bool> aRes( mpStyleMap->insert( aValue ) );
	OSL_ENSURE( aRes.second, "duplicate style name" );

}

OUString SvXMLImport::GetStyleDisplayName( sal_uInt16 nFamily,
										   const OUString& rName ) const
{
	OUString sName( rName );
	if( mpStyleMap && rName.getLength() )
	{
		StyleMap::key_type aKey( nFamily, rName );
		StyleMap::const_iterator aIter = mpStyleMap->find( aKey );
		if( aIter != mpStyleMap->end() )
			sName = (*aIter).second;
	}
	return sName;
}

void SvXMLImport::SetViewSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&)
{
}

void SvXMLImport::SetConfigurationSettings(const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&)
{
}

void SvXMLImport::SetDocumentSpecificSettings(const ::rtl::OUString& _rSettingsGroupName, const uno::Sequence<beans::PropertyValue>& _rSettings)
{
	(void)_rSettingsGroupName;
	(void)_rSettings;
}

ProgressBarHelper*	SvXMLImport::GetProgressBarHelper()
{
	if (!mpProgressBarHelper)
	{
		mpProgressBarHelper = new ProgressBarHelper(mxStatusIndicator, sal_False);

		if (mxImportInfo.is())
		{
			uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo();
			if (xPropertySetInfo.is())
			{
				OUString sProgressRange(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSRANGE));
				OUString sProgressMax(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSMAX));
				OUString sProgressCurrent(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSCURRENT));
				OUString sRepeat(RTL_CONSTASCII_USTRINGPARAM(XML_PROGRESSREPEAT));
				if (xPropertySetInfo->hasPropertyByName(sProgressMax) &&
					xPropertySetInfo->hasPropertyByName(sProgressCurrent) &&
					xPropertySetInfo->hasPropertyByName(sProgressRange))
				{
					uno::Any aAny;
					sal_Int32 nProgressMax(0);
					sal_Int32 nProgressCurrent(0);
					sal_Int32 nProgressRange(0);
					aAny = mxImportInfo->getPropertyValue(sProgressRange);
					if (aAny >>= nProgressRange)
						mpProgressBarHelper->SetRange(nProgressRange);
					aAny = mxImportInfo->getPropertyValue(sProgressMax);
					if (aAny >>= nProgressMax)
						mpProgressBarHelper->SetReference(nProgressMax);
					aAny = mxImportInfo->getPropertyValue(sProgressCurrent);
					if (aAny >>= nProgressCurrent)
						mpProgressBarHelper->SetValue(nProgressCurrent);
				}
                if (xPropertySetInfo->hasPropertyByName(sRepeat))
                {
                    uno::Any aAny = mxImportInfo->getPropertyValue(sRepeat);
                    if (aAny.getValueType() == getBooleanCppuType())
                        mpProgressBarHelper->SetRepeat(::cppu::any2bool(aAny));
                    else {
                        DBG_ERRORFILE("why is it no boolean?");
                    }
                }
			}
		}
	}
	return mpProgressBarHelper;
}

void SvXMLImport::AddNumberStyle(sal_Int32 nKey, const OUString& rName)
{
	if (!mxNumberStyles.is())
		mxNumberStyles = uno::Reference< container::XNameContainer >( comphelper::NameContainer_createInstance( ::getCppuType((const sal_Int32*)0)) );
	if (mxNumberStyles.is())
	{
		uno::Any aAny;
		aAny <<= nKey;
		try
		{
			mxNumberStyles->insertByName(rName, aAny);
		}
		catch ( uno::Exception& )
		{
			DBG_ERROR("Numberformat could not be inserted");
		}
	}
	else {
		DBG_ERROR("not possible to create NameContainer");
	}
}

XMLEventImportHelper& SvXMLImport::GetEventImport()
{
#ifndef SVX_LIGHT
	if (!mpEventImportHelper)
	{
		// construct event helper and register StarBasic handler and standard
		// event tables
		mpEventImportHelper = new XMLEventImportHelper();
		OUString sStarBasic(GetXMLToken(XML_STARBASIC));
		mpEventImportHelper->RegisterFactory(sStarBasic,
											new XMLStarBasicContextFactory());
		OUString sScript(GetXMLToken(XML_SCRIPT));
		mpEventImportHelper->RegisterFactory(sScript,
											new XMLScriptContextFactory());
		mpEventImportHelper->AddTranslationTable(aStandardEventTable);

		// register StarBasic event handler with capitalized spelling
		OUString sStarBasicCap(RTL_CONSTASCII_USTRINGPARAM("StarBasic"));
		mpEventImportHelper->RegisterFactory(sStarBasicCap,
											new XMLStarBasicContextFactory());
	}
#endif

	return *mpEventImportHelper;
}

void SvXMLImport::SetFontDecls( XMLFontStylesContext *pFontDecls )
{
	mxFontDecls = pFontDecls;
	GetTextImport()->SetFontDecls( pFontDecls );
}

void SvXMLImport::SetStyles( SvXMLStylesContext *pStyles )
{
	mxStyles = pStyles;
}

void SvXMLImport::SetAutoStyles( SvXMLStylesContext *pAutoStyles )
{
	if (pAutoStyles && mxNumberStyles.is() && (mnImportFlags & IMPORT_CONTENT) )
	{
		uno::Reference<xml::sax::XAttributeList> xAttrList;
		uno::Sequence< ::rtl::OUString > aNames = mxNumberStyles->getElementNames();
		sal_uInt32 nCount(aNames.getLength());
		if (nCount)
		{
			const OUString* pNames = aNames.getConstArray();
			if ( pNames )
			{
				SvXMLStyleContext* pContext;
				uno::Any aAny;
				sal_Int32 nKey(0);
				for (sal_uInt32 i = 0; i < nCount; i++, pNames++)
				{
					aAny = mxNumberStyles->getByName(*pNames);
					if (aAny >>= nKey)
					{
						pContext = new SvXMLNumFormatContext( *this, XML_NAMESPACE_NUMBER,
									*pNames, xAttrList, nKey, *pAutoStyles );
						pAutoStyles->AddStyle(*pContext);
					}
				}
			}
		}
	}
	mxAutoStyles = pAutoStyles;
	GetTextImport()->SetAutoStyles( pAutoStyles );
	GetShapeImport()->SetAutoStylesContext( pAutoStyles );
#ifndef SVX_LIGHT
	GetChartImport()->SetAutoStylesContext( pAutoStyles );
	GetFormImport()->setAutoStyleContext( pAutoStyles );
#endif
}

void SvXMLImport::SetMasterStyles( SvXMLStylesContext *pMasterStyles )
{
	mxMasterStyles = pMasterStyles;
}

XMLFontStylesContext *SvXMLImport::GetFontDecls()
{
	return (XMLFontStylesContext *)&mxFontDecls;
}

SvXMLStylesContext *SvXMLImport::GetStyles()
{
	return (SvXMLStylesContext *)&mxStyles;
}

SvXMLStylesContext *SvXMLImport::GetAutoStyles()
{
	return (SvXMLStylesContext *)&mxAutoStyles;
}

SvXMLStylesContext *SvXMLImport::GetMasterStyles()
{
	return (SvXMLStylesContext *)&mxMasterStyles;
}

const XMLFontStylesContext *SvXMLImport::GetFontDecls() const
{
	return (const XMLFontStylesContext *)&mxFontDecls;
}

const SvXMLStylesContext *SvXMLImport::GetStyles() const
{
	return (const SvXMLStylesContext *)&mxStyles;
}

const SvXMLStylesContext *SvXMLImport::GetAutoStyles() const
{
	return (const SvXMLStylesContext *)&mxAutoStyles;
}

const SvXMLStylesContext *SvXMLImport::GetMasterStyles() const
{
	return (const SvXMLStylesContext *)&mxMasterStyles;
}

OUString SvXMLImport::GetAbsoluteReference(const OUString& rValue) const
{
	if( rValue.getLength() == 0 || rValue[0] == '#' )
		return rValue;

	INetURLObject aAbsURL;
	if( mpImpl->aBaseURL.GetNewAbsURL( rValue, &aAbsURL ) )
		return aAbsURL.GetMainURL( INetURLObject::DECODE_TO_IURI );
	else
		return rValue;
}

sal_Bool SvXMLImport::IsODFVersionConsistent( const ::rtl::OUString& aODFVersion )
{
	// the check returns sal_False only if the storage version could be retrieved
	sal_Bool bResult = sal_True;

    if ( aODFVersion.getLength() && aODFVersion.compareTo( ODFVER_012_TEXT ) >= 0 )
    {
        // check the consistency only for the ODF1.2 and later ( according to content.xml )
        // manifest.xml might have no version, it should be checked here and the correct version should be set
        try
        {
            uno::Reference< document::XStorageBasedDocument > xDoc( mxModel, uno::UNO_QUERY_THROW );
            uno::Reference< embed::XStorage > xStor = xDoc->getDocumentStorage();
            uno::Reference< beans::XPropertySet > xStorProps( xStor, uno::UNO_QUERY_THROW );

            // the check should be done only for OASIS format
            ::rtl::OUString aMediaType;
            xStorProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) ) >>= aMediaType;
            if ( ::comphelper::OStorageHelper::GetXStorageFormat( xStor ) >= SOFFICE_FILEFORMAT_8 )
            {
                sal_Bool bRepairPackage = sal_False;
                try
                {
                    xStorProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RepairPackage" ) ) )
                        >>= bRepairPackage;
                } catch ( uno::Exception& )
                {}

                // check only if not in Repair mode
                if ( !bRepairPackage )
                {
                    ::rtl::OUString aStorVersion;
                    xStorProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) )
                        >>= aStorVersion;

                    // if the storage version is set in manifest.xml, it must be the same as in content.xml
                    // if not, set it explicitly to be used further ( it will work even for readonly storage )
                    // This workaround is not nice, but I see no other way to handle it, since there are
                    // ODF1.2 documents without version in manifest.xml
                    if ( aStorVersion.getLength() )
                        bResult = aODFVersion.equals( aStorVersion );
                    else
                        xStorProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ),
                                                      uno::makeAny( aODFVersion ) );

                    if ( bResult )
                    {
                        sal_Bool bInconsistent = sal_False;
                        xStorProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsInconsistent" ) ) )
                            >>= bInconsistent;
                        bResult = !bInconsistent;
                    }
                }
            }
        }
        catch( uno::Exception& )
        {}
    }

    return bResult;
}

void SvXMLImport::_CreateNumberFormatsSupplier()
{
    DBG_ASSERT( !mxNumberFormatsSupplier.is(),
                "number formats supplier already exists!" );
    if(mxModel.is())
    	mxNumberFormatsSupplier =
        	uno::Reference< util::XNumberFormatsSupplier> (mxModel, uno::UNO_QUERY);
}


void SvXMLImport::_CreateDataStylesImport()
{
    DBG_ASSERT( mpNumImport == NULL, "data styles import already exists!" );
    uno::Reference<util::XNumberFormatsSupplier> xNum =
        GetNumberFormatsSupplier();
    if ( xNum.is() )
        mpNumImport = new SvXMLNumFmtHelper(xNum, getServiceFactory());
}


sal_Unicode SvXMLImport::ConvStarBatsCharToStarSymbol( sal_Unicode c )
{
	sal_Unicode cNew = c;
	if( !mpImpl->hBatsFontConv )
	{
		OUString sStarBats( RTL_CONSTASCII_USTRINGPARAM( "StarBats" ) );
		mpImpl->hBatsFontConv = CreateFontToSubsFontConverter( sStarBats,
				 FONTTOSUBSFONT_IMPORT|FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
		OSL_ENSURE( mpImpl->hBatsFontConv, "Got no symbol font converter" );
	}
	if( mpImpl->hBatsFontConv )
	{
		cNew = ConvertFontToSubsFontChar( mpImpl->hBatsFontConv, c );
	}

	return cNew;
}

sal_Unicode SvXMLImport::ConvStarMathCharToStarSymbol( sal_Unicode c )
{
	sal_Unicode cNew = c;
	if( !mpImpl->hMathFontConv )
	{
		OUString sStarMath( RTL_CONSTASCII_USTRINGPARAM( "StarMath" ) );
		mpImpl->hMathFontConv = CreateFontToSubsFontConverter( sStarMath,
				 FONTTOSUBSFONT_IMPORT|FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
		OSL_ENSURE( mpImpl->hMathFontConv, "Got no symbol font converter" );
	}
	if( mpImpl->hMathFontConv )
	{
		cNew = ConvertFontToSubsFontChar( mpImpl->hMathFontConv, c );
	}

	return cNew;
}



void SvXMLImport::SetError(
	sal_Int32 nId,
	const Sequence<OUString>& rMsgParams,
	const OUString& rExceptionMessage,
	const Reference<xml::sax::XLocator>& rLocator )
{
    // maintain error flags
    if ( ( nId & XMLERROR_FLAG_ERROR ) != 0 )
        mnErrorFlags |= ERROR_ERROR_OCCURED;
    if ( ( nId & XMLERROR_FLAG_WARNING ) != 0 )
        mnErrorFlags |= ERROR_WARNING_OCCURED;
    if ( ( nId & XMLERROR_FLAG_SEVERE ) != 0 )
        mnErrorFlags |= ERROR_DO_NOTHING;

    // create error list on demand
    if ( mpXMLErrors == NULL )
        mpXMLErrors = new XMLErrors();

    // save error information
    // use document locator (if none supplied)
    mpXMLErrors->AddRecord( nId, rMsgParams, rExceptionMessage,
                           rLocator.is() ? rLocator : mxLocator );
}

void SvXMLImport::SetError(
    sal_Int32 nId,
    const Sequence<OUString>& rMsgParams)
{
    OUString sEmpty;
    SetError( nId, rMsgParams, sEmpty, NULL );
}

void SvXMLImport::SetError(
    sal_Int32 nId)
{
    Sequence<OUString> aSeq(0);
    SetError( nId, aSeq );
}

void SvXMLImport::SetError(
    sal_Int32 nId,
    const OUString& rMsg1)
{
    Sequence<OUString> aSeq(1);
    OUString* pSeq = aSeq.getArray();
    pSeq[0] = rMsg1;
    SetError( nId, aSeq );
}

void SvXMLImport::SetError(
    sal_Int32 nId,
    const OUString& rMsg1,
    const OUString& rMsg2)
{
    Sequence<OUString> aSeq(2);
    OUString* pSeq = aSeq.getArray();
    pSeq[0] = rMsg1;
    pSeq[1] = rMsg2;
    SetError( nId, aSeq );
}

void SvXMLImport::SetError(
    sal_Int32 nId,
    const OUString& rMsg1,
    const OUString& rMsg2,
    const OUString& rMsg3)
{
    Sequence<OUString> aSeq(3);
    OUString* pSeq = aSeq.getArray();
    pSeq[0] = rMsg1;
    pSeq[1] = rMsg2;
    pSeq[2] = rMsg3;
    SetError( nId, aSeq );
}

void SvXMLImport::SetError(
    sal_Int32 nId,
    const OUString& rMsg1,
    const OUString& rMsg2,
    const OUString& rMsg3,
    const OUString& rMsg4)
{
    Sequence<OUString> aSeq(4);
    OUString* pSeq = aSeq.getArray();
    pSeq[0] = rMsg1;
    pSeq[1] = rMsg2;
    pSeq[2] = rMsg3;
    pSeq[3] = rMsg4;
    SetError( nId, aSeq );
}

XMLErrors* SvXMLImport::GetErrors()
{
	return mpXMLErrors;
}

void SvXMLImport::DisposingModel()
{
	if( mxFontDecls.Is() )
		((SvXMLStylesContext *)&mxFontDecls)->Clear();
	if( mxStyles.Is() )
		((SvXMLStylesContext *)&mxStyles)->Clear();
	if( mxAutoStyles.Is() )
		((SvXMLStylesContext *)&mxAutoStyles)->Clear();
	if( mxMasterStyles.Is() )
		((SvXMLStylesContext *)&mxMasterStyles)->Clear();

	mxModel.set(0);
	mxEventListener.set(NULL);
}

::comphelper::UnoInterfaceToUniqueIdentifierMapper& SvXMLImport::getInterfaceToIdentifierMapper()
{
	return mpImpl->maInterfaceToIdentifierMapper;
}

::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > SvXMLImport::getServiceFactory()
{
	// #110680#
	return mxServiceFactory;
}

uno::Reference< uno::XComponentContext >
SvXMLImport::GetComponentContext() const
{
	return mpImpl->mxComponentContext;
}

String SvXMLImport::GetBaseURL() const
{
	return mpImpl->aBaseURL.GetMainURL( INetURLObject::NO_DECODE );
}

String SvXMLImport::GetDocumentBase() const
{
	return mpImpl->aDocBase.GetMainURL( INetURLObject::NO_DECODE );
}

::rtl::OUString SvXMLImport::GetStreamName() const
{
	return mpImpl->mStreamName;
}

// --> OD 2004-08-10 #i28749#
sal_Bool SvXMLImport::IsShapePositionInHoriL2R() const
{
	return mpImpl->mbShapePositionInHoriL2R;
}
// <--

// --> OD 2007-12-19 #152540#
sal_Bool SvXMLImport::IsTextDocInOOoFileFormat() const
{
	return mpImpl->mbTextDocInOOoFileFormat;
}

// <--

void SvXMLImport::initXForms()
{
	// dummy method; to be implemented by derived classes supporting XForms
}

bool SvXMLImport::getBuildIds( sal_Int32& rUPD, sal_Int32& rBuild ) const
{
	bool bRet = false;
	if( mxImportInfo.is() ) try
	{
		const OUString aPropName(RTL_CONSTASCII_USTRINGPARAM("BuildId"));
		Reference< XPropertySetInfo > xSetInfo( mxImportInfo->getPropertySetInfo() );
		if( xSetInfo.is() && xSetInfo->hasPropertyByName( aPropName ) )
		{
			OUString aBuildId;
			mxImportInfo->getPropertyValue( aPropName ) >>= aBuildId;
			if( aBuildId.getLength() )
			{
				sal_Int32 nIndex = aBuildId.indexOf('$');
				if( nIndex != -1 )
				{
					rUPD = aBuildId.copy( 0, nIndex ).toInt32();
					rBuild = aBuildId.copy( nIndex+1 ).toInt32();
					bRet = true;
				}
			}
		}
	}
	catch( Exception& )
	{
	}
	return bRet;
}

sal_uInt16 SvXMLImport::getGeneratorVersion() const
{
	// --> ORW
	return mpImpl->getGeneratorVersion( *this );
	// <--
}

bool SvXMLImport::isGraphicLoadOnDemandSupported() const
{
	return mbIsGraphicLoadOnDemandSupported;
}

::rtl::OUString SvXMLImport::GetODFVersion() const
{
	return mpImpl->aODFVersion;
}

// xml:id for RDF metadata
void SvXMLImport::SetXmlId(uno::Reference<uno::XInterface> const & i_xIfc,
    ::rtl::OUString const & i_rXmlId)
{
    if (i_rXmlId.getLength() > 0) {
        try {
            const uno::Reference<rdf::XMetadatable> xMeta(i_xIfc,
                uno::UNO_QUERY);
//FIXME: not yet
//            OSL_ENSURE(xMeta.is(), "xml:id: not XMetadatable");
            if (xMeta.is()) {
                const beans::StringPair mdref( GetStreamName(), i_rXmlId );
                try {
                    xMeta->setMetadataReference(mdref);
                } catch (lang::IllegalArgumentException &) {
                    // probably duplicate; ignore
                    OSL_TRACE("SvXMLImport::SetXmlId: cannot set xml:id");
                }
            }
        } catch (uno::Exception &) {
            OSL_ENSURE(false, "SvXMLImport::SetXmlId: exception?");
        }
    }
}

SAL_DLLPRIVATE ::xmloff::RDFaImportHelper &
SvXMLImport::GetRDFaImportHelper()
{
	if (!mpImpl->mpRDFaHelper.get())
	{
		mpImpl->mpRDFaHelper.reset( new ::xmloff::RDFaImportHelper(*this) );
	}
	return *mpImpl->mpRDFaHelper;
}

void
SvXMLImport::AddRDFa(uno::Reference<rdf::XMetadatable> i_xObject,
	::rtl::OUString const & i_rAbout,
	::rtl::OUString const & i_rProperty,
	::rtl::OUString const & i_rContent,
	::rtl::OUString const & i_rDatatype)
{
    // N.B.: we only get called if i_xObject had xhtml:about attribute
    // (an empty attribute value is valid)
    ::xmloff::RDFaImportHelper & rRDFaHelper( GetRDFaImportHelper() );
    rRDFaHelper.ParseAndAddRDFa(i_xObject,
        i_rAbout, i_rProperty, i_rContent, i_rDatatype);
}

/* vim: set noet sw=4 ts=4: */
