/**************************************************************
 * 
 * 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/util/XStringSubstitution.hpp>
#include <xmloff/DocumentSettingsContext.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmluconv.hxx>
#include <tools/debug.hxx>

#ifndef __SGI_STL_LIST
#include <list>
#endif
#include <com/sun/star/i18n/XForbiddenCharacters.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/formula/SymbolDescriptor.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/document/XViewDataSupplier.hpp>
#include <com/sun/star/document/PrinterIndependentLayout.hpp>
#include <comphelper/configurationhelper.hxx>
#include <rtl/ustrbuf.hxx>
#include <xmlenums.hxx>

using namespace com::sun::star;
using namespace ::xmloff::token;

#define C2U(cChar) ::rtl::OUString::createFromAscii(cChar)

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

class XMLMyList
{
	std::list<beans::PropertyValue>	aProps;
	sal_uInt32						nCount;

	// #110680#
	::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceFactory;

public:
	// #110680#
	XMLMyList(const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory);
	~XMLMyList();

	void push_back(beans::PropertyValue& aProp) { aProps.push_back(aProp); nCount++; }
	uno::Sequence<beans::PropertyValue> GetSequence();
	uno::Reference<container::XNameContainer> GetNameContainer();
	uno::Reference<container::XIndexContainer> GetIndexContainer();
};

// #110680#
XMLMyList::XMLMyList(const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory)
:	nCount(0),
	mxServiceFactory(xServiceFactory)
{
	DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
}

// #110680#
XMLMyList::~XMLMyList()
{
}

uno::Sequence<beans::PropertyValue> XMLMyList::GetSequence()
{
	uno::Sequence<beans::PropertyValue> aSeq;
	if(nCount)
	{
		DBG_ASSERT(nCount == aProps.size(), "wrong count of PropertyValue");
		aSeq.realloc(nCount);
		beans::PropertyValue* pProps = aSeq.getArray();
		std::list<beans::PropertyValue>::iterator aItr = aProps.begin();
		while (aItr != aProps.end())
		{
			*pProps = *aItr;
			pProps++;
			aItr++;
		}
	}
	return aSeq;
}

uno::Reference<container::XNameContainer> XMLMyList::GetNameContainer()
{
	uno::Reference<container::XNameContainer> xNameContainer;

	// #110680#
	// uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory();
	// DBG_ASSERT( xServiceFactory.is(), "got no service manager" );

	if( mxServiceFactory.is() )
	{
		rtl::OUString sName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.NamedPropertyValues"));
		xNameContainer = uno::Reference<container::XNameContainer>(mxServiceFactory->createInstance(sName), uno::UNO_QUERY);
		if (xNameContainer.is())
		{
			std::list<beans::PropertyValue>::iterator aItr = aProps.begin();
			while (aItr != aProps.end())
			{
				xNameContainer->insertByName(aItr->Name, aItr->Value);
				aItr++;
			}
		}
	}
	return xNameContainer;
}

uno::Reference<container::XIndexContainer> XMLMyList::GetIndexContainer()
{
	uno::Reference<container::XIndexContainer> xIndexContainer;
	// #110680#
	// uno::Reference<lang::XMultiServiceFactory> xServiceFactory = comphelper::getProcessServiceFactory();
	// DBG_ASSERT( xServiceFactory.is(), "got no service manager" );

	if( mxServiceFactory.is() )
	{
		rtl::OUString sName(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.IndexedPropertyValues"));
		xIndexContainer = uno::Reference<container::XIndexContainer>(mxServiceFactory->createInstance(sName), uno::UNO_QUERY);
		if (xIndexContainer.is())
		{
			std::list<beans::PropertyValue>::iterator aItr = aProps.begin();
			sal_uInt32 i(0);
			while (aItr != aProps.end())
			{
				xIndexContainer->insertByIndex(i, aItr->Value);
				aItr++;
				i++;
			}
		}
	}
	return xIndexContainer;
}

//=============================================================================

class XMLConfigBaseContext : public SvXMLImportContext
{
protected:
	XMLMyList					maProps;
	beans::PropertyValue		maProp;
	com::sun::star::uno::Any&	mrAny;
	XMLConfigBaseContext*		mpBaseContext;
public:
	XMLConfigBaseContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									com::sun::star::uno::Any& rAny,
									XMLConfigBaseContext* pBaseContext);
	virtual ~XMLConfigBaseContext();

	void AddPropertyValue() { maProps.push_back(maProp); }
};

//=============================================================================

class XMLConfigItemContext : public SvXMLImportContext
{
	rtl::OUString				msType;
	rtl::OUString				msValue;
	uno::Sequence<sal_Int8>		maDecoded;
	com::sun::star::uno::Any&	mrAny;
    const rtl::OUString         mrItemName;
	XMLConfigBaseContext*		mpBaseContext;

public:
	XMLConfigItemContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>& xAttrList,
									com::sun::star::uno::Any& rAny,
                                    const rtl::OUString& rItemName,
									XMLConfigBaseContext* pBaseContext);
	virtual ~XMLConfigItemContext();

	virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
													const rtl::OUString& rLocalName,
													const ::com::sun::star::uno::Reference<
									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList );
	virtual void Characters( const ::rtl::OUString& rChars );

	virtual void EndElement();

    virtual void ManipulateConfigItem();
};

//=============================================================================

class XMLConfigItemSetContext : public XMLConfigBaseContext
{
public:
	XMLConfigItemSetContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>& xAttrList,
									com::sun::star::uno::Any& rAny,
									XMLConfigBaseContext* pBaseContext);
	virtual ~XMLConfigItemSetContext();

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

	virtual void EndElement();
};

//=============================================================================

class XMLConfigItemMapNamedContext : public XMLConfigBaseContext
{
public:
	XMLConfigItemMapNamedContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>& xAttrList,
									com::sun::star::uno::Any& rAny,
									XMLConfigBaseContext* pBaseContext);
	virtual ~XMLConfigItemMapNamedContext();

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

	virtual void EndElement();
};

//=============================================================================

class XMLConfigItemMapIndexedContext : public XMLConfigBaseContext
{
private:
	rtl::OUString maConfigItemName;

public:
	XMLConfigItemMapIndexedContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
									const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>& xAttrList,
									com::sun::star::uno::Any& rAny,
									const rtl::OUString& rConfigItemName,
									XMLConfigBaseContext* pBaseContext);
	virtual ~XMLConfigItemMapIndexedContext();

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

	virtual void EndElement();
};

//=============================================================================

SvXMLImportContext *CreateSettingsContext(SvXMLImport& rImport, sal_uInt16 p_nPrefix,
						const rtl::OUString& rLocalName,
						const uno::Reference<xml::sax::XAttributeList>& xAttrList,
						beans::PropertyValue& rProp, XMLConfigBaseContext* pBaseContext)
{
	SvXMLImportContext *pContext = 0;

	rProp.Name = rtl::OUString();
	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
		rtl::OUString aLocalName;
		sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
											sAttrName, &aLocalName );
		rtl::OUString sValue = xAttrList->getValueByIndex( i );

		if (nPrefix == XML_NAMESPACE_CONFIG)
		{
			if (IsXMLToken(aLocalName, XML_NAME))
				rProp.Name = sValue;
		}
	}

	if (p_nPrefix == XML_NAMESPACE_CONFIG)
	{
		if (IsXMLToken(rLocalName, XML_CONFIG_ITEM))
			pContext = new XMLConfigItemContext(rImport, p_nPrefix, rLocalName, xAttrList, rProp.Value, rProp.Name, pBaseContext);
		else if((IsXMLToken(rLocalName, XML_CONFIG_ITEM_SET)) ||
				(IsXMLToken(rLocalName, XML_CONFIG_ITEM_MAP_ENTRY)) )
			pContext = new XMLConfigItemSetContext(rImport, p_nPrefix, rLocalName, xAttrList, rProp.Value, pBaseContext);
		else if(IsXMLToken(rLocalName, XML_CONFIG_ITEM_MAP_NAMED))
			pContext = new XMLConfigItemMapNamedContext(rImport, p_nPrefix, rLocalName, xAttrList, rProp.Value, pBaseContext);
		else if(IsXMLToken(rLocalName, XML_CONFIG_ITEM_MAP_INDEXED))
			pContext = new XMLConfigItemMapIndexedContext(rImport, p_nPrefix, rLocalName, xAttrList, rProp.Value, rProp.Name, pBaseContext);
	}

	if( !pContext )
		pContext = new SvXMLImportContext( rImport, p_nPrefix, rLocalName );

	return pContext;
}

//=============================================================================
namespace
{
    struct SettingsGroup
    {
        ::rtl::OUString sGroupName;
        uno::Any        aSettings;

        SettingsGroup()
            :sGroupName()
            ,aSettings()
        {
        }

        SettingsGroup( const ::rtl::OUString& _rGroupName, const uno::Any& _rSettings )
            :sGroupName( _rGroupName )
            ,aSettings( _rSettings )
        {
        }
    };
}

struct XMLDocumentSettingsContext_Data
{
	com::sun::star::uno::Any	    aViewProps;
	com::sun::star::uno::Any	    aConfigProps;
    ::std::list< SettingsGroup >    aDocSpecificSettings;
};

//=============================================================================

XMLDocumentSettingsContext::XMLDocumentSettingsContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
					const uno::Reference<xml::sax::XAttributeList>& )
	: SvXMLImportContext( rImport, nPrfx, rLName )
    , m_pData( new XMLDocumentSettingsContext_Data )
{
	// here are no attributes
}

XMLDocumentSettingsContext::~XMLDocumentSettingsContext()
{
}

SvXMLImportContext *XMLDocumentSettingsContext::CreateChildContext( sal_uInt16 p_nPrefix,
									 const rtl::OUString& rLocalName,
									 const ::com::sun::star::uno::Reference<
									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
	SvXMLImportContext *pContext = 0;
	rtl::OUString sName;

	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
		rtl::OUString aLocalName;
		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName(
											sAttrName, &aLocalName );
		rtl::OUString sValue = xAttrList->getValueByIndex( i );

		if (nPrefix == XML_NAMESPACE_CONFIG)
		{
			if (IsXMLToken(aLocalName, XML_NAME))
				sName = sValue;
		}
	}

	if (p_nPrefix == XML_NAMESPACE_CONFIG)
	{
		if (IsXMLToken(rLocalName, XML_CONFIG_ITEM_SET))
		{
			::rtl::OUString aLocalConfigName;
			sal_uInt16 nConfigPrefix =
				GetImport().GetNamespaceMap().GetKeyByAttrName(
											sName, &aLocalConfigName );

			if( XML_NAMESPACE_OOO == nConfigPrefix )
			{
				if (IsXMLToken(aLocalConfigName, XML_VIEW_SETTINGS))
					pContext = new XMLConfigItemSetContext(GetImport(),
										p_nPrefix, rLocalName, xAttrList,
										m_pData->aViewProps, NULL);
				else if (IsXMLToken(aLocalConfigName,
												XML_CONFIGURATION_SETTINGS))
					pContext = new XMLConfigItemSetContext(GetImport(),
										p_nPrefix, rLocalName, xAttrList,
										m_pData->aConfigProps, NULL);
                else
                {
                    m_pData->aDocSpecificSettings.push_back( SettingsGroup( aLocalConfigName, uno::Any() ) );

                    ::std::list< SettingsGroup >::reverse_iterator settingsPos =
                        m_pData->aDocSpecificSettings.rbegin();

                    pContext = new XMLConfigItemSetContext(GetImport(),
										p_nPrefix, rLocalName, xAttrList,
										settingsPos->aSettings, NULL);
                }
			}
		}
	}

	if( !pContext )
		pContext = new SvXMLImportContext( GetImport(), p_nPrefix, rLocalName );

	return pContext;
}

void XMLDocumentSettingsContext::EndElement()
{
	uno::Sequence<beans::PropertyValue> aSeqViewProps;
	if (m_pData->aViewProps >>= aSeqViewProps)
	{
		GetImport().SetViewSettings(aSeqViewProps);
		sal_Int32 i(aSeqViewProps.getLength() - 1);
		sal_Bool bFound(sal_False);
		while((i >= 0) && !bFound)
		{
			if (aSeqViewProps[i].Name.compareToAscii("Views") == 0)
			{
				bFound = sal_True;
				uno::Reference<container::XIndexAccess> xIndexAccess;
				if (aSeqViewProps[i].Value >>= xIndexAccess)
				{
					uno::Reference<document::XViewDataSupplier> xViewDataSupplier(GetImport().GetModel(), uno::UNO_QUERY);
					if (xViewDataSupplier.is())
						xViewDataSupplier->setViewData(xIndexAccess);
				}
			}
			else
				i--;
		}
	}

    sal_Bool bLoadDocPrinter( sal_True );
    ::comphelper::ConfigurationHelper::readDirectKey(
        ::comphelper::getProcessServiceFactory(),
        C2U("org.openoffice.Office.Common/"), C2U("Save/Document"), C2U("LoadPrinter"),
        ::comphelper::ConfigurationHelper::E_READONLY ) >>= bLoadDocPrinter;
    uno::Sequence<beans::PropertyValue> aSeqConfigProps;
    if ( m_pData->aConfigProps >>= aSeqConfigProps )
    {
        if ( !bLoadDocPrinter )
        {
            sal_Int32 i = aSeqConfigProps.getLength() - 1;
            int nFound = 0;

            while ( ( i >= 0 ) && nFound < 2 )
            {
                rtl::OUString sProp( aSeqConfigProps[i].Name );

                if ( sProp.compareToAscii("PrinterName") == 0 )
                {
                    rtl::OUString sEmpty;
                    aSeqConfigProps[i].Value = uno::makeAny( sEmpty );
                    nFound++;
                }
                else if ( sProp.compareToAscii("PrinterSetup") == 0 )
                {
                    uno::Sequence< sal_Int8 > aEmpty;
                    aSeqConfigProps[i].Value = uno::makeAny( aEmpty );
                    nFound++;
                }

                i--;
            }
        }

        GetImport().SetConfigurationSettings( aSeqConfigProps );
    }

    for (   ::std::list< SettingsGroup >::const_iterator settings = m_pData->aDocSpecificSettings.begin();
            settings != m_pData->aDocSpecificSettings.end();
            ++settings
        )
    {
        uno::Sequence< beans::PropertyValue > aDocSettings;
        OSL_VERIFY( settings->aSettings >>= aDocSettings );
        GetImport().SetDocumentSpecificSettings( settings->sGroupName, aDocSettings );
    }
}

//=============================================================================

XMLConfigBaseContext::XMLConfigBaseContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
		const rtl::OUString& rLName, com::sun::star::uno::Any& rTempAny,
		XMLConfigBaseContext* pTempBaseContext)
	: SvXMLImportContext( rImport, nPrfx, rLName ),
	// #110680#
	maProps(rImport.getServiceFactory()),
	maProp(),
	mrAny(rTempAny),
	mpBaseContext(pTempBaseContext)
{
}

XMLConfigBaseContext::~XMLConfigBaseContext()
{
}

//=============================================================================

XMLConfigItemSetContext::XMLConfigItemSetContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
									const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>&,
									com::sun::star::uno::Any& rAny,
									XMLConfigBaseContext* pBaseContext)
	: XMLConfigBaseContext( rImport, nPrfx, rLName, rAny, pBaseContext )
{
	// here are no attributes
}

XMLConfigItemSetContext::~XMLConfigItemSetContext()
{
}

SvXMLImportContext *XMLConfigItemSetContext::CreateChildContext( sal_uInt16 nPrefix,
									 const rtl::OUString& rLocalName,
									 const ::com::sun::star::uno::Reference<
									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
	return CreateSettingsContext(GetImport(), nPrefix, rLocalName, xAttrList, maProp, this);
}

void XMLConfigItemSetContext::EndElement()
{
	mrAny <<= maProps.GetSequence();
	if (mpBaseContext)
		mpBaseContext->AddPropertyValue();
}

//=============================================================================

XMLConfigItemContext::XMLConfigItemContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>& xAttrList,
									com::sun::star::uno::Any& rTempAny,
                                    const rtl::OUString& rTempItemName,
									XMLConfigBaseContext* pTempBaseContext)
	: SvXMLImportContext(rImport, nPrfx, rLName),
	mrAny(rTempAny),
    mrItemName(rTempItemName),
	mpBaseContext(pTempBaseContext)
{
	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
	for( sal_Int16 i=0; i < nAttrCount; i++ )
	{
		rtl::OUString sAttrName = xAttrList->getNameByIndex( i );
		rtl::OUString aLocalName;
		sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName(
											sAttrName, &aLocalName );
		rtl::OUString sValue = xAttrList->getValueByIndex( i );

		if (nPrefix == XML_NAMESPACE_CONFIG)
		{
			if (IsXMLToken(aLocalName, XML_TYPE))
				msType = sValue;
		}
	}
}

XMLConfigItemContext::~XMLConfigItemContext()
{
}

SvXMLImportContext *XMLConfigItemContext::CreateChildContext( sal_uInt16 nPrefix,
													const rtl::OUString& rLocalName,
													const ::com::sun::star::uno::Reference<
									  	::com::sun::star::xml::sax::XAttributeList>& )
{
	SvXMLImportContext* pContext = new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
	return pContext;
}

void XMLConfigItemContext::Characters( const ::rtl::OUString& rChars )
{
	if (IsXMLToken(msType, XML_BASE64BINARY))
	{
		rtl::OUString sTrimmedChars( rChars.trim() );
		if( sTrimmedChars.getLength() )
		{
			rtl::OUString sChars;
			if( msValue )
			{
				sChars = msValue;
				sChars += sTrimmedChars;
				msValue = rtl::OUString();
			}
			else
			{
				sChars = sTrimmedChars;
			}
			uno::Sequence<sal_Int8> aBuffer((sChars.getLength() / 4) * 3 );
			sal_Int32 nCharsDecoded =
				GetImport().GetMM100UnitConverter().
					decodeBase64SomeChars( aBuffer, sChars );
			sal_uInt32 nStartPos(maDecoded.getLength());
			sal_uInt32 nCount(aBuffer.getLength());
			maDecoded.realloc(nStartPos + nCount);
			sal_Int8* pDecoded = maDecoded.getArray();
			sal_Int8* pBuffer = aBuffer.getArray();
			for (sal_uInt32 i = 0; i < nCount; i++, pBuffer++)
				pDecoded[nStartPos + i] = *pBuffer;
			if( nCharsDecoded != sChars.getLength() )
				msValue = sChars.copy( nCharsDecoded );
		}
	}
	else
		msValue += rChars;
}


void XMLConfigItemContext::EndElement()
{
	if (mpBaseContext)
	{
		if (IsXMLToken(msType, XML_BOOLEAN))
		{
			sal_Bool bValue(sal_False);
			if (IsXMLToken(msValue, XML_TRUE))
				bValue = sal_True;
			mrAny <<= bValue;
		}
		else if (IsXMLToken(msType, XML_BYTE))
		{
			sal_Int32 nValue(0);
			SvXMLUnitConverter::convertNumber(nValue, msValue);
			mrAny <<= static_cast<sal_Int8>(nValue);
		}
		else if (IsXMLToken(msType, XML_SHORT))
		{
			sal_Int32 nValue(0);
			SvXMLUnitConverter::convertNumber(nValue, msValue);
			mrAny <<= static_cast<sal_Int16>(nValue);
		}
		else if (IsXMLToken(msType, XML_INT))
		{
			sal_Int32 nValue(0);
			SvXMLUnitConverter::convertNumber(nValue, msValue);
			mrAny <<= nValue;
		}
		else if (IsXMLToken(msType, XML_LONG))
		{
			sal_Int64 nValue(msValue.toInt64());
			mrAny <<= nValue;
		}
		else if (IsXMLToken(msType, XML_DOUBLE))
		{
			double fValue(0.0);
			SvXMLUnitConverter::convertDouble(fValue, msValue);
			mrAny <<= fValue;
		}
		else if (IsXMLToken(msType, XML_STRING))
		{
			mrAny <<= msValue;
		}
		else if (IsXMLToken(msType, XML_DATETIME))
		{
			util::DateTime aDateTime;
			SvXMLUnitConverter::convertDateTime(aDateTime, msValue);
			mrAny <<= aDateTime;
		}
		else if (IsXMLToken(msType, XML_BASE64BINARY))
		{
			mrAny <<= maDecoded;
		}
		else {
			DBG_ERROR("wrong type");
        }

        ManipulateConfigItem();

		mpBaseContext->AddPropertyValue();
	}
	else {
		DBG_ERROR("no BaseContext");
    }
}

/** There are some instances where there is a mismatch between API and
 * XML mapping of a setting. In this case, this method allows us to
 * manipulate the values accordingly. */
