Update ooo320-m1
[ooovba.git] / xmloff / source / style / xmlexppr.cxx
blobeac3d834cc66e4409c491b4a86b8b2fdf1fc2c25
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlexppr.cxx,v $
10 * $Revision: 1.51 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/xml/AttributeData.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertyState.hpp>
37 #include <com/sun/star/lang/XTypeProvider.hpp>
38 #include <com/sun/star/beans/XMultiPropertySet.hpp>
39 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
40 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
41 #include <rtl/ustrbuf.hxx>
42 #include <list>
43 #include <hash_map>
45 #include <xmloff/xmlexppr.hxx>
46 #include <xmloff/xmltoken.hxx>
47 #include <xmloff/attrlist.hxx>
48 #include <xmloff/nmspmap.hxx>
49 #include "xmlnmspe.hxx"
50 #include <xmloff/xmlexp.hxx>
51 #include <xmloff/xmlprmap.hxx>
52 #include <xmloff/PropertySetInfoHash.hxx>
53 #include <comphelper/stl_types.hxx>
55 #ifndef _SVSTDARR_USHORTS
56 #define _SVSTDARR_USHORTS
57 #include <svtools/svstdarr.hxx>
58 #endif
60 using ::rtl::OUString;
61 using ::rtl::OUStringBuffer;
63 using namespace ::std;
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::lang;
68 using namespace ::xmloff::token;
70 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
72 struct XMLPropTokens_Impl
74 sal_uInt16 nType;
75 XMLTokenEnum eToken;
78 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
79 const sal_uInt16 MAX_PROP_TYPES =
80 (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
81 (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
83 static XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
85 ENTRY(CHART),
86 ENTRY(GRAPHIC),
87 ENTRY(TABLE),
88 ENTRY(TABLE_COLUMN),
89 ENTRY(TABLE_ROW),
90 ENTRY(TABLE_CELL),
91 ENTRY(LIST_LEVEL),
92 ENTRY(PARAGRAPH),
93 ENTRY(TEXT),
94 ENTRY(DRAWING_PAGE),
95 ENTRY(PAGE_LAYOUT),
96 ENTRY(HEADER_FOOTER),
97 ENTRY(RUBY),
98 ENTRY(SECTION)
101 ///////////////////////////////////////////////////////////////////////////////
103 // public methods
106 ///////////////////////////////////////////////////////////////////////////
108 // Take all properties of the XPropertySet which are also found in the
109 // XMLPropertyMapEntry-array and which are not set to their default-value,
110 // if a state is available.
112 // After that I call the method 'ContextFilter'.
115 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
117 class XMLPropertyStates_Impl
119 XMLPropertyStateList_Impl aPropStates;
120 XMLPropertyStateList_Impl::iterator aLastItr;
121 sal_uInt32 nCount;
122 public:
123 XMLPropertyStates_Impl();
124 void AddPropertyState(const XMLPropertyState& rPropState);
125 void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
128 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
129 aPropStates(),
130 nCount(0)
132 aLastItr = aPropStates.begin();
135 void XMLPropertyStates_Impl::AddPropertyState(
136 const XMLPropertyState& rPropState)
138 XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
139 sal_Bool bInserted(sal_False);
140 if (nCount)
142 if (aLastItr->mnIndex < rPropState.mnIndex)
143 aItr = ++aLastItr;
147 // TODO: one path required only
148 if (aItr == aPropStates.end())
150 aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
151 bInserted = sal_True;
152 nCount++;
154 else if (aItr->mnIndex > rPropState.mnIndex)
156 aLastItr = aPropStates.insert(aItr, rPropState);
157 bInserted = sal_True;
158 nCount++;
161 while(!bInserted && (aItr++ != aPropStates.end()));
164 void XMLPropertyStates_Impl::FillPropertyStateVector(
165 std::vector<XMLPropertyState>& rVector)
167 if (nCount)
169 rVector.resize(nCount, XMLPropertyState(-1));
170 ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
174 class FilterPropertyInfo_Impl
176 const rtl::OUString sApiName;
177 std::list<sal_uInt32> aIndexes;
178 sal_uInt32 nCount;
180 public:
182 FilterPropertyInfo_Impl( const rtl::OUString& rApiName,
183 const sal_uInt32 nIndex);
185 const OUString& GetApiName() const { return sApiName; }
186 std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
188 void AddIndex( sal_uInt32 nIndex )
190 aIndexes.push_back(nIndex);
191 nCount++;
194 // for sort
195 sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
197 return (GetApiName() < rArg.GetApiName());
201 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
202 const rtl::OUString& rApiName,
203 const sal_uInt32 nIndex ) :
204 sApiName( rApiName ),
205 aIndexes(),
206 nCount(1)
208 aIndexes.push_back(nIndex);
211 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
213 // ----------------------------------------------------------------------------
215 class FilterPropertiesInfo_Impl
217 sal_uInt32 nCount;
218 FilterPropertyInfoList_Impl aPropInfos;
219 FilterPropertyInfoList_Impl::iterator aLastItr;
221 Sequence <OUString> *pApiNames;
223 public:
224 FilterPropertiesInfo_Impl();
225 ~FilterPropertiesInfo_Impl();
227 void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex);
228 const uno::Sequence<OUString>& GetApiNames();
229 void FillPropertyStateArray(
230 vector< XMLPropertyState >& rPropStates,
231 const Reference< XPropertySet >& xPropSet,
232 const UniReference< XMLPropertySetMapper >& maPropMapper,
233 const sal_Bool bDefault = sal_False);
234 sal_uInt32 GetPropertyCount() const { return nCount; }
237 // ----------------------------------------------------------------------------
239 typedef std::hash_map
241 PropertySetInfoKey,
242 FilterPropertiesInfo_Impl *,
243 PropertySetInfoHash,
244 PropertySetInfoHash
246 FilterOropertiesHashMap_Impl;
248 class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
250 public:
251 ~FilterPropertiesInfos_Impl ();
254 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
256 FilterOropertiesHashMap_Impl::iterator aIter = begin();
257 FilterOropertiesHashMap_Impl::iterator aEnd = end();
258 while( aIter != aEnd )
260 delete (*aIter).second;
261 (*aIter).second = 0;
262 ++aIter;
266 // ----------------------------------------------------------------------------
268 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
269 nCount(0),
270 aPropInfos(),
271 pApiNames( 0 )
273 aLastItr = aPropInfos.begin();
276 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
278 delete pApiNames;
281 void FilterPropertiesInfo_Impl::AddProperty(
282 const rtl::OUString& rApiName, const sal_uInt32 nIndex)
284 aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
285 nCount++;
287 OSL_ENSURE( !pApiNames, "perfomance warning: API names already retrieved" );
288 if( pApiNames )
290 delete pApiNames;
291 pApiNames = NULL;
294 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
296 OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
297 if( !pApiNames )
299 // we have to do three things:
300 // 1) sort API names,
301 // 2) merge duplicates,
302 // 3) construct sequence
304 // sort names
305 aPropInfos.sort();
307 // merge duplicates
308 if ( nCount > 1 )
310 FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
311 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
312 FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
313 aCurrent++;
315 while ( aCurrent != aEnd )
317 // equal to next element?
318 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
320 // if equal: merge index lists
321 aOld->GetIndexes().merge( aCurrent->GetIndexes() );
322 // erase element, and continue with next
323 aCurrent = aPropInfos.erase( aCurrent );
324 nCount--;
326 else
328 // remember old element and continue with next
329 aOld = aCurrent;
330 aCurrent++;
335 // construct sequence
336 pApiNames = new Sequence < OUString >( nCount );
337 OUString *pNames = pApiNames->getArray();
338 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
339 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
340 for ( ; aItr != aEnd; aItr++, pNames++)
341 *pNames = aItr->GetApiName();
344 return *pApiNames;
347 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
348 vector< XMLPropertyState >& rPropStates,
349 const Reference< XPropertySet >& rPropSet,
350 const UniReference< XMLPropertySetMapper >& rPropMapper,
351 const sal_Bool bDefault )
353 XMLPropertyStates_Impl aPropStates;
355 const uno::Sequence<OUString>& rApiNames = GetApiNames();
357 Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
358 if (xTolPropSet.is())
360 if (!bDefault)
362 Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
363 sal_Int32 nResultCount(aResults.getLength());
364 if (nResultCount > 0)
366 const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
367 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
368 XMLPropertyState aNewProperty( -1 );
369 sal_uInt32 i = 0;
370 while (nResultCount > 0 && i < nCount)
372 if (pResults->Name == aPropIter->GetApiName())
374 aNewProperty.mnIndex = -1;
375 aNewProperty.maValue = pResults->Value;
377 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
378 aIndexItr != aPropIter->GetIndexes().end();
379 ++aIndexItr )
381 aNewProperty.mnIndex = *aIndexItr;
382 aPropStates.AddPropertyState( aNewProperty );
384 ++pResults;
385 --nResultCount;
387 ++aPropIter;
388 ++i;
392 else
394 Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
395 OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
396 const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
397 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
398 XMLPropertyState aNewProperty( -1 );
399 sal_uInt32 nResultCount(aResults.getLength());
400 OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
401 for( sal_uInt32 i = 0; i < nResultCount; ++i )
403 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
404 ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
406 aNewProperty.mnIndex = -1;
407 aNewProperty.maValue = pResults->Value;
409 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
410 aIndexItr != aPropIter->GetIndexes().end();
411 ++aIndexItr )
413 aNewProperty.mnIndex = *aIndexItr;
414 aPropStates.AddPropertyState( aNewProperty );
417 ++pResults;
418 ++aPropIter;
422 else
424 Sequence < PropertyState > aStates;
425 const PropertyState *pStates = 0;
426 Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
427 if( xPropState.is() )
429 aStates = xPropState->getPropertyStates( rApiNames );
430 pStates = aStates.getConstArray();
433 Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
434 if( xMultiPropSet.is() && !bDefault )
436 Sequence < Any > aValues;
437 if( pStates )
439 // step 1: get value count
440 sal_uInt32 nValueCount = 0;
441 sal_uInt32 i;
443 for( i = 0; i < nCount; ++i, ++pStates )
445 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
446 nValueCount++;
449 if( nValueCount )
451 // step 2: collect property names
452 Sequence < OUString > aAPINames( nValueCount );
453 OUString *pAPINames = aAPINames.getArray();
455 ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
456 aPropIters.reserve( nValueCount );
458 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
459 OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
461 pStates = aStates.getConstArray();
462 i = 0;
463 while( i < nValueCount )
465 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
467 *pAPINames++ = aItr->GetApiName();
468 aPropIters.push_back( aItr );
469 ++i;
471 ++aItr;
472 ++pStates;
475 aValues = xMultiPropSet->getPropertyValues( aAPINames );
476 const Any *pValues = aValues.getConstArray();
478 ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
479 pPropIter = aPropIters.begin();
481 XMLPropertyState aNewProperty( -1 );
482 for( i = 0; i < nValueCount; i++ )
484 aNewProperty.mnIndex = -1;
485 aNewProperty.maValue = *pValues;
487 const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
488 for ( std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
489 aIndexItr != rIndexes.end();
490 ++aIndexItr
493 aNewProperty.mnIndex = *aIndexItr;
494 aPropStates.AddPropertyState( aNewProperty );
497 ++pPropIter;
498 ++pValues;
502 else
504 aValues = xMultiPropSet->getPropertyValues( rApiNames );
505 const Any *pValues = aValues.getConstArray();
507 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
508 for(sal_uInt32 i = 0; i < nCount; i++ )
510 // The value is stored in the PropertySet itself, add to list.
511 XMLPropertyState aNewProperty( -1 );
512 aNewProperty.maValue = *pValues;
513 ++pValues;
514 for( std::list<sal_uInt32>::iterator aIndexItr =
515 aItr->GetIndexes().begin();
516 aIndexItr != aItr->GetIndexes().end();
517 aIndexItr++ )
519 aNewProperty.mnIndex = *aIndexItr;
520 aPropStates.AddPropertyState( aNewProperty );
522 aItr++;
526 else
528 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
529 for(sal_uInt32 i = 0; i < nCount; i++ )
531 sal_Bool bDirectValue =
532 !pStates || *pStates == PropertyState_DIRECT_VALUE;
533 if( bDirectValue || bDefault )
535 // The value is stored in the PropertySet itself, add to list.
536 sal_Bool bGotValue = sal_False;
537 XMLPropertyState aNewProperty( -1 );
538 for( std::list<sal_uInt32>::const_iterator aIndexItr =
539 aItr->GetIndexes().begin();
540 aIndexItr != aItr->GetIndexes().end();
541 aIndexItr++ )
543 if( bDirectValue ||
544 (rPropMapper->GetEntryFlags( *aIndexItr ) &
545 MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
549 if( !bGotValue )
551 aNewProperty.maValue =
552 rPropSet->getPropertyValue( aItr->GetApiName() );
553 bGotValue = sal_True;
555 aNewProperty.mnIndex = *aIndexItr;
556 aPropStates.AddPropertyState( aNewProperty );
558 catch( UnknownPropertyException& )
560 // might be a problem of getImplemenetationId
561 OSL_ENSURE( !this, "unknown property in getPropertyValue" );
568 aItr++;
569 if( pStates )
570 pStates++;
574 aPropStates.FillPropertyStateVector(rPropStates);
577 ///////////////////////////////////////////////////////////////////////////////
579 // ctor/dtor , class SvXMLExportPropertyMapper
582 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
583 const UniReference< XMLPropertySetMapper >& rMapper ) :
584 pCache( 0 ),
585 maPropMapper( rMapper )
589 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
591 delete pCache;
592 mxNextMapper = 0;
595 void SvXMLExportPropertyMapper::ChainExportMapper(
596 const UniReference< SvXMLExportPropertyMapper>& rMapper )
598 // add map entries from rMapper to current map
599 maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
600 // rMapper uses the same map as 'this'
601 rMapper->maPropMapper = maPropMapper;
603 // set rMapper as last mapper in current chain
604 UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
605 if( xNext.is())
607 while( xNext->mxNextMapper.is())
608 xNext = xNext->mxNextMapper;
609 xNext->mxNextMapper = rMapper;
611 else
612 mxNextMapper = rMapper;
614 // if rMapper was already chained, correct
615 // map pointer of successors
616 xNext = rMapper;
618 while( xNext->mxNextMapper.is())
620 xNext = xNext->mxNextMapper;
621 xNext->maPropMapper = maPropMapper;
626 vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
627 const Reference< XPropertySet > xPropSet,
628 const sal_Bool bDefault ) const
630 vector< XMLPropertyState > aPropStateArray;
632 // Retrieve XPropertySetInfo and XPropertyState
633 Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
634 if( !xInfo.is() )
635 return aPropStateArray;
637 sal_Int32 nProps = maPropMapper->GetEntryCount();
639 FilterPropertiesInfo_Impl *pFilterInfo = 0;
641 Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
642 Sequence< sal_Int8 > aImplId;
643 if( xTypeProv.is() )
645 aImplId = xTypeProv->getImplementationId();
646 if( aImplId.getLength() == 16 )
648 if( pCache )
650 // The key must not be created outside this block, because it
651 // keeps a reference to the property set info.
652 PropertySetInfoKey aKey( xInfo, aImplId );
653 FilterPropertiesInfos_Impl::iterator aIter =
654 pCache->find( aKey );
655 if( aIter != pCache->end() )
656 pFilterInfo = (*aIter).second;
661 sal_Bool bDelInfo = sal_False;
662 if( !pFilterInfo )
664 pFilterInfo = new FilterPropertiesInfo_Impl;
665 for( sal_Int32 i=0; i < nProps; i++ )
667 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
668 // Does the PropertySet contain name of mpEntries-array ?
669 const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
670 const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
671 if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
672 ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
673 xInfo->hasPropertyByName( rAPIName ) ) )
675 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
676 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
677 maPropMapper->GetEarliestODFVersionForExport( i ) );
678 if( nCurrentVersion >= nEarliestODFVersionForExport
679 || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
680 || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
681 pFilterInfo->AddProperty(rAPIName, i);
685 if( xTypeProv.is() && aImplId.getLength() == 16 )
687 // Check whether the property set info is destroyed if it is
688 // assigned to a weak reference only. If it is destroyed, then
689 // every instance of getPropertySetInfo returns a new object.
690 // Such property set infos must not be cached.
691 WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
692 xInfo = 0;
693 xInfo = xWeakInfo;
694 if( xInfo.is() )
696 if( !pCache )
697 ((SvXMLExportPropertyMapper *)this)->pCache =
698 new FilterPropertiesInfos_Impl;
699 PropertySetInfoKey aKey( xInfo, aImplId );
700 (*pCache)[aKey] = pFilterInfo;
702 else
703 bDelInfo = sal_True;
705 else
707 OSL_ENSURE(sal_False, "here is no TypeProvider or the ImplId is wrong");
708 bDelInfo = sal_True;
712 if( pFilterInfo->GetPropertyCount() )
716 pFilterInfo->FillPropertyStateArray(aPropStateArray,
717 xPropSet, maPropMapper,
718 bDefault);
720 catch( UnknownPropertyException& )
722 // might be a problem of getImplemenetationId
723 OSL_ENSURE( !this, "unknown property in getPropertyStates" );
727 // Call centext-filter
728 if( !aPropStateArray.empty() )
729 ContextFilter( aPropStateArray, xPropSet );
731 // Have to do if we change from a vector to a list or something like that
732 /*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin();
733 while (aItr != aPropStateArray.end())
735 if (aItr->mnIndex == -1)
736 aItr = aPropStateArray.erase(aItr);
737 else
738 aItr++;
741 if( bDelInfo )
742 delete pFilterInfo;
744 return aPropStateArray;
747 void SvXMLExportPropertyMapper::ContextFilter(
748 vector< XMLPropertyState >& rProperties,
749 Reference< XPropertySet > rPropSet ) const
751 // Derived class could implement this.
752 if( mxNextMapper.is() )
753 mxNextMapper->ContextFilter( rProperties, rPropSet );
756 ///////////////////////////////////////////////////////////////////////////
758 // Compares two Sequences of XMLPropertyState:
759 // 1.Number of elements equal ?
760 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
761 // 3.Value of each element equal ?
763 sal_Bool SvXMLExportPropertyMapper::Equals(
764 const vector< XMLPropertyState >& aProperties1,
765 const vector< XMLPropertyState >& aProperties2 ) const
767 sal_Bool bRet = sal_True;
768 sal_uInt32 nCount = aProperties1.size();
770 if( nCount == aProperties2.size() )
772 sal_uInt32 nIndex = 0;
773 while( bRet && nIndex < nCount )
775 const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
776 const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
778 // Compare index. If equal, compare value
779 if( rProp1.mnIndex == rProp2.mnIndex )
781 if( rProp1.mnIndex != -1 )
783 // Now compare values
784 if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
785 XML_TYPE_BUILDIN_CMP ) != 0 )
786 // simple type ( binary compare )
787 bRet = ( rProp1.maValue == rProp2.maValue );
788 else
789 // complex type ( ask for compare-function )
790 bRet = maPropMapper->GetPropertyHandler(
791 rProp1.mnIndex )->equals( rProp1.maValue,
792 rProp2.maValue );
795 else
796 bRet = sal_False;
798 nIndex++;
801 else
802 bRet = sal_False;
804 return bRet;
808 /** fills the given attribute list with the items in the given set
809 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
810 const ::std::vector< XMLPropertyState >& rProperties,
811 const SvXMLUnitConverter& rUnitConverter,
812 const SvXMLNamespaceMap& rNamespaceMap,
813 sal_uInt16 nFlags ) const
815 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
816 nFlags, 0, -1, -1 );
820 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
821 const ::std::vector< XMLPropertyState >& rProperties,
822 const SvXMLUnitConverter& rUnitConverter,
823 const SvXMLNamespaceMap& rNamespaceMap,
824 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
825 sal_uInt16 nFlags ) const
827 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
828 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
833 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
834 const XMLPropertyState& rProperty,
835 const SvXMLUnitConverter& rUnitConverter,
836 const SvXMLNamespaceMap& rNamespaceMap,
837 sal_uInt16 nFlags ) const
839 if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
840 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
841 _exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap,
842 nFlags );
845 void SvXMLExportPropertyMapper::exportXML(
846 SvXMLExport& rExport,
847 const ::std::vector< XMLPropertyState >& rProperties,
848 sal_uInt16 nFlags ) const
850 exportXML( rExport, rProperties, -1, -1, nFlags );
853 void SvXMLExportPropertyMapper::exportXML(
854 SvXMLExport& rExport,
855 const ::std::vector< XMLPropertyState >& rProperties,
856 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
857 sal_uInt16 nFlags ) const
859 sal_uInt16 nPropTypeFlags = 0;
860 for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
862 sal_uInt16 nPropType = aPropTokens[i].nType;
863 if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
865 SvUShorts aIndexArray;
867 _exportXML( nPropType, nPropTypeFlags,
868 rExport.GetAttrList(), rProperties,
869 rExport.GetMM100UnitConverter(),
870 rExport.GetNamespaceMap(),
871 nFlags, &aIndexArray,
872 nPropMapStartIdx, nPropMapEndIdx );
874 if( rExport.GetAttrList().getLength() > 0L ||
875 (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
876 aIndexArray.Count() != 0 )
878 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
879 aPropTokens[i].eToken,
880 (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
881 sal_False );
883 exportElementItems( rExport, rProperties, nFlags, aIndexArray );
889 /** this method is called for every item that has the
890 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
891 void SvXMLExportPropertyMapper::handleSpecialItem(
892 SvXMLAttributeList& rAttrList,
893 const XMLPropertyState& rProperty,
894 const SvXMLUnitConverter& rUnitConverter,
895 const SvXMLNamespaceMap& rNamespaceMap,
896 const ::std::vector< XMLPropertyState > *pProperties,
897 sal_uInt32 nIdx ) const
899 OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
900 if( mxNextMapper.is() )
901 mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
902 rNamespaceMap, pProperties, nIdx );
905 /** this method is called for every item that has the
906 MID_FLAG_ELEMENT_EXPORT flag set */
907 void SvXMLExportPropertyMapper::handleElementItem(
908 SvXMLExport& rExport,
909 const XMLPropertyState& rProperty,
910 sal_uInt16 nFlags,
911 const ::std::vector< XMLPropertyState > *pProperties,
912 sal_uInt32 nIdx ) const
914 OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
915 if( mxNextMapper.is() )
916 mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
917 pProperties, nIdx );
920 ///////////////////////////////////////////////////////////////////////////////
922 // protected methods
925 /** fills the given attribute list with the items in the given set */
926 void SvXMLExportPropertyMapper::_exportXML(
927 sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
928 SvXMLAttributeList& rAttrList,
929 const ::std::vector< XMLPropertyState >& rProperties,
930 const SvXMLUnitConverter& rUnitConverter,
931 const SvXMLNamespaceMap& rNamespaceMap,
932 sal_uInt16 nFlags,
933 SvUShorts* pIndexArray,
934 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
936 const sal_uInt32 nCount = rProperties.size();
937 sal_uInt32 nIndex = 0;
939 if( -1 == nPropMapStartIdx )
940 nPropMapStartIdx = 0;
941 if( -1 == nPropMapEndIdx )
942 nPropMapEndIdx = maPropMapper->GetEntryCount();
944 while( nIndex < nCount )
946 sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
947 if( nPropMapIdx >= nPropMapStartIdx &&
948 nPropMapIdx < nPropMapEndIdx )// valid entry?
950 sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
951 sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
952 OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
953 "no prop type sepcified" );
954 rPropTypeFlags |= (1 << nEPType);
955 if( nEPType == nPropType )
957 // we have a valid map entry here, so lets use it...
958 if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
960 // element items do not add any properties,
961 // we export it later
962 if( pIndexArray )
963 pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() );
965 else
967 _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
968 rNamespaceMap, nFlags, &rProperties, nIndex );
973 nIndex++;
977 void SvXMLExportPropertyMapper::_exportXML(
978 SvXMLAttributeList& rAttrList,
979 const XMLPropertyState& rProperty,
980 const SvXMLUnitConverter& rUnitConverter,
981 const SvXMLNamespaceMap& rNamespaceMap,
982 sal_uInt16 /*nFlags*/,
983 const ::std::vector< XMLPropertyState > *pProperties,
984 sal_uInt32 nIdx ) const
986 OUString sCDATA( GetXMLToken(XML_CDATA) );
988 if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
989 MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
991 uno::Reference< container::XNameContainer > xAttrContainer;
992 if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
994 SvXMLNamespaceMap *pNewNamespaceMap = 0;
995 const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
997 uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
998 const OUString* pAttribName = aAttribNames.getConstArray();
1000 const sal_Int32 nCount = aAttribNames.getLength();
1002 OUStringBuffer sNameBuffer;
1003 xml::AttributeData aData;
1004 for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
1006 xAttrContainer->getByName( *pAttribName ) >>= aData;
1007 OUString sAttribName( *pAttribName );
1009 // extract namespace prefix from attribute name if it exists
1010 OUString sPrefix;
1011 const sal_Int32 nColonPos =
1012 pAttribName->indexOf( sal_Unicode(':') );
1013 if( nColonPos != -1 )
1014 sPrefix = pAttribName->copy( 0, nColonPos );
1016 if( sPrefix.getLength() )
1018 OUString sNamespace( aData.Namespace );
1020 // if the prefix isn't defined yet or has another meaning,
1021 // we have to redefine it now.
1022 sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1023 if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
1025 sal_Bool bAddNamespace = sal_False;
1026 if( USHRT_MAX == nKey )
1028 // The prefix is unused, so it is sufficient
1029 // to add it to the namespace map.
1030 bAddNamespace = sal_True;
1032 else
1034 // check if there is a prefix registered for the
1035 // namepsace URI
1036 nKey = pNamespaceMap->GetKeyByName( sNamespace );
1037 if( XML_NAMESPACE_UNKNOWN == nKey )
1039 // There is no prefix for the namespace, so
1040 // we have to generate one and have to add it.
1041 sal_Int32 n=0;
1042 OUString sOrigPrefix( sPrefix );
1045 sNameBuffer.append( sOrigPrefix );
1046 sNameBuffer.append( ++n );
1047 sPrefix = sNameBuffer.makeStringAndClear();
1048 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1050 while( nKey != USHRT_MAX );
1052 bAddNamespace = sal_True;
1054 else
1056 // If there is a prefix for the namespace,
1057 // we reuse that.
1058 sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
1060 // In any case, the attribute name has to be adapted.
1061 sNameBuffer.append( sPrefix );
1062 sNameBuffer.append( sal_Unicode(':') );
1063 sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
1064 sAttribName = sNameBuffer.makeStringAndClear();
1067 if( bAddNamespace )
1069 if( !pNewNamespaceMap )
1071 pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
1072 pNamespaceMap = pNewNamespaceMap;
1074 pNewNamespaceMap->Add( sPrefix, sNamespace );
1075 sNameBuffer.append( GetXMLToken(XML_XMLNS) );
1076 sNameBuffer.append( sal_Unicode(':') );
1077 sNameBuffer.append( sPrefix );
1078 rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
1079 sNamespace );
1083 OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
1084 OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" );
1085 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
1086 if( !sOldValue.getLength() )
1087 rAttrList.AddAttribute( sAttribName, aData.Value );
1090 delete pNewNamespaceMap;
1092 else
1094 handleSpecialItem( rAttrList, rProperty, rUnitConverter,
1095 rNamespaceMap, pProperties, nIdx );
1098 else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1099 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
1101 OUString aValue;
1102 const OUString sName( rNamespaceMap.GetQNameByKey(
1103 maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
1104 maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );
1106 sal_Bool bRemove = sal_False;
1107 if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1108 MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
1110 aValue = rAttrList.getValueByName( sName );
1111 bRemove = sal_True; //aValue.getLength() != 0;
1114 if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
1116 if( bRemove )
1117 rAttrList.RemoveAttribute( sName );
1118 rAttrList.AddAttribute( sName, aValue );
1123 void SvXMLExportPropertyMapper::exportElementItems(
1124 SvXMLExport& rExport,
1125 const ::std::vector< XMLPropertyState >& rProperties,
1126 sal_uInt16 nFlags,
1127 const SvUShorts& rIndexArray ) const
1129 const sal_uInt16 nCount = rIndexArray.Count();
1131 sal_Bool bItemsExported = sal_False;
1132 OUString sWS( GetXMLToken(XML_WS) );
1133 for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
1135 const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );
1137 OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
1138 rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
1139 "wrong mid flag!" );
1141 rExport.IgnorableWhitespace();
1142 handleElementItem( rExport, rProperties[nElement],
1143 nFlags, &rProperties, nElement );
1144 bItemsExported = sal_True;
1147 if( bItemsExported )
1148 rExport.IgnorableWhitespace();