1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/container/XNameContainer.hpp>
21 #include <com/sun/star/xml/AttributeData.hpp>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/beans/XPropertyState.hpp>
24 #include <com/sun/star/lang/XTypeProvider.hpp>
25 #include <com/sun/star/beans/XMultiPropertySet.hpp>
26 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
27 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
28 #include <rtl/ustrbuf.hxx>
30 #include <boost/unordered_map.hpp>
32 #include <xmloff/xmlexppr.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/attrlist.hxx>
35 #include <xmloff/nmspmap.hxx>
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmlexp.hxx>
38 #include <xmloff/xmlprmap.hxx>
39 #include <xmloff/PropertySetInfoHash.hxx>
40 #include <comphelper/stl_types.hxx>
43 using namespace ::std
;
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::com::sun::star::uno
;
47 using namespace ::com::sun::star::lang
;
48 using namespace ::xmloff::token
;
50 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
52 struct XMLPropTokens_Impl
58 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
59 const sal_uInt16 MAX_PROP_TYPES
=
60 (XML_TYPE_PROP_END
>> XML_TYPE_PROP_SHIFT
) -
61 (XML_TYPE_PROP_START
>> XML_TYPE_PROP_SHIFT
);
63 static XMLPropTokens_Impl aPropTokens
[MAX_PROP_TYPES
] =
81 ///////////////////////////////////////////////////////////////////////////////
86 ///////////////////////////////////////////////////////////////////////////
88 // Take all properties of the XPropertySet which are also found in the
89 // XMLPropertyMapEntry-array and which are not set to their default-value,
90 // if a state is available.
92 // After that I call the method 'ContextFilter'.
95 typedef std::list
<XMLPropertyState
> XMLPropertyStateList_Impl
;
97 class XMLPropertyStates_Impl
99 XMLPropertyStateList_Impl aPropStates
;
100 XMLPropertyStateList_Impl::iterator aLastItr
;
103 XMLPropertyStates_Impl();
104 void AddPropertyState(const XMLPropertyState
& rPropState
);
105 void FillPropertyStateVector(std::vector
<XMLPropertyState
>& rVector
);
108 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
112 aLastItr
= aPropStates
.begin();
115 void XMLPropertyStates_Impl::AddPropertyState(
116 const XMLPropertyState
& rPropState
)
118 XMLPropertyStateList_Impl::iterator aItr
= aPropStates
.begin();
119 sal_Bool
bInserted(sal_False
);
122 if (aLastItr
->mnIndex
< rPropState
.mnIndex
)
127 // TODO: one path required only
128 if (aItr
== aPropStates
.end())
130 aLastItr
= aPropStates
.insert(aPropStates
.end(), rPropState
);
131 bInserted
= sal_True
;
134 else if (aItr
->mnIndex
> rPropState
.mnIndex
)
136 aLastItr
= aPropStates
.insert(aItr
, rPropState
);
137 bInserted
= sal_True
;
141 while(!bInserted
&& (aItr
++ != aPropStates
.end()));
144 void XMLPropertyStates_Impl::FillPropertyStateVector(
145 std::vector
<XMLPropertyState
>& rVector
)
149 rVector
.resize(nCount
, XMLPropertyState(-1));
150 ::std::copy( aPropStates
.begin(), aPropStates
.end(), rVector
.begin() );
154 class FilterPropertyInfo_Impl
156 const OUString sApiName
;
157 std::list
<sal_uInt32
> aIndexes
;
162 FilterPropertyInfo_Impl( const OUString
& rApiName
,
163 const sal_uInt32 nIndex
);
165 const OUString
& GetApiName() const { return sApiName
; }
166 std::list
<sal_uInt32
>& GetIndexes() { return aIndexes
; }
168 void AddIndex( sal_uInt32 nIndex
)
170 aIndexes
.push_back(nIndex
);
175 sal_Bool
operator< ( const FilterPropertyInfo_Impl
& rArg
) const
177 return (GetApiName() < rArg
.GetApiName());
181 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
182 const OUString
& rApiName
,
183 const sal_uInt32 nIndex
) :
184 sApiName( rApiName
),
188 aIndexes
.push_back(nIndex
);
191 typedef std::list
<FilterPropertyInfo_Impl
> FilterPropertyInfoList_Impl
;
193 // ----------------------------------------------------------------------------
195 class FilterPropertiesInfo_Impl
198 FilterPropertyInfoList_Impl aPropInfos
;
199 FilterPropertyInfoList_Impl::iterator aLastItr
;
201 Sequence
<OUString
> *pApiNames
;
204 FilterPropertiesInfo_Impl();
205 ~FilterPropertiesInfo_Impl();
207 void AddProperty(const OUString
& rApiName
, const sal_uInt32 nIndex
);
208 const uno::Sequence
<OUString
>& GetApiNames();
209 void FillPropertyStateArray(
210 vector
< XMLPropertyState
>& rPropStates
,
211 const Reference
< XPropertySet
>& xPropSet
,
212 const UniReference
< XMLPropertySetMapper
>& maPropMapper
,
213 const sal_Bool bDefault
= sal_False
);
214 sal_uInt32
GetPropertyCount() const { return nCount
; }
217 // ----------------------------------------------------------------------------
219 typedef boost::unordered_map
222 FilterPropertiesInfo_Impl
*,
226 FilterOropertiesHashMap_Impl
;
228 class FilterPropertiesInfos_Impl
: public FilterOropertiesHashMap_Impl
231 ~FilterPropertiesInfos_Impl ();
234 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
236 FilterOropertiesHashMap_Impl::iterator aIter
= begin();
237 FilterOropertiesHashMap_Impl::iterator aEnd
= end();
238 while( aIter
!= aEnd
)
240 delete (*aIter
).second
;
246 // ----------------------------------------------------------------------------
248 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
253 aLastItr
= aPropInfos
.begin();
256 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
261 void FilterPropertiesInfo_Impl::AddProperty(
262 const OUString
& rApiName
, const sal_uInt32 nIndex
)
264 aPropInfos
.push_back(FilterPropertyInfo_Impl(rApiName
, nIndex
));
267 OSL_ENSURE( !pApiNames
, "perfomance warning: API names already retrieved" );
274 const uno::Sequence
<OUString
>& FilterPropertiesInfo_Impl::GetApiNames()
276 OSL_ENSURE(nCount
== aPropInfos
.size(), "wrong property count");
279 // we have to do three things:
280 // 1) sort API names,
281 // 2) merge duplicates,
282 // 3) construct sequence
290 FilterPropertyInfoList_Impl::iterator aOld
= aPropInfos
.begin();
291 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
292 FilterPropertyInfoList_Impl::iterator aCurrent
= aOld
;
295 while ( aCurrent
!= aEnd
)
297 // equal to next element?
298 if ( aOld
->GetApiName().equals( aCurrent
->GetApiName() ) )
300 // if equal: merge index lists
301 aOld
->GetIndexes().merge( aCurrent
->GetIndexes() );
302 // erase element, and continue with next
303 aCurrent
= aPropInfos
.erase( aCurrent
);
308 // remember old element and continue with next
315 // construct sequence
316 pApiNames
= new Sequence
< OUString
>( nCount
);
317 OUString
*pNames
= pApiNames
->getArray();
318 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
319 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
320 for ( ; aItr
!= aEnd
; ++aItr
, ++pNames
)
321 *pNames
= aItr
->GetApiName();
327 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
328 vector
< XMLPropertyState
>& rPropStates
,
329 const Reference
< XPropertySet
>& rPropSet
,
330 const UniReference
< XMLPropertySetMapper
>& rPropMapper
,
331 const sal_Bool bDefault
)
333 XMLPropertyStates_Impl aPropStates
;
335 const uno::Sequence
<OUString
>& rApiNames
= GetApiNames();
337 Reference
< XTolerantMultiPropertySet
> xTolPropSet( rPropSet
, UNO_QUERY
);
338 if (xTolPropSet
.is())
342 Sequence
< beans::GetDirectPropertyTolerantResult
> aResults(xTolPropSet
->getDirectPropertyValuesTolerant(rApiNames
));
343 sal_Int32
nResultCount(aResults
.getLength());
344 if (nResultCount
> 0)
346 const beans::GetDirectPropertyTolerantResult
*pResults
= aResults
.getConstArray();
347 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
348 XMLPropertyState
aNewProperty( -1 );
350 while (nResultCount
> 0 && i
< nCount
)
352 if (pResults
->Name
== aPropIter
->GetApiName())
354 aNewProperty
.mnIndex
= -1;
355 aNewProperty
.maValue
= pResults
->Value
;
357 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
358 aIndexItr
!= aPropIter
->GetIndexes().end();
361 aNewProperty
.mnIndex
= *aIndexItr
;
362 aPropStates
.AddPropertyState( aNewProperty
);
374 Sequence
< beans::GetPropertyTolerantResult
> aResults(xTolPropSet
->getPropertyValuesTolerant(rApiNames
));
375 OSL_ENSURE( rApiNames
.getLength() == aResults
.getLength(), "wrong implemented XTolerantMultiPropertySet" );
376 const beans::GetPropertyTolerantResult
*pResults
= aResults
.getConstArray();
377 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
378 XMLPropertyState
aNewProperty( -1 );
379 sal_uInt32
nResultCount(aResults
.getLength());
380 OSL_ENSURE( nCount
== nResultCount
, "wrong implemented XTolerantMultiPropertySet??" );
381 for( sal_uInt32 i
= 0; i
< nResultCount
; ++i
)
383 if ((pResults
->Result
== beans::TolerantPropertySetResultType::SUCCESS
) &&
384 ((pResults
->State
== PropertyState_DIRECT_VALUE
) || (pResults
->State
== PropertyState_DEFAULT_VALUE
)))
386 aNewProperty
.mnIndex
= -1;
387 aNewProperty
.maValue
= pResults
->Value
;
389 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
390 aIndexItr
!= aPropIter
->GetIndexes().end();
393 aNewProperty
.mnIndex
= *aIndexItr
;
394 aPropStates
.AddPropertyState( aNewProperty
);
404 Sequence
< PropertyState
> aStates
;
405 const PropertyState
*pStates
= 0;
406 Reference
< XPropertyState
> xPropState( rPropSet
, UNO_QUERY
);
407 if( xPropState
.is() )
409 aStates
= xPropState
->getPropertyStates( rApiNames
);
410 pStates
= aStates
.getConstArray();
413 Reference
< XMultiPropertySet
> xMultiPropSet( rPropSet
, UNO_QUERY
);
414 if( xMultiPropSet
.is() && !bDefault
)
416 Sequence
< Any
> aValues
;
419 // step 1: get value count
420 sal_uInt32 nValueCount
= 0;
423 for( i
= 0; i
< nCount
; ++i
, ++pStates
)
425 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
431 // step 2: collect property names
432 Sequence
< OUString
> aAPINames( nValueCount
);
433 OUString
*pAPINames
= aAPINames
.getArray();
435 ::std::vector
< FilterPropertyInfoList_Impl::iterator
> aPropIters
;
436 aPropIters
.reserve( nValueCount
);
438 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
439 OSL_ENSURE(aItr
!= aPropInfos
.end(),"Invalid iterator!");
441 pStates
= aStates
.getConstArray();
443 while( i
< nValueCount
)
445 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
447 *pAPINames
++ = aItr
->GetApiName();
448 aPropIters
.push_back( aItr
);
455 aValues
= xMultiPropSet
->getPropertyValues( aAPINames
);
456 const Any
*pValues
= aValues
.getConstArray();
458 ::std::vector
< FilterPropertyInfoList_Impl::iterator
>::const_iterator
459 pPropIter
= aPropIters
.begin();
461 XMLPropertyState
aNewProperty( -1 );
462 for( i
= 0; i
< nValueCount
; ++i
)
464 aNewProperty
.mnIndex
= -1;
465 aNewProperty
.maValue
= *pValues
;
467 const ::std::list
< sal_uInt32
>& rIndexes( (*pPropIter
)->GetIndexes() );
468 for ( std::list
<sal_uInt32
>::const_iterator aIndexItr
= rIndexes
.begin();
469 aIndexItr
!= rIndexes
.end();
473 aNewProperty
.mnIndex
= *aIndexItr
;
474 aPropStates
.AddPropertyState( aNewProperty
);
484 aValues
= xMultiPropSet
->getPropertyValues( rApiNames
);
485 const Any
*pValues
= aValues
.getConstArray();
487 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
488 for(sal_uInt32 i
= 0; i
< nCount
; ++i
)
490 // The value is stored in the PropertySet itself, add to list.
491 XMLPropertyState
aNewProperty( -1 );
492 aNewProperty
.maValue
= *pValues
;
494 for( std::list
<sal_uInt32
>::iterator aIndexItr
=
495 aItr
->GetIndexes().begin();
496 aIndexItr
!= aItr
->GetIndexes().end();
499 aNewProperty
.mnIndex
= *aIndexItr
;
500 aPropStates
.AddPropertyState( aNewProperty
);
508 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
509 for(sal_uInt32 i
= 0; i
< nCount
; ++i
)
511 sal_Bool bDirectValue
=
512 !pStates
|| *pStates
== PropertyState_DIRECT_VALUE
;
513 if( bDirectValue
|| bDefault
)
515 // The value is stored in the PropertySet itself, add to list.
516 sal_Bool bGotValue
= sal_False
;
517 XMLPropertyState
aNewProperty( -1 );
518 for( std::list
<sal_uInt32
>::const_iterator aIndexItr
=
519 aItr
->GetIndexes().begin();
520 aIndexItr
!= aItr
->GetIndexes().end();
524 (rPropMapper
->GetEntryFlags( *aIndexItr
) &
525 MID_FLAG_DEFAULT_ITEM_EXPORT
) != 0 )
531 aNewProperty
.maValue
=
532 rPropSet
->getPropertyValue( aItr
->GetApiName() );
533 bGotValue
= sal_True
;
535 aNewProperty
.mnIndex
= *aIndexItr
;
536 aPropStates
.AddPropertyState( aNewProperty
);
538 catch( UnknownPropertyException
& )
540 // might be a problem of getImplemenetationId
541 OSL_ENSURE( !this, "unknown property in getPropertyValue" );
554 aPropStates
.FillPropertyStateVector(rPropStates
);
557 ///////////////////////////////////////////////////////////////////////////////
559 // ctor/dtor , class SvXMLExportPropertyMapper
562 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
563 const UniReference
< XMLPropertySetMapper
>& rMapper
) :
565 maPropMapper( rMapper
)
569 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
575 void SvXMLExportPropertyMapper::ChainExportMapper(
576 const UniReference
< SvXMLExportPropertyMapper
>& rMapper
)
578 // add map entries from rMapper to current map
579 maPropMapper
->AddMapperEntry( rMapper
->getPropertySetMapper() );
580 // rMapper uses the same map as 'this'
581 rMapper
->maPropMapper
= maPropMapper
;
583 // set rMapper as last mapper in current chain
584 UniReference
< SvXMLExportPropertyMapper
> xNext
= mxNextMapper
;
587 while( xNext
->mxNextMapper
.is())
588 xNext
= xNext
->mxNextMapper
;
589 xNext
->mxNextMapper
= rMapper
;
592 mxNextMapper
= rMapper
;
594 // if rMapper was already chained, correct
595 // map pointer of successors
598 while( xNext
->mxNextMapper
.is())
600 xNext
= xNext
->mxNextMapper
;
601 xNext
->maPropMapper
= maPropMapper
;
606 vector
< XMLPropertyState
> SvXMLExportPropertyMapper::_Filter(
607 const Reference
< XPropertySet
> xPropSet
,
608 bool bDefault
, bool bEnableFoFontFamily
) const
610 vector
< XMLPropertyState
> aPropStateArray
;
612 // Retrieve XPropertySetInfo and XPropertyState
613 Reference
< XPropertySetInfo
> xInfo( xPropSet
->getPropertySetInfo() );
615 return aPropStateArray
;
617 sal_Int32 nProps
= maPropMapper
->GetEntryCount();
619 FilterPropertiesInfo_Impl
*pFilterInfo
= 0;
621 Reference
< XTypeProvider
> xTypeProv( xPropSet
, UNO_QUERY
);
622 Sequence
< sal_Int8
> aImplId
;
625 aImplId
= xTypeProv
->getImplementationId();
626 if( aImplId
.getLength() == 16 )
630 // The key must not be created outside this block, because it
631 // keeps a reference to the property set info.
632 PropertySetInfoKey
aKey( xInfo
, aImplId
);
633 FilterPropertiesInfos_Impl::iterator aIter
=
634 pCache
->find( aKey
);
635 if( aIter
!= pCache
->end() )
636 pFilterInfo
= (*aIter
).second
;
641 sal_Bool bDelInfo
= sal_False
;
644 pFilterInfo
= new FilterPropertiesInfo_Impl
;
645 for( sal_Int32 i
=0; i
< nProps
; i
++ )
647 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
648 // Does the PropertySet contain name of mpEntries-array ?
649 const OUString
& rAPIName
= maPropMapper
->GetEntryAPIName( i
);
650 const sal_Int32 nFlags
= maPropMapper
->GetEntryFlags( i
);
651 if( (0 == (nFlags
& MID_FLAG_NO_PROPERTY_EXPORT
)) &&
652 ( (0 != (nFlags
& MID_FLAG_MUST_EXIST
)) ||
653 xInfo
->hasPropertyByName( rAPIName
) ) )
655 const SvtSaveOptions::ODFDefaultVersion
nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
656 const SvtSaveOptions::ODFDefaultVersion
nEarliestODFVersionForExport(
657 maPropMapper
->GetEarliestODFVersionForExport( i
) );
658 if( nCurrentVersion
>= nEarliestODFVersionForExport
659 || nCurrentVersion
== SvtSaveOptions::ODFVER_UNKNOWN
660 || nEarliestODFVersionForExport
== SvtSaveOptions::ODFVER_UNKNOWN
)
661 pFilterInfo
->AddProperty(rAPIName
, i
);
665 if( xTypeProv
.is() && aImplId
.getLength() == 16 )
667 // Check whether the property set info is destroyed if it is
668 // assigned to a weak reference only. If it is destroyed, then
669 // every instance of getPropertySetInfo returns a new object.
670 // Such property set infos must not be cached.
671 WeakReference
< XPropertySetInfo
> xWeakInfo( xInfo
);
677 ((SvXMLExportPropertyMapper
*)this)->pCache
=
678 new FilterPropertiesInfos_Impl
;
679 PropertySetInfoKey
aKey( xInfo
, aImplId
);
680 (*pCache
)[aKey
] = pFilterInfo
;
687 OSL_FAIL("here is no TypeProvider or the ImplId is wrong");
692 if( pFilterInfo
->GetPropertyCount() )
696 pFilterInfo
->FillPropertyStateArray(aPropStateArray
,
697 xPropSet
, maPropMapper
,
700 catch( UnknownPropertyException
& )
702 // might be a problem of getImplemenetationId
703 OSL_ENSURE( !this, "unknown property in getPropertyStates" );
707 // Call centext-filter
708 if( !aPropStateArray
.empty() )
709 ContextFilter(bEnableFoFontFamily
, aPropStateArray
, xPropSet
);
711 // Have to do if we change from a vector to a list or something like that
716 return aPropStateArray
;
719 void SvXMLExportPropertyMapper::ContextFilter(
720 bool bEnableFoFontFamily
,
721 vector
< XMLPropertyState
>& rProperties
,
722 Reference
< XPropertySet
> rPropSet
) const
724 // Derived class could implement this.
725 if( mxNextMapper
.is() )
726 mxNextMapper
->ContextFilter( bEnableFoFontFamily
, rProperties
, rPropSet
);
729 ///////////////////////////////////////////////////////////////////////////
731 // Compares two Sequences of XMLPropertyState:
732 // 1.Number of elements equal ?
733 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
734 // 3.Value of each element equal ?
736 sal_Bool
SvXMLExportPropertyMapper::Equals(
737 const vector
< XMLPropertyState
>& aProperties1
,
738 const vector
< XMLPropertyState
>& aProperties2
) const
740 sal_Bool bRet
= sal_True
;
741 sal_uInt32 nCount
= aProperties1
.size();
743 if( nCount
== aProperties2
.size() )
745 sal_uInt32 nIndex
= 0;
746 while( bRet
&& nIndex
< nCount
)
748 const XMLPropertyState
& rProp1
= aProperties1
[ nIndex
];
749 const XMLPropertyState
& rProp2
= aProperties2
[ nIndex
];
751 // Compare index. If equal, compare value
752 if( rProp1
.mnIndex
== rProp2
.mnIndex
)
754 if( rProp1
.mnIndex
!= -1 )
756 // Now compare values
757 if( ( maPropMapper
->GetEntryType( rProp1
.mnIndex
) &
758 XML_TYPE_BUILDIN_CMP
) != 0 )
759 // simple type ( binary compare )
760 bRet
= ( rProp1
.maValue
== rProp2
.maValue
);
762 // complex type ( ask for compare-function )
763 bRet
= maPropMapper
->GetPropertyHandler(
764 rProp1
.mnIndex
)->equals( rProp1
.maValue
,
781 /** fills the given attribute list with the items in the given set
782 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
783 const ::std::vector< XMLPropertyState >& rProperties,
784 const SvXMLUnitConverter& rUnitConverter,
785 const SvXMLNamespaceMap& rNamespaceMap,
786 sal_uInt16 nFlags ) const
788 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
793 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
794 const ::std::vector< XMLPropertyState >& rProperties,
795 const SvXMLUnitConverter& rUnitConverter,
796 const SvXMLNamespaceMap& rNamespaceMap,
797 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
798 sal_uInt16 nFlags ) const
800 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
801 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
805 void SvXMLExportPropertyMapper::exportXML(
806 SvXMLExport
& rExport
,
807 const ::std::vector
< XMLPropertyState
>& rProperties
,
808 sal_uInt16 nFlags
) const
810 exportXML( rExport
, rProperties
, -1, -1, nFlags
);
813 void SvXMLExportPropertyMapper::exportXML(
814 SvXMLExport
& rExport
,
815 const ::std::vector
< XMLPropertyState
>& rProperties
,
816 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
,
817 sal_uInt16 nFlags
) const
819 sal_uInt16 nPropTypeFlags
= 0;
820 for( sal_uInt16 i
=0; i
<MAX_PROP_TYPES
; ++i
)
822 sal_uInt16 nPropType
= aPropTokens
[i
].nType
;
823 if( 0==i
|| (nPropTypeFlags
& (1 << nPropType
)) != 0 )
825 std::vector
<sal_uInt16
> aIndexArray
;
827 _exportXML( nPropType
, nPropTypeFlags
,
828 rExport
.GetAttrList(), rProperties
,
829 rExport
.GetMM100UnitConverter(),
830 rExport
.GetNamespaceMap(),
831 nFlags
, &aIndexArray
,
832 nPropMapStartIdx
, nPropMapEndIdx
);
834 if( rExport
.GetAttrList().getLength() > 0L ||
835 (nFlags
& XML_EXPORT_FLAG_EMPTY
) != 0 ||
836 !aIndexArray
.empty() )
838 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_STYLE
,
839 aPropTokens
[i
].eToken
,
840 (nFlags
& XML_EXPORT_FLAG_IGN_WS
) != 0,
843 exportElementItems( rExport
, rProperties
, nFlags
, aIndexArray
);
849 /** this method is called for every item that has the
850 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
851 void SvXMLExportPropertyMapper::handleSpecialItem(
852 SvXMLAttributeList
& rAttrList
,
853 const XMLPropertyState
& rProperty
,
854 const SvXMLUnitConverter
& rUnitConverter
,
855 const SvXMLNamespaceMap
& rNamespaceMap
,
856 const ::std::vector
< XMLPropertyState
> *pProperties
,
857 sal_uInt32 nIdx
) const
859 OSL_ENSURE( mxNextMapper
.is(), "special item not handled in xml export" );
860 if( mxNextMapper
.is() )
861 mxNextMapper
->handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
862 rNamespaceMap
, pProperties
, nIdx
);
865 /** this method is called for every item that has the
866 MID_FLAG_ELEMENT_EXPORT flag set */
867 void SvXMLExportPropertyMapper::handleElementItem(
868 SvXMLExport
& rExport
,
869 const XMLPropertyState
& rProperty
,
871 const ::std::vector
< XMLPropertyState
> *pProperties
,
872 sal_uInt32 nIdx
) const
874 OSL_ENSURE( mxNextMapper
.is(), "element item not handled in xml export" );
875 if( mxNextMapper
.is() )
876 mxNextMapper
->handleElementItem( rExport
, rProperty
, nFlags
,
880 ///////////////////////////////////////////////////////////////////////////////
885 /** fills the given attribute list with the items in the given set */
886 void SvXMLExportPropertyMapper::_exportXML(
887 sal_uInt16 nPropType
, sal_uInt16
& rPropTypeFlags
,
888 SvXMLAttributeList
& rAttrList
,
889 const ::std::vector
< XMLPropertyState
>& rProperties
,
890 const SvXMLUnitConverter
& rUnitConverter
,
891 const SvXMLNamespaceMap
& rNamespaceMap
,
893 std::vector
<sal_uInt16
>* pIndexArray
,
894 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
) const
896 const sal_uInt32 nCount
= rProperties
.size();
897 sal_uInt32 nIndex
= 0;
899 if( -1 == nPropMapStartIdx
)
900 nPropMapStartIdx
= 0;
901 if( -1 == nPropMapEndIdx
)
902 nPropMapEndIdx
= maPropMapper
->GetEntryCount();
904 while( nIndex
< nCount
)
906 sal_Int32 nPropMapIdx
= rProperties
[nIndex
].mnIndex
;
907 if( nPropMapIdx
>= nPropMapStartIdx
&&
908 nPropMapIdx
< nPropMapEndIdx
)// valid entry?
910 sal_uInt32 nEFlags
= maPropMapper
->GetEntryFlags( nPropMapIdx
);
911 sal_uInt16 nEPType
= GET_PROP_TYPE(nEFlags
);
912 OSL_ENSURE( nEPType
>= (XML_TYPE_PROP_START
>>XML_TYPE_PROP_SHIFT
),
913 "no prop type sepcified" );
914 rPropTypeFlags
|= (1 << nEPType
);
915 if( nEPType
== nPropType
)
917 // we have a valid map entry here, so lets use it...
918 if( ( nEFlags
& MID_FLAG_ELEMENT_ITEM_EXPORT
) != 0 )
920 // element items do not add any properties,
921 // we export it later
924 pIndexArray
->push_back( (sal_uInt16
)nIndex
);
929 _exportXML( rAttrList
, rProperties
[nIndex
], rUnitConverter
,
930 rNamespaceMap
, nFlags
, &rProperties
, nIndex
);
939 void SvXMLExportPropertyMapper::_exportXML(
940 SvXMLAttributeList
& rAttrList
,
941 const XMLPropertyState
& rProperty
,
942 const SvXMLUnitConverter
& rUnitConverter
,
943 const SvXMLNamespaceMap
& rNamespaceMap
,
944 sal_uInt16
/*nFlags*/,
945 const ::std::vector
< XMLPropertyState
> *pProperties
,
946 sal_uInt32 nIdx
) const
948 if ( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
949 MID_FLAG_SPECIAL_ITEM_EXPORT
) != 0 )
951 uno::Reference
< container::XNameContainer
> xAttrContainer
;
952 if( (rProperty
.maValue
>>= xAttrContainer
) && xAttrContainer
.is() )
954 SvXMLNamespaceMap
*pNewNamespaceMap
= 0;
955 const SvXMLNamespaceMap
*pNamespaceMap
= &rNamespaceMap
;
957 uno::Sequence
< OUString
> aAttribNames( xAttrContainer
->getElementNames() );
958 const OUString
* pAttribName
= aAttribNames
.getConstArray();
960 const sal_Int32 nCount
= aAttribNames
.getLength();
962 OUStringBuffer sNameBuffer
;
963 xml::AttributeData aData
;
964 for( sal_Int32 i
=0; i
< nCount
; i
++, pAttribName
++ )
966 xAttrContainer
->getByName( *pAttribName
) >>= aData
;
967 OUString
sAttribName( *pAttribName
);
969 // extract namespace prefix from attribute name if it exists
971 const sal_Int32 nColonPos
=
972 pAttribName
->indexOf( sal_Unicode(':') );
973 if( nColonPos
!= -1 )
974 sPrefix
= pAttribName
->copy( 0, nColonPos
);
976 if( !sPrefix
.isEmpty() )
978 OUString
sNamespace( aData
.Namespace
);
980 // if the prefix isn't defined yet or has another meaning,
981 // we have to redefine it now.
982 sal_uInt16 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
983 if( USHRT_MAX
== nKey
|| pNamespaceMap
->GetNameByKey( nKey
) != sNamespace
)
985 sal_Bool bAddNamespace
= sal_False
;
986 if( USHRT_MAX
== nKey
)
988 // The prefix is unused, so it is sufficient
989 // to add it to the namespace map.
990 bAddNamespace
= sal_True
;
994 // check if there is a prefix registered for the
996 nKey
= pNamespaceMap
->GetKeyByName( sNamespace
);
997 if( XML_NAMESPACE_UNKNOWN
== nKey
)
999 // There is no prefix for the namespace, so
1000 // we have to generate one and have to add it.
1002 OUString
sOrigPrefix( sPrefix
);
1005 sNameBuffer
.append( sOrigPrefix
);
1006 sNameBuffer
.append( ++n
);
1007 sPrefix
= sNameBuffer
.makeStringAndClear();
1008 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
1010 while( nKey
!= USHRT_MAX
);
1012 bAddNamespace
= sal_True
;
1016 // If there is a prefix for the namespace,
1018 sPrefix
= pNamespaceMap
->GetPrefixByKey( nKey
);
1020 // In any case, the attribute name has to be adapted.
1021 sNameBuffer
.append( sPrefix
);
1022 sNameBuffer
.append( sal_Unicode(':') );
1023 sNameBuffer
.append( pAttribName
->copy( nColonPos
+1 ) );
1024 sAttribName
= sNameBuffer
.makeStringAndClear();
1029 if( !pNewNamespaceMap
)
1031 pNewNamespaceMap
= new SvXMLNamespaceMap( rNamespaceMap
);
1032 pNamespaceMap
= pNewNamespaceMap
;
1034 pNewNamespaceMap
->Add( sPrefix
, sNamespace
);
1035 sNameBuffer
.append( GetXMLToken(XML_XMLNS
) );
1036 sNameBuffer
.append( sal_Unicode(':') );
1037 sNameBuffer
.append( sPrefix
);
1038 rAttrList
.AddAttribute( sNameBuffer
.makeStringAndClear(),
1043 OUString
sOldValue( rAttrList
.getValueByName( sAttribName
) );
1044 OSL_ENSURE( sOldValue
.isEmpty(), "alien attribute exists already" );
1045 OSL_ENSURE(aData
.Type
== GetXMLToken(XML_CDATA
), "different type to our default type which should be written out");
1046 if( sOldValue
.isEmpty() )
1047 rAttrList
.AddAttribute( sAttribName
, aData
.Value
);
1050 delete pNewNamespaceMap
;
1054 handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
1055 rNamespaceMap
, pProperties
, nIdx
);
1058 else if ( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
1059 MID_FLAG_ELEMENT_ITEM_EXPORT
) == 0 )
1062 const OUString
sName( rNamespaceMap
.GetQNameByKey(
1063 maPropMapper
->GetEntryNameSpace( rProperty
.mnIndex
),
1064 maPropMapper
->GetEntryXMLName( rProperty
.mnIndex
) ) );
1066 sal_Bool bRemove
= sal_False
;
1067 if( ( maPropMapper
->GetEntryFlags( rProperty
.mnIndex
) &
1068 MID_FLAG_MERGE_ATTRIBUTE
) != 0 )
1070 aValue
= rAttrList
.getValueByName( sName
);
1074 if( maPropMapper
->exportXML( aValue
, rProperty
, rUnitConverter
) )
1077 rAttrList
.RemoveAttribute( sName
);
1078 rAttrList
.AddAttribute( sName
, aValue
);
1083 void SvXMLExportPropertyMapper::exportElementItems(
1084 SvXMLExport
& rExport
,
1085 const ::std::vector
< XMLPropertyState
>& rProperties
,
1087 const std::vector
<sal_uInt16
>& rIndexArray
) const
1089 const sal_uInt16 nCount
= rIndexArray
.size();
1091 sal_Bool bItemsExported
= sal_False
;
1092 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
1094 const sal_uInt16 nElement
= rIndexArray
[nIndex
];
1096 OSL_ENSURE( 0 != ( maPropMapper
->GetEntryFlags(
1097 rProperties
[nElement
].mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
),
1098 "wrong mid flag!" );
1100 rExport
.IgnorableWhitespace();
1101 handleElementItem( rExport
, rProperties
[nElement
],
1102 nFlags
, &rProperties
, nElement
);
1103 bItemsExported
= sal_True
;
1106 if( bItemsExported
)
1107 rExport
.IgnorableWhitespace();
1110 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */