/**************************************************************
 *
 * 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/container/XNameContainer.hpp>
#include <com/sun/star/xml/AttributeData.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/lang/XTypeProvider.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
#include <rtl/ustrbuf.hxx>
#include <list>
#include <hash_map>

#include <xmloff/xmlexppr.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/attrlist.hxx>
#include <xmloff/nmspmap.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmlprmap.hxx>
#include <xmloff/PropertySetInfoHash.hxx>
#include <comphelper/stl_types.hxx>

#ifndef _SVSTDARR_USHORTS
#define _SVSTDARR_USHORTS
#include <svl/svstdarr.hxx>
#endif

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

using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::xmloff::token;

#define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)

struct XMLPropTokens_Impl
{
	sal_uInt16 nType;
	XMLTokenEnum eToken;
};

#define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
const sal_uInt16 MAX_PROP_TYPES =
	(XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
	(XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);

static  XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
{
	ENTRY(CHART),
	ENTRY(GRAPHIC),
	ENTRY(TABLE),
	ENTRY(TABLE_COLUMN),
	ENTRY(TABLE_ROW),
	ENTRY(TABLE_CELL),
	ENTRY(LIST_LEVEL),
	ENTRY(PARAGRAPH),
	ENTRY(TEXT),
	ENTRY(DRAWING_PAGE),
	ENTRY(PAGE_LAYOUT),
	ENTRY(HEADER_FOOTER),
	ENTRY(RUBY),
	ENTRY(SECTION)
};

///////////////////////////////////////////////////////////////////////////////
//
// public methods
//

///////////////////////////////////////////////////////////////////////////
//
// Take all properties of the XPropertySet which are also found in the
// XMLPropertyMapEntry-array and which are not set to their default-value,
// if a state is available.
//
// After that I call the method 'ContextFilter'.
//

typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;

class XMLPropertyStates_Impl
{
	XMLPropertyStateList_Impl			aPropStates;
	XMLPropertyStateList_Impl::iterator	aLastItr;
	sal_uInt32							nCount;
public:
	XMLPropertyStates_Impl();
	void AddPropertyState(const XMLPropertyState& rPropState);
	void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
};

XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
	aPropStates(),
	nCount(0)
{
	aLastItr = aPropStates.begin();
}

void XMLPropertyStates_Impl::AddPropertyState(
		const XMLPropertyState& rPropState)
{
	XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
	sal_Bool bInserted(sal_False);
	if (nCount)
	{
		if (aLastItr->mnIndex < rPropState.mnIndex)
			aItr = ++aLastItr;
	}
	do
	{
		// TODO: one path required only
		if (aItr == aPropStates.end())
		{
			aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
			bInserted = sal_True;
			nCount++;
		}
		else if (aItr->mnIndex > rPropState.mnIndex)
		{
			aLastItr = aPropStates.insert(aItr, rPropState);
			bInserted = sal_True;
			nCount++;
		}
	}
	while(!bInserted && (aItr++ != aPropStates.end()));
}

void XMLPropertyStates_Impl::FillPropertyStateVector(
		std::vector<XMLPropertyState>& rVector)
{
	if (nCount)
	{
		rVector.resize(nCount, XMLPropertyState(-1));
        ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
	}
}

class FilterPropertyInfo_Impl
{
	const rtl::OUString		sApiName;
	std::list<sal_uInt32>	aIndexes;
	sal_uInt32				nCount;

public:

	FilterPropertyInfo_Impl( const rtl::OUString& rApiName,
							 const sal_uInt32 nIndex);

	const OUString& GetApiName() const { return sApiName; }
	std::list<sal_uInt32>& GetIndexes() { return aIndexes; }

	void AddIndex( sal_uInt32 nIndex )
	{
		aIndexes.push_back(nIndex);
		nCount++;
	}

    // for sort
    sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
    {
        return (GetApiName() < rArg.GetApiName());
    }
};

FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
		const rtl::OUString& rApiName,
		const sal_uInt32 nIndex ) :
	sApiName( rApiName ),
	aIndexes(),
	nCount(1)
{
	aIndexes.push_back(nIndex);
}

typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;

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

class FilterPropertiesInfo_Impl
{
	sal_uInt32								nCount;
	FilterPropertyInfoList_Impl				aPropInfos;
	FilterPropertyInfoList_Impl::iterator	aLastItr;

	Sequence <OUString> 					*pApiNames;

public:
	FilterPropertiesInfo_Impl();
	~FilterPropertiesInfo_Impl();

	void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex);
	const uno::Sequence<OUString>& GetApiNames();
	void FillPropertyStateArray(
			vector< XMLPropertyState >& rPropStates,
			const Reference< XPropertySet >& xPropSet,
			const UniReference< XMLPropertySetMapper >& maPropMapper,
			const sal_Bool bDefault = sal_False);
	sal_uInt32 GetPropertyCount() const { return nCount; }
};

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

typedef std::hash_map
<
	PropertySetInfoKey,
	FilterPropertiesInfo_Impl *,
	PropertySetInfoHash,
	PropertySetInfoHash
>
FilterOropertiesHashMap_Impl;

class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
{
public:
	~FilterPropertiesInfos_Impl ();
};

FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
{
	FilterOropertiesHashMap_Impl::iterator aIter = begin();
	FilterOropertiesHashMap_Impl::iterator aEnd = end();
	while( aIter != aEnd )
	{
		delete (*aIter).second;
		(*aIter).second = 0;
		++aIter;
	}
}

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

FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
	nCount(0),
	aPropInfos(),
	pApiNames( 0 )
{
	aLastItr = aPropInfos.begin();
}

FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
{
	delete pApiNames;
}

void FilterPropertiesInfo_Impl::AddProperty(
		const rtl::OUString& rApiName, const sal_uInt32 nIndex)
{
    aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
    nCount++;

	OSL_ENSURE( !pApiNames, "performance warning: API names already retrieved" );
	if( pApiNames )
	{
		delete pApiNames;
		pApiNames = NULL;
	}
}
const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
{
	OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
	if( !pApiNames )
	{
        // we have to do three things:
        // 1) sort API names,
        // 2) merge duplicates,
        // 3) construct sequence

        // sort names
        aPropInfos.sort();

        // merge duplicates
        if ( nCount > 1 )
        {
            FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
            FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
            FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
            aCurrent++;

            while ( aCurrent != aEnd )
            {
                // equal to next element?
                if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
                {
                    // if equal: merge index lists
                    aOld->GetIndexes().merge( aCurrent->GetIndexes() );
                    // erase element, and continue with next
                    aCurrent = aPropInfos.erase( aCurrent );
					nCount--;
                }
                else
                {
                    // remember old element and continue with next
                    aOld = aCurrent;
                    aCurrent++;
                }
            }
        }

        // construct sequence
		pApiNames = new Sequence < OUString >( nCount );
		OUString *pNames = pApiNames->getArray();
		FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
		FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
		for ( ; aItr != aEnd; aItr++, pNames++)
			*pNames = aItr->GetApiName();
	}

	return *pApiNames;
}

void FilterPropertiesInfo_Impl::FillPropertyStateArray(
		vector< XMLPropertyState >& rPropStates,
		const Reference< XPropertySet >& rPropSet,
		const UniReference< XMLPropertySetMapper >& rPropMapper,
		const sal_Bool bDefault )
{
	XMLPropertyStates_Impl aPropStates;

	const uno::Sequence<OUString>& rApiNames = GetApiNames();

    Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
    if (xTolPropSet.is())
    {
        if (!bDefault)
        {
            Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
            sal_Int32 nResultCount(aResults.getLength());
            if (nResultCount > 0)
            {
		        const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
		        FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
		        XMLPropertyState aNewProperty( -1 );
                sal_uInt32 i = 0;
                while (nResultCount > 0 && i < nCount)
		        {
                    if (pResults->Name == aPropIter->GetApiName())
                    {
			            aNewProperty.mnIndex = -1;
			            aNewProperty.maValue = pResults->Value;

			            for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
				            aIndexItr != aPropIter->GetIndexes().end();
				            ++aIndexItr )
			            {
				            aNewProperty.mnIndex = *aIndexItr;
				            aPropStates.AddPropertyState( aNewProperty );
			            }
    			        ++pResults;
                        --nResultCount;
                    }
		            ++aPropIter;
                    ++i;
                }
		    }
        }
        else
        {
            Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
            OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
		    const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
		    FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
		    XMLPropertyState aNewProperty( -1 );
            sal_uInt32 nResultCount(aResults.getLength());
            OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
		    for( sal_uInt32 i = 0; i < nResultCount; ++i )
		    {
                if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
                    ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
                {
			        aNewProperty.mnIndex = -1;
			        aNewProperty.maValue = pResults->Value;

			        for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
				        aIndexItr != aPropIter->GetIndexes().end();
				        ++aIndexItr )
			        {
				        aNewProperty.mnIndex = *aIndexItr;
				        aPropStates.AddPropertyState( aNewProperty );
			        }
                }
    			++pResults;
    		    ++aPropIter;
		    }
        }
    }
    else
    {
	    Sequence < PropertyState > aStates;
	    const PropertyState *pStates = 0;
	    Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
   	    if( xPropState.is() )
	    {
		    aStates = xPropState->getPropertyStates( rApiNames );
		    pStates = aStates.getConstArray();
	    }

	    Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
	    if( xMultiPropSet.is() && !bDefault )
	    {
		    Sequence < Any > aValues;
		    if( pStates )
		    {
			    // step 1: get value count
			    sal_uInt32 nValueCount = 0;
			    sal_uInt32 i;

			    for( i = 0; i < nCount; ++i, ++pStates )
			    {
				    if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
					    nValueCount++;
			    }

			    if( nValueCount )
			    {
				    // step 2: collect property names
				    Sequence < OUString > aAPINames( nValueCount );
				    OUString *pAPINames = aAPINames.getArray();

                    ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
                    aPropIters.reserve( nValueCount );

				    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
    				OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");

				    pStates = aStates.getConstArray();
				    i = 0;
				    while( i < nValueCount )
				    {
					    if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
					    {
						    *pAPINames++ = aItr->GetApiName();
                            aPropIters.push_back( aItr );
						    ++i;
					    }
                        ++aItr;
					    ++pStates;
				    }

				    aValues = xMultiPropSet->getPropertyValues( aAPINames );
				    const Any *pValues = aValues.getConstArray();

                    ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
                        pPropIter = aPropIters.begin();

				    XMLPropertyState aNewProperty( -1 );
				    for( i = 0; i < nValueCount; i++ )
				    {
					    aNewProperty.mnIndex = -1;
					    aNewProperty.maValue = *pValues;

                        const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
					    for (   std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
						        aIndexItr != rIndexes.end();
						        ++aIndexItr
                            )
					    {
						    aNewProperty.mnIndex = *aIndexItr;
						    aPropStates.AddPropertyState( aNewProperty );
					    }

					    ++pPropIter;
					    ++pValues;
				    }
			    }
		    }
		    else
		    {
			    aValues = xMultiPropSet->getPropertyValues( rApiNames );
			    const Any *pValues = aValues.getConstArray();

			    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
			    for(sal_uInt32 i = 0; i < nCount; i++ )
			    {
				    // The value is stored in the PropertySet itself, add to list.
				    XMLPropertyState aNewProperty( -1 );
				    aNewProperty.maValue = *pValues;
				    ++pValues;
				    for( std::list<sal_uInt32>::iterator aIndexItr =
						    aItr->GetIndexes().begin();
					    aIndexItr != aItr->GetIndexes().end();
					    aIndexItr++ )
				    {
					    aNewProperty.mnIndex = *aIndexItr;
					    aPropStates.AddPropertyState( aNewProperty );
				    }
				    aItr++;
			    }
		    }
	    }
	    else
	    {
		    FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
		    for(sal_uInt32 i = 0; i < nCount; i++ )
		    {
			    sal_Bool bDirectValue =
				    !pStates || *pStates == PropertyState_DIRECT_VALUE;
			    if( bDirectValue || bDefault )
			    {
				    // The value is stored in the PropertySet itself, add to list.
				    sal_Bool bGotValue = sal_False;
				    XMLPropertyState aNewProperty( -1 );
				    for( std::list<sal_uInt32>::const_iterator aIndexItr =
						    aItr->GetIndexes().begin();
					    aIndexItr != aItr->GetIndexes().end();
					    aIndexItr++ )
				    {
					    if( bDirectValue ||
						    (rPropMapper->GetEntryFlags( *aIndexItr ) &
										    MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
					    {
						    try
						    {
							    if( !bGotValue )
							    {
								    aNewProperty.maValue =
									    rPropSet->getPropertyValue( aItr->GetApiName() );
								    bGotValue = sal_True;
							    }
							    aNewProperty.mnIndex = *aIndexItr;
							    aPropStates.AddPropertyState( aNewProperty );
						    }
						    catch( UnknownPropertyException& )
						    {
							    // might be a problem of getImplemenetationId
							    OSL_ENSURE( sal_False, "unknown property in getPropertyValue" );
						    }

					    }
				    }
			    }

			    aItr++;
			    if( pStates )
				    pStates++;
		    }
	    }
    }
	aPropStates.FillPropertyStateVector(rPropStates);
}

///////////////////////////////////////////////////////////////////////////////
//
// ctor/dtor , class SvXMLExportPropertyMapper
//

SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
		const UniReference< XMLPropertySetMapper >& rMapper ) :
	pCache( 0 ),
	maPropMapper( rMapper )
{
}

SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
{
	delete pCache;
	mxNextMapper = 0;
}

void SvXMLExportPropertyMapper::ChainExportMapper(
		const UniReference< SvXMLExportPropertyMapper>& rMapper )
{
	// add map entries from rMapper to current map
	maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
	// rMapper uses the same map as 'this'
	rMapper->maPropMapper = maPropMapper;

	// set rMapper as last mapper in current chain
	UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
	if( xNext.is())
	{
		while( xNext->mxNextMapper.is())
			xNext = xNext->mxNextMapper;
		xNext->mxNextMapper = rMapper;
	}
	else
		mxNextMapper = rMapper;

	// if rMapper was already chained, correct
	// map pointer of successors
	xNext = rMapper;

	while( xNext->mxNextMapper.is())
	{
		xNext = xNext->mxNextMapper;
		xNext->maPropMapper = maPropMapper;
	}
}


vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
		const Reference< XPropertySet > xPropSet,
		const sal_Bool bDefault ) const
{
	vector< XMLPropertyState > aPropStateArray;

	// Retrieve XPropertySetInfo and XPropertyState
	Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
	if( !xInfo.is() )
		return aPropStateArray;

	sal_Int32 nProps = maPropMapper->GetEntryCount();

	FilterPropertiesInfo_Impl *pFilterInfo = 0;

	Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
	Sequence< sal_Int8 > aImplId;
	if( xTypeProv.is() )
	{
		aImplId = xTypeProv->getImplementationId();
		if( aImplId.getLength() == 16 )
		{
			if( pCache )
			{
				// The key must not be created outside this block, because it
				// keeps a reference to the property set info.
				PropertySetInfoKey aKey( xInfo, aImplId );
				FilterPropertiesInfos_Impl::iterator aIter =
					pCache->find( aKey );
				if( aIter != pCache->end() )
					pFilterInfo = (*aIter).second;
			}
		}
	}

	sal_Bool bDelInfo = sal_False;
	if( !pFilterInfo )
	{
		pFilterInfo = new FilterPropertiesInfo_Impl;
		for( sal_Int32 i=0; i < nProps; i++ )
		{
			// Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
			// Does the PropertySet contain name of mpEntries-array ?
			const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
			const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
			if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
				( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
				  xInfo->hasPropertyByName( rAPIName ) ) )
            {
                const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
                const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
                        maPropMapper->GetEarliestODFVersionForExport( i ) );
                if( nCurrentVersion >= nEarliestODFVersionForExport
                        || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
                        || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
                    pFilterInfo->AddProperty(rAPIName, i);
            }
		}

		if( xTypeProv.is() && aImplId.getLength() == 16 )
		{
			// Check whether the property set info is destroyed if it is
			// assigned to a weak reference only. If it is destroyed, then
			// every instance of getPropertySetInfo returns a new object.
			// Such property set infos must not be cached.
			WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
			xInfo = 0;
			xInfo = xWeakInfo;
			if( xInfo.is() )
			{
				if( !pCache )
					((SvXMLExportPropertyMapper *)this)->pCache =
						new FilterPropertiesInfos_Impl;
				PropertySetInfoKey aKey( xInfo, aImplId );
				(*pCache)[aKey] = pFilterInfo;
			}
			else
				bDelInfo = sal_True;
		}
		else
		{
			OSL_ENSURE(sal_False, "here is no TypeProvider or the ImplId is wrong");
			bDelInfo = sal_True;
		}
	}

	if( pFilterInfo->GetPropertyCount() )
	{
		try
		{
			pFilterInfo->FillPropertyStateArray(aPropStateArray,
												xPropSet, maPropMapper,
												bDefault);
		}
		catch( UnknownPropertyException& )
		{
			// might be a problem of getImplemenetationId
			OSL_ENSURE( sal_False, "unknown property in getPropertyStates" );
		}
	}

	// Call centext-filter
	if( !aPropStateArray.empty() )
		ContextFilter( aPropStateArray, xPropSet );

	// Have to do if we change from a vector to a list or something like that
	/*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin();
	while (aItr != aPropStateArray.end())
	{
		if (aItr->mnIndex == -1)
			aItr = aPropStateArray.erase(aItr);
		else
			aItr++;
	}*/

	if( bDelInfo )
		delete pFilterInfo;

	return aPropStateArray;
}

