bump product version to 4.1.6.2
[LibreOffice.git] / xmloff / source / style / xmlexppr.cxx
blob6808db5e5bca533743e0bf4ac312e8bbc1379056
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/container/XNameContainer.hpp>
21 #include <com/sun/star/xml/AttributeData.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/beans/XPropertyState.hpp>
24 #include <com/sun/star/lang/XTypeProvider.hpp>
25 #include <com/sun/star/beans/XMultiPropertySet.hpp>
26 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
27 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
28 #include <rtl/ustrbuf.hxx>
29 #include <list>
30 #include <boost/unordered_map.hpp>
32 #include <xmloff/xmlexppr.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/attrlist.hxx>
35 #include <xmloff/nmspmap.hxx>
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmlexp.hxx>
38 #include <xmloff/xmlprmap.hxx>
39 #include <xmloff/PropertySetInfoHash.hxx>
40 #include <comphelper/stl_types.hxx>
43 using namespace ::std;
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::xmloff::token;
50 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
52 struct XMLPropTokens_Impl
54 sal_uInt16 nType;
55 XMLTokenEnum eToken;
58 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
59 const sal_uInt16 MAX_PROP_TYPES =
60 (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
61 (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
63 static XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
65 ENTRY(CHART),
66 ENTRY(GRAPHIC),
67 ENTRY(TABLE),
68 ENTRY(TABLE_COLUMN),
69 ENTRY(TABLE_ROW),
70 ENTRY(TABLE_CELL),
71 ENTRY(LIST_LEVEL),
72 ENTRY(PARAGRAPH),
73 ENTRY(TEXT),
74 ENTRY(DRAWING_PAGE),
75 ENTRY(PAGE_LAYOUT),
76 ENTRY(HEADER_FOOTER),
77 ENTRY(RUBY),
78 ENTRY(SECTION)
81 ///////////////////////////////////////////////////////////////////////////////
83 // public methods
86 ///////////////////////////////////////////////////////////////////////////
88 // Take all properties of the XPropertySet which are also found in the
89 // XMLPropertyMapEntry-array and which are not set to their default-value,
90 // if a state is available.
92 // After that I call the method 'ContextFilter'.
95 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
97 class XMLPropertyStates_Impl
99 XMLPropertyStateList_Impl aPropStates;
100 XMLPropertyStateList_Impl::iterator aLastItr;
101 sal_uInt32 nCount;
102 public:
103 XMLPropertyStates_Impl();
104 void AddPropertyState(const XMLPropertyState& rPropState);
105 void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
108 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
109 aPropStates(),
110 nCount(0)
112 aLastItr = aPropStates.begin();
115 void XMLPropertyStates_Impl::AddPropertyState(
116 const XMLPropertyState& rPropState)
118 XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
119 sal_Bool bInserted(sal_False);
120 if (nCount)
122 if (aLastItr->mnIndex < rPropState.mnIndex)
123 aItr = ++aLastItr;
127 // TODO: one path required only
128 if (aItr == aPropStates.end())
130 aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
131 bInserted = sal_True;
132 nCount++;
134 else if (aItr->mnIndex > rPropState.mnIndex)
136 aLastItr = aPropStates.insert(aItr, rPropState);
137 bInserted = sal_True;
138 nCount++;
141 while(!bInserted && (aItr++ != aPropStates.end()));
144 void XMLPropertyStates_Impl::FillPropertyStateVector(
145 std::vector<XMLPropertyState>& rVector)
147 if (nCount)
149 rVector.resize(nCount, XMLPropertyState(-1));
150 ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
154 class FilterPropertyInfo_Impl
156 const OUString sApiName;
157 std::list<sal_uInt32> aIndexes;
158 sal_uInt32 nCount;
160 public:
162 FilterPropertyInfo_Impl( const OUString& rApiName,
163 const sal_uInt32 nIndex);
165 const OUString& GetApiName() const { return sApiName; }
166 std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
168 void AddIndex( sal_uInt32 nIndex )
170 aIndexes.push_back(nIndex);
171 nCount++;
174 // for sort
175 sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
177 return (GetApiName() < rArg.GetApiName());
181 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
182 const OUString& rApiName,
183 const sal_uInt32 nIndex ) :
184 sApiName( rApiName ),
185 aIndexes(),
186 nCount(1)
188 aIndexes.push_back(nIndex);
191 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
193 // ----------------------------------------------------------------------------
195 class FilterPropertiesInfo_Impl
197 sal_uInt32 nCount;
198 FilterPropertyInfoList_Impl aPropInfos;
199 FilterPropertyInfoList_Impl::iterator aLastItr;
201 Sequence <OUString> *pApiNames;
203 public:
204 FilterPropertiesInfo_Impl();
205 ~FilterPropertiesInfo_Impl();
207 void AddProperty(const OUString& rApiName, const sal_uInt32 nIndex);
208 const uno::Sequence<OUString>& GetApiNames();
209 void FillPropertyStateArray(
210 vector< XMLPropertyState >& rPropStates,
211 const Reference< XPropertySet >& xPropSet,
212 const UniReference< XMLPropertySetMapper >& maPropMapper,
213 const sal_Bool bDefault = sal_False);
214 sal_uInt32 GetPropertyCount() const { return nCount; }
217 // ----------------------------------------------------------------------------
219 typedef boost::unordered_map
221 PropertySetInfoKey,
222 FilterPropertiesInfo_Impl *,
223 PropertySetInfoHash,
224 PropertySetInfoHash
226 FilterOropertiesHashMap_Impl;
228 class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
230 public:
231 ~FilterPropertiesInfos_Impl ();
234 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
236 FilterOropertiesHashMap_Impl::iterator aIter = begin();
237 FilterOropertiesHashMap_Impl::iterator aEnd = end();
238 while( aIter != aEnd )
240 delete (*aIter).second;
241 (*aIter).second = 0;
242 ++aIter;
246 // ----------------------------------------------------------------------------
248 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
249 nCount(0),
250 aPropInfos(),
251 pApiNames( 0 )
253 aLastItr = aPropInfos.begin();
256 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
258 delete pApiNames;
261 void FilterPropertiesInfo_Impl::AddProperty(
262 const OUString& rApiName, const sal_uInt32 nIndex)
264 aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
265 nCount++;
267 OSL_ENSURE( !pApiNames, "perfomance warning: API names already retrieved" );
268 if( pApiNames )
270 delete pApiNames;
271 pApiNames = NULL;
274 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
276 OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
277 if( !pApiNames )
279 // we have to do three things:
280 // 1) sort API names,
281 // 2) merge duplicates,
282 // 3) construct sequence
284 // sort names
285 aPropInfos.sort();
287 // merge duplicates
288 if ( nCount > 1 )
290 FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
291 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
292 FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
293 ++aCurrent;
295 while ( aCurrent != aEnd )
297 // equal to next element?
298 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
300 // if equal: merge index lists
301 aOld->GetIndexes().merge( aCurrent->GetIndexes() );
302 // erase element, and continue with next
303 aCurrent = aPropInfos.erase( aCurrent );
304 nCount--;
306 else
308 // remember old element and continue with next
309 aOld = aCurrent;
310 ++aCurrent;
315 // construct sequence
316 pApiNames = new Sequence < OUString >( nCount );
317 OUString *pNames = pApiNames->getArray();
318 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
319 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
320 for ( ; aItr != aEnd; ++aItr, ++pNames)
321 *pNames = aItr->GetApiName();
324 return *pApiNames;
327 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
328 vector< XMLPropertyState >& rPropStates,
329 const Reference< XPropertySet >& rPropSet,
330 const UniReference< XMLPropertySetMapper >& rPropMapper,
331 const sal_Bool bDefault )
333 XMLPropertyStates_Impl aPropStates;
335 const uno::Sequence<OUString>& rApiNames = GetApiNames();
337 Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
338 if (xTolPropSet.is())
340 if (!bDefault)
342 Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
343 sal_Int32 nResultCount(aResults.getLength());
344 if (nResultCount > 0)
346 const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
347 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
348 XMLPropertyState aNewProperty( -1 );
349 sal_uInt32 i = 0;
350 while (nResultCount > 0 && i < nCount)
352 if (pResults->Name == aPropIter->GetApiName())
354 aNewProperty.mnIndex = -1;
355 aNewProperty.maValue = pResults->Value;
357 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
358 aIndexItr != aPropIter->GetIndexes().end();
359 ++aIndexItr )
361 aNewProperty.mnIndex = *aIndexItr;
362 aPropStates.AddPropertyState( aNewProperty );
364 ++pResults;
365 --nResultCount;
367 ++aPropIter;
368 ++i;
372 else
374 Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
375 OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
376 const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
377 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
378 XMLPropertyState aNewProperty( -1 );
379 sal_uInt32 nResultCount(aResults.getLength());
380 OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
381 for( sal_uInt32 i = 0; i < nResultCount; ++i )
383 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
384 ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
386 aNewProperty.mnIndex = -1;
387 aNewProperty.maValue = pResults->Value;
389 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
390 aIndexItr != aPropIter->GetIndexes().end();
391 ++aIndexItr )
393 aNewProperty.mnIndex = *aIndexItr;
394 aPropStates.AddPropertyState( aNewProperty );
397 ++pResults;
398 ++aPropIter;
402 else
404 Sequence < PropertyState > aStates;
405 const PropertyState *pStates = 0;
406 Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
407 if( xPropState.is() )
409 aStates = xPropState->getPropertyStates( rApiNames );
410 pStates = aStates.getConstArray();
413 Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
414 if( xMultiPropSet.is() && !bDefault )
416 Sequence < Any > aValues;
417 if( pStates )
419 // step 1: get value count
420 sal_uInt32 nValueCount = 0;
421 sal_uInt32 i;
423 for( i = 0; i < nCount; ++i, ++pStates )
425 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
426 nValueCount++;
429 if( nValueCount )
431 // step 2: collect property names
432 Sequence < OUString > aAPINames( nValueCount );
433 OUString *pAPINames = aAPINames.getArray();
435 ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
436 aPropIters.reserve( nValueCount );
438 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
439 OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
441 pStates = aStates.getConstArray();
442 i = 0;
443 while( i < nValueCount )
445 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
447 *pAPINames++ = aItr->GetApiName();
448 aPropIters.push_back( aItr );
449 ++i;
451 ++aItr;
452 ++pStates;
455 aValues = xMultiPropSet->getPropertyValues( aAPINames );
456 const Any *pValues = aValues.getConstArray();
458 ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
459 pPropIter = aPropIters.begin();
461 XMLPropertyState aNewProperty( -1 );
462 for( i = 0; i < nValueCount; ++i )
464 aNewProperty.mnIndex = -1;
465 aNewProperty.maValue = *pValues;
467 const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
468 for ( std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
469 aIndexItr != rIndexes.end();
470 ++aIndexItr
473 aNewProperty.mnIndex = *aIndexItr;
474 aPropStates.AddPropertyState( aNewProperty );
477 ++pPropIter;
478 ++pValues;
482 else
484 aValues = xMultiPropSet->getPropertyValues( rApiNames );
485 const Any *pValues = aValues.getConstArray();
487 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
488 for(sal_uInt32 i = 0; i < nCount; ++i)
490 // The value is stored in the PropertySet itself, add to list.
491 XMLPropertyState aNewProperty( -1 );
492 aNewProperty.maValue = *pValues;
493 ++pValues;
494 for( std::list<sal_uInt32>::iterator aIndexItr =
495 aItr->GetIndexes().begin();
496 aIndexItr != aItr->GetIndexes().end();
497 ++aIndexItr )
499 aNewProperty.mnIndex = *aIndexItr;
500 aPropStates.AddPropertyState( aNewProperty );
502 ++aItr;
506 else
508 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
509 for(sal_uInt32 i = 0; i < nCount; ++i)
511 sal_Bool bDirectValue =
512 !pStates || *pStates == PropertyState_DIRECT_VALUE;
513 if( bDirectValue || bDefault )
515 // The value is stored in the PropertySet itself, add to list.
516 sal_Bool bGotValue = sal_False;
517 XMLPropertyState aNewProperty( -1 );
518 for( std::list<sal_uInt32>::const_iterator aIndexItr =
519 aItr->GetIndexes().begin();
520 aIndexItr != aItr->GetIndexes().end();
521 ++aIndexItr )
523 if( bDirectValue ||
524 (rPropMapper->GetEntryFlags( *aIndexItr ) &
525 MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
529 if( !bGotValue )
531 aNewProperty.maValue =
532 rPropSet->getPropertyValue( aItr->GetApiName() );
533 bGotValue = sal_True;
535 aNewProperty.mnIndex = *aIndexItr;
536 aPropStates.AddPropertyState( aNewProperty );
538 catch( UnknownPropertyException& )
540 // might be a problem of getImplemenetationId
541 OSL_ENSURE( !this, "unknown property in getPropertyValue" );
548 ++aItr;
549 if( pStates )
550 ++pStates;
554 aPropStates.FillPropertyStateVector(rPropStates);
557 ///////////////////////////////////////////////////////////////////////////////
559 // ctor/dtor , class SvXMLExportPropertyMapper
562 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
563 const UniReference< XMLPropertySetMapper >& rMapper ) :
564 pCache( 0 ),
565 maPropMapper( rMapper )
569 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
571 delete pCache;
572 mxNextMapper = 0;
575 void SvXMLExportPropertyMapper::ChainExportMapper(
576 const UniReference< SvXMLExportPropertyMapper>& rMapper )
578 // add map entries from rMapper to current map
579 maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
580 // rMapper uses the same map as 'this'
581 rMapper->maPropMapper = maPropMapper;
583 // set rMapper as last mapper in current chain
584 UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
585 if( xNext.is())
587 while( xNext->mxNextMapper.is())
588 xNext = xNext->mxNextMapper;
589 xNext->mxNextMapper = rMapper;
591 else
592 mxNextMapper = rMapper;
594 // if rMapper was already chained, correct
595 // map pointer of successors
596 xNext = rMapper;
598 while( xNext->mxNextMapper.is())
600 xNext = xNext->mxNextMapper;
601 xNext->maPropMapper = maPropMapper;
606 vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
607 const Reference< XPropertySet > xPropSet,
608 bool bDefault, bool bEnableFoFontFamily) const
610 vector< XMLPropertyState > aPropStateArray;
612 // Retrieve XPropertySetInfo and XPropertyState
613 Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
614 if( !xInfo.is() )
615 return aPropStateArray;
617 sal_Int32 nProps = maPropMapper->GetEntryCount();
619 FilterPropertiesInfo_Impl *pFilterInfo = 0;
621 Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
622 Sequence< sal_Int8 > aImplId;
623 if( xTypeProv.is() )
625 aImplId = xTypeProv->getImplementationId();
626 if( aImplId.getLength() == 16 )
628 if( pCache )
630 // The key must not be created outside this block, because it
631 // keeps a reference to the property set info.
632 PropertySetInfoKey aKey( xInfo, aImplId );
633 FilterPropertiesInfos_Impl::iterator aIter =
634 pCache->find( aKey );
635 if( aIter != pCache->end() )
636 pFilterInfo = (*aIter).second;
641 sal_Bool bDelInfo = sal_False;
642 if( !pFilterInfo )
644 pFilterInfo = new FilterPropertiesInfo_Impl;
645 for( sal_Int32 i=0; i < nProps; i++ )
647 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
648 // Does the PropertySet contain name of mpEntries-array ?
649 const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
650 const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
651 if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
652 ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
653 xInfo->hasPropertyByName( rAPIName ) ) )
655 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
656 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
657 maPropMapper->GetEarliestODFVersionForExport( i ) );
658 if( nCurrentVersion >= nEarliestODFVersionForExport
659 || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
660 || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
661 pFilterInfo->AddProperty(rAPIName, i);
665 if( xTypeProv.is() && aImplId.getLength() == 16 )
667 // Check whether the property set info is destroyed if it is
668 // assigned to a weak reference only. If it is destroyed, then
669 // every instance of getPropertySetInfo returns a new object.
670 // Such property set infos must not be cached.
671 WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
672 xInfo = 0;
673 xInfo = xWeakInfo;
674 if( xInfo.is() )
676 if( !pCache )
677 ((SvXMLExportPropertyMapper *)this)->pCache =
678 new FilterPropertiesInfos_Impl;
679 PropertySetInfoKey aKey( xInfo, aImplId );
680 (*pCache)[aKey] = pFilterInfo;
682 else
683 bDelInfo = sal_True;
685 else
687 OSL_FAIL("here is no TypeProvider or the ImplId is wrong");
688 bDelInfo = sal_True;
692 if( pFilterInfo->GetPropertyCount() )
696 pFilterInfo->FillPropertyStateArray(aPropStateArray,
697 xPropSet, maPropMapper,
698 bDefault);
700 catch( UnknownPropertyException& )
702 // might be a problem of getImplemenetationId
703 OSL_ENSURE( !this, "unknown property in getPropertyStates" );
707 // Call centext-filter
708 if( !aPropStateArray.empty() )
709 ContextFilter(bEnableFoFontFamily, aPropStateArray, xPropSet);
711 // Have to do if we change from a vector to a list or something like that
713 if( bDelInfo )
714 delete pFilterInfo;
716 return aPropStateArray;
719 void SvXMLExportPropertyMapper::ContextFilter(
720 bool bEnableFoFontFamily,
721 vector< XMLPropertyState >& rProperties,
722 Reference< XPropertySet > rPropSet ) const
724 // Derived class could implement this.
725 if( mxNextMapper.is() )
726 mxNextMapper->ContextFilter( bEnableFoFontFamily, rProperties, rPropSet );
729 ///////////////////////////////////////////////////////////////////////////
731 // Compares two Sequences of XMLPropertyState:
732 // 1.Number of elements equal ?
733 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
734 // 3.Value of each element equal ?
736 sal_Bool SvXMLExportPropertyMapper::Equals(
737 const vector< XMLPropertyState >& aProperties1,
738 const vector< XMLPropertyState >& aProperties2 ) const
740 sal_Bool bRet = sal_True;
741 sal_uInt32 nCount = aProperties1.size();
743 if( nCount == aProperties2.size() )
745 sal_uInt32 nIndex = 0;
746 while( bRet && nIndex < nCount )
748 const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
749 const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
751 // Compare index. If equal, compare value
752 if( rProp1.mnIndex == rProp2.mnIndex )
754 if( rProp1.mnIndex != -1 )
756 // Now compare values
757 if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
758 XML_TYPE_BUILDIN_CMP ) != 0 )
759 // simple type ( binary compare )
760 bRet = ( rProp1.maValue == rProp2.maValue );
761 else
762 // complex type ( ask for compare-function )
763 bRet = maPropMapper->GetPropertyHandler(
764 rProp1.mnIndex )->equals( rProp1.maValue,
765 rProp2.maValue );
768 else
769 bRet = sal_False;
771 nIndex++;
774 else
775 bRet = sal_False;
777 return bRet;
781 /** fills the given attribute list with the items in the given set
782 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
783 const ::std::vector< XMLPropertyState >& rProperties,
784 const SvXMLUnitConverter& rUnitConverter,
785 const SvXMLNamespaceMap& rNamespaceMap,
786 sal_uInt16 nFlags ) const
788 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
789 nFlags, 0, -1, -1 );
793 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
794 const ::std::vector< XMLPropertyState >& rProperties,
795 const SvXMLUnitConverter& rUnitConverter,
796 const SvXMLNamespaceMap& rNamespaceMap,
797 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
798 sal_uInt16 nFlags ) const
800 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
801 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
805 void SvXMLExportPropertyMapper::exportXML(
806 SvXMLExport& rExport,
807 const ::std::vector< XMLPropertyState >& rProperties,
808 sal_uInt16 nFlags ) const
810 exportXML( rExport, rProperties, -1, -1, nFlags );
813 void SvXMLExportPropertyMapper::exportXML(
814 SvXMLExport& rExport,
815 const ::std::vector< XMLPropertyState >& rProperties,
816 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
817 sal_uInt16 nFlags ) const
819 sal_uInt16 nPropTypeFlags = 0;
820 for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
822 sal_uInt16 nPropType = aPropTokens[i].nType;
823 if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
825 std::vector<sal_uInt16> aIndexArray;
827 _exportXML( nPropType, nPropTypeFlags,
828 rExport.GetAttrList(), rProperties,
829 rExport.GetMM100UnitConverter(),
830 rExport.GetNamespaceMap(),
831 nFlags, &aIndexArray,
832 nPropMapStartIdx, nPropMapEndIdx );
834 if( rExport.GetAttrList().getLength() > 0L ||
835 (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
836 !aIndexArray.empty() )
838 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
839 aPropTokens[i].eToken,
840 (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
841 sal_False );
843 exportElementItems( rExport, rProperties, nFlags, aIndexArray );
849 /** this method is called for every item that has the
850 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
851 void SvXMLExportPropertyMapper::handleSpecialItem(
852 SvXMLAttributeList& rAttrList,
853 const XMLPropertyState& rProperty,
854 const SvXMLUnitConverter& rUnitConverter,
855 const SvXMLNamespaceMap& rNamespaceMap,
856 const ::std::vector< XMLPropertyState > *pProperties,
857 sal_uInt32 nIdx ) const
859 OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
860 if( mxNextMapper.is() )
861 mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
862 rNamespaceMap, pProperties, nIdx );
865 /** this method is called for every item that has the
866 MID_FLAG_ELEMENT_EXPORT flag set */
867 void SvXMLExportPropertyMapper::handleElementItem(
868 SvXMLExport& rExport,
869 const XMLPropertyState& rProperty,
870 sal_uInt16 nFlags,
871 const ::std::vector< XMLPropertyState > *pProperties,
872 sal_uInt32 nIdx ) const
874 OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
875 if( mxNextMapper.is() )
876 mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
877 pProperties, nIdx );
880 ///////////////////////////////////////////////////////////////////////////////
882 // protected methods
885 /** fills the given attribute list with the items in the given set */
886 void SvXMLExportPropertyMapper::_exportXML(
887 sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
888 SvXMLAttributeList& rAttrList,
889 const ::std::vector< XMLPropertyState >& rProperties,
890 const SvXMLUnitConverter& rUnitConverter,
891 const SvXMLNamespaceMap& rNamespaceMap,
892 sal_uInt16 nFlags,
893 std::vector<sal_uInt16>* pIndexArray,
894 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
896 const sal_uInt32 nCount = rProperties.size();
897 sal_uInt32 nIndex = 0;
899 if( -1 == nPropMapStartIdx )
900 nPropMapStartIdx = 0;
901 if( -1 == nPropMapEndIdx )
902 nPropMapEndIdx = maPropMapper->GetEntryCount();
904 while( nIndex < nCount )
906 sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
907 if( nPropMapIdx >= nPropMapStartIdx &&
908 nPropMapIdx < nPropMapEndIdx )// valid entry?
910 sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
911 sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
912 OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
913 "no prop type sepcified" );
914 rPropTypeFlags |= (1 << nEPType);
915 if( nEPType == nPropType )
917 // we have a valid map entry here, so lets use it...
918 if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
920 // element items do not add any properties,
921 // we export it later
922 if( pIndexArray )
924 pIndexArray->push_back( (sal_uInt16)nIndex );
927 else
929 _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
930 rNamespaceMap, nFlags, &rProperties, nIndex );
935 nIndex++;
939 void SvXMLExportPropertyMapper::_exportXML(
940 SvXMLAttributeList& rAttrList,
941 const XMLPropertyState& rProperty,
942 const SvXMLUnitConverter& rUnitConverter,
943 const SvXMLNamespaceMap& rNamespaceMap,
944 sal_uInt16 /*nFlags*/,
945 const ::std::vector< XMLPropertyState > *pProperties,
946 sal_uInt32 nIdx ) const
948 if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
949 MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
951 uno::Reference< container::XNameContainer > xAttrContainer;
952 if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
954 SvXMLNamespaceMap *pNewNamespaceMap = 0;
955 const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
957 uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
958 const OUString* pAttribName = aAttribNames.getConstArray();
960 const sal_Int32 nCount = aAttribNames.getLength();
962 OUStringBuffer sNameBuffer;
963 xml::AttributeData aData;
964 for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
966 xAttrContainer->getByName( *pAttribName ) >>= aData;
967 OUString sAttribName( *pAttribName );
969 // extract namespace prefix from attribute name if it exists
970 OUString sPrefix;
971 const sal_Int32 nColonPos =
972 pAttribName->indexOf( sal_Unicode(':') );
973 if( nColonPos != -1 )
974 sPrefix = pAttribName->copy( 0, nColonPos );
976 if( !sPrefix.isEmpty() )
978 OUString sNamespace( aData.Namespace );
980 // if the prefix isn't defined yet or has another meaning,
981 // we have to redefine it now.
982 sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
983 if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
985 sal_Bool bAddNamespace = sal_False;
986 if( USHRT_MAX == nKey )
988 // The prefix is unused, so it is sufficient
989 // to add it to the namespace map.
990 bAddNamespace = sal_True;
992 else
994 // check if there is a prefix registered for the
995 // namepsace URI
996 nKey = pNamespaceMap->GetKeyByName( sNamespace );
997 if( XML_NAMESPACE_UNKNOWN == nKey )
999 // There is no prefix for the namespace, so
1000 // we have to generate one and have to add it.
1001 sal_Int32 n=0;
1002 OUString sOrigPrefix( sPrefix );
1005 sNameBuffer.append( sOrigPrefix );
1006 sNameBuffer.append( ++n );
1007 sPrefix = sNameBuffer.makeStringAndClear();
1008 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1010 while( nKey != USHRT_MAX );
1012 bAddNamespace = sal_True;
1014 else
1016 // If there is a prefix for the namespace,
1017 // we reuse that.
1018 sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
1020 // In any case, the attribute name has to be adapted.
1021 sNameBuffer.append( sPrefix );
1022 sNameBuffer.append( sal_Unicode(':') );
1023 sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
1024 sAttribName = sNameBuffer.makeStringAndClear();
1027 if( bAddNamespace )
1029 if( !pNewNamespaceMap )
1031 pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
1032 pNamespaceMap = pNewNamespaceMap;
1034 pNewNamespaceMap->Add( sPrefix, sNamespace );
1035 sNameBuffer.append( GetXMLToken(XML_XMLNS) );
1036 sNameBuffer.append( sal_Unicode(':') );
1037 sNameBuffer.append( sPrefix );
1038 rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
1039 sNamespace );
1043 OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
1044 OSL_ENSURE( sOldValue.isEmpty(), "alien attribute exists already" );
1045 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
1046 if( sOldValue.isEmpty() )
1047 rAttrList.AddAttribute( sAttribName, aData.Value );
1050 delete pNewNamespaceMap;
1052 else
1054 handleSpecialItem( rAttrList, rProperty, rUnitConverter,
1055 rNamespaceMap, pProperties, nIdx );
1058 else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1059 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
1061 OUString aValue;
1062 const OUString sName( rNamespaceMap.GetQNameByKey(
1063 maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
1064 maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );
1066 sal_Bool bRemove = sal_False;
1067 if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1068 MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
1070 aValue = rAttrList.getValueByName( sName );
1071 bRemove = sal_True;
1074 if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
1076 if( bRemove )
1077 rAttrList.RemoveAttribute( sName );
1078 rAttrList.AddAttribute( sName, aValue );
1083 void SvXMLExportPropertyMapper::exportElementItems(
1084 SvXMLExport& rExport,
1085 const ::std::vector< XMLPropertyState >& rProperties,
1086 sal_uInt16 nFlags,
1087 const std::vector<sal_uInt16>& rIndexArray ) const
1089 const sal_uInt16 nCount = rIndexArray.size();
1091 sal_Bool bItemsExported = sal_False;
1092 for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
1094 const sal_uInt16 nElement = rIndexArray[nIndex];
1096 OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
1097 rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
1098 "wrong mid flag!" );
1100 rExport.IgnorableWhitespace();
1101 handleElementItem( rExport, rProperties[nElement],
1102 nFlags, &rProperties, nElement );
1103 bItemsExported = sal_True;
1106 if( bItemsExported )
1107 rExport.IgnorableWhitespace();
1110 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */