/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xmloff/xmlnmspe.hxx" #include #include #include #include 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((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 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& 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& rVector) { if (nCount) { rVector.resize(nCount, XMLPropertyState(-1)); ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() ); } } class FilterPropertyInfo_Impl { const OUString sApiName; std::list aIndexes; sal_uInt32 nCount; public: FilterPropertyInfo_Impl( const OUString& rApiName, const sal_uInt32 nIndex); const OUString& GetApiName() const { return sApiName; } std::list& 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 OUString& rApiName, const sal_uInt32 nIndex ) : sApiName( rApiName ), aIndexes(), nCount(1) { aIndexes.push_back(nIndex); } typedef std::list FilterPropertyInfoList_Impl; // ---------------------------------------------------------------------------- class FilterPropertiesInfo_Impl { sal_uInt32 nCount; FilterPropertyInfoList_Impl aPropInfos; FilterPropertyInfoList_Impl::iterator aLastItr; Sequence *pApiNames; public: FilterPropertiesInfo_Impl(); ~FilterPropertiesInfo_Impl(); void AddProperty(const OUString& rApiName, const sal_uInt32 nIndex); const uno::Sequence& 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 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& 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& 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::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::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::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::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::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, bool bDefault, bool bEnableFoFontFamily) 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(bEnableFoFontFamily, 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( bool bEnableFoFontFamily, vector< XMLPropertyState >& rProperties, Reference< XPropertySet > rPropSet ) const { // Derived class could implement this. if( mxNextMapper.is() ) mxNextMapper->ContextFilter( bEnableFoFontFamily, 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( 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 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* 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 { 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.isEmpty() ) { 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.isEmpty(), "alien attribute exists already" ); OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out"); if( sOldValue.isEmpty() ) 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& rIndexArray ) const { const sal_uInt16 nCount = rIndexArray.size(); sal_Bool bItemsExported = sal_False; 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: */