void XMLConfigItemContext::ManipulateConfigItem()
{
    if( mrItemName.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM( "PrinterIndependentLayout" ) ) )
    {
        rtl::OUString sValue;
        mrAny >>= sValue;

        sal_Int16 nTmp = document::PrinterIndependentLayout::HIGH_RESOLUTION;

        if( sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("enabled")) ||
            sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("low-resolution")) )
        {
            nTmp = document::PrinterIndependentLayout::LOW_RESOLUTION;
        }
        else if( sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("disabled")) )
        {
            nTmp = document::PrinterIndependentLayout::DISABLED;
        }
        // else: default to high_resolution

        mrAny <<= nTmp;
    }
	else if( (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ColorTableURL" ) ) ) ||
			 (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "LineEndTableURL" ) ) ) ||
			 (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "HatchTableURL" ) ) ) ||
			 (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DashTableURL" ) ) ) ||
			 (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GradientTableURL") ) ) ||
			 (mrItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BitmapTableURL" ) ) ) )
	{
		if( GetImport().getServiceFactory().is() ) try
		{
			uno::Reference< util::XStringSubstitution > xStringSubsitution(
				GetImport().getServiceFactory()->
					createInstance(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.PathSubstitution" ) ) ), uno::UNO_QUERY );

			if( xStringSubsitution.is() )
			{
				rtl::OUString aURL;
				mrAny >>= aURL;
				aURL = xStringSubsitution->substituteVariables( aURL, sal_False );
				mrAny <<= aURL;
			}
		}
		catch( uno::Exception& )
		{
		}
	}
}


//=============================================================================

XMLConfigItemMapNamedContext::XMLConfigItemMapNamedContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>&,
									com::sun::star::uno::Any& rAny,
									XMLConfigBaseContext* pBaseContext)
	: XMLConfigBaseContext(rImport, nPrfx, rLName, rAny, pBaseContext)
{
}

XMLConfigItemMapNamedContext::~XMLConfigItemMapNamedContext()
{
}

SvXMLImportContext *XMLConfigItemMapNamedContext::CreateChildContext( sal_uInt16 nPrefix,
													const rtl::OUString& rLocalName,
													const ::com::sun::star::uno::Reference<
									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
	return CreateSettingsContext(GetImport(), nPrefix, rLocalName, xAttrList, maProp, this);
}

void XMLConfigItemMapNamedContext::EndElement()
{
	if (mpBaseContext)
	{
		mrAny <<= maProps.GetNameContainer();
		mpBaseContext->AddPropertyValue();
	}
	else {
		DBG_ERROR("no BaseContext");
    }
}

//=============================================================================

XMLConfigItemMapIndexedContext::XMLConfigItemMapIndexedContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
									const rtl::OUString& rLName,
									const ::com::sun::star::uno::Reference<
									::com::sun::star::xml::sax::XAttributeList>&,
									com::sun::star::uno::Any& rAny,
									const ::rtl::OUString& rConfigItemName,
									XMLConfigBaseContext* pBaseContext)
	: XMLConfigBaseContext(rImport, nPrfx, rLName, rAny, pBaseContext),
	  maConfigItemName( rConfigItemName )
{
}

XMLConfigItemMapIndexedContext::~XMLConfigItemMapIndexedContext()
{
}

SvXMLImportContext *XMLConfigItemMapIndexedContext::CreateChildContext( sal_uInt16 nPrefix,
													const rtl::OUString& rLocalName,
													const ::com::sun::star::uno::Reference<
										::com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
	return CreateSettingsContext(GetImport(), nPrefix, rLocalName, xAttrList, maProp, this);
}

void XMLConfigItemMapIndexedContext::EndElement()
{
	if (mpBaseContext)
	{
		if( maConfigItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ForbiddenCharacters" ) ) )
		{
			uno::Reference< i18n::XForbiddenCharacters > xForbChars;

			// get the forbidden characters from the document
			uno::Reference< lang::XMultiServiceFactory > xFac( GetImport().GetModel(), uno::UNO_QUERY );
			if( xFac.is() )
			{
				uno::Reference< beans::XPropertySet > xProps( xFac->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.Settings" ) ) ), uno::UNO_QUERY );
				if( xProps.is() && xProps->getPropertySetInfo()->hasPropertyByName( maConfigItemName ) )
				{
					xProps->getPropertyValue( maConfigItemName ) >>= xForbChars;
				}
			}

			if( xForbChars.is() )
			{

				uno::Reference< container::XIndexAccess > xIndex( maProps.GetIndexContainer(), uno::UNO_QUERY );

				const sal_Int32 nCount = xIndex->getCount();
				uno::Sequence < beans::PropertyValue > aProps;
				for (sal_Int32 i = 0; i < nCount; i++)
				{
					if ((xIndex->getByIndex( i ) >>= aProps) && (aProps.getLength() == XML_FORBIDDEN_CHARACTER_MAX ) )
					{
						beans::PropertyValue *pForChar = aProps.getArray();
						i18n::ForbiddenCharacters aForbid;
						lang::Locale aLocale;
						const rtl::OUString sLanguage  ( RTL_CONSTASCII_USTRINGPARAM ( "Language" ) );
						const rtl::OUString sCountry   ( RTL_CONSTASCII_USTRINGPARAM ( "Country" ) );
						const rtl::OUString sVariant   ( RTL_CONSTASCII_USTRINGPARAM ( "Variant" ) );
						const rtl::OUString sBeginLine ( RTL_CONSTASCII_USTRINGPARAM ( "BeginLine" ) );
						const rtl::OUString sEndLine   ( RTL_CONSTASCII_USTRINGPARAM ( "EndLine" ) );
						sal_Bool bHaveLanguage = sal_False, bHaveCountry = sal_False, bHaveVariant = sal_False,
								 bHaveBegin = sal_False, bHaveEnd = sal_False;

						for ( sal_Int32 j = 0 ; j < XML_FORBIDDEN_CHARACTER_MAX ; j++ )
						{
							if (pForChar->Name.equals (sLanguage ) )
							{
								pForChar->Value >>= aLocale.Language;
								bHaveLanguage = sal_True;
							}
							else if (pForChar->Name.equals (sCountry ) )
							{
								pForChar->Value >>= aLocale.Country;
								bHaveCountry = sal_True;
							}
							else if (pForChar->Name.equals (sVariant ) )
							{
								pForChar->Value >>= aLocale.Variant;
								bHaveVariant = sal_True;
							}
							else if (pForChar->Name.equals (sBeginLine ) )
							{
								pForChar->Value >>= aForbid.beginLine;
								bHaveBegin = sal_True;
							}
							else if (pForChar->Name.equals (sEndLine ) )
							{
								pForChar->Value >>= aForbid.endLine;
								bHaveEnd = sal_True;
							}
							pForChar++;
						}

						if ( bHaveLanguage && bHaveCountry && bHaveVariant && bHaveBegin && bHaveEnd )
						{
							try
							{
								xForbChars->setForbiddenCharacters( aLocale, aForbid );
							}
							catch( uno::Exception& )
							{
								DBG_ERROR( "Exception while importing forbidden characters" );
							}
						}
					}
				}
			}
			else
			{
				DBG_ERROR( "could not get the XForbiddenCharacters from document!" );
				mrAny <<= maProps.GetIndexContainer();
			}
		}
		else if( maConfigItemName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Symbols" ) ) )
		{
			uno::Reference< container::XIndexAccess > xIndex( maProps.GetIndexContainer(), uno::UNO_QUERY );

			const sal_Int32 nCount = xIndex->getCount();
			uno::Sequence < beans::PropertyValue > aProps;
			uno::Sequence < formula::SymbolDescriptor > aSymbolList ( nCount );

			formula::SymbolDescriptor *pDescriptor = aSymbolList.getArray();

			const rtl::OUString sName     ( RTL_CONSTASCII_USTRINGPARAM ( "Name" ) );
			const rtl::OUString sExportName ( RTL_CONSTASCII_USTRINGPARAM ( "ExportName" ) );
			const rtl::OUString sFontName ( RTL_CONSTASCII_USTRINGPARAM ( "FontName" ) );
			const rtl::OUString sSymbolSet ( RTL_CONSTASCII_USTRINGPARAM ( "SymbolSet" ) );
			const rtl::OUString sCharacter ( RTL_CONSTASCII_USTRINGPARAM ( "Character" ) );
			const rtl::OUString sCharSet  ( RTL_CONSTASCII_USTRINGPARAM ( "CharSet" ) );
			const rtl::OUString sFamily   ( RTL_CONSTASCII_USTRINGPARAM ( "Family" ) );
			const rtl::OUString sPitch    ( RTL_CONSTASCII_USTRINGPARAM ( "Pitch" ) );
			const rtl::OUString sWeight   ( RTL_CONSTASCII_USTRINGPARAM ( "Weight" ) );
			const rtl::OUString sItalic   ( RTL_CONSTASCII_USTRINGPARAM ( "Italic" ) );
			sal_Int16 nNumFullEntries = 0;

			for ( sal_Int32 i = 0; i < nCount; i++ )
			{
				if ((xIndex->getByIndex( i ) >>= aProps) && (aProps.getLength() == XML_SYMBOL_DESCRIPTOR_MAX ) )
				{
					sal_Bool bHaveName = sal_False, bHaveExportName = sal_False, bHaveCharSet = sal_False,
					 		 bHaveFontName = sal_False, bHaveFamily = sal_False, bHavePitch = sal_False,
					 		 bHaveWeight = sal_False, bHaveItalic = sal_False, bHaveSymbolSet = sal_False,
							 bHaveCharacter = sal_False;
					beans::PropertyValue *pSymbol = aProps.getArray();

					for ( sal_Int32 j = 0 ; j < XML_SYMBOL_DESCRIPTOR_MAX ; j++ )
					{
						if (pSymbol->Name.equals ( sName ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].sName;
							bHaveName = sal_True;
						}
						else if (pSymbol->Name.equals (sExportName ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].sExportName;
							bHaveExportName = sal_True;
						}
						else if (pSymbol->Name.equals (sFontName ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].sFontName;
							bHaveFontName = sal_True;
						}
						else if (pSymbol->Name.equals (sCharSet ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nCharSet;
							bHaveCharSet = sal_True;
						}
						else if (pSymbol->Name.equals (sFamily ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nFamily;
							bHaveFamily = sal_True;
						}
						else if (pSymbol->Name.equals (sPitch ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nPitch;
							bHavePitch = sal_True;
						}
						else if (pSymbol->Name.equals (sWeight ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nWeight;
							bHaveWeight = sal_True;
						}
						else if (pSymbol->Name.equals (sItalic ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nItalic;
							bHaveItalic = sal_True;
						}
						else if (pSymbol->Name.equals (sSymbolSet ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].sSymbolSet;
							bHaveSymbolSet = sal_True;
						}
						else if (pSymbol->Name.equals (sCharacter ) )
						{
							pSymbol->Value >>= pDescriptor[nNumFullEntries].nCharacter;
							bHaveCharacter = sal_True;
						}
						pSymbol++;
					}
					if ( bHaveName && bHaveExportName && bHaveCharSet && bHaveFontName && bHaveCharacter
						 && bHaveFamily && bHavePitch && bHaveWeight && bHaveItalic && bHaveSymbolSet)
						nNumFullEntries++;
				}
			}
			aSymbolList.realloc (nNumFullEntries);
			mrAny <<= aSymbolList;
		}
		else
		{
			mrAny <<= maProps.GetIndexContainer();
		}
		mpBaseContext->AddPropertyValue();
	}
	else {
		DBG_ERROR("no BaseContext");
    }
}