void SvXMLExportPropertyMapper::ContextFilter(
		vector< XMLPropertyState >& rProperties,
		Reference< XPropertySet > rPropSet ) const
{
	// Derived class could implement this.
	if( mxNextMapper.is() )
		mxNextMapper->ContextFilter( rProperties, rPropSet );
}

///////////////////////////////////////////////////////////////////////////
//
// Compares two Sequences of XMLPropertyState:
//	1.Number of elements equal ?
//	2.Index of each element equal ? (So I know whether the propertynames are the same)
//	3.Value of each element equal ?
//
sal_Bool SvXMLExportPropertyMapper::Equals(
		const vector< XMLPropertyState >& aProperties1,
	    const vector< XMLPropertyState >& aProperties2 ) const
{
	sal_Bool bRet = sal_True;
	sal_uInt32 nCount = aProperties1.size();

	if( nCount == aProperties2.size() )
	{
		sal_uInt32 nIndex = 0;
		while( bRet && nIndex < nCount )
		{
			const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
			const XMLPropertyState& rProp2 = aProperties2[ nIndex ];

			// Compare index. If equal, compare value
			if( rProp1.mnIndex == rProp2.mnIndex )
			{
				if( rProp1.mnIndex != -1 )
				{
					// Now compare values
					if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
						  XML_TYPE_BUILDIN_CMP ) != 0 )
						// simple type ( binary compare )
						bRet = ( rProp1.maValue == rProp2.maValue );
					else
						// complex type ( ask for compare-function )
						bRet = maPropMapper->GetPropertyHandler(
									rProp1.mnIndex )->equals( rProp1.maValue,
															  rProp2.maValue );
				}
			}
			else
				bRet = sal_False;

			nIndex++;
		}
	}
	else
		bRet = sal_False;

	return bRet;
}


/** fills the given attribute list with the items in the given set
void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
		const ::std::vector< XMLPropertyState >& rProperties,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		sal_uInt16 nFlags ) const
{
	_exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
				nFlags, 0, -1, -1 );
}


void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
		const ::std::vector< XMLPropertyState >& rProperties,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
		sal_uInt16 nFlags ) const
{
	_exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
				nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
}
*/


void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
		const XMLPropertyState& rProperty,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		sal_uInt16 nFlags ) const
{
	if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
				MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
		_exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap,
					nFlags );
}

void SvXMLExportPropertyMapper::exportXML(
        SvXMLExport& rExport,
		const ::std::vector< XMLPropertyState >& rProperties,
		sal_uInt16 nFlags ) const
{
	exportXML( rExport, rProperties, -1, -1,  nFlags );
}

void SvXMLExportPropertyMapper::exportXML(
        SvXMLExport& rExport,
		const ::std::vector< XMLPropertyState >& rProperties,
		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
		sal_uInt16 nFlags ) const
{
	sal_uInt16 nPropTypeFlags = 0;
	for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
	{
		sal_uInt16 nPropType = aPropTokens[i].nType;
		if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
		{
			SvUShorts aIndexArray;

			_exportXML( nPropType, nPropTypeFlags,
						rExport.GetAttrList(), rProperties,
						rExport.GetMM100UnitConverter(),
						rExport.GetNamespaceMap(),
						nFlags, &aIndexArray,
						nPropMapStartIdx, nPropMapEndIdx );

			if( rExport.GetAttrList().getLength() > 0L ||
				(nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
				aIndexArray.Count() != 0 )
			{
				SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
								  aPropTokens[i].eToken,
								  (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
								  sal_False );

				exportElementItems( rExport, rProperties, nFlags, aIndexArray );
			}
		}
	}
}

/** this method is called for every item that has the
    MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
void SvXMLExportPropertyMapper::handleSpecialItem(
		SvXMLAttributeList& rAttrList,
		const XMLPropertyState& rProperty,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		const ::std::vector< XMLPropertyState > *pProperties,
		sal_uInt32 nIdx ) const
{
	OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
	if( mxNextMapper.is() )
		mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
										rNamespaceMap, pProperties, nIdx );
}

/** this method is called for every item that has the
    MID_FLAG_ELEMENT_EXPORT flag set */
void SvXMLExportPropertyMapper::handleElementItem(
        SvXMLExport& rExport,
		const XMLPropertyState& rProperty,
		sal_uInt16 nFlags,
		const ::std::vector< XMLPropertyState > *pProperties,
		sal_uInt32 nIdx ) const
{
	OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
	if( mxNextMapper.is() )
		mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
                                         pProperties, nIdx );
}

///////////////////////////////////////////////////////////////////////////////
//
// protected methods
//

/** fills the given attribute list with the items in the given set */
void SvXMLExportPropertyMapper::_exportXML(
		sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
		SvXMLAttributeList& rAttrList,
		const ::std::vector< XMLPropertyState >& rProperties,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		sal_uInt16 nFlags,
		SvUShorts* pIndexArray,
		sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
{
	const sal_uInt32 nCount = rProperties.size();
	sal_uInt32 nIndex = 0;

	if( -1 == nPropMapStartIdx )
		nPropMapStartIdx = 0;
	if( -1 == nPropMapEndIdx )
		nPropMapEndIdx = maPropMapper->GetEntryCount();

	while( nIndex < nCount )
	{
		sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
		if( nPropMapIdx >= nPropMapStartIdx &&
			nPropMapIdx < nPropMapEndIdx  )// valid entry?
		{
			sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
			sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
			OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
						"no prop type sepcified" );
			rPropTypeFlags |= (1 << nEPType);
			if( nEPType == nPropType )
			{
				// we have a valid map entry here, so lets use it...
				if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
				{
					// element items do not add any properties,
					// we export it later
					if( pIndexArray )
						pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() );
				}
				else
				{
					_exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
								rNamespaceMap, nFlags, &rProperties, nIndex );
				}
			}
		}

		nIndex++;
	}
}

