bump product version to 5.0.4.1
[LibreOffice.git] / xmloff / source / style / xmlexppr.cxx
blob16b48126b4d3cda036dc8cd2cd4ca851a3b91df3
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/XPropertyState.hpp>
23 #include <com/sun/star/beans/XMultiPropertySet.hpp>
24 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
25 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
26 #include <rtl/ustrbuf.hxx>
27 #include <list>
28 #include <map>
30 #include <xmloff/xmlexppr.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/attrlist.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmlnmspe.hxx>
35 #include <xmloff/xmlexp.hxx>
36 #include <xmloff/xmlprmap.hxx>
37 #include <xmloff/maptype.hxx>
38 #include <xmloff/xmltypes.hxx>
39 #include <xmloff/xmlprhdl.hxx>
41 using namespace ::std;
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::lang;
46 using namespace ::xmloff::token;
48 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
49 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
51 namespace {
53 struct XMLPropTokens_Impl
55 sal_uInt16 nType;
56 XMLTokenEnum eToken;
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 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 // public methods
83 // Take all properties of the XPropertySet which are also found in the
84 // XMLPropertyMapEntry-array and which are not set to their default-value,
85 // if a state is available.
86 // After that I call the method 'ContextFilter'.
88 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
90 class XMLPropertyStates_Impl
92 XMLPropertyStateList_Impl aPropStates;
93 XMLPropertyStateList_Impl::iterator aLastItr;
94 sal_uInt32 nCount;
95 public:
96 XMLPropertyStates_Impl();
97 void AddPropertyState(const XMLPropertyState& rPropState);
98 void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
101 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
102 aPropStates(),
103 nCount(0)
105 aLastItr = aPropStates.begin();
108 void XMLPropertyStates_Impl::AddPropertyState(
109 const XMLPropertyState& rPropState)
111 XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
112 bool bInserted(false);
113 if (nCount)
115 if (aLastItr->mnIndex < rPropState.mnIndex)
116 aItr = ++aLastItr;
120 // TODO: one path required only
121 if (aItr == aPropStates.end())
123 aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
124 bInserted = true;
125 nCount++;
127 else if (aItr->mnIndex > rPropState.mnIndex)
129 aLastItr = aPropStates.insert(aItr, rPropState);
130 bInserted = true;
131 nCount++;
134 while(!bInserted && (aItr++ != aPropStates.end()));
137 void XMLPropertyStates_Impl::FillPropertyStateVector(
138 std::vector<XMLPropertyState>& rVector)
140 if (nCount)
142 rVector.resize(nCount, XMLPropertyState(-1));
143 ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
147 class FilterPropertyInfo_Impl
149 const OUString sApiName;
150 std::list<sal_uInt32> aIndexes;
152 public:
154 FilterPropertyInfo_Impl( const OUString& rApiName,
155 const sal_uInt32 nIndex);
157 const OUString& GetApiName() const { return sApiName; }
158 std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
160 // for sort
161 bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
163 return (GetApiName() < rArg.GetApiName());
167 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
168 const OUString& rApiName,
169 const sal_uInt32 nIndex ) :
170 sApiName( rApiName )
172 aIndexes.push_back(nIndex);
175 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
177 class FilterPropertiesInfo_Impl
179 sal_uInt32 nCount;
180 FilterPropertyInfoList_Impl aPropInfos;
181 FilterPropertyInfoList_Impl::iterator aLastItr;
183 Sequence <OUString> *pApiNames;
185 public:
186 FilterPropertiesInfo_Impl();
187 ~FilterPropertiesInfo_Impl();
189 void AddProperty(const OUString& rApiName, const sal_uInt32 nIndex);
190 const uno::Sequence<OUString>& GetApiNames();
191 void FillPropertyStateArray(
192 vector< XMLPropertyState >& rPropStates,
193 const Reference< XPropertySet >& xPropSet,
194 const rtl::Reference< XMLPropertySetMapper >& maPropMapper,
195 const bool bDefault = false);
196 sal_uInt32 GetPropertyCount() const { return nCount; }
199 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
200 nCount(0),
201 aPropInfos(),
202 pApiNames( 0 )
204 aLastItr = aPropInfos.begin();
207 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
209 delete pApiNames;
212 void FilterPropertiesInfo_Impl::AddProperty(
213 const OUString& rApiName, const sal_uInt32 nIndex)
215 aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
216 nCount++;
218 OSL_ENSURE( !pApiNames, "performance warning: API names already retrieved" );
219 if( pApiNames )
221 delete pApiNames;
222 pApiNames = NULL;
226 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
228 OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
229 if( !pApiNames )
231 // we have to do three things:
232 // 1) sort API names,
233 // 2) merge duplicates,
234 // 3) construct sequence
236 // sort names
237 aPropInfos.sort();
239 // merge duplicates
240 if ( nCount > 1 )
242 FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
243 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
244 FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
245 ++aCurrent;
247 while ( aCurrent != aEnd )
249 // equal to next element?
250 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
252 // if equal: merge index lists
253 aOld->GetIndexes().merge( aCurrent->GetIndexes() );
254 // erase element, and continue with next
255 aCurrent = aPropInfos.erase( aCurrent );
256 nCount--;
258 else
260 // remember old element and continue with next
261 aOld = aCurrent;
262 ++aCurrent;
267 // construct sequence
268 pApiNames = new Sequence < OUString >( nCount );
269 OUString *pNames = pApiNames->getArray();
270 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
271 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
272 for ( ; aItr != aEnd; ++aItr, ++pNames)
273 *pNames = aItr->GetApiName();
276 return *pApiNames;
279 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
280 vector< XMLPropertyState >& rPropStates,
281 const Reference< XPropertySet >& rPropSet,
282 const rtl::Reference< XMLPropertySetMapper >& rPropMapper,
283 const bool bDefault )
285 XMLPropertyStates_Impl aPropStates;
287 const uno::Sequence<OUString>& rApiNames = GetApiNames();
289 Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
290 if (xTolPropSet.is())
292 if (!bDefault)
294 Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
295 sal_Int32 nResultCount(aResults.getLength());
296 if (nResultCount > 0)
298 const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
299 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
300 XMLPropertyState aNewProperty( -1 );
301 sal_uInt32 i = 0;
302 while (nResultCount > 0 && i < nCount)
304 if (pResults->Name == aPropIter->GetApiName())
306 aNewProperty.mnIndex = -1;
307 aNewProperty.maValue = pResults->Value;
309 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
310 aIndexItr != aPropIter->GetIndexes().end();
311 ++aIndexItr )
313 aNewProperty.mnIndex = *aIndexItr;
314 aPropStates.AddPropertyState( aNewProperty );
316 ++pResults;
317 --nResultCount;
319 ++aPropIter;
320 ++i;
324 else
326 Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
327 OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
328 const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
329 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
330 XMLPropertyState aNewProperty( -1 );
331 sal_uInt32 nResultCount(aResults.getLength());
332 OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
333 for( sal_uInt32 i = 0; i < nResultCount; ++i )
335 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
336 ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
338 aNewProperty.mnIndex = -1;
339 aNewProperty.maValue = pResults->Value;
341 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
342 aIndexItr != aPropIter->GetIndexes().end();
343 ++aIndexItr )
345 aNewProperty.mnIndex = *aIndexItr;
346 aPropStates.AddPropertyState( aNewProperty );
349 ++pResults;
350 ++aPropIter;
354 else
356 Sequence < PropertyState > aStates;
357 const PropertyState *pStates = 0;
358 Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
359 if( xPropState.is() )
361 aStates = xPropState->getPropertyStates( rApiNames );
362 pStates = aStates.getConstArray();
365 Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
366 if( xMultiPropSet.is() && !bDefault )
368 Sequence < Any > aValues;
369 if( pStates )
371 // step 1: get value count
372 sal_uInt32 nValueCount = 0;
373 sal_uInt32 i;
375 for( i = 0; i < nCount; ++i, ++pStates )
377 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
378 nValueCount++;
381 if( nValueCount )
383 // step 2: collect property names
384 Sequence < OUString > aAPINames( nValueCount );
385 OUString *pAPINames = aAPINames.getArray();
387 ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
388 aPropIters.reserve( nValueCount );
390 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
391 OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
393 pStates = aStates.getConstArray();
394 i = 0;
395 while( i < nValueCount )
397 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
399 *pAPINames++ = aItr->GetApiName();
400 aPropIters.push_back( aItr );
401 ++i;
403 ++aItr;
404 ++pStates;
407 aValues = xMultiPropSet->getPropertyValues( aAPINames );
408 const Any *pValues = aValues.getConstArray();
410 ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
411 pPropIter = aPropIters.begin();
413 XMLPropertyState aNewProperty( -1 );
414 for( i = 0; i < nValueCount; ++i )
416 aNewProperty.mnIndex = -1;
417 aNewProperty.maValue = *pValues;
419 const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
420 for ( std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
421 aIndexItr != rIndexes.end();
422 ++aIndexItr
425 aNewProperty.mnIndex = *aIndexItr;
426 aPropStates.AddPropertyState( aNewProperty );
429 ++pPropIter;
430 ++pValues;
434 else
436 aValues = xMultiPropSet->getPropertyValues( rApiNames );
437 const Any *pValues = aValues.getConstArray();
439 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
440 for(sal_uInt32 i = 0; i < nCount; ++i)
442 // The value is stored in the PropertySet itself, add to list.
443 XMLPropertyState aNewProperty( -1 );
444 aNewProperty.maValue = *pValues;
445 ++pValues;
446 for( std::list<sal_uInt32>::iterator aIndexItr =
447 aItr->GetIndexes().begin();
448 aIndexItr != aItr->GetIndexes().end();
449 ++aIndexItr )
451 aNewProperty.mnIndex = *aIndexItr;
452 aPropStates.AddPropertyState( aNewProperty );
454 ++aItr;
458 else
460 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
461 for(sal_uInt32 i = 0; i < nCount; ++i)
463 bool bDirectValue =
464 !pStates || *pStates == PropertyState_DIRECT_VALUE;
465 if( bDirectValue || bDefault )
467 // The value is stored in the PropertySet itself, add to list.
468 bool bGotValue = false;
469 XMLPropertyState aNewProperty( -1 );
470 for( std::list<sal_uInt32>::const_iterator aIndexItr =
471 aItr->GetIndexes().begin();
472 aIndexItr != aItr->GetIndexes().end();
473 ++aIndexItr )
475 if( bDirectValue ||
476 (rPropMapper->GetEntryFlags( *aIndexItr ) &
477 MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
481 if( !bGotValue )
483 aNewProperty.maValue =
484 rPropSet->getPropertyValue( aItr->GetApiName() );
485 bGotValue = true;
487 aNewProperty.mnIndex = *aIndexItr;
488 aPropStates.AddPropertyState( aNewProperty );
490 catch( UnknownPropertyException& )
492 // might be a problem of getImplemenetationId
493 OSL_ENSURE( false, "unknown property in getPropertyValue" );
500 ++aItr;
501 if( pStates )
502 ++pStates;
506 aPropStates.FillPropertyStateVector(rPropStates);
511 struct SvXMLExportPropertyMapper::Impl
513 typedef std::map<css::uno::Reference<css::beans::XPropertySetInfo>, FilterPropertiesInfo_Impl*> CacheType;
514 CacheType maCache;
516 rtl::Reference<SvXMLExportPropertyMapper> mxNextMapper;
517 rtl::Reference<XMLPropertySetMapper> mxPropMapper;
519 OUString maStyleName;
521 ~Impl()
523 CacheType::iterator it = maCache.begin(), itEnd = maCache.end();
524 for (; it != itEnd; ++it)
525 delete it->second;
529 // ctor/dtor , class SvXMLExportPropertyMapper
531 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
532 const rtl::Reference< XMLPropertySetMapper >& rMapper ) :
533 mpImpl(new Impl)
535 mpImpl->mxPropMapper = rMapper;
538 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
540 delete mpImpl;
543 void SvXMLExportPropertyMapper::ChainExportMapper(
544 const rtl::Reference< SvXMLExportPropertyMapper>& rMapper )
546 // add map entries from rMapper to current map
547 mpImpl->mxPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
548 // rMapper uses the same map as 'this'
549 rMapper->mpImpl->mxPropMapper = mpImpl->mxPropMapper;
551 // set rMapper as last mapper in current chain
552 rtl::Reference< SvXMLExportPropertyMapper > xNext = mpImpl->mxNextMapper;
553 if( xNext.is())
555 while (xNext->mpImpl->mxNextMapper.is())
556 xNext = xNext->mpImpl->mxNextMapper;
557 xNext->mpImpl->mxNextMapper = rMapper;
559 else
560 mpImpl->mxNextMapper = rMapper;
562 // if rMapper was already chained, correct
563 // map pointer of successors
564 xNext = rMapper;
566 while (xNext->mpImpl->mxNextMapper.is())
568 xNext = xNext->mpImpl->mxNextMapper;
569 xNext->mpImpl->mxPropMapper = mpImpl->mxPropMapper;
573 std::vector<XMLPropertyState> SvXMLExportPropertyMapper::Filter(
574 const uno::Reference<beans::XPropertySet>& rPropSet, bool bEnableFoFontFamily ) const
576 return _Filter(rPropSet, false, bEnableFoFontFamily);
579 std::vector<XMLPropertyState> SvXMLExportPropertyMapper::FilterDefaults(
580 const uno::Reference<beans::XPropertySet>& rPropSet, bool bEnableFoFontFamily ) const
582 return _Filter(rPropSet, true, bEnableFoFontFamily);
585 vector<XMLPropertyState> SvXMLExportPropertyMapper::_Filter(
586 const Reference<XPropertySet>& xPropSet, bool bDefault, bool bEnableFoFontFamily ) const
588 vector< XMLPropertyState > aPropStateArray;
590 // Retrieve XPropertySetInfo and XPropertyState
591 Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
592 if( !xInfo.is() )
593 return aPropStateArray;
595 sal_Int32 nProps = mpImpl->mxPropMapper->GetEntryCount();
597 FilterPropertiesInfo_Impl *pFilterInfo = 0;
599 Impl::CacheType::iterator aIter = mpImpl->maCache.find(xInfo);
600 if (aIter != mpImpl->maCache.end())
601 pFilterInfo = (*aIter).second;
603 bool bDelInfo = false;
604 if( !pFilterInfo )
606 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
607 pFilterInfo = new FilterPropertiesInfo_Impl;
608 for( sal_Int32 i=0; i < nProps; i++ )
610 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
611 // Does the PropertySet contain name of mpEntries-array ?
612 const OUString& rAPIName = mpImpl->mxPropMapper->GetEntryAPIName( i );
613 const sal_Int32 nFlags = mpImpl->mxPropMapper->GetEntryFlags( i );
614 if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
615 ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
616 xInfo->hasPropertyByName( rAPIName ) ) )
618 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
619 mpImpl->mxPropMapper->GetEarliestODFVersionForExport(i));
620 if( nCurrentVersion >= nEarliestODFVersionForExport
621 || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
622 || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
623 pFilterInfo->AddProperty(rAPIName, i);
627 // Check whether the property set info is destroyed if it is assigned to
628 // a weak reference only; If it is destroyed, then every instance of
629 // getPropertySetInfo returns a new object; such property set infos must
630 // not be cached:
631 WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
632 xInfo = 0;
633 xInfo = xWeakInfo;
634 if( xInfo.is() )
636 mpImpl->maCache.insert(Impl::CacheType::value_type(xInfo, pFilterInfo));
638 else
639 bDelInfo = true;
642 if( pFilterInfo->GetPropertyCount() )
646 pFilterInfo->FillPropertyStateArray(
647 aPropStateArray, xPropSet, mpImpl->mxPropMapper, bDefault);
649 catch( UnknownPropertyException& )
651 // might be a problem of getImplemenetationId
652 OSL_ENSURE( false, "unknown property in getPropertyStates" );
656 // Call centext-filter
657 if( !aPropStateArray.empty() )
658 ContextFilter(bEnableFoFontFamily, aPropStateArray, xPropSet);
660 // Have to do if we change from a vector to a list or something like that
662 if( bDelInfo )
663 delete pFilterInfo;
665 return aPropStateArray;
668 void SvXMLExportPropertyMapper::ContextFilter(
669 bool bEnableFoFontFamily,
670 vector< XMLPropertyState >& rProperties,
671 Reference< XPropertySet > rPropSet ) const
673 // Derived class could implement this.
674 if (mpImpl->mxNextMapper.is())
675 mpImpl->mxNextMapper->ContextFilter(bEnableFoFontFamily, rProperties, rPropSet);
678 // Compares two Sequences of XMLPropertyState:
679 // 1.Number of elements equal ?
680 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
681 // 3.Value of each element equal ?
682 bool SvXMLExportPropertyMapper::Equals(
683 const vector< XMLPropertyState >& aProperties1,
684 const vector< XMLPropertyState >& aProperties2 ) const
686 bool bRet = true;
687 sal_uInt32 nCount = aProperties1.size();
689 if( nCount == aProperties2.size() )
691 sal_uInt32 nIndex = 0;
692 while( bRet && nIndex < nCount )
694 const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
695 const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
697 // Compare index. If equal, compare value
698 if( rProp1.mnIndex == rProp2.mnIndex )
700 if( rProp1.mnIndex != -1 )
702 // Now compare values
703 if ( (mpImpl->mxPropMapper->GetEntryType( rProp1.mnIndex ) &
704 XML_TYPE_BUILDIN_CMP ) != 0 )
705 // simple type ( binary compare )
706 bRet = ( rProp1.maValue == rProp2.maValue );
707 else
708 // complex type ( ask for compare-function )
709 bRet = mpImpl->mxPropMapper->GetPropertyHandler(
710 rProp1.mnIndex )->equals( rProp1.maValue,
711 rProp2.maValue );
714 else
715 bRet = false;
717 nIndex++;
720 else
721 bRet = false;
723 return bRet;
726 /** fills the given attribute list with the items in the given set
727 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
728 const ::std::vector< XMLPropertyState >& rProperties,
729 const SvXMLUnitConverter& rUnitConverter,
730 const SvXMLNamespaceMap& rNamespaceMap,
731 sal_uInt16 nFlags ) const
733 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
734 nFlags, 0, -1, -1 );
737 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
738 const ::std::vector< XMLPropertyState >& rProperties,
739 const SvXMLUnitConverter& rUnitConverter,
740 const SvXMLNamespaceMap& rNamespaceMap,
741 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
742 sal_uInt16 nFlags ) const
744 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
745 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
749 void SvXMLExportPropertyMapper::exportXML(
750 SvXMLExport& rExport,
751 const ::std::vector< XMLPropertyState >& rProperties,
752 SvXmlExportFlags nFlags,
753 bool bUseExtensionNamespaceForGraphicProperties) const
755 exportXML(rExport, rProperties, -1, -1, nFlags, bUseExtensionNamespaceForGraphicProperties);
759 void SvXMLExportPropertyMapper::exportXML(
760 SvXMLExport& rExport,
761 const ::std::vector< XMLPropertyState >& rProperties,
762 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
763 SvXmlExportFlags nFlags, bool bUseExtensionNamespaceForGraphicProperties) const
765 sal_uInt16 nPropTypeFlags = 0;
766 for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
768 sal_uInt16 nPropType = aPropTokens[i].nType;
769 if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
771 sal_uInt16 nNamespace = XML_NAMESPACE_STYLE;
772 if (bUseExtensionNamespaceForGraphicProperties &&
773 aPropTokens[i].eToken == xmloff::token::XML_GRAPHIC_PROPERTIES)
775 nNamespace = XML_NAMESPACE_LO_EXT;
776 if (rExport.getDefaultVersion() <= SvtSaveOptions::ODFVER_012)
778 continue; // don't write for ODF <= 1.2
782 std::vector<sal_uInt16> aIndexArray;
784 _exportXML( nPropType, nPropTypeFlags,
785 rExport.GetAttrList(), rProperties,
786 rExport.GetMM100UnitConverter(),
787 rExport.GetNamespaceMap(),
788 nFlags, &aIndexArray,
789 nPropMapStartIdx, nPropMapEndIdx );
791 if( rExport.GetAttrList().getLength() > 0L ||
792 (nFlags & SvXmlExportFlags::EMPTY) ||
793 !aIndexArray.empty() )
795 SvXMLElementExport aElem( rExport, nNamespace,
796 aPropTokens[i].eToken,
797 bool(nFlags & SvXmlExportFlags::IGN_WS),
798 false );
800 exportElementItems( rExport, rProperties, nFlags, aIndexArray );
806 /** this method is called for every item that has the
807 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
808 void SvXMLExportPropertyMapper::handleSpecialItem(
809 SvXMLAttributeList& rAttrList,
810 const XMLPropertyState& rProperty,
811 const SvXMLUnitConverter& rUnitConverter,
812 const SvXMLNamespaceMap& rNamespaceMap,
813 const ::std::vector< XMLPropertyState > *pProperties,
814 sal_uInt32 nIdx ) const
816 OSL_ENSURE(mpImpl->mxNextMapper.is(), "special item not handled in xml export");
817 if (mpImpl->mxNextMapper.is())
818 mpImpl->mxNextMapper->handleSpecialItem(
819 rAttrList, rProperty, rUnitConverter, rNamespaceMap, pProperties, nIdx);
822 /** this method is called for every item that has the
823 MID_FLAG_ELEMENT_EXPORT flag set */
824 void SvXMLExportPropertyMapper::handleElementItem(
825 SvXMLExport& rExport,
826 const XMLPropertyState& rProperty,
827 SvXmlExportFlags nFlags,
828 const ::std::vector< XMLPropertyState > *pProperties,
829 sal_uInt32 nIdx ) const
831 OSL_ENSURE(mpImpl->mxNextMapper.is(), "element item not handled in xml export");
832 if (mpImpl->mxNextMapper.is())
833 mpImpl->mxNextMapper->handleElementItem(rExport, rProperty, nFlags, pProperties, nIdx);
836 // protected methods
838 /** fills the given attribute list with the items in the given set */
839 void SvXMLExportPropertyMapper::_exportXML(
840 sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
841 SvXMLAttributeList& rAttrList,
842 const ::std::vector< XMLPropertyState >& rProperties,
843 const SvXMLUnitConverter& rUnitConverter,
844 const SvXMLNamespaceMap& rNamespaceMap,
845 SvXmlExportFlags nFlags,
846 std::vector<sal_uInt16>* pIndexArray,
847 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
849 const sal_uInt32 nCount = rProperties.size();
850 sal_uInt32 nIndex = 0;
852 if( -1 == nPropMapStartIdx )
853 nPropMapStartIdx = 0;
854 if( -1 == nPropMapEndIdx )
855 nPropMapEndIdx = mpImpl->mxPropMapper->GetEntryCount();
857 while( nIndex < nCount )
859 sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
860 if( nPropMapIdx >= nPropMapStartIdx &&
861 nPropMapIdx < nPropMapEndIdx )// valid entry?
863 sal_uInt32 nEFlags = mpImpl->mxPropMapper->GetEntryFlags(nPropMapIdx);
864 sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
865 OSL_ENSURE(nEPType >= (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT),
866 "no prop type specified");
867 rPropTypeFlags |= (1 << nEPType);
868 if( nEPType == nPropType )
870 // we have a valid map entry here, so lets use it...
871 if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
873 // element items do not add any properties,
874 // we export it later
875 if( pIndexArray )
877 pIndexArray->push_back( (sal_uInt16)nIndex );
880 else
882 _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
883 rNamespaceMap, nFlags, &rProperties, nIndex );
888 nIndex++;
892 void SvXMLExportPropertyMapper::_exportXML(
893 SvXMLAttributeList& rAttrList,
894 const XMLPropertyState& rProperty,
895 const SvXMLUnitConverter& rUnitConverter,
896 const SvXMLNamespaceMap& rNamespaceMap,
897 SvXmlExportFlags /*nFlags*/,
898 const ::std::vector< XMLPropertyState > *pProperties,
899 sal_uInt32 nIdx ) const
901 if ((mpImpl->mxPropMapper->GetEntryFlags(rProperty.mnIndex) & MID_FLAG_SPECIAL_ITEM_EXPORT) != 0)
903 uno::Reference< container::XNameContainer > xAttrContainer;
904 if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
906 SvXMLNamespaceMap *pNewNamespaceMap = 0;
907 const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
909 uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
910 const OUString* pAttribName = aAttribNames.getConstArray();
912 const sal_Int32 nCount = aAttribNames.getLength();
914 OUStringBuffer sNameBuffer;
915 xml::AttributeData aData;
916 for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
918 xAttrContainer->getByName( *pAttribName ) >>= aData;
919 OUString sAttribName( *pAttribName );
921 // extract namespace prefix from attribute name if it exists
922 OUString sPrefix;
923 const sal_Int32 nColonPos =
924 pAttribName->indexOf( ':' );
925 if( nColonPos != -1 )
926 sPrefix = pAttribName->copy( 0, nColonPos );
928 if( !sPrefix.isEmpty() )
930 OUString sNamespace( aData.Namespace );
932 // if the prefix isn't defined yet or has another meaning,
933 // we have to redefine it now.
934 sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
935 if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
937 bool bAddNamespace = false;
938 if( USHRT_MAX == nKey )
940 // The prefix is unused, so it is sufficient
941 // to add it to the namespace map.
942 bAddNamespace = true;
944 else
946 // check if there is a prefix registered for the
947 // namepsace URI
948 nKey = pNamespaceMap->GetKeyByName( sNamespace );
949 if( XML_NAMESPACE_UNKNOWN == nKey )
951 // There is no prefix for the namespace, so
952 // we have to generate one and have to add it.
953 sal_Int32 n=0;
954 OUString sOrigPrefix( sPrefix );
957 sNameBuffer.append( sOrigPrefix );
958 sNameBuffer.append( ++n );
959 sPrefix = sNameBuffer.makeStringAndClear();
960 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
962 while( nKey != USHRT_MAX );
964 bAddNamespace = true;
966 else
968 // If there is a prefix for the namespace,
969 // we reuse that.
970 sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
972 // In any case, the attribute name has to be adapted.
973 sNameBuffer.append( sPrefix + ":" + pAttribName->copy( nColonPos+1 ) );
974 sAttribName = sNameBuffer.makeStringAndClear();
977 if( bAddNamespace )
979 if( !pNewNamespaceMap )
981 pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
982 pNamespaceMap = pNewNamespaceMap;
984 pNewNamespaceMap->Add( sPrefix, sNamespace );
985 sNameBuffer.append( GetXMLToken(XML_XMLNS) + ":" + sPrefix );
986 rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
987 sNamespace );
991 OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
992 OSL_ENSURE( sOldValue.isEmpty(), "alien attribute exists already" );
993 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
994 if( sOldValue.isEmpty() )
995 rAttrList.AddAttribute( sAttribName, aData.Value );
998 delete pNewNamespaceMap;
1000 else
1002 handleSpecialItem( rAttrList, rProperty, rUnitConverter,
1003 rNamespaceMap, pProperties, nIdx );
1006 else if ((mpImpl->mxPropMapper->GetEntryFlags(rProperty.mnIndex) & MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0)
1008 OUString aValue;
1009 const OUString sName = rNamespaceMap.GetQNameByKey(
1010 mpImpl->mxPropMapper->GetEntryNameSpace(rProperty.mnIndex),
1011 mpImpl->mxPropMapper->GetEntryXMLName(rProperty.mnIndex));
1013 bool bRemove = false;
1014 if ((mpImpl->mxPropMapper->GetEntryFlags( rProperty.mnIndex ) & MID_FLAG_MERGE_ATTRIBUTE) != 0)
1016 aValue = rAttrList.getValueByName( sName );
1017 bRemove = true;
1020 if (mpImpl->mxPropMapper->exportXML(aValue, rProperty, rUnitConverter))
1022 if( bRemove )
1023 rAttrList.RemoveAttribute( sName );
1024 rAttrList.AddAttribute( sName, aValue );
1029 void SvXMLExportPropertyMapper::exportElementItems(
1030 SvXMLExport& rExport,
1031 const ::std::vector< XMLPropertyState >& rProperties,
1032 SvXmlExportFlags nFlags,
1033 const std::vector<sal_uInt16>& rIndexArray ) const
1035 const sal_uInt16 nCount = rIndexArray.size();
1037 bool bItemsExported = false;
1038 for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
1040 const sal_uInt16 nElement = rIndexArray[nIndex];
1042 OSL_ENSURE( 0 != (mpImpl->mxPropMapper->GetEntryFlags(
1043 rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
1044 "wrong mid flag!" );
1046 rExport.IgnorableWhitespace();
1047 handleElementItem( rExport, rProperties[nElement],
1048 nFlags, &rProperties, nElement );
1049 bItemsExported = true;
1052 if( bItemsExported )
1053 rExport.IgnorableWhitespace();
1056 const rtl::Reference<XMLPropertySetMapper>& SvXMLExportPropertyMapper::getPropertySetMapper() const
1058 return mpImpl->mxPropMapper;
1061 void SvXMLExportPropertyMapper::SetStyleName( const OUString& rStyleName )
1063 mpImpl->maStyleName = rStyleName;
1066 const OUString& SvXMLExportPropertyMapper::GetStyleName() const
1068 return mpImpl->maStyleName;
1071 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */