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