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/XPropertyState.hpp>
23 #include <com/sun/star/beans/XMultiPropertySet.hpp>
24 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
25 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
26 #include <rtl/ustrbuf.hxx>
30 #include <xmloff/xmlexppr.hxx>
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/attrlist.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include <xmloff/xmlnmspe.hxx>
35 #include <xmloff/xmlexp.hxx>
36 #include <xmloff/xmlprmap.hxx>
37 #include <xmloff/maptype.hxx>
38 #include <xmloff/xmltypes.hxx>
39 #include <xmloff/xmlprhdl.hxx>
41 using namespace ::std
;
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::beans
;
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::lang
;
46 using namespace ::xmloff::token
;
48 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
49 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
53 struct XMLPropTokens_Impl
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 XMLPropTokens_Impl aPropTokens
[MAX_PROP_TYPES
] =
83 // Take all properties of the XPropertySet which are also found in the
84 // XMLPropertyMapEntry-array and which are not set to their default-value,
85 // if a state is available.
86 // After that I call the method 'ContextFilter'.
88 typedef std::list
<XMLPropertyState
> XMLPropertyStateList_Impl
;
90 class XMLPropertyStates_Impl
92 XMLPropertyStateList_Impl aPropStates
;
93 XMLPropertyStateList_Impl::iterator aLastItr
;
96 XMLPropertyStates_Impl();
97 void AddPropertyState(const XMLPropertyState
& rPropState
);
98 void FillPropertyStateVector(std::vector
<XMLPropertyState
>& rVector
);
101 XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
105 aLastItr
= aPropStates
.begin();
108 void XMLPropertyStates_Impl::AddPropertyState(
109 const XMLPropertyState
& rPropState
)
111 XMLPropertyStateList_Impl::iterator aItr
= aPropStates
.begin();
112 bool bInserted(false);
115 if (aLastItr
->mnIndex
< rPropState
.mnIndex
)
120 // TODO: one path required only
121 if (aItr
== aPropStates
.end())
123 aLastItr
= aPropStates
.insert(aPropStates
.end(), rPropState
);
127 else if (aItr
->mnIndex
> rPropState
.mnIndex
)
129 aLastItr
= aPropStates
.insert(aItr
, rPropState
);
134 while(!bInserted
&& (aItr
++ != aPropStates
.end()));
137 void XMLPropertyStates_Impl::FillPropertyStateVector(
138 std::vector
<XMLPropertyState
>& rVector
)
142 rVector
.resize(nCount
, XMLPropertyState(-1));
143 ::std::copy( aPropStates
.begin(), aPropStates
.end(), rVector
.begin() );
147 class FilterPropertyInfo_Impl
149 const OUString sApiName
;
150 std::list
<sal_uInt32
> aIndexes
;
154 FilterPropertyInfo_Impl( const OUString
& rApiName
,
155 const sal_uInt32 nIndex
);
157 const OUString
& GetApiName() const { return sApiName
; }
158 std::list
<sal_uInt32
>& GetIndexes() { return aIndexes
; }
161 bool operator< ( const FilterPropertyInfo_Impl
& rArg
) const
163 return (GetApiName() < rArg
.GetApiName());
167 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
168 const OUString
& rApiName
,
169 const sal_uInt32 nIndex
) :
172 aIndexes
.push_back(nIndex
);
175 typedef std::list
<FilterPropertyInfo_Impl
> FilterPropertyInfoList_Impl
;
177 class FilterPropertiesInfo_Impl
180 FilterPropertyInfoList_Impl aPropInfos
;
181 FilterPropertyInfoList_Impl::iterator aLastItr
;
183 Sequence
<OUString
> *pApiNames
;
186 FilterPropertiesInfo_Impl();
187 ~FilterPropertiesInfo_Impl();
189 void AddProperty(const OUString
& rApiName
, const sal_uInt32 nIndex
);
190 const uno::Sequence
<OUString
>& GetApiNames();
191 void FillPropertyStateArray(
192 vector
< XMLPropertyState
>& rPropStates
,
193 const Reference
< XPropertySet
>& xPropSet
,
194 const rtl::Reference
< XMLPropertySetMapper
>& maPropMapper
,
195 const bool bDefault
= false);
196 sal_uInt32
GetPropertyCount() const { return nCount
; }
199 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
204 aLastItr
= aPropInfos
.begin();
207 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
212 void FilterPropertiesInfo_Impl::AddProperty(
213 const OUString
& rApiName
, const sal_uInt32 nIndex
)
215 aPropInfos
.push_back(FilterPropertyInfo_Impl(rApiName
, nIndex
));
218 OSL_ENSURE( !pApiNames
, "performance warning: API names already retrieved" );
226 const uno::Sequence
<OUString
>& FilterPropertiesInfo_Impl::GetApiNames()
228 OSL_ENSURE(nCount
== aPropInfos
.size(), "wrong property count");
231 // we have to do three things:
232 // 1) sort API names,
233 // 2) merge duplicates,
234 // 3) construct sequence
242 FilterPropertyInfoList_Impl::iterator aOld
= aPropInfos
.begin();
243 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
244 FilterPropertyInfoList_Impl::iterator aCurrent
= aOld
;
247 while ( aCurrent
!= aEnd
)
249 // equal to next element?
250 if ( aOld
->GetApiName().equals( aCurrent
->GetApiName() ) )
252 // if equal: merge index lists
253 aOld
->GetIndexes().merge( aCurrent
->GetIndexes() );
254 // erase element, and continue with next
255 aCurrent
= aPropInfos
.erase( aCurrent
);
260 // remember old element and continue with next
267 // construct sequence
268 pApiNames
= new Sequence
< OUString
>( nCount
);
269 OUString
*pNames
= pApiNames
->getArray();
270 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
271 FilterPropertyInfoList_Impl::iterator aEnd
= aPropInfos
.end();
272 for ( ; aItr
!= aEnd
; ++aItr
, ++pNames
)
273 *pNames
= aItr
->GetApiName();
279 void FilterPropertiesInfo_Impl::FillPropertyStateArray(
280 vector
< XMLPropertyState
>& rPropStates
,
281 const Reference
< XPropertySet
>& rPropSet
,
282 const rtl::Reference
< XMLPropertySetMapper
>& rPropMapper
,
283 const bool bDefault
)
285 XMLPropertyStates_Impl aPropStates
;
287 const uno::Sequence
<OUString
>& rApiNames
= GetApiNames();
289 Reference
< XTolerantMultiPropertySet
> xTolPropSet( rPropSet
, UNO_QUERY
);
290 if (xTolPropSet
.is())
294 Sequence
< beans::GetDirectPropertyTolerantResult
> aResults(xTolPropSet
->getDirectPropertyValuesTolerant(rApiNames
));
295 sal_Int32
nResultCount(aResults
.getLength());
296 if (nResultCount
> 0)
298 const beans::GetDirectPropertyTolerantResult
*pResults
= aResults
.getConstArray();
299 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
300 XMLPropertyState
aNewProperty( -1 );
302 while (nResultCount
> 0 && i
< nCount
)
304 if (pResults
->Name
== aPropIter
->GetApiName())
306 aNewProperty
.mnIndex
= -1;
307 aNewProperty
.maValue
= pResults
->Value
;
309 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
310 aIndexItr
!= aPropIter
->GetIndexes().end();
313 aNewProperty
.mnIndex
= *aIndexItr
;
314 aPropStates
.AddPropertyState( aNewProperty
);
326 Sequence
< beans::GetPropertyTolerantResult
> aResults(xTolPropSet
->getPropertyValuesTolerant(rApiNames
));
327 OSL_ENSURE( rApiNames
.getLength() == aResults
.getLength(), "wrong implemented XTolerantMultiPropertySet" );
328 const beans::GetPropertyTolerantResult
*pResults
= aResults
.getConstArray();
329 FilterPropertyInfoList_Impl::iterator
aPropIter(aPropInfos
.begin());
330 XMLPropertyState
aNewProperty( -1 );
331 sal_uInt32
nResultCount(aResults
.getLength());
332 OSL_ENSURE( nCount
== nResultCount
, "wrong implemented XTolerantMultiPropertySet??" );
333 for( sal_uInt32 i
= 0; i
< nResultCount
; ++i
)
335 if ((pResults
->Result
== beans::TolerantPropertySetResultType::SUCCESS
) &&
336 ((pResults
->State
== PropertyState_DIRECT_VALUE
) || (pResults
->State
== PropertyState_DEFAULT_VALUE
)))
338 aNewProperty
.mnIndex
= -1;
339 aNewProperty
.maValue
= pResults
->Value
;
341 for( std::list
<sal_uInt32
>::iterator
aIndexItr(aPropIter
->GetIndexes().begin());
342 aIndexItr
!= aPropIter
->GetIndexes().end();
345 aNewProperty
.mnIndex
= *aIndexItr
;
346 aPropStates
.AddPropertyState( aNewProperty
);
356 Sequence
< PropertyState
> aStates
;
357 const PropertyState
*pStates
= 0;
358 Reference
< XPropertyState
> xPropState( rPropSet
, UNO_QUERY
);
359 if( xPropState
.is() )
361 aStates
= xPropState
->getPropertyStates( rApiNames
);
362 pStates
= aStates
.getConstArray();
365 Reference
< XMultiPropertySet
> xMultiPropSet( rPropSet
, UNO_QUERY
);
366 if( xMultiPropSet
.is() && !bDefault
)
368 Sequence
< Any
> aValues
;
371 // step 1: get value count
372 sal_uInt32 nValueCount
= 0;
375 for( i
= 0; i
< nCount
; ++i
, ++pStates
)
377 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
383 // step 2: collect property names
384 Sequence
< OUString
> aAPINames( nValueCount
);
385 OUString
*pAPINames
= aAPINames
.getArray();
387 ::std::vector
< FilterPropertyInfoList_Impl::iterator
> aPropIters
;
388 aPropIters
.reserve( nValueCount
);
390 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
391 OSL_ENSURE(aItr
!= aPropInfos
.end(),"Invalid iterator!");
393 pStates
= aStates
.getConstArray();
395 while( i
< nValueCount
)
397 if( (*pStates
== PropertyState_DIRECT_VALUE
)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
399 *pAPINames
++ = aItr
->GetApiName();
400 aPropIters
.push_back( aItr
);
407 aValues
= xMultiPropSet
->getPropertyValues( aAPINames
);
408 const Any
*pValues
= aValues
.getConstArray();
410 ::std::vector
< FilterPropertyInfoList_Impl::iterator
>::const_iterator
411 pPropIter
= aPropIters
.begin();
413 XMLPropertyState
aNewProperty( -1 );
414 for( i
= 0; i
< nValueCount
; ++i
)
416 aNewProperty
.mnIndex
= -1;
417 aNewProperty
.maValue
= *pValues
;
419 const ::std::list
< sal_uInt32
>& rIndexes( (*pPropIter
)->GetIndexes() );
420 for ( std::list
<sal_uInt32
>::const_iterator aIndexItr
= rIndexes
.begin();
421 aIndexItr
!= rIndexes
.end();
425 aNewProperty
.mnIndex
= *aIndexItr
;
426 aPropStates
.AddPropertyState( aNewProperty
);
436 aValues
= xMultiPropSet
->getPropertyValues( rApiNames
);
437 const Any
*pValues
= aValues
.getConstArray();
439 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
440 for(sal_uInt32 i
= 0; i
< nCount
; ++i
)
442 // The value is stored in the PropertySet itself, add to list.
443 XMLPropertyState
aNewProperty( -1 );
444 aNewProperty
.maValue
= *pValues
;
446 for( std::list
<sal_uInt32
>::iterator aIndexItr
=
447 aItr
->GetIndexes().begin();
448 aIndexItr
!= aItr
->GetIndexes().end();
451 aNewProperty
.mnIndex
= *aIndexItr
;
452 aPropStates
.AddPropertyState( aNewProperty
);
460 FilterPropertyInfoList_Impl::iterator aItr
= aPropInfos
.begin();
461 for(sal_uInt32 i
= 0; i
< nCount
; ++i
)
464 !pStates
|| *pStates
== PropertyState_DIRECT_VALUE
;
465 if( bDirectValue
|| bDefault
)
467 // The value is stored in the PropertySet itself, add to list.
468 bool bGotValue
= false;
469 XMLPropertyState
aNewProperty( -1 );
470 for( std::list
<sal_uInt32
>::const_iterator aIndexItr
=
471 aItr
->GetIndexes().begin();
472 aIndexItr
!= aItr
->GetIndexes().end();
476 (rPropMapper
->GetEntryFlags( *aIndexItr
) &
477 MID_FLAG_DEFAULT_ITEM_EXPORT
) != 0 )
483 aNewProperty
.maValue
=
484 rPropSet
->getPropertyValue( aItr
->GetApiName() );
487 aNewProperty
.mnIndex
= *aIndexItr
;
488 aPropStates
.AddPropertyState( aNewProperty
);
490 catch( UnknownPropertyException
& )
492 // might be a problem of getImplemenetationId
493 OSL_ENSURE( false, "unknown property in getPropertyValue" );
506 aPropStates
.FillPropertyStateVector(rPropStates
);
511 struct SvXMLExportPropertyMapper::Impl
513 typedef std::map
<css::uno::Reference
<css::beans::XPropertySetInfo
>, FilterPropertiesInfo_Impl
*> CacheType
;
516 rtl::Reference
<SvXMLExportPropertyMapper
> mxNextMapper
;
517 rtl::Reference
<XMLPropertySetMapper
> mxPropMapper
;
519 OUString maStyleName
;
523 CacheType::iterator it
= maCache
.begin(), itEnd
= maCache
.end();
524 for (; it
!= itEnd
; ++it
)
529 // ctor/dtor , class SvXMLExportPropertyMapper
531 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
532 const rtl::Reference
< XMLPropertySetMapper
>& rMapper
) :
535 mpImpl
->mxPropMapper
= rMapper
;
538 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
543 void SvXMLExportPropertyMapper::ChainExportMapper(
544 const rtl::Reference
< SvXMLExportPropertyMapper
>& rMapper
)
546 // add map entries from rMapper to current map
547 mpImpl
->mxPropMapper
->AddMapperEntry( rMapper
->getPropertySetMapper() );
548 // rMapper uses the same map as 'this'
549 rMapper
->mpImpl
->mxPropMapper
= mpImpl
->mxPropMapper
;
551 // set rMapper as last mapper in current chain
552 rtl::Reference
< SvXMLExportPropertyMapper
> xNext
= mpImpl
->mxNextMapper
;
555 while (xNext
->mpImpl
->mxNextMapper
.is())
556 xNext
= xNext
->mpImpl
->mxNextMapper
;
557 xNext
->mpImpl
->mxNextMapper
= rMapper
;
560 mpImpl
->mxNextMapper
= rMapper
;
562 // if rMapper was already chained, correct
563 // map pointer of successors
566 while (xNext
->mpImpl
->mxNextMapper
.is())
568 xNext
= xNext
->mpImpl
->mxNextMapper
;
569 xNext
->mpImpl
->mxPropMapper
= mpImpl
->mxPropMapper
;
573 std::vector
<XMLPropertyState
> SvXMLExportPropertyMapper::Filter(
574 const uno::Reference
<beans::XPropertySet
>& rPropSet
, bool bEnableFoFontFamily
) const
576 return _Filter(rPropSet
, false, bEnableFoFontFamily
);
579 std::vector
<XMLPropertyState
> SvXMLExportPropertyMapper::FilterDefaults(
580 const uno::Reference
<beans::XPropertySet
>& rPropSet
, bool bEnableFoFontFamily
) const
582 return _Filter(rPropSet
, true, bEnableFoFontFamily
);
585 vector
<XMLPropertyState
> SvXMLExportPropertyMapper::_Filter(
586 const Reference
<XPropertySet
>& xPropSet
, bool bDefault
, bool bEnableFoFontFamily
) const
588 vector
< XMLPropertyState
> aPropStateArray
;
590 // Retrieve XPropertySetInfo and XPropertyState
591 Reference
< XPropertySetInfo
> xInfo( xPropSet
->getPropertySetInfo() );
593 return aPropStateArray
;
595 sal_Int32 nProps
= mpImpl
->mxPropMapper
->GetEntryCount();
597 FilterPropertiesInfo_Impl
*pFilterInfo
= 0;
599 Impl::CacheType::iterator aIter
= mpImpl
->maCache
.find(xInfo
);
600 if (aIter
!= mpImpl
->maCache
.end())
601 pFilterInfo
= (*aIter
).second
;
603 bool bDelInfo
= false;
606 const SvtSaveOptions::ODFDefaultVersion
nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
607 pFilterInfo
= new FilterPropertiesInfo_Impl
;
608 for( sal_Int32 i
=0; i
< nProps
; i
++ )
610 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
611 // Does the PropertySet contain name of mpEntries-array ?
612 const OUString
& rAPIName
= mpImpl
->mxPropMapper
->GetEntryAPIName( i
);
613 const sal_Int32 nFlags
= mpImpl
->mxPropMapper
->GetEntryFlags( i
);
614 if( (0 == (nFlags
& MID_FLAG_NO_PROPERTY_EXPORT
)) &&
615 ( (0 != (nFlags
& MID_FLAG_MUST_EXIST
)) ||
616 xInfo
->hasPropertyByName( rAPIName
) ) )
618 const SvtSaveOptions::ODFDefaultVersion
nEarliestODFVersionForExport(
619 mpImpl
->mxPropMapper
->GetEarliestODFVersionForExport(i
));
620 if( nCurrentVersion
>= nEarliestODFVersionForExport
621 || nCurrentVersion
== SvtSaveOptions::ODFVER_UNKNOWN
622 || nEarliestODFVersionForExport
== SvtSaveOptions::ODFVER_UNKNOWN
)
623 pFilterInfo
->AddProperty(rAPIName
, i
);
627 // Check whether the property set info is destroyed if it is assigned to
628 // a weak reference only; If it is destroyed, then every instance of
629 // getPropertySetInfo returns a new object; such property set infos must
631 WeakReference
< XPropertySetInfo
> xWeakInfo( xInfo
);
636 mpImpl
->maCache
.insert(Impl::CacheType::value_type(xInfo
, pFilterInfo
));
642 if( pFilterInfo
->GetPropertyCount() )
646 pFilterInfo
->FillPropertyStateArray(
647 aPropStateArray
, xPropSet
, mpImpl
->mxPropMapper
, bDefault
);
649 catch( UnknownPropertyException
& )
651 // might be a problem of getImplemenetationId
652 OSL_ENSURE( false, "unknown property in getPropertyStates" );
656 // Call centext-filter
657 if( !aPropStateArray
.empty() )
658 ContextFilter(bEnableFoFontFamily
, aPropStateArray
, xPropSet
);
660 // Have to do if we change from a vector to a list or something like that
665 return aPropStateArray
;
668 void SvXMLExportPropertyMapper::ContextFilter(
669 bool bEnableFoFontFamily
,
670 vector
< XMLPropertyState
>& rProperties
,
671 Reference
< XPropertySet
> rPropSet
) const
673 // Derived class could implement this.
674 if (mpImpl
->mxNextMapper
.is())
675 mpImpl
->mxNextMapper
->ContextFilter(bEnableFoFontFamily
, rProperties
, rPropSet
);
678 // Compares two Sequences of XMLPropertyState:
679 // 1.Number of elements equal ?
680 // 2.Index of each element equal ? (So I know whether the propertynames are the same)
681 // 3.Value of each element equal ?
682 bool SvXMLExportPropertyMapper::Equals(
683 const vector
< XMLPropertyState
>& aProperties1
,
684 const vector
< XMLPropertyState
>& aProperties2
) const
687 sal_uInt32 nCount
= aProperties1
.size();
689 if( nCount
== aProperties2
.size() )
691 sal_uInt32 nIndex
= 0;
692 while( bRet
&& nIndex
< nCount
)
694 const XMLPropertyState
& rProp1
= aProperties1
[ nIndex
];
695 const XMLPropertyState
& rProp2
= aProperties2
[ nIndex
];
697 // Compare index. If equal, compare value
698 if( rProp1
.mnIndex
== rProp2
.mnIndex
)
700 if( rProp1
.mnIndex
!= -1 )
702 // Now compare values
703 if ( (mpImpl
->mxPropMapper
->GetEntryType( rProp1
.mnIndex
) &
704 XML_TYPE_BUILDIN_CMP
) != 0 )
705 // simple type ( binary compare )
706 bRet
= ( rProp1
.maValue
== rProp2
.maValue
);
708 // complex type ( ask for compare-function )
709 bRet
= mpImpl
->mxPropMapper
->GetPropertyHandler(
710 rProp1
.mnIndex
)->equals( rProp1
.maValue
,
726 /** fills the given attribute list with the items in the given set
727 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
728 const ::std::vector< XMLPropertyState >& rProperties,
729 const SvXMLUnitConverter& rUnitConverter,
730 const SvXMLNamespaceMap& rNamespaceMap,
731 sal_uInt16 nFlags ) const
733 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
737 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
738 const ::std::vector< XMLPropertyState >& rProperties,
739 const SvXMLUnitConverter& rUnitConverter,
740 const SvXMLNamespaceMap& rNamespaceMap,
741 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
742 sal_uInt16 nFlags ) const
744 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
745 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
749 void SvXMLExportPropertyMapper::exportXML(
750 SvXMLExport
& rExport
,
751 const ::std::vector
< XMLPropertyState
>& rProperties
,
752 SvXmlExportFlags nFlags
,
753 bool bUseExtensionNamespaceForGraphicProperties
) const
755 exportXML(rExport
, rProperties
, -1, -1, nFlags
, bUseExtensionNamespaceForGraphicProperties
);
759 void SvXMLExportPropertyMapper::exportXML(
760 SvXMLExport
& rExport
,
761 const ::std::vector
< XMLPropertyState
>& rProperties
,
762 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
,
763 SvXmlExportFlags nFlags
, bool bUseExtensionNamespaceForGraphicProperties
) const
765 sal_uInt16 nPropTypeFlags
= 0;
766 for( sal_uInt16 i
=0; i
<MAX_PROP_TYPES
; ++i
)
768 sal_uInt16 nPropType
= aPropTokens
[i
].nType
;
769 if( 0==i
|| (nPropTypeFlags
& (1 << nPropType
)) != 0 )
771 sal_uInt16 nNamespace
= XML_NAMESPACE_STYLE
;
772 if (bUseExtensionNamespaceForGraphicProperties
&&
773 aPropTokens
[i
].eToken
== xmloff::token::XML_GRAPHIC_PROPERTIES
)
775 nNamespace
= XML_NAMESPACE_LO_EXT
;
776 if (rExport
.getDefaultVersion() <= SvtSaveOptions::ODFVER_012
)
778 continue; // don't write for ODF <= 1.2
782 std::vector
<sal_uInt16
> aIndexArray
;
784 _exportXML( nPropType
, nPropTypeFlags
,
785 rExport
.GetAttrList(), rProperties
,
786 rExport
.GetMM100UnitConverter(),
787 rExport
.GetNamespaceMap(),
788 nFlags
, &aIndexArray
,
789 nPropMapStartIdx
, nPropMapEndIdx
);
791 if( rExport
.GetAttrList().getLength() > 0L ||
792 (nFlags
& SvXmlExportFlags::EMPTY
) ||
793 !aIndexArray
.empty() )
795 SvXMLElementExport
aElem( rExport
, nNamespace
,
796 aPropTokens
[i
].eToken
,
797 bool(nFlags
& SvXmlExportFlags::IGN_WS
),
800 exportElementItems( rExport
, rProperties
, nFlags
, aIndexArray
);
806 /** this method is called for every item that has the
807 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
808 void SvXMLExportPropertyMapper::handleSpecialItem(
809 SvXMLAttributeList
& rAttrList
,
810 const XMLPropertyState
& rProperty
,
811 const SvXMLUnitConverter
& rUnitConverter
,
812 const SvXMLNamespaceMap
& rNamespaceMap
,
813 const ::std::vector
< XMLPropertyState
> *pProperties
,
814 sal_uInt32 nIdx
) const
816 OSL_ENSURE(mpImpl
->mxNextMapper
.is(), "special item not handled in xml export");
817 if (mpImpl
->mxNextMapper
.is())
818 mpImpl
->mxNextMapper
->handleSpecialItem(
819 rAttrList
, rProperty
, rUnitConverter
, rNamespaceMap
, pProperties
, nIdx
);
822 /** this method is called for every item that has the
823 MID_FLAG_ELEMENT_EXPORT flag set */
824 void SvXMLExportPropertyMapper::handleElementItem(
825 SvXMLExport
& rExport
,
826 const XMLPropertyState
& rProperty
,
827 SvXmlExportFlags nFlags
,
828 const ::std::vector
< XMLPropertyState
> *pProperties
,
829 sal_uInt32 nIdx
) const
831 OSL_ENSURE(mpImpl
->mxNextMapper
.is(), "element item not handled in xml export");
832 if (mpImpl
->mxNextMapper
.is())
833 mpImpl
->mxNextMapper
->handleElementItem(rExport
, rProperty
, nFlags
, pProperties
, nIdx
);
838 /** fills the given attribute list with the items in the given set */
839 void SvXMLExportPropertyMapper::_exportXML(
840 sal_uInt16 nPropType
, sal_uInt16
& rPropTypeFlags
,
841 SvXMLAttributeList
& rAttrList
,
842 const ::std::vector
< XMLPropertyState
>& rProperties
,
843 const SvXMLUnitConverter
& rUnitConverter
,
844 const SvXMLNamespaceMap
& rNamespaceMap
,
845 SvXmlExportFlags nFlags
,
846 std::vector
<sal_uInt16
>* pIndexArray
,
847 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
) const
849 const sal_uInt32 nCount
= rProperties
.size();
850 sal_uInt32 nIndex
= 0;
852 if( -1 == nPropMapStartIdx
)
853 nPropMapStartIdx
= 0;
854 if( -1 == nPropMapEndIdx
)
855 nPropMapEndIdx
= mpImpl
->mxPropMapper
->GetEntryCount();
857 while( nIndex
< nCount
)
859 sal_Int32 nPropMapIdx
= rProperties
[nIndex
].mnIndex
;
860 if( nPropMapIdx
>= nPropMapStartIdx
&&
861 nPropMapIdx
< nPropMapEndIdx
)// valid entry?
863 sal_uInt32 nEFlags
= mpImpl
->mxPropMapper
->GetEntryFlags(nPropMapIdx
);
864 sal_uInt16 nEPType
= GET_PROP_TYPE(nEFlags
);
865 OSL_ENSURE(nEPType
>= (XML_TYPE_PROP_START
>> XML_TYPE_PROP_SHIFT
),
866 "no prop type specified");
867 rPropTypeFlags
|= (1 << nEPType
);
868 if( nEPType
== nPropType
)
870 // we have a valid map entry here, so lets use it...
871 if( ( nEFlags
& MID_FLAG_ELEMENT_ITEM_EXPORT
) != 0 )
873 // element items do not add any properties,
874 // we export it later
877 pIndexArray
->push_back( (sal_uInt16
)nIndex
);
882 _exportXML( rAttrList
, rProperties
[nIndex
], rUnitConverter
,
883 rNamespaceMap
, nFlags
, &rProperties
, nIndex
);
892 void SvXMLExportPropertyMapper::_exportXML(
893 SvXMLAttributeList
& rAttrList
,
894 const XMLPropertyState
& rProperty
,
895 const SvXMLUnitConverter
& rUnitConverter
,
896 const SvXMLNamespaceMap
& rNamespaceMap
,
897 SvXmlExportFlags
/*nFlags*/,
898 const ::std::vector
< XMLPropertyState
> *pProperties
,
899 sal_uInt32 nIdx
) const
901 if ((mpImpl
->mxPropMapper
->GetEntryFlags(rProperty
.mnIndex
) & MID_FLAG_SPECIAL_ITEM_EXPORT
) != 0)
903 uno::Reference
< container::XNameContainer
> xAttrContainer
;
904 if( (rProperty
.maValue
>>= xAttrContainer
) && xAttrContainer
.is() )
906 SvXMLNamespaceMap
*pNewNamespaceMap
= 0;
907 const SvXMLNamespaceMap
*pNamespaceMap
= &rNamespaceMap
;
909 uno::Sequence
< OUString
> aAttribNames( xAttrContainer
->getElementNames() );
910 const OUString
* pAttribName
= aAttribNames
.getConstArray();
912 const sal_Int32 nCount
= aAttribNames
.getLength();
914 OUStringBuffer sNameBuffer
;
915 xml::AttributeData aData
;
916 for( sal_Int32 i
=0; i
< nCount
; i
++, pAttribName
++ )
918 xAttrContainer
->getByName( *pAttribName
) >>= aData
;
919 OUString
sAttribName( *pAttribName
);
921 // extract namespace prefix from attribute name if it exists
923 const sal_Int32 nColonPos
=
924 pAttribName
->indexOf( ':' );
925 if( nColonPos
!= -1 )
926 sPrefix
= pAttribName
->copy( 0, nColonPos
);
928 if( !sPrefix
.isEmpty() )
930 OUString
sNamespace( aData
.Namespace
);
932 // if the prefix isn't defined yet or has another meaning,
933 // we have to redefine it now.
934 sal_uInt16 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
935 if( USHRT_MAX
== nKey
|| pNamespaceMap
->GetNameByKey( nKey
) != sNamespace
)
937 bool bAddNamespace
= false;
938 if( USHRT_MAX
== nKey
)
940 // The prefix is unused, so it is sufficient
941 // to add it to the namespace map.
942 bAddNamespace
= true;
946 // check if there is a prefix registered for the
948 nKey
= pNamespaceMap
->GetKeyByName( sNamespace
);
949 if( XML_NAMESPACE_UNKNOWN
== nKey
)
951 // There is no prefix for the namespace, so
952 // we have to generate one and have to add it.
954 OUString
sOrigPrefix( sPrefix
);
957 sNameBuffer
.append( sOrigPrefix
);
958 sNameBuffer
.append( ++n
);
959 sPrefix
= sNameBuffer
.makeStringAndClear();
960 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
962 while( nKey
!= USHRT_MAX
);
964 bAddNamespace
= true;
968 // If there is a prefix for the namespace,
970 sPrefix
= pNamespaceMap
->GetPrefixByKey( nKey
);
972 // In any case, the attribute name has to be adapted.
973 sNameBuffer
.append( sPrefix
+ ":" + pAttribName
->copy( nColonPos
+1 ) );
974 sAttribName
= sNameBuffer
.makeStringAndClear();
979 if( !pNewNamespaceMap
)
981 pNewNamespaceMap
= new SvXMLNamespaceMap( rNamespaceMap
);
982 pNamespaceMap
= pNewNamespaceMap
;
984 pNewNamespaceMap
->Add( sPrefix
, sNamespace
);
985 sNameBuffer
.append( GetXMLToken(XML_XMLNS
) + ":" + sPrefix
);
986 rAttrList
.AddAttribute( sNameBuffer
.makeStringAndClear(),
991 OUString
sOldValue( rAttrList
.getValueByName( sAttribName
) );
992 OSL_ENSURE( sOldValue
.isEmpty(), "alien attribute exists already" );
993 OSL_ENSURE(aData
.Type
== GetXMLToken(XML_CDATA
), "different type to our default type which should be written out");
994 if( sOldValue
.isEmpty() )
995 rAttrList
.AddAttribute( sAttribName
, aData
.Value
);
998 delete pNewNamespaceMap
;
1002 handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
1003 rNamespaceMap
, pProperties
, nIdx
);
1006 else if ((mpImpl
->mxPropMapper
->GetEntryFlags(rProperty
.mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
) == 0)
1009 const OUString sName
= rNamespaceMap
.GetQNameByKey(
1010 mpImpl
->mxPropMapper
->GetEntryNameSpace(rProperty
.mnIndex
),
1011 mpImpl
->mxPropMapper
->GetEntryXMLName(rProperty
.mnIndex
));
1013 bool bRemove
= false;
1014 if ((mpImpl
->mxPropMapper
->GetEntryFlags( rProperty
.mnIndex
) & MID_FLAG_MERGE_ATTRIBUTE
) != 0)
1016 aValue
= rAttrList
.getValueByName( sName
);
1020 if (mpImpl
->mxPropMapper
->exportXML(aValue
, rProperty
, rUnitConverter
))
1023 rAttrList
.RemoveAttribute( sName
);
1024 rAttrList
.AddAttribute( sName
, aValue
);
1029 void SvXMLExportPropertyMapper::exportElementItems(
1030 SvXMLExport
& rExport
,
1031 const ::std::vector
< XMLPropertyState
>& rProperties
,
1032 SvXmlExportFlags nFlags
,
1033 const std::vector
<sal_uInt16
>& rIndexArray
) const
1035 const sal_uInt16 nCount
= rIndexArray
.size();
1037 bool bItemsExported
= false;
1038 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
1040 const sal_uInt16 nElement
= rIndexArray
[nIndex
];
1042 OSL_ENSURE( 0 != (mpImpl
->mxPropMapper
->GetEntryFlags(
1043 rProperties
[nElement
].mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
),
1044 "wrong mid flag!" );
1046 rExport
.IgnorableWhitespace();
1047 handleElementItem( rExport
, rProperties
[nElement
],
1048 nFlags
, &rProperties
, nElement
);
1049 bItemsExported
= true;
1052 if( bItemsExported
)
1053 rExport
.IgnorableWhitespace();
1056 const rtl::Reference
<XMLPropertySetMapper
>& SvXMLExportPropertyMapper::getPropertySetMapper() const
1058 return mpImpl
->mxPropMapper
;
1061 void SvXMLExportPropertyMapper::SetStyleName( const OUString
& rStyleName
)
1063 mpImpl
->maStyleName
= rStyleName
;
1066 const OUString
& SvXMLExportPropertyMapper::GetStyleName() const
1068 return mpImpl
->maStyleName
;
1071 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */