1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xmlexppr.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/xml/AttributeData.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertyState.hpp>
37 #include <com/sun/star/lang/XTypeProvider.hpp>
38 #include <com/sun/star/beans/XMultiPropertySet.hpp>
39 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
40 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
41 #include <rtl/ustrbuf.hxx>
45 #include <xmloff/xmlexppr.hxx>
46 #include <xmloff/xmltoken.hxx>
47 #include <xmloff/attrlist.hxx>
48 #include <xmloff/nmspmap.hxx>
49 #include "xmlnmspe.hxx"
50 #include <xmloff/xmlexp.hxx>
51 #include <xmloff/xmlprmap.hxx>
52 #include <xmloff/PropertySetInfoHash.hxx>
53 #include <comphelper/stl_types.hxx>
55 #ifndef _SVSTDARR_USHORTS
56 #define _SVSTDARR_USHORTS
57 #include <svtools/svstdarr.hxx>
60 using ::rtl::OUString
;
61 using ::rtl::OUStringBuffer
;
63 using namespace ::std
;
64 using namespace ::com::sun::star
;
65 using namespace ::com::sun::star::beans
;
66 using namespace ::com::sun::star::uno
;
67 using namespace ::com::sun::star::lang
;
68 using namespace ::xmloff::token
;
70 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
72 struct XMLPropTokens_Impl
78 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
79 const sal_uInt16 MAX_PROP_TYPES
=
80 (XML_TYPE_PROP_END
>> XML_TYPE_PROP_SHIFT
) -
81 (XML_TYPE_PROP_START
>> XML_TYPE_PROP_SHIFT
);
83 static XMLPropTokens_Impl aPropTokens
[MAX_PROP_TYPES
] =
101 ///////////////////////////////////////////////////////////////////////////////
106 ///////////////////////////////////////////////////////////////////////////
108 // Take all properties of the XPropertySet which are also found in the
109 // XMLPropertyMapEntry-array and which are not set to their default-value,
110 // if a state is available.
112 // After that I call the method 'ContextFilter'.
115 typedef std::list
<XMLPropertyState
> XMLPropertyStateList_Impl
;
117 class XMLPropertyStates_Impl
119 XMLPropertyStateList_Impl aPropStates
;
120 XMLPropertyStateList_Impl::iterator aLastItr
;
123 XMLPropertyStates_Impl();
124 void AddPropertyState(const XMLPropertyState
& rPropState
);
125 void FillPropertyStateVector(std::vector
<XMLPropertyState
>& rVector
);
128 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
132 aLastItr
= aPropStates
.begin();
135 void XMLPropertyStates_Impl::AddPropertyState(
136 const XMLPropertyState
& rPropState
)
138 XMLPropertyStateList_Impl::iterator aItr
= aPropStates
.begin();
139 sal_Bool
bInserted(sal_False
);
142 if (aLastItr
->mnIndex
< rPropState
.mnIndex
)
147 // TODO: one path required only
148 if (aItr
== aPropStates
.end())
150 aLastItr
= aPropStates
.insert(aPropStates
.end(), rPropState
);
151 bInserted
= sal_True
;
154 else if (aItr
->mnIndex
> rPropState
.mnIndex
)
156 aLastItr
= aPropStates
.insert(aItr
, rPropState
);
157 bInserted
= sal_True
;
161 while(!bInserted
&& (aItr
++ != aPropStates
.end()));
164 void XMLPropertyStates_Impl::FillPropertyStateVector(
165 std::vector
<XMLPropertyState
>& rVector
)
169 rVector
.resize(nCount
, XMLPropertyState(-1));
170 ::std::copy( aPropStates
.begin(), aPropStates
.end(), rVector
.begin() );
174 class FilterPropertyInfo_Impl
176 const rtl::OUString sApiName
;
177 std::list
<sal_uInt32
> aIndexes
;
182 FilterPropertyInfo_Impl( const rtl::OUString
& rApiName
,
183 const sal_uInt32 nIndex
);
185 const OUString
& GetApiName() const { return sApiName
; }
186 std::list
<sal_uInt32
>& GetIndexes() { return aIndexes
; }
188 void AddIndex( sal_uInt32 nIndex
)
190 aIndexes
.push_back(nIndex
);
195 sal_Bool
operator< ( const FilterPropertyInfo_Impl
& rArg
) const
197 return (GetApiName() < rArg
.GetApiName());
201 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
202 const rtl::OUString
& rApiName
,
203 const sal_uInt32 nIndex
) :
204 sApiName( rApiName
),
208 aIndexes
.push_back(nIndex
);
211 typedef std::list
<FilterPropertyInfo_Impl
> FilterPropertyInfoList_Impl
;
213 // ----------------------------------------------------------------------------
215 class FilterPropertiesInfo_Impl
218 FilterPropertyInfoList_Impl aPropInfos
;
219 FilterPropertyInfoList_Impl::iterator aLastItr
;
221 Sequence
<OUString
> *pApiNames
;
224 FilterPropertiesInfo_Impl();
225 ~FilterPropertiesInfo_Impl();
227 void AddProperty(const rtl::OUString
& rApiName
, const sal_uInt32 nIndex
);
228 const uno::Sequence
<OUString
>& GetApiNames();
229 void FillPropertyStateArray(
230 vector
< XMLPropertyState
>& rPropStates
,
231 const Reference
< XPropertySet
>& xPropSet
,
232 const UniReference
< XMLPropertySetMapper
>& maPropMapper
,
233 const sal_Bool bDefault
= sal_False
);
234 sal_uInt32
GetPropertyCount() const { return nCount
; }
237 // ----------------------------------------------------------------------------
239 typedef std::hash_map
242 FilterPropertiesInfo_Impl
*,
246 FilterOropertiesHashMap_Impl
;
248 class FilterPropertiesInfos_Impl
: public FilterOropertiesHashMap_Impl
251 ~FilterPropertiesInfos_Impl ();
254 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
256 FilterOropertiesHashMap_Impl::iterator aIter
= begin();
257 FilterOropertiesHashMap_Impl::iterator aEnd
= end();
258 while( aIter
!= aEnd
)
260 delete (*aIter
).second
;
266 // ----------------------------------------------------------------------------
268 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
273 aLastItr
= aPropInfos
.begin();
276 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
281 void FilterPropertiesInfo_Impl::AddProperty(
282 const rtl::OUString
& rApiName
, const sal_uInt32 nIndex
)
284 aPropInfos
.push_back(FilterPropertyInfo_Impl(rApiName
, nIndex
));
287 OSL_ENSURE( !pApiNames
, "perfomance warning: API names already retrieved" );
294 const uno::Sequence
<OUString
>& FilterPropertiesInfo_Impl::GetApiNames()
296 OSL_ENSURE(nCount
== aPropInfos
.size(), "wrong property count");
299 // we have to do three things:
300 // 1) sort API names,
301 // 2) merge duplicates,
302 // 3) construct sequence
310 FilterPropertyInfoList_Impl::iterator aOld
= aPropInfos
.begin();
311 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
312 FilterPropertyInfoList_Impl::iterator aCurrent
= aOld
;
315 while ( aCurrent
!= aEnd
)
317 // equal to next element?
318 if ( aOld
->GetApiName().equals( aCurrent
->GetApiName() ) )
320 // if equal: merge index lists
321 aOld
->GetIndexes().merge( aCurrent
->GetIndexes() );
322 // erase element, and continue with next
323 aCurrent
= aPropInfos
.erase( aCurrent
);
328 // remember old element and continue with next
335 // construct sequence
336 pApiNames
= new Sequence
< OUString
>( nCount
);
337 OUString
*pNames
= pApiNames
->getArray();
338 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
339 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
340 for ( ; aItr
!= aEnd
; aItr
++, pNames
++)
341 *pNames
= aItr
->GetApiName();
347 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
348 vector
< XMLPropertyState
>& rPropStates
,
349 const Reference
< XPropertySet
>& rPropSet
,
350 const UniReference
< XMLPropertySetMapper
>& rPropMapper
,
351 const sal_Bool bDefault
)
353 XMLPropertyStates_Impl aPropStates
;
355 const uno::Sequence
<OUString
>& rApiNames
= GetApiNames();
357 Reference
< XTolerantMultiPropertySet
> xTolPropSet( rPropSet
, UNO_QUERY
);
358 if (xTolPropSet
.is())
362 Sequence
< beans::GetDirectPropertyTolerantResult
> aResults(xTolPropSet
->getDirectPropertyValuesTolerant(rApiNames
));
363 sal_Int32
nResultCount(aResults
.getLength());
364 if (nResultCount
> 0)
366 const beans::GetDirectPropertyTolerantResult
*pResults
= aResults
.getConstArray();
367 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
368 XMLPropertyState
aNewProperty( -1 );
370 while (nResultCount
> 0 && i
< nCount
)
372 if (pResults
->Name
== aPropIter
->GetApiName())
374 aNewProperty
.mnIndex
= -1;
375 aNewProperty
.maValue
= pResults
->Value
;
377 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
378 aIndexItr
!= aPropIter
->GetIndexes().end();
381 aNewProperty
.mnIndex
= *aIndexItr
;
382 aPropStates
.AddPropertyState( aNewProperty
);
394 Sequence
< beans::GetPropertyTolerantResult
> aResults(xTolPropSet
->getPropertyValuesTolerant(rApiNames
));
395 OSL_ENSURE( rApiNames
.getLength() == aResults
.getLength(), "wrong implemented XTolerantMultiPropertySet" );
396 const beans::GetPropertyTolerantResult
*pResults
= aResults
.getConstArray();
397 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
398 XMLPropertyState
aNewProperty( -1 );
399 sal_uInt32
nResultCount(aResults
.getLength());
400 OSL_ENSURE( nCount
== nResultCount
, "wrong implemented XTolerantMultiPropertySet??" );
401 for( sal_uInt32 i
= 0; i
< nResultCount
; ++i
)
403 if ((pResults
->Result
== beans::TolerantPropertySetResultType::SUCCESS
) &&
404 ((pResults
->State
== PropertyState_DIRECT_VALUE
) || (pResults
->State
== PropertyState_DEFAULT_VALUE
)))
406 aNewProperty
.mnIndex
= -1;
407 aNewProperty
.maValue
= pResults
->Value
;
409 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
410 aIndexItr
!= aPropIter
->GetIndexes().end();
413 aNewProperty
.mnIndex
= *aIndexItr
;
414 aPropStates
.AddPropertyState( aNewProperty
);
424 Sequence
< PropertyState
> aStates
;
425 const PropertyState
*pStates
= 0;
426 Reference
< XPropertyState
> xPropState( rPropSet
, UNO_QUERY
);
427 if( xPropState
.is() )
429 aStates
= xPropState
->getPropertyStates( rApiNames
);
430 pStates
= aStates
.getConstArray();
433 Reference
< XMultiPropertySet
> xMultiPropSet( rPropSet
, UNO_QUERY
);
434 if( xMultiPropSet
.is() && !bDefault
)
436 Sequence
< Any
> aValues
;
439 // step 1: get value count
440 sal_uInt32 nValueCount
= 0;
443 for( i
= 0; i
< nCount
; ++i
, ++pStates
)
445 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
451 // step 2: collect property names
452 Sequence
< OUString
> aAPINames( nValueCount
);
453 OUString
*pAPINames
= aAPINames
.getArray();
455 ::std::vector
< FilterPropertyInfoList_Impl::iterator
> aPropIters
;
456 aPropIters
.reserve( nValueCount
);
458 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
459 OSL_ENSURE(aItr
!= aPropInfos
.end(),"Invalid iterator!");
461 pStates
= aStates
.getConstArray();
463 while( i
< nValueCount
)
465 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
467 *pAPINames
++ = aItr
->GetApiName();
468 aPropIters
.push_back( aItr
);
475 aValues
= xMultiPropSet
->getPropertyValues( aAPINames
);
476 const Any
*pValues
= aValues
.getConstArray();
478 ::std::vector
< FilterPropertyInfoList_Impl::iterator
>::const_iterator
479 pPropIter
= aPropIters
.begin();
481 XMLPropertyState
aNewProperty( -1 );
482 for( i
= 0; i
< nValueCount
; i
++ )
484 aNewProperty
.mnIndex
= -1;
485 aNewProperty
.maValue
= *pValues
;
487 const ::std::list
< sal_uInt32
>& rIndexes( (*pPropIter
)->GetIndexes() );
488 for ( std::list
<sal_uInt32
>::const_iterator aIndexItr
= rIndexes
.begin();
489 aIndexItr
!= rIndexes
.end();
493 aNewProperty
.mnIndex
= *aIndexItr
;
494 aPropStates
.AddPropertyState( aNewProperty
);
504 aValues
= xMultiPropSet
->getPropertyValues( rApiNames
);
505 const Any
*pValues
= aValues
.getConstArray();
507 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
508 for(sal_uInt32 i
= 0; i
< nCount
; i
++ )
510 // The value is stored in the PropertySet itself, add to list.
511 XMLPropertyState
aNewProperty( -1 );
512 aNewProperty
.maValue
= *pValues
;
514 for( std::list
<sal_uInt32
>::iterator aIndexItr
=
515 aItr
->GetIndexes().begin();
516 aIndexItr
!= aItr
->GetIndexes().end();
519 aNewProperty
.mnIndex
= *aIndexItr
;
520 aPropStates
.AddPropertyState( aNewProperty
);
528 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
529 for(sal_uInt32 i
= 0; i
< nCount
; i
++ )
531 sal_Bool bDirectValue
=
532 !pStates
|| *pStates
== PropertyState_DIRECT_VALUE
;
533 if( bDirectValue
|| bDefault
)
535 // The value is stored in the PropertySet itself, add to list.
536 sal_Bool bGotValue
= sal_False
;
537 XMLPropertyState
aNewProperty( -1 );
538 for( std::list
<sal_uInt32
>::const_iterator aIndexItr
=
539 aItr
->GetIndexes().begin();
540 aIndexItr
!= aItr
->GetIndexes().end();
544 (rPropMapper
->GetEntryFlags( *aIndexItr
) &
545 MID_FLAG_DEFAULT_ITEM_EXPORT
) != 0 )
551 aNewProperty
.maValue
=
552 rPropSet
->getPropertyValue( aItr
->GetApiName() );
553 bGotValue
= sal_True
;
555 aNewProperty
.mnIndex
= *aIndexItr
;
556 aPropStates
.AddPropertyState( aNewProperty
);
558 catch( UnknownPropertyException
& )
560 // might be a problem of getImplemenetationId
561 OSL_ENSURE( !this, "unknown property in getPropertyValue" );
574 aPropStates
.FillPropertyStateVector(rPropStates
);
577 ///////////////////////////////////////////////////////////////////////////////
579 // ctor/dtor , class SvXMLExportPropertyMapper
582 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
583 const UniReference
< XMLPropertySetMapper
>& rMapper
) :
585 maPropMapper( rMapper
)
589 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
595 void SvXMLExportPropertyMapper::ChainExportMapper(
596 const UniReference
< SvXMLExportPropertyMapper
>& rMapper
)
598 // add map entries from rMapper to current map
599 maPropMapper
->AddMapperEntry( rMapper
->getPropertySetMapper() );
600 // rMapper uses the same map as 'this'
601 rMapper
->maPropMapper
= maPropMapper
;
603 // set rMapper as last mapper in current chain
604 UniReference
< SvXMLExportPropertyMapper
> xNext
= mxNextMapper
;
607 while( xNext
->mxNextMapper
.is())
608 xNext
= xNext
->mxNextMapper
;
609 xNext
->mxNextMapper
= rMapper
;
612 mxNextMapper
= rMapper
;
614 // if rMapper was already chained, correct
615 // map pointer of successors
618 while( xNext
->mxNextMapper
.is())
620 xNext
= xNext
->mxNextMapper
;
621 xNext
->maPropMapper
= maPropMapper
;
626 vector
< XMLPropertyState
> SvXMLExportPropertyMapper::_Filter(
627 const Reference
< XPropertySet
> xPropSet
,
628 const sal_Bool bDefault
) const
630 vector
< XMLPropertyState
> aPropStateArray
;
632 // Retrieve XPropertySetInfo and XPropertyState
633 Reference
< XPropertySetInfo
> xInfo( xPropSet
->getPropertySetInfo() );
635 return aPropStateArray
;
637 sal_Int32 nProps
= maPropMapper
->GetEntryCount();
639 FilterPropertiesInfo_Impl
*pFilterInfo
= 0;
641 Reference
< XTypeProvider
> xTypeProv( xPropSet
, UNO_QUERY
);
642 Sequence
< sal_Int8
> aImplId
;
645 aImplId
= xTypeProv
->getImplementationId();
646 if( aImplId
.getLength() == 16 )
650 // The key must not be created outside this block, because it
651 // keeps a reference to the property set info.
652 PropertySetInfoKey
aKey( xInfo
, aImplId
);
653 FilterPropertiesInfos_Impl::iterator aIter
=
654 pCache
->find( aKey
);
655 if( aIter
!= pCache
->end() )
656 pFilterInfo
= (*aIter
).second
;
661 sal_Bool bDelInfo
= sal_False
;
664 pFilterInfo
= new FilterPropertiesInfo_Impl
;
665 for( sal_Int32 i
=0; i
< nProps
; i
++ )
667 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
668 // Does the PropertySet contain name of mpEntries-array ?
669 const OUString
& rAPIName
= maPropMapper
->GetEntryAPIName( i
);
670 const sal_Int32 nFlags
= maPropMapper
->GetEntryFlags( i
);
671 if( (0 == (nFlags
& MID_FLAG_NO_PROPERTY_EXPORT
)) &&
672 ( (0 != (nFlags
& MID_FLAG_MUST_EXIST
)) ||
673 xInfo
->hasPropertyByName( rAPIName
) ) )
675 const SvtSaveOptions::ODFDefaultVersion
nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
676 const SvtSaveOptions::ODFDefaultVersion
nEarliestODFVersionForExport(
677 maPropMapper
->GetEarliestODFVersionForExport( i
) );
678 if( nCurrentVersion
>= nEarliestODFVersionForExport
679 || nCurrentVersion
== SvtSaveOptions::ODFVER_UNKNOWN
680 || nEarliestODFVersionForExport
== SvtSaveOptions::ODFVER_UNKNOWN
)
681 pFilterInfo
->AddProperty(rAPIName
, i
);
685 if( xTypeProv
.is() && aImplId
.getLength() == 16 )
687 // Check whether the property set info is destroyed if it is
688 // assigned to a weak reference only. If it is destroyed, then
689 // every instance of getPropertySetInfo returns a new object.
690 // Such property set infos must not be cached.
691 WeakReference
< XPropertySetInfo
> xWeakInfo( xInfo
);
697 ((SvXMLExportPropertyMapper
*)this)->pCache
=
698 new FilterPropertiesInfos_Impl
;
699 PropertySetInfoKey
aKey( xInfo
, aImplId
);
700 (*pCache
)[aKey
] = pFilterInfo
;
707 OSL_ENSURE(sal_False
, "here is no TypeProvider or the ImplId is wrong");
712 if( pFilterInfo
->GetPropertyCount() )
716 pFilterInfo
->FillPropertyStateArray(aPropStateArray
,
717 xPropSet
, maPropMapper
,
720 catch( UnknownPropertyException
& )
722 // might be a problem of getImplemenetationId
723 OSL_ENSURE( !this, "unknown property in getPropertyStates" );
727 // Call centext-filter
728 if( !aPropStateArray
.empty() )
729 ContextFilter( aPropStateArray
, xPropSet
);
731 // Have to do if we change from a vector to a list or something like that
732 /*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin();
733 while (aItr != aPropStateArray.end())
735 if (aItr->mnIndex == -1)
736 aItr = aPropStateArray.erase(aItr);
744 return aPropStateArray
;
747 void SvXMLExportPropertyMapper::ContextFilter(
748 vector
< XMLPropertyState
>& rProperties
,
749 Reference
< XPropertySet
> rPropSet
) const
751 // Derived class could implement this.
752 if( mxNextMapper
.is() )
753 mxNextMapper
->ContextFilter( rProperties
, rPropSet
);
756 ///////////////////////////////////////////////////////////////////////////
758 // Compares two Sequences of XMLPropertyState:
759 // 1.Number of elements equal ?
760 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
761 // 3.Value of each element equal ?
763 sal_Bool
SvXMLExportPropertyMapper::Equals(
764 const vector
< XMLPropertyState
>& aProperties1
,
765 const vector
< XMLPropertyState
>& aProperties2
) const
767 sal_Bool bRet
= sal_True
;
768 sal_uInt32 nCount
= aProperties1
.size();
770 if( nCount
== aProperties2
.size() )
772 sal_uInt32 nIndex
= 0;
773 while( bRet
&& nIndex
< nCount
)
775 const XMLPropertyState
& rProp1
= aProperties1
[ nIndex
];
776 const XMLPropertyState
& rProp2
= aProperties2
[ nIndex
];
778 // Compare index. If equal, compare value
779 if( rProp1
.mnIndex
== rProp2
.mnIndex
)
781 if( rProp1
.mnIndex
!= -1 )
783 // Now compare values
784 if( ( maPropMapper
->GetEntryType( rProp1
.mnIndex
) &
785 XML_TYPE_BUILDIN_CMP
) != 0 )
786 // simple type ( binary compare )
787 bRet
= ( rProp1
.maValue
== rProp2
.maValue
);
789 // complex type ( ask for compare-function )
790 bRet
= maPropMapper
->GetPropertyHandler(
791 rProp1
.mnIndex
)->equals( rProp1
.maValue
,
808 /** fills the given attribute list with the items in the given set
809 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
810 const ::std::vector< XMLPropertyState >& rProperties,
811 const SvXMLUnitConverter& rUnitConverter,
812 const SvXMLNamespaceMap& rNamespaceMap,
813 sal_uInt16 nFlags ) const
815 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
820 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
821 const ::std::vector< XMLPropertyState >& rProperties,
822 const SvXMLUnitConverter& rUnitConverter,
823 const SvXMLNamespaceMap& rNamespaceMap,
824 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
825 sal_uInt16 nFlags ) const
827 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
828 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
833 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList
& rAttrList
,
834 const XMLPropertyState
& rProperty
,
835 const SvXMLUnitConverter
& rUnitConverter
,
836 const SvXMLNamespaceMap
& rNamespaceMap
,
837 sal_uInt16 nFlags
) const
839 if( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
840 MID_FLAG_ELEMENT_ITEM_EXPORT
) == 0 )
841 _exportXML( rAttrList
, rProperty
, rUnitConverter
, rNamespaceMap
,
845 void SvXMLExportPropertyMapper::exportXML(
846 SvXMLExport
& rExport
,
847 const ::std::vector
< XMLPropertyState
>& rProperties
,
848 sal_uInt16 nFlags
) const
850 exportXML( rExport
, rProperties
, -1, -1, nFlags
);
853 void SvXMLExportPropertyMapper::exportXML(
854 SvXMLExport
& rExport
,
855 const ::std::vector
< XMLPropertyState
>& rProperties
,
856 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
,
857 sal_uInt16 nFlags
) const
859 sal_uInt16 nPropTypeFlags
= 0;
860 for( sal_uInt16 i
=0; i
<MAX_PROP_TYPES
; ++i
)
862 sal_uInt16 nPropType
= aPropTokens
[i
].nType
;
863 if( 0==i
|| (nPropTypeFlags
& (1 << nPropType
)) != 0 )
865 SvUShorts aIndexArray
;
867 _exportXML( nPropType
, nPropTypeFlags
,
868 rExport
.GetAttrList(), rProperties
,
869 rExport
.GetMM100UnitConverter(),
870 rExport
.GetNamespaceMap(),
871 nFlags
, &aIndexArray
,
872 nPropMapStartIdx
, nPropMapEndIdx
);
874 if( rExport
.GetAttrList().getLength() > 0L ||
875 (nFlags
& XML_EXPORT_FLAG_EMPTY
) != 0 ||
876 aIndexArray
.Count() != 0 )
878 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_STYLE
,
879 aPropTokens
[i
].eToken
,
880 (nFlags
& XML_EXPORT_FLAG_IGN_WS
) != 0,
883 exportElementItems( rExport
, rProperties
, nFlags
, aIndexArray
);
889 /** this method is called for every item that has the
890 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
891 void SvXMLExportPropertyMapper::handleSpecialItem(
892 SvXMLAttributeList
& rAttrList
,
893 const XMLPropertyState
& rProperty
,
894 const SvXMLUnitConverter
& rUnitConverter
,
895 const SvXMLNamespaceMap
& rNamespaceMap
,
896 const ::std::vector
< XMLPropertyState
> *pProperties
,
897 sal_uInt32 nIdx
) const
899 OSL_ENSURE( mxNextMapper
.is(), "special item not handled in xml export" );
900 if( mxNextMapper
.is() )
901 mxNextMapper
->handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
902 rNamespaceMap
, pProperties
, nIdx
);
905 /** this method is called for every item that has the
906 MID_FLAG_ELEMENT_EXPORT flag set */
907 void SvXMLExportPropertyMapper::handleElementItem(
908 SvXMLExport
& rExport
,
909 const XMLPropertyState
& rProperty
,
911 const ::std::vector
< XMLPropertyState
> *pProperties
,
912 sal_uInt32 nIdx
) const
914 OSL_ENSURE( mxNextMapper
.is(), "element item not handled in xml export" );
915 if( mxNextMapper
.is() )
916 mxNextMapper
->handleElementItem( rExport
, rProperty
, nFlags
,
920 ///////////////////////////////////////////////////////////////////////////////
925 /** fills the given attribute list with the items in the given set */
926 void SvXMLExportPropertyMapper::_exportXML(
927 sal_uInt16 nPropType
, sal_uInt16
& rPropTypeFlags
,
928 SvXMLAttributeList
& rAttrList
,
929 const ::std::vector
< XMLPropertyState
>& rProperties
,
930 const SvXMLUnitConverter
& rUnitConverter
,
931 const SvXMLNamespaceMap
& rNamespaceMap
,
933 SvUShorts
* pIndexArray
,
934 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
) const
936 const sal_uInt32 nCount
= rProperties
.size();
937 sal_uInt32 nIndex
= 0;
939 if( -1 == nPropMapStartIdx
)
940 nPropMapStartIdx
= 0;
941 if( -1 == nPropMapEndIdx
)
942 nPropMapEndIdx
= maPropMapper
->GetEntryCount();
944 while( nIndex
< nCount
)
946 sal_Int32 nPropMapIdx
= rProperties
[nIndex
].mnIndex
;
947 if( nPropMapIdx
>= nPropMapStartIdx
&&
948 nPropMapIdx
< nPropMapEndIdx
)// valid entry?
950 sal_uInt32 nEFlags
= maPropMapper
->GetEntryFlags( nPropMapIdx
);
951 sal_uInt16 nEPType
= GET_PROP_TYPE(nEFlags
);
952 OSL_ENSURE( nEPType
>= (XML_TYPE_PROP_START
>>XML_TYPE_PROP_SHIFT
),
953 "no prop type sepcified" );
954 rPropTypeFlags
|= (1 << nEPType
);
955 if( nEPType
== nPropType
)
957 // we have a valid map entry here, so lets use it...
958 if( ( nEFlags
& MID_FLAG_ELEMENT_ITEM_EXPORT
) != 0 )
960 // element items do not add any properties,
961 // we export it later
963 pIndexArray
->Insert( (sal_uInt16
)nIndex
, pIndexArray
->Count() );
967 _exportXML( rAttrList
, rProperties
[nIndex
], rUnitConverter
,
968 rNamespaceMap
, nFlags
, &rProperties
, nIndex
);
977 void SvXMLExportPropertyMapper::_exportXML(
978 SvXMLAttributeList
& rAttrList
,
979 const XMLPropertyState
& rProperty
,
980 const SvXMLUnitConverter
& rUnitConverter
,
981 const SvXMLNamespaceMap
& rNamespaceMap
,
982 sal_uInt16
/*nFlags*/,
983 const ::std::vector
< XMLPropertyState
> *pProperties
,
984 sal_uInt32 nIdx
) const
986 OUString
sCDATA( GetXMLToken(XML_CDATA
) );
988 if ( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
989 MID_FLAG_SPECIAL_ITEM_EXPORT
) != 0 )
991 uno::Reference
< container::XNameContainer
> xAttrContainer
;
992 if( (rProperty
.maValue
>>= xAttrContainer
) && xAttrContainer
.is() )
994 SvXMLNamespaceMap
*pNewNamespaceMap
= 0;
995 const SvXMLNamespaceMap
*pNamespaceMap
= &rNamespaceMap
;
997 uno::Sequence
< OUString
> aAttribNames( xAttrContainer
->getElementNames() );
998 const OUString
* pAttribName
= aAttribNames
.getConstArray();
1000 const sal_Int32 nCount
= aAttribNames
.getLength();
1002 OUStringBuffer sNameBuffer
;
1003 xml::AttributeData aData
;
1004 for( sal_Int32 i
=0; i
< nCount
; i
++, pAttribName
++ )
1006 xAttrContainer
->getByName( *pAttribName
) >>= aData
;
1007 OUString
sAttribName( *pAttribName
);
1009 // extract namespace prefix from attribute name if it exists
1011 const sal_Int32 nColonPos
=
1012 pAttribName
->indexOf( sal_Unicode(':') );
1013 if( nColonPos
!= -1 )
1014 sPrefix
= pAttribName
->copy( 0, nColonPos
);
1016 if( sPrefix
.getLength() )
1018 OUString
sNamespace( aData
.Namespace
);
1020 // if the prefix isn't defined yet or has another meaning,
1021 // we have to redefine it now.
1022 sal_uInt16 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
1023 if( USHRT_MAX
== nKey
|| pNamespaceMap
->GetNameByKey( nKey
) != sNamespace
)
1025 sal_Bool bAddNamespace
= sal_False
;
1026 if( USHRT_MAX
== nKey
)
1028 // The prefix is unused, so it is sufficient
1029 // to add it to the namespace map.
1030 bAddNamespace
= sal_True
;
1034 // check if there is a prefix registered for the
1036 nKey
= pNamespaceMap
->GetKeyByName( sNamespace
);
1037 if( XML_NAMESPACE_UNKNOWN
== nKey
)
1039 // There is no prefix for the namespace, so
1040 // we have to generate one and have to add it.
1042 OUString
sOrigPrefix( sPrefix
);
1045 sNameBuffer
.append( sOrigPrefix
);
1046 sNameBuffer
.append( ++n
);
1047 sPrefix
= sNameBuffer
.makeStringAndClear();
1048 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
1050 while( nKey
!= USHRT_MAX
);
1052 bAddNamespace
= sal_True
;
1056 // If there is a prefix for the namespace,
1058 sPrefix
= pNamespaceMap
->GetPrefixByKey( nKey
);
1060 // In any case, the attribute name has to be adapted.
1061 sNameBuffer
.append( sPrefix
);
1062 sNameBuffer
.append( sal_Unicode(':') );
1063 sNameBuffer
.append( pAttribName
->copy( nColonPos
+1 ) );
1064 sAttribName
= sNameBuffer
.makeStringAndClear();
1069 if( !pNewNamespaceMap
)
1071 pNewNamespaceMap
= new SvXMLNamespaceMap( rNamespaceMap
);
1072 pNamespaceMap
= pNewNamespaceMap
;
1074 pNewNamespaceMap
->Add( sPrefix
, sNamespace
);
1075 sNameBuffer
.append( GetXMLToken(XML_XMLNS
) );
1076 sNameBuffer
.append( sal_Unicode(':') );
1077 sNameBuffer
.append( sPrefix
);
1078 rAttrList
.AddAttribute( sNameBuffer
.makeStringAndClear(),
1083 OUString
sOldValue( rAttrList
.getValueByName( sAttribName
) );
1084 OSL_ENSURE( sOldValue
.getLength() == 0, "alien attribute exists already" );
1085 OSL_ENSURE(aData
.Type
== GetXMLToken(XML_CDATA
), "different type to our default type which should be written out");
1086 if( !sOldValue
.getLength() )
1087 rAttrList
.AddAttribute( sAttribName
, aData
.Value
);
1090 delete pNewNamespaceMap
;
1094 handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
1095 rNamespaceMap
, pProperties
, nIdx
);
1098 else if ( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
1099 MID_FLAG_ELEMENT_ITEM_EXPORT
) == 0 )
1102 const OUString
sName( rNamespaceMap
.GetQNameByKey(
1103 maPropMapper
->GetEntryNameSpace( rProperty
.mnIndex
),
1104 maPropMapper
->GetEntryXMLName( rProperty
.mnIndex
) ) );
1106 sal_Bool bRemove
= sal_False
;
1107 if( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
1108 MID_FLAG_MERGE_ATTRIBUTE
) != 0 )
1110 aValue
= rAttrList
.getValueByName( sName
);
1111 bRemove
= sal_True
; //aValue.getLength() != 0;
1114 if( maPropMapper
->exportXML( aValue
, rProperty
, rUnitConverter
) )
1117 rAttrList
.RemoveAttribute( sName
);
1118 rAttrList
.AddAttribute( sName
, aValue
);
1123 void SvXMLExportPropertyMapper::exportElementItems(
1124 SvXMLExport
& rExport
,
1125 const ::std::vector
< XMLPropertyState
>& rProperties
,
1127 const SvUShorts
& rIndexArray
) const
1129 const sal_uInt16 nCount
= rIndexArray
.Count();
1131 sal_Bool bItemsExported
= sal_False
;
1132 OUString
sWS( GetXMLToken(XML_WS
) );
1133 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
1135 const sal_uInt16 nElement
= rIndexArray
.GetObject( nIndex
);
1137 OSL_ENSURE( 0 != ( maPropMapper
->GetEntryFlags(
1138 rProperties
[nElement
].mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
),
1139 "wrong mid flag!" );
1141 rExport
.IgnorableWhitespace();
1142 handleElementItem( rExport
, rProperties
[nElement
],
1143 nFlags
, &rProperties
, nElement
);
1144 bItemsExported
= sal_True
;
1147 if( bItemsExported
)
1148 rExport
.IgnorableWhitespace();