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
) const
754 exportXML( rExport
, rProperties
, -1, -1, nFlags
);
757 void SvXMLExportPropertyMapper::exportXML(
758 SvXMLExport
& rExport
,
759 const ::std::vector
< XMLPropertyState
>& rProperties
,
760 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
,
761 SvXmlExportFlags nFlags
, bool bExtensionNamespace
) const
763 sal_uInt16 nPropTypeFlags
= 0;
764 for( sal_uInt16 i
=0; i
<MAX_PROP_TYPES
; ++i
)
766 sal_uInt16 nPropType
= aPropTokens
[i
].nType
;
767 if( 0==i
|| (nPropTypeFlags
& (1 << nPropType
)) != 0 )
769 std::vector
<sal_uInt16
> aIndexArray
;
771 _exportXML( nPropType
, nPropTypeFlags
,
772 rExport
.GetAttrList(), rProperties
,
773 rExport
.GetMM100UnitConverter(),
774 rExport
.GetNamespaceMap(),
775 nFlags
, &aIndexArray
,
776 nPropMapStartIdx
, nPropMapEndIdx
);
778 if( rExport
.GetAttrList().getLength() > 0L ||
779 (nFlags
& SvXmlExportFlags::EMPTY
) ||
780 !aIndexArray
.empty() )
782 sal_uInt16 nNamespace
= XML_NAMESPACE_STYLE
;
783 if(bExtensionNamespace
&& aPropTokens
[i
].eToken
==
784 xmloff::token::XML_GRAPHIC_PROPERTIES
)
785 nNamespace
= XML_NAMESPACE_LO_EXT
;
786 SvXMLElementExport
aElem( rExport
, nNamespace
,
787 aPropTokens
[i
].eToken
,
788 bool(nFlags
& SvXmlExportFlags::IGN_WS
),
791 exportElementItems( rExport
, rProperties
, nFlags
, aIndexArray
);
797 /** this method is called for every item that has the
798 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
799 void SvXMLExportPropertyMapper::handleSpecialItem(
800 SvXMLAttributeList
& rAttrList
,
801 const XMLPropertyState
& rProperty
,
802 const SvXMLUnitConverter
& rUnitConverter
,
803 const SvXMLNamespaceMap
& rNamespaceMap
,
804 const ::std::vector
< XMLPropertyState
> *pProperties
,
805 sal_uInt32 nIdx
) const
807 OSL_ENSURE(mpImpl
->mxNextMapper
.is(), "special item not handled in xml export");
808 if (mpImpl
->mxNextMapper
.is())
809 mpImpl
->mxNextMapper
->handleSpecialItem(
810 rAttrList
, rProperty
, rUnitConverter
, rNamespaceMap
, pProperties
, nIdx
);
813 /** this method is called for every item that has the
814 MID_FLAG_ELEMENT_EXPORT flag set */
815 void SvXMLExportPropertyMapper::handleElementItem(
816 SvXMLExport
& rExport
,
817 const XMLPropertyState
& rProperty
,
818 SvXmlExportFlags nFlags
,
819 const ::std::vector
< XMLPropertyState
> *pProperties
,
820 sal_uInt32 nIdx
) const
822 OSL_ENSURE(mpImpl
->mxNextMapper
.is(), "element item not handled in xml export");
823 if (mpImpl
->mxNextMapper
.is())
824 mpImpl
->mxNextMapper
->handleElementItem(rExport
, rProperty
, nFlags
, pProperties
, nIdx
);
829 /** fills the given attribute list with the items in the given set */
830 void SvXMLExportPropertyMapper::_exportXML(
831 sal_uInt16 nPropType
, sal_uInt16
& rPropTypeFlags
,
832 SvXMLAttributeList
& rAttrList
,
833 const ::std::vector
< XMLPropertyState
>& rProperties
,
834 const SvXMLUnitConverter
& rUnitConverter
,
835 const SvXMLNamespaceMap
& rNamespaceMap
,
836 SvXmlExportFlags nFlags
,
837 std::vector
<sal_uInt16
>* pIndexArray
,
838 sal_Int32 nPropMapStartIdx
, sal_Int32 nPropMapEndIdx
) const
840 const sal_uInt32 nCount
= rProperties
.size();
841 sal_uInt32 nIndex
= 0;
843 if( -1 == nPropMapStartIdx
)
844 nPropMapStartIdx
= 0;
845 if( -1 == nPropMapEndIdx
)
846 nPropMapEndIdx
= mpImpl
->mxPropMapper
->GetEntryCount();
848 while( nIndex
< nCount
)
850 sal_Int32 nPropMapIdx
= rProperties
[nIndex
].mnIndex
;
851 if( nPropMapIdx
>= nPropMapStartIdx
&&
852 nPropMapIdx
< nPropMapEndIdx
)// valid entry?
854 sal_uInt32 nEFlags
= mpImpl
->mxPropMapper
->GetEntryFlags(nPropMapIdx
);
855 sal_uInt16 nEPType
= GET_PROP_TYPE(nEFlags
);
856 OSL_ENSURE(nEPType
>= (XML_TYPE_PROP_START
>> XML_TYPE_PROP_SHIFT
),
857 "no prop type specified");
858 rPropTypeFlags
|= (1 << nEPType
);
859 if( nEPType
== nPropType
)
861 // we have a valid map entry here, so lets use it...
862 if( ( nEFlags
& MID_FLAG_ELEMENT_ITEM_EXPORT
) != 0 )
864 // element items do not add any properties,
865 // we export it later
868 pIndexArray
->push_back( (sal_uInt16
)nIndex
);
873 _exportXML( rAttrList
, rProperties
[nIndex
], rUnitConverter
,
874 rNamespaceMap
, nFlags
, &rProperties
, nIndex
);
883 void SvXMLExportPropertyMapper::_exportXML(
884 SvXMLAttributeList
& rAttrList
,
885 const XMLPropertyState
& rProperty
,
886 const SvXMLUnitConverter
& rUnitConverter
,
887 const SvXMLNamespaceMap
& rNamespaceMap
,
888 SvXmlExportFlags
/*nFlags*/,
889 const ::std::vector
< XMLPropertyState
> *pProperties
,
890 sal_uInt32 nIdx
) const
892 if ((mpImpl
->mxPropMapper
->GetEntryFlags(rProperty
.mnIndex
) & MID_FLAG_SPECIAL_ITEM_EXPORT
) != 0)
894 uno::Reference
< container::XNameContainer
> xAttrContainer
;
895 if( (rProperty
.maValue
>>= xAttrContainer
) && xAttrContainer
.is() )
897 SvXMLNamespaceMap
*pNewNamespaceMap
= 0;
898 const SvXMLNamespaceMap
*pNamespaceMap
= &rNamespaceMap
;
900 uno::Sequence
< OUString
> aAttribNames( xAttrContainer
->getElementNames() );
901 const OUString
* pAttribName
= aAttribNames
.getConstArray();
903 const sal_Int32 nCount
= aAttribNames
.getLength();
905 OUStringBuffer sNameBuffer
;
906 xml::AttributeData aData
;
907 for( sal_Int32 i
=0; i
< nCount
; i
++, pAttribName
++ )
909 xAttrContainer
->getByName( *pAttribName
) >>= aData
;
910 OUString
sAttribName( *pAttribName
);
912 // extract namespace prefix from attribute name if it exists
914 const sal_Int32 nColonPos
=
915 pAttribName
->indexOf( ':' );
916 if( nColonPos
!= -1 )
917 sPrefix
= pAttribName
->copy( 0, nColonPos
);
919 if( !sPrefix
.isEmpty() )
921 OUString
sNamespace( aData
.Namespace
);
923 // if the prefix isn't defined yet or has another meaning,
924 // we have to redefine it now.
925 sal_uInt16 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
926 if( USHRT_MAX
== nKey
|| pNamespaceMap
->GetNameByKey( nKey
) != sNamespace
)
928 bool bAddNamespace
= false;
929 if( USHRT_MAX
== nKey
)
931 // The prefix is unused, so it is sufficient
932 // to add it to the namespace map.
933 bAddNamespace
= true;
937 // check if there is a prefix registered for the
939 nKey
= pNamespaceMap
->GetKeyByName( sNamespace
);
940 if( XML_NAMESPACE_UNKNOWN
== nKey
)
942 // There is no prefix for the namespace, so
943 // we have to generate one and have to add it.
945 OUString
sOrigPrefix( sPrefix
);
948 sNameBuffer
.append( sOrigPrefix
);
949 sNameBuffer
.append( ++n
);
950 sPrefix
= sNameBuffer
.makeStringAndClear();
951 nKey
= pNamespaceMap
->GetKeyByPrefix( sPrefix
);
953 while( nKey
!= USHRT_MAX
);
955 bAddNamespace
= true;
959 // If there is a prefix for the namespace,
961 sPrefix
= pNamespaceMap
->GetPrefixByKey( nKey
);
963 // In any case, the attribute name has to be adapted.
964 sNameBuffer
.append( sPrefix
+ ":" + pAttribName
->copy( nColonPos
+1 ) );
965 sAttribName
= sNameBuffer
.makeStringAndClear();
970 if( !pNewNamespaceMap
)
972 pNewNamespaceMap
= new SvXMLNamespaceMap( rNamespaceMap
);
973 pNamespaceMap
= pNewNamespaceMap
;
975 pNewNamespaceMap
->Add( sPrefix
, sNamespace
);
976 sNameBuffer
.append( GetXMLToken(XML_XMLNS
) + ":" + sPrefix
);
977 rAttrList
.AddAttribute( sNameBuffer
.makeStringAndClear(),
982 OUString
sOldValue( rAttrList
.getValueByName( sAttribName
) );
983 OSL_ENSURE( sOldValue
.isEmpty(), "alien attribute exists already" );
984 OSL_ENSURE(aData
.Type
== GetXMLToken(XML_CDATA
), "different type to our default type which should be written out");
985 if( sOldValue
.isEmpty() )
986 rAttrList
.AddAttribute( sAttribName
, aData
.Value
);
989 delete pNewNamespaceMap
;
993 handleSpecialItem( rAttrList
, rProperty
, rUnitConverter
,
994 rNamespaceMap
, pProperties
, nIdx
);
997 else if ((mpImpl
->mxPropMapper
->GetEntryFlags(rProperty
.mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
) == 0)
1000 const OUString sName
= rNamespaceMap
.GetQNameByKey(
1001 mpImpl
->mxPropMapper
->GetEntryNameSpace(rProperty
.mnIndex
),
1002 mpImpl
->mxPropMapper
->GetEntryXMLName(rProperty
.mnIndex
));
1004 bool bRemove
= false;
1005 if ((mpImpl
->mxPropMapper
->GetEntryFlags( rProperty
.mnIndex
) & MID_FLAG_MERGE_ATTRIBUTE
) != 0)
1007 aValue
= rAttrList
.getValueByName( sName
);
1011 if (mpImpl
->mxPropMapper
->exportXML(aValue
, rProperty
, rUnitConverter
))
1014 rAttrList
.RemoveAttribute( sName
);
1015 rAttrList
.AddAttribute( sName
, aValue
);
1020 void SvXMLExportPropertyMapper::exportElementItems(
1021 SvXMLExport
& rExport
,
1022 const ::std::vector
< XMLPropertyState
>& rProperties
,
1023 SvXmlExportFlags nFlags
,
1024 const std::vector
<sal_uInt16
>& rIndexArray
) const
1026 const sal_uInt16 nCount
= rIndexArray
.size();
1028 bool bItemsExported
= false;
1029 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
1031 const sal_uInt16 nElement
= rIndexArray
[nIndex
];
1033 OSL_ENSURE( 0 != (mpImpl
->mxPropMapper
->GetEntryFlags(
1034 rProperties
[nElement
].mnIndex
) & MID_FLAG_ELEMENT_ITEM_EXPORT
),
1035 "wrong mid flag!" );
1037 rExport
.IgnorableWhitespace();
1038 handleElementItem( rExport
, rProperties
[nElement
],
1039 nFlags
, &rProperties
, nElement
);
1040 bItemsExported
= true;
1043 if( bItemsExported
)
1044 rExport
.IgnorableWhitespace();
1047 const rtl::Reference
<XMLPropertySetMapper
>& SvXMLExportPropertyMapper::getPropertySetMapper() const
1049 return mpImpl
->mxPropMapper
;
1052 void SvXMLExportPropertyMapper::SetStyleName( const OUString
& rStyleName
)
1054 mpImpl
->maStyleName
= rStyleName
;
1057 const OUString
& SvXMLExportPropertyMapper::GetStyleName() const
1059 return mpImpl
->maStyleName
;
1062 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */