diff options
Diffstat (limited to 'xmloff/source/style/xmlexppr.cxx')
-rw-r--r-- | xmloff/source/style/xmlexppr.cxx | 1141 |
1 files changed, 1141 insertions, 0 deletions
diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx new file mode 100644 index 000000000000..48f383a9a376 --- /dev/null +++ b/xmloff/source/style/xmlexppr.cxx @@ -0,0 +1,1141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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 <boost/unordered_map.hpp> + +#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 boost::unordered_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, "perfomance 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( !this, "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_FAIL("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( !this, "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 + + 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 + // namepsace 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; + } + + 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(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |