office-gobmx/xmloff/source/style/xmlexppr.cxx
2011-11-27 13:27:50 -06:00

1114 lines
40 KiB
C++

/* -*- 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.
*
************************************************************************/
#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/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>
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
<
Reference< XPropertySetInfo >,
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;
if( pCache )
{
FilterPropertiesInfos_Impl::iterator aIter =
pCache->find( xInfo );
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);
}
}
// 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;
(*pCache)[xInfo] = pFilterInfo;
}
else
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 )
{
std::vector<sal_uInt16> 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.empty() )
{
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,
std::vector<sal_uInt16>* 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->push_back( (sal_uInt16)nIndex );
}
}
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 std::vector<sal_uInt16>& rIndexArray ) const
{
const sal_uInt16 nCount = rIndexArray.size();
sal_Bool bItemsExported = sal_False;
OUString sWS( GetXMLToken(XML_WS) );
for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
{
const sal_uInt16 nElement = rIndexArray[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: */