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