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