xref: /trunk/main/xmloff/source/style/xmlexppr.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/xml/AttributeData.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/beans/XPropertyState.hpp>
34 #include <com/sun/star/lang/XTypeProvider.hpp>
35 #include <com/sun/star/beans/XMultiPropertySet.hpp>
36 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
37 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
38 #include <rtl/ustrbuf.hxx>
39 #include <list>
40 #include <hash_map>
41 
42 #include <xmloff/xmlexppr.hxx>
43 #include <xmloff/xmltoken.hxx>
44 #include <xmloff/attrlist.hxx>
45 #include <xmloff/nmspmap.hxx>
46 #include "xmloff/xmlnmspe.hxx"
47 #include <xmloff/xmlexp.hxx>
48 #include <xmloff/xmlprmap.hxx>
49 #include <xmloff/PropertySetInfoHash.hxx>
50 #include <comphelper/stl_types.hxx>
51 
52 #ifndef _SVSTDARR_USHORTS
53 #define _SVSTDARR_USHORTS
54 #include <svl/svstdarr.hxx>
55 #endif
56 
57 using ::rtl::OUString;
58 using ::rtl::OUStringBuffer;
59 
60 using namespace ::std;
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::beans;
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::lang;
65 using namespace ::xmloff::token;
66 
67 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
68 
69 struct XMLPropTokens_Impl
70 {
71     sal_uInt16 nType;
72     XMLTokenEnum eToken;
73 };
74 
75 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
76 const sal_uInt16 MAX_PROP_TYPES =
77     (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
78     (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
79 
80 static  XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
81 {
82     ENTRY(CHART),
83     ENTRY(GRAPHIC),
84     ENTRY(TABLE),
85     ENTRY(TABLE_COLUMN),
86     ENTRY(TABLE_ROW),
87     ENTRY(TABLE_CELL),
88     ENTRY(LIST_LEVEL),
89     ENTRY(PARAGRAPH),
90     ENTRY(TEXT),
91     ENTRY(DRAWING_PAGE),
92     ENTRY(PAGE_LAYOUT),
93     ENTRY(HEADER_FOOTER),
94     ENTRY(RUBY),
95     ENTRY(SECTION)
96 };
97 
98 ///////////////////////////////////////////////////////////////////////////////
99 //
100 // public methods
101 //
102 
103 ///////////////////////////////////////////////////////////////////////////
104 //
105 // Take all properties of the XPropertySet which are also found in the
106 // XMLPropertyMapEntry-array and which are not set to their default-value,
107 // if a state is available.
108 //
109 // After that I call the method 'ContextFilter'.
110 //
111 
112 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
113 
114 class XMLPropertyStates_Impl
115 {
116     XMLPropertyStateList_Impl           aPropStates;
117     XMLPropertyStateList_Impl::iterator aLastItr;
118     sal_uInt32                          nCount;
119 public:
120     XMLPropertyStates_Impl();
121     void AddPropertyState(const XMLPropertyState& rPropState);
122     void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
123 };
124 
125 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
126     aPropStates(),
127     nCount(0)
128 {
129     aLastItr = aPropStates.begin();
130 }
131 
132 void XMLPropertyStates_Impl::AddPropertyState(
133         const XMLPropertyState& rPropState)
134 {
135     XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
136     sal_Bool bInserted(sal_False);
137     if (nCount)
138     {
139         if (aLastItr->mnIndex < rPropState.mnIndex)
140             aItr = ++aLastItr;
141     }
142     do
143     {
144         // TODO: one path required only
145         if (aItr == aPropStates.end())
146         {
147             aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
148             bInserted = sal_True;
149             nCount++;
150         }
151         else if (aItr->mnIndex > rPropState.mnIndex)
152         {
153             aLastItr = aPropStates.insert(aItr, rPropState);
154             bInserted = sal_True;
155             nCount++;
156         }
157     }
158     while(!bInserted && (aItr++ != aPropStates.end()));
159 }
160 
161 void XMLPropertyStates_Impl::FillPropertyStateVector(
162         std::vector<XMLPropertyState>& rVector)
163 {
164     if (nCount)
165     {
166         rVector.resize(nCount, XMLPropertyState(-1));
167         ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
168     }
169 }
170 
171 class FilterPropertyInfo_Impl
172 {
173     const rtl::OUString     sApiName;
174     std::list<sal_uInt32>   aIndexes;
175     sal_uInt32              nCount;
176 
177 public:
178 
179     FilterPropertyInfo_Impl( const rtl::OUString& rApiName,
180                              const sal_uInt32 nIndex);
181 
182     const OUString& GetApiName() const { return sApiName; }
183     std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
184 
185     void AddIndex( sal_uInt32 nIndex )
186     {
187         aIndexes.push_back(nIndex);
188         nCount++;
189     }
190 
191     // for sort
192     sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
193     {
194         return (GetApiName() < rArg.GetApiName());
195     }
196 };
197 
198 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
199         const rtl::OUString& rApiName,
200         const sal_uInt32 nIndex ) :
201     sApiName( rApiName ),
202     aIndexes(),
203     nCount(1)
204 {
205     aIndexes.push_back(nIndex);
206 }
207 
208 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
209 
210 // ----------------------------------------------------------------------------
211 
212 class FilterPropertiesInfo_Impl
213 {
214     sal_uInt32                              nCount;
215     FilterPropertyInfoList_Impl             aPropInfos;
216     FilterPropertyInfoList_Impl::iterator   aLastItr;
217 
218     Sequence <OUString>                     *pApiNames;
219 
220 public:
221     FilterPropertiesInfo_Impl();
222     ~FilterPropertiesInfo_Impl();
223 
224     void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex);
225     const uno::Sequence<OUString>& GetApiNames();
226     void FillPropertyStateArray(
227             vector< XMLPropertyState >& rPropStates,
228             const Reference< XPropertySet >& xPropSet,
229             const UniReference< XMLPropertySetMapper >& maPropMapper,
230             const sal_Bool bDefault = sal_False);
231     sal_uInt32 GetPropertyCount() const { return nCount; }
232 };
233 
234 // ----------------------------------------------------------------------------
235 
236 typedef std::hash_map
237 <
238     PropertySetInfoKey,
239     FilterPropertiesInfo_Impl *,
240     PropertySetInfoHash,
241     PropertySetInfoHash
242 >
243 FilterOropertiesHashMap_Impl;
244 
245 class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
246 {
247 public:
248     ~FilterPropertiesInfos_Impl ();
249 };
250 
251 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
252 {
253     FilterOropertiesHashMap_Impl::iterator aIter = begin();
254     FilterOropertiesHashMap_Impl::iterator aEnd = end();
255     while( aIter != aEnd )
256     {
257         delete (*aIter).second;
258         (*aIter).second = 0;
259         ++aIter;
260     }
261 }
262 
263 // ----------------------------------------------------------------------------
264 
265 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
266     nCount(0),
267     aPropInfos(),
268     pApiNames( 0 )
269 {
270     aLastItr = aPropInfos.begin();
271 }
272 
273 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
274 {
275     delete pApiNames;
276 }
277 
278 void FilterPropertiesInfo_Impl::AddProperty(
279         const rtl::OUString& rApiName, const sal_uInt32 nIndex)
280 {
281     aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
282     nCount++;
283 
284     OSL_ENSURE( !pApiNames, "perfomance warning: API names already retrieved" );
285     if( pApiNames )
286     {
287         delete pApiNames;
288         pApiNames = NULL;
289     }
290 }
291 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
292 {
293     OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
294     if( !pApiNames )
295     {
296         // we have to do three things:
297         // 1) sort API names,
298         // 2) merge duplicates,
299         // 3) construct sequence
300 
301         // sort names
302         aPropInfos.sort();
303 
304         // merge duplicates
305         if ( nCount > 1 )
306         {
307             FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
308             FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
309             FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
310             aCurrent++;
311 
312             while ( aCurrent != aEnd )
313             {
314                 // equal to next element?
315                 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
316                 {
317                     // if equal: merge index lists
318                     aOld->GetIndexes().merge( aCurrent->GetIndexes() );
319                     // erase element, and continue with next
320                     aCurrent = aPropInfos.erase( aCurrent );
321                     nCount--;
322                 }
323                 else
324                 {
325                     // remember old element and continue with next
326                     aOld = aCurrent;
327                     aCurrent++;
328                 }
329             }
330         }
331 
332         // construct sequence
333         pApiNames = new Sequence < OUString >( nCount );
334         OUString *pNames = pApiNames->getArray();
335         FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
336         FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
337         for ( ; aItr != aEnd; aItr++, pNames++)
338             *pNames = aItr->GetApiName();
339     }
340 
341     return *pApiNames;
342 }
343 
344 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
345         vector< XMLPropertyState >& rPropStates,
346         const Reference< XPropertySet >& rPropSet,
347         const UniReference< XMLPropertySetMapper >& rPropMapper,
348         const sal_Bool bDefault )
349 {
350     XMLPropertyStates_Impl aPropStates;
351 
352     const uno::Sequence<OUString>& rApiNames = GetApiNames();
353 
354     Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
355     if (xTolPropSet.is())
356     {
357         if (!bDefault)
358         {
359             Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
360             sal_Int32 nResultCount(aResults.getLength());
361             if (nResultCount > 0)
362             {
363                 const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
364                 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
365                 XMLPropertyState aNewProperty( -1 );
366                 sal_uInt32 i = 0;
367                 while (nResultCount > 0 && i < nCount)
368                 {
369                     if (pResults->Name == aPropIter->GetApiName())
370                     {
371                         aNewProperty.mnIndex = -1;
372                         aNewProperty.maValue = pResults->Value;
373 
374                         for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
375                             aIndexItr != aPropIter->GetIndexes().end();
376                             ++aIndexItr )
377                         {
378                             aNewProperty.mnIndex = *aIndexItr;
379                             aPropStates.AddPropertyState( aNewProperty );
380                         }
381                         ++pResults;
382                         --nResultCount;
383                     }
384                     ++aPropIter;
385                     ++i;
386                 }
387             }
388         }
389         else
390         {
391             Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
392             OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
393             const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
394             FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
395             XMLPropertyState aNewProperty( -1 );
396             sal_uInt32 nResultCount(aResults.getLength());
397             OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
398             for( sal_uInt32 i = 0; i < nResultCount; ++i )
399             {
400                 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
401                     ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
402                 {
403                     aNewProperty.mnIndex = -1;
404                     aNewProperty.maValue = pResults->Value;
405 
406                     for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
407                         aIndexItr != aPropIter->GetIndexes().end();
408                         ++aIndexItr )
409                     {
410                         aNewProperty.mnIndex = *aIndexItr;
411                         aPropStates.AddPropertyState( aNewProperty );
412                     }
413                 }
414                 ++pResults;
415                 ++aPropIter;
416             }
417         }
418     }
419     else
420     {
421         Sequence < PropertyState > aStates;
422         const PropertyState *pStates = 0;
423         Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
424         if( xPropState.is() )
425         {
426             aStates = xPropState->getPropertyStates( rApiNames );
427             pStates = aStates.getConstArray();
428         }
429 
430         Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
431         if( xMultiPropSet.is() && !bDefault )
432         {
433             Sequence < Any > aValues;
434             if( pStates )
435             {
436                 // step 1: get value count
437                 sal_uInt32 nValueCount = 0;
438                 sal_uInt32 i;
439 
440                 for( i = 0; i < nCount; ++i, ++pStates )
441                 {
442                     if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
443                         nValueCount++;
444                 }
445 
446                 if( nValueCount )
447                 {
448                     // step 2: collect property names
449                     Sequence < OUString > aAPINames( nValueCount );
450                     OUString *pAPINames = aAPINames.getArray();
451 
452                     ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
453                     aPropIters.reserve( nValueCount );
454 
455                     FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
456                     OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
457 
458                     pStates = aStates.getConstArray();
459                     i = 0;
460                     while( i < nValueCount )
461                     {
462                         if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
463                         {
464                             *pAPINames++ = aItr->GetApiName();
465                             aPropIters.push_back( aItr );
466                             ++i;
467                         }
468                         ++aItr;
469                         ++pStates;
470                     }
471 
472                     aValues = xMultiPropSet->getPropertyValues( aAPINames );
473                     const Any *pValues = aValues.getConstArray();
474 
475                     ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
476                         pPropIter = aPropIters.begin();
477 
478                     XMLPropertyState aNewProperty( -1 );
479                     for( i = 0; i < nValueCount; i++ )
480                     {
481                         aNewProperty.mnIndex = -1;
482                         aNewProperty.maValue = *pValues;
483 
484                         const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
485                         for (   std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
486                                 aIndexItr != rIndexes.end();
487                                 ++aIndexItr
488                             )
489                         {
490                             aNewProperty.mnIndex = *aIndexItr;
491                             aPropStates.AddPropertyState( aNewProperty );
492                         }
493 
494                         ++pPropIter;
495                         ++pValues;
496                     }
497                 }
498             }
499             else
500             {
501                 aValues = xMultiPropSet->getPropertyValues( rApiNames );
502                 const Any *pValues = aValues.getConstArray();
503 
504                 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
505                 for(sal_uInt32 i = 0; i < nCount; i++ )
506                 {
507                     // The value is stored in the PropertySet itself, add to list.
508                     XMLPropertyState aNewProperty( -1 );
509                     aNewProperty.maValue = *pValues;
510                     ++pValues;
511                     for( std::list<sal_uInt32>::iterator aIndexItr =
512                             aItr->GetIndexes().begin();
513                         aIndexItr != aItr->GetIndexes().end();
514                         aIndexItr++ )
515                     {
516                         aNewProperty.mnIndex = *aIndexItr;
517                         aPropStates.AddPropertyState( aNewProperty );
518                     }
519                     aItr++;
520                 }
521             }
522         }
523         else
524         {
525             FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
526             for(sal_uInt32 i = 0; i < nCount; i++ )
527             {
528                 sal_Bool bDirectValue =
529                     !pStates || *pStates == PropertyState_DIRECT_VALUE;
530                 if( bDirectValue || bDefault )
531                 {
532                     // The value is stored in the PropertySet itself, add to list.
533                     sal_Bool bGotValue = sal_False;
534                     XMLPropertyState aNewProperty( -1 );
535                     for( std::list<sal_uInt32>::const_iterator aIndexItr =
536                             aItr->GetIndexes().begin();
537                         aIndexItr != aItr->GetIndexes().end();
538                         aIndexItr++ )
539                     {
540                         if( bDirectValue ||
541                             (rPropMapper->GetEntryFlags( *aIndexItr ) &
542                                             MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
543                         {
544                             try
545                             {
546                                 if( !bGotValue )
547                                 {
548                                     aNewProperty.maValue =
549                                         rPropSet->getPropertyValue( aItr->GetApiName() );
550                                     bGotValue = sal_True;
551                                 }
552                                 aNewProperty.mnIndex = *aIndexItr;
553                                 aPropStates.AddPropertyState( aNewProperty );
554                             }
555                             catch( UnknownPropertyException& )
556                             {
557                                 // might be a problem of getImplemenetationId
558                                 OSL_ENSURE( !this, "unknown property in getPropertyValue" );
559                             }
560 
561                         }
562                     }
563                 }
564 
565                 aItr++;
566                 if( pStates )
567                     pStates++;
568             }
569         }
570     }
571     aPropStates.FillPropertyStateVector(rPropStates);
572 }
573 
574 ///////////////////////////////////////////////////////////////////////////////
575 //
576 // ctor/dtor , class SvXMLExportPropertyMapper
577 //
578 
579 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
580         const UniReference< XMLPropertySetMapper >& rMapper ) :
581     pCache( 0 ),
582     maPropMapper( rMapper )
583 {
584 }
585 
586 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
587 {
588     delete pCache;
589     mxNextMapper = 0;
590 }
591 
592 void SvXMLExportPropertyMapper::ChainExportMapper(
593         const UniReference< SvXMLExportPropertyMapper>& rMapper )
594 {
595     // add map entries from rMapper to current map
596     maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
597     // rMapper uses the same map as 'this'
598     rMapper->maPropMapper = maPropMapper;
599 
600     // set rMapper as last mapper in current chain
601     UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
602     if( xNext.is())
603     {
604         while( xNext->mxNextMapper.is())
605             xNext = xNext->mxNextMapper;
606         xNext->mxNextMapper = rMapper;
607     }
608     else
609         mxNextMapper = rMapper;
610 
611     // if rMapper was already chained, correct
612     // map pointer of successors
613     xNext = rMapper;
614 
615     while( xNext->mxNextMapper.is())
616     {
617         xNext = xNext->mxNextMapper;
618         xNext->maPropMapper = maPropMapper;
619     }
620 }
621 
622 
623 vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
624         const Reference< XPropertySet > xPropSet,
625         const sal_Bool bDefault ) const
626 {
627     vector< XMLPropertyState > aPropStateArray;
628 
629     // Retrieve XPropertySetInfo and XPropertyState
630     Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
631     if( !xInfo.is() )
632         return aPropStateArray;
633 
634     sal_Int32 nProps = maPropMapper->GetEntryCount();
635 
636     FilterPropertiesInfo_Impl *pFilterInfo = 0;
637 
638     Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
639     Sequence< sal_Int8 > aImplId;
640     if( xTypeProv.is() )
641     {
642         aImplId = xTypeProv->getImplementationId();
643         if( aImplId.getLength() == 16 )
644         {
645             if( pCache )
646             {
647                 // The key must not be created outside this block, because it
648                 // keeps a reference to the property set info.
649                 PropertySetInfoKey aKey( xInfo, aImplId );
650                 FilterPropertiesInfos_Impl::iterator aIter =
651                     pCache->find( aKey );
652                 if( aIter != pCache->end() )
653                     pFilterInfo = (*aIter).second;
654             }
655         }
656     }
657 
658     sal_Bool bDelInfo = sal_False;
659     if( !pFilterInfo )
660     {
661         pFilterInfo = new FilterPropertiesInfo_Impl;
662         for( sal_Int32 i=0; i < nProps; i++ )
663         {
664             // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
665             // Does the PropertySet contain name of mpEntries-array ?
666             const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
667             const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
668             if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
669                 ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
670                   xInfo->hasPropertyByName( rAPIName ) ) )
671             {
672                 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
673                 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
674                         maPropMapper->GetEarliestODFVersionForExport( i ) );
675                 if( nCurrentVersion >= nEarliestODFVersionForExport
676                         || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
677                         || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
678                     pFilterInfo->AddProperty(rAPIName, i);
679             }
680         }
681 
682         if( xTypeProv.is() && aImplId.getLength() == 16 )
683         {
684             // Check whether the property set info is destroyed if it is
685             // assigned to a weak reference only. If it is destroyed, then
686             // every instance of getPropertySetInfo returns a new object.
687             // Such property set infos must not be cached.
688             WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
689             xInfo = 0;
690             xInfo = xWeakInfo;
691             if( xInfo.is() )
692             {
693                 if( !pCache )
694                     ((SvXMLExportPropertyMapper *)this)->pCache =
695                         new FilterPropertiesInfos_Impl;
696                 PropertySetInfoKey aKey( xInfo, aImplId );
697                 (*pCache)[aKey] = pFilterInfo;
698             }
699             else
700                 bDelInfo = sal_True;
701         }
702         else
703         {
704             OSL_ENSURE(sal_False, "here is no TypeProvider or the ImplId is wrong");
705             bDelInfo = sal_True;
706         }
707     }
708 
709     if( pFilterInfo->GetPropertyCount() )
710     {
711         try
712         {
713             pFilterInfo->FillPropertyStateArray(aPropStateArray,
714                                                 xPropSet, maPropMapper,
715                                                 bDefault);
716         }
717         catch( UnknownPropertyException& )
718         {
719             // might be a problem of getImplemenetationId
720             OSL_ENSURE( !this, "unknown property in getPropertyStates" );
721         }
722     }
723 
724     // Call centext-filter
725     if( !aPropStateArray.empty() )
726         ContextFilter( aPropStateArray, xPropSet );
727 
728     // Have to do if we change from a vector to a list or something like that
729     /*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin();
730     while (aItr != aPropStateArray.end())
731     {
732         if (aItr->mnIndex == -1)
733             aItr = aPropStateArray.erase(aItr);
734         else
735             aItr++;
736     }*/
737 
738     if( bDelInfo )
739         delete pFilterInfo;
740 
741     return aPropStateArray;
742 }
743 
744 void SvXMLExportPropertyMapper::ContextFilter(
745         vector< XMLPropertyState >& rProperties,
746         Reference< XPropertySet > rPropSet ) const
747 {
748     // Derived class could implement this.
749     if( mxNextMapper.is() )
750         mxNextMapper->ContextFilter( rProperties, rPropSet );
751 }
752 
753 ///////////////////////////////////////////////////////////////////////////
754 //
755 // Compares two Sequences of XMLPropertyState:
756 //  1.Number of elements equal ?
757 //  2.Index of each element equal ? (So I know whether the propertynames are the same)
758 //  3.Value of each element equal ?
759 //
760 sal_Bool SvXMLExportPropertyMapper::Equals(
761         const vector< XMLPropertyState >& aProperties1,
762         const vector< XMLPropertyState >& aProperties2 ) const
763 {
764     sal_Bool bRet = sal_True;
765     sal_uInt32 nCount = aProperties1.size();
766 
767     if( nCount == aProperties2.size() )
768     {
769         sal_uInt32 nIndex = 0;
770         while( bRet && nIndex < nCount )
771         {
772             const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
773             const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
774 
775             // Compare index. If equal, compare value
776             if( rProp1.mnIndex == rProp2.mnIndex )
777             {
778                 if( rProp1.mnIndex != -1 )
779                 {
780                     // Now compare values
781                     if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
782                           XML_TYPE_BUILDIN_CMP ) != 0 )
783                         // simple type ( binary compare )
784                         bRet = ( rProp1.maValue == rProp2.maValue );
785                     else
786                         // complex type ( ask for compare-function )
787                         bRet = maPropMapper->GetPropertyHandler(
788                                     rProp1.mnIndex )->equals( rProp1.maValue,
789                                                               rProp2.maValue );
790                 }
791             }
792             else
793                 bRet = sal_False;
794 
795             nIndex++;
796         }
797     }
798     else
799         bRet = sal_False;
800 
801     return bRet;
802 }
803 
804 
805 /** fills the given attribute list with the items in the given set
806 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
807         const ::std::vector< XMLPropertyState >& rProperties,
808         const SvXMLUnitConverter& rUnitConverter,
809         const SvXMLNamespaceMap& rNamespaceMap,
810         sal_uInt16 nFlags ) const
811 {
812     _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
813                 nFlags, 0, -1, -1 );
814 }
815 
816 
817 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
818         const ::std::vector< XMLPropertyState >& rProperties,
819         const SvXMLUnitConverter& rUnitConverter,
820         const SvXMLNamespaceMap& rNamespaceMap,
821         sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
822         sal_uInt16 nFlags ) const
823 {
824     _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
825                 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
826 }
827 */
828 
829 
830 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
831         const XMLPropertyState& rProperty,
832         const SvXMLUnitConverter& rUnitConverter,
833         const SvXMLNamespaceMap& rNamespaceMap,
834         sal_uInt16 nFlags ) const
835 {
836     if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
837                 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
838         _exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap,
839                     nFlags );
840 }
841 
842 void SvXMLExportPropertyMapper::exportXML(
843         SvXMLExport& rExport,
844         const ::std::vector< XMLPropertyState >& rProperties,
845         sal_uInt16 nFlags ) const
846 {
847     exportXML( rExport, rProperties, -1, -1,  nFlags );
848 }
849 
850 void SvXMLExportPropertyMapper::exportXML(
851         SvXMLExport& rExport,
852         const ::std::vector< XMLPropertyState >& rProperties,
853         sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
854         sal_uInt16 nFlags ) const
855 {
856     sal_uInt16 nPropTypeFlags = 0;
857     for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
858     {
859         sal_uInt16 nPropType = aPropTokens[i].nType;
860         if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
861         {
862             SvUShorts aIndexArray;
863 
864             _exportXML( nPropType, nPropTypeFlags,
865                         rExport.GetAttrList(), rProperties,
866                         rExport.GetMM100UnitConverter(),
867                         rExport.GetNamespaceMap(),
868                         nFlags, &aIndexArray,
869                         nPropMapStartIdx, nPropMapEndIdx );
870 
871             if( rExport.GetAttrList().getLength() > 0L ||
872                 (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
873                 aIndexArray.Count() != 0 )
874             {
875                 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
876                                   aPropTokens[i].eToken,
877                                   (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
878                                   sal_False );
879 
880                 exportElementItems( rExport, rProperties, nFlags, aIndexArray );
881             }
882         }
883     }
884 }
885 
886 /** this method is called for every item that has the
887     MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
888 void SvXMLExportPropertyMapper::handleSpecialItem(
889         SvXMLAttributeList& rAttrList,
890         const XMLPropertyState& rProperty,
891         const SvXMLUnitConverter& rUnitConverter,
892         const SvXMLNamespaceMap& rNamespaceMap,
893         const ::std::vector< XMLPropertyState > *pProperties,
894         sal_uInt32 nIdx ) const
895 {
896     OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
897     if( mxNextMapper.is() )
898         mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
899                                         rNamespaceMap, pProperties, nIdx );
900 }
901 
902 /** this method is called for every item that has the
903     MID_FLAG_ELEMENT_EXPORT flag set */
904 void SvXMLExportPropertyMapper::handleElementItem(
905         SvXMLExport& rExport,
906         const XMLPropertyState& rProperty,
907         sal_uInt16 nFlags,
908         const ::std::vector< XMLPropertyState > *pProperties,
909         sal_uInt32 nIdx ) const
910 {
911     OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
912     if( mxNextMapper.is() )
913         mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
914                                          pProperties, nIdx );
915 }
916 
917 ///////////////////////////////////////////////////////////////////////////////
918 //
919 // protected methods
920 //
921 
922 /** fills the given attribute list with the items in the given set */
923 void SvXMLExportPropertyMapper::_exportXML(
924         sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
925         SvXMLAttributeList& rAttrList,
926         const ::std::vector< XMLPropertyState >& rProperties,
927         const SvXMLUnitConverter& rUnitConverter,
928         const SvXMLNamespaceMap& rNamespaceMap,
929         sal_uInt16 nFlags,
930         SvUShorts* pIndexArray,
931         sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
932 {
933     const sal_uInt32 nCount = rProperties.size();
934     sal_uInt32 nIndex = 0;
935 
936     if( -1 == nPropMapStartIdx )
937         nPropMapStartIdx = 0;
938     if( -1 == nPropMapEndIdx )
939         nPropMapEndIdx = maPropMapper->GetEntryCount();
940 
941     while( nIndex < nCount )
942     {
943         sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
944         if( nPropMapIdx >= nPropMapStartIdx &&
945             nPropMapIdx < nPropMapEndIdx  )// valid entry?
946         {
947             sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
948             sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
949             OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
950                         "no prop type sepcified" );
951             rPropTypeFlags |= (1 << nEPType);
952             if( nEPType == nPropType )
953             {
954                 // we have a valid map entry here, so lets use it...
955                 if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
956                 {
957                     // element items do not add any properties,
958                     // we export it later
959                     if( pIndexArray )
960                         pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() );
961                 }
962                 else
963                 {
964                     _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
965                                 rNamespaceMap, nFlags, &rProperties, nIndex );
966                 }
967             }
968         }
969 
970         nIndex++;
971     }
972 }
973 
974 void SvXMLExportPropertyMapper::_exportXML(
975         SvXMLAttributeList& rAttrList,
976         const XMLPropertyState& rProperty,
977         const SvXMLUnitConverter& rUnitConverter,
978         const SvXMLNamespaceMap& rNamespaceMap,
979         sal_uInt16 /*nFlags*/,
980         const ::std::vector< XMLPropertyState > *pProperties,
981         sal_uInt32 nIdx ) const
982 {
983     OUString sCDATA( GetXMLToken(XML_CDATA) );
984 
985     if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
986                 MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
987     {
988         uno::Reference< container::XNameContainer > xAttrContainer;
989         if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
990         {
991             SvXMLNamespaceMap *pNewNamespaceMap = 0;
992             const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
993 
994             uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
995             const OUString* pAttribName = aAttribNames.getConstArray();
996 
997             const sal_Int32 nCount = aAttribNames.getLength();
998 
999             OUStringBuffer sNameBuffer;
1000             xml::AttributeData aData;
1001             for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
1002             {
1003                 xAttrContainer->getByName( *pAttribName ) >>= aData;
1004                 OUString sAttribName( *pAttribName );
1005 
1006                 // extract namespace prefix from attribute name if it exists
1007                 OUString sPrefix;
1008                 const sal_Int32 nColonPos =
1009                     pAttribName->indexOf( sal_Unicode(':') );
1010                 if( nColonPos != -1 )
1011                     sPrefix = pAttribName->copy( 0, nColonPos );
1012 
1013                 if( sPrefix.getLength() )
1014                 {
1015                     OUString sNamespace( aData.Namespace );
1016 
1017                     // if the prefix isn't defined yet or has another meaning,
1018                     // we have to redefine it now.
1019                     sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1020                     if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
1021                     {
1022                         sal_Bool bAddNamespace = sal_False;
1023                         if( USHRT_MAX == nKey )
1024                         {
1025                             // The prefix is unused, so it is sufficient
1026                             // to add it to the namespace map.
1027                             bAddNamespace = sal_True;
1028                         }
1029                         else
1030                         {
1031                             // check if there is a prefix registered for the
1032                             // namepsace URI
1033                             nKey = pNamespaceMap->GetKeyByName( sNamespace );
1034                             if( XML_NAMESPACE_UNKNOWN == nKey )
1035                             {
1036                                 // There is no prefix for the namespace, so
1037                                 // we have to generate one and have to add it.
1038                                 sal_Int32 n=0;
1039                                 OUString sOrigPrefix( sPrefix );
1040                                 do
1041                                 {
1042                                     sNameBuffer.append( sOrigPrefix );
1043                                     sNameBuffer.append( ++n );
1044                                     sPrefix = sNameBuffer.makeStringAndClear();
1045                                     nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
1046                                 }
1047                                 while( nKey != USHRT_MAX );
1048 
1049                                 bAddNamespace = sal_True;
1050                             }
1051                             else
1052                             {
1053                                 // If there is a prefix for the namespace,
1054                                 // we reuse that.
1055                                 sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
1056                             }
1057                             // In any case, the attribute name has to be adapted.
1058                             sNameBuffer.append( sPrefix );
1059                             sNameBuffer.append( sal_Unicode(':') );
1060                             sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
1061                             sAttribName = sNameBuffer.makeStringAndClear();
1062                         }
1063 
1064                         if( bAddNamespace )
1065                         {
1066                             if( !pNewNamespaceMap )
1067                             {
1068                                 pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
1069                                 pNamespaceMap = pNewNamespaceMap;
1070                             }
1071                             pNewNamespaceMap->Add( sPrefix, sNamespace );
1072                             sNameBuffer.append( GetXMLToken(XML_XMLNS) );
1073                             sNameBuffer.append( sal_Unicode(':') );
1074                             sNameBuffer.append( sPrefix );
1075                             rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
1076                                                     sNamespace );
1077                         }
1078                     }
1079                 }
1080                 OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
1081                 OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" );
1082                 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
1083                 if( !sOldValue.getLength() )
1084                     rAttrList.AddAttribute( sAttribName, aData.Value );
1085             }
1086 
1087             delete pNewNamespaceMap;
1088         }
1089         else
1090         {
1091             handleSpecialItem( rAttrList, rProperty, rUnitConverter,
1092                                rNamespaceMap, pProperties, nIdx );
1093         }
1094     }
1095     else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1096                     MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
1097     {
1098         OUString aValue;
1099         const OUString sName( rNamespaceMap.GetQNameByKey(
1100                     maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
1101                     maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );
1102 
1103         sal_Bool bRemove = sal_False;
1104         if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
1105                     MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
1106         {
1107             aValue = rAttrList.getValueByName( sName );
1108             bRemove = sal_True; //aValue.getLength() != 0;
1109         }
1110 
1111         if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
1112         {
1113             if( bRemove )
1114                 rAttrList.RemoveAttribute( sName );
1115             rAttrList.AddAttribute( sName, aValue );
1116         }
1117     }
1118 }
1119 
1120 void SvXMLExportPropertyMapper::exportElementItems(
1121         SvXMLExport& rExport,
1122         const ::std::vector< XMLPropertyState >& rProperties,
1123         sal_uInt16 nFlags,
1124         const SvUShorts& rIndexArray ) const
1125 {
1126     const sal_uInt16 nCount = rIndexArray.Count();
1127 
1128     sal_Bool bItemsExported = sal_False;
1129     OUString sWS( GetXMLToken(XML_WS) );
1130     for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
1131     {
1132         const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );
1133 
1134         OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
1135                 rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
1136                 "wrong mid flag!" );
1137 
1138         rExport.IgnorableWhitespace();
1139         handleElementItem( rExport, rProperties[nElement],
1140                            nFlags, &rProperties, nElement );
1141         bItemsExported = sal_True;
1142     }
1143 
1144     if( bItemsExported )
1145         rExport.IgnorableWhitespace();
1146 }
1147