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