void SvXMLExportPropertyMapper::_exportXML(
		SvXMLAttributeList& rAttrList,
		const XMLPropertyState& rProperty,
		const SvXMLUnitConverter& rUnitConverter,
		const SvXMLNamespaceMap& rNamespaceMap,
		sal_uInt16 /*nFlags*/,
		const ::std::vector< XMLPropertyState > *pProperties,
		sal_uInt32 nIdx ) const
{
	OUString sCDATA( GetXMLToken(XML_CDATA) );

	if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
				MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
	{
		uno::Reference< container::XNameContainer > xAttrContainer;
		if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
		{
			SvXMLNamespaceMap *pNewNamespaceMap = 0;
			const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;

			uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
			const OUString* pAttribName = aAttribNames.getConstArray();

			const sal_Int32 nCount = aAttribNames.getLength();

			OUStringBuffer sNameBuffer;
			xml::AttributeData aData;
			for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
			{
				xAttrContainer->getByName( *pAttribName ) >>= aData;
				OUString sAttribName( *pAttribName );

				// extract namespace prefix from attribute name if it exists
				OUString sPrefix;
				const sal_Int32 nColonPos =
					pAttribName->indexOf( sal_Unicode(':') );
				if( nColonPos != -1 )
					sPrefix = pAttribName->copy( 0, nColonPos );

				if( sPrefix.getLength() )
				{
					OUString sNamespace( aData.Namespace );

					// if the prefix isn't defined yet or has another meaning,
					// we have to redefine it now.
					sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
					if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
					{
						sal_Bool bAddNamespace = sal_False;
						if( USHRT_MAX == nKey )
						{
							// The prefix is unused, so it is sufficient
							// to add it to the namespace map.
							bAddNamespace = sal_True;
						}
						else
						{
							// check if there is a prefix registered for the
							// namespace URI
							nKey = pNamespaceMap->GetKeyByName( sNamespace );
							if( XML_NAMESPACE_UNKNOWN == nKey )
							{
								// There is no prefix for the namespace, so
								// we have to generate one and have to add it.
								sal_Int32 n=0;
								OUString sOrigPrefix( sPrefix );
								do
								{
									sNameBuffer.append( sOrigPrefix );
									sNameBuffer.append( ++n );
									sPrefix = sNameBuffer.makeStringAndClear();
									nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
								}
								while( nKey != USHRT_MAX );

								bAddNamespace = sal_True;
							}
							else
							{
								// If there is a prefix for the namespace,
								// we reuse that.
								sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
							}
							// In any case, the attribute name has to be adapted.
							sNameBuffer.append( sPrefix );
							sNameBuffer.append( sal_Unicode(':') );
							sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
							sAttribName = sNameBuffer.makeStringAndClear();
						}

						if( bAddNamespace )
						{
							if( !pNewNamespaceMap )
							{
								pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
								pNamespaceMap = pNewNamespaceMap;
							}
							pNewNamespaceMap->Add( sPrefix, sNamespace );
							sNameBuffer.append( GetXMLToken(XML_XMLNS) );
							sNameBuffer.append( sal_Unicode(':') );
							sNameBuffer.append( sPrefix );
							rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
													sNamespace );
						}
					}
				}
				OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
				OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" );
                OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
				if( !sOldValue.getLength() )
					rAttrList.AddAttribute( sAttribName, aData.Value );
			}

			delete pNewNamespaceMap;
		}
		else
		{
			handleSpecialItem( rAttrList, rProperty, rUnitConverter,
							   rNamespaceMap, pProperties, nIdx );
		}
	}
	else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
					MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
	{
		OUString aValue;
		const OUString sName( rNamespaceMap.GetQNameByKey(
					maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
				    maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );

		sal_Bool bRemove = sal_False;
		if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
					MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
		{
			aValue = rAttrList.getValueByName( sName );
			bRemove = sal_True; //aValue.getLength() != 0;
		}

		if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
		{
			if( bRemove )
				rAttrList.RemoveAttribute( sName );
			rAttrList.AddAttribute( sName, aValue );
		}
	}
}

void SvXMLExportPropertyMapper::exportElementItems(
        SvXMLExport& rExport,
		const ::std::vector< XMLPropertyState >& rProperties,
		sal_uInt16 nFlags,
		const SvUShorts& rIndexArray ) const
{
	const sal_uInt16 nCount = rIndexArray.Count();

	sal_Bool bItemsExported = sal_False;
	OUString sWS( GetXMLToken(XML_WS) );
	for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
	{
		const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );

		OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
				rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
				"wrong mid flag!" );

		rExport.IgnorableWhitespace();
		handleElementItem( rExport, rProperties[nElement],
                           nFlags, &rProperties, nElement );
		bItemsExported = sal_True;
	}

	if( bItemsExported )
		rExport.IgnorableWhitespace();
}
