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