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, "performance 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( sal_False, "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( sal_False, "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