Version 24.2.2.2, tag libreoffice-24.2.2.2
[LibreOffice.git] / xmloff / source / style / xmlimppr.cxx
blobf72d6906e1eae23b437de157e4ac95a6ab348a85
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/xml/AttributeData.hpp>
21 #include <com/sun/star/beans/XMultiPropertySet.hpp>
22 #include <com/sun/star/lang/IllegalArgumentException.hpp>
23 #include <com/sun/star/lang/WrappedTargetException.hpp>
24 #include <com/sun/star/beans/UnknownPropertyException.hpp>
25 #include <com/sun/star/beans/PropertyVetoException.hpp>
26 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
27 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <rtl/ustrbuf.hxx>
30 #include <sal/log.hxx>
31 #include <osl/diagnose.h>
32 #include <utility>
33 #include <xmloff/xmlprmap.hxx>
34 #include <xmloff/namespacemap.hxx>
35 #include <xmloff/xmlimppr.hxx>
36 #include <xmloff/xmlimp.hxx>
38 #include <xmloff/unoatrcn.hxx>
39 #include <xmloff/xmlnamespace.hxx>
40 #include <xmloff/xmltoken.hxx>
41 #include <xmloff/xmlerror.hxx>
42 #include <xmloff/contextid.hxx>
43 #include <xmloff/xmltypes.hxx>
44 #include <xmloff/maptype.hxx>
46 #include <algorithm>
47 #include <vector>
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::container;
52 using namespace ::com::sun::star::xml;
53 using namespace ::com::sun::star::xml::sax;
55 using namespace ::xmloff::token;
56 using ::com::sun::star::lang::IllegalArgumentException;
57 using ::com::sun::star::lang::WrappedTargetException;
58 using ::com::sun::star::beans::UnknownPropertyException;
59 using ::com::sun::star::beans::PropertyVetoException;
62 SvXMLImportPropertyMapper::SvXMLImportPropertyMapper(
63 rtl::Reference< XMLPropertySetMapper > xMapper,
64 SvXMLImport& rImp ):
65 m_rImport(rImp),
66 maPropMapper (std::move( xMapper ))
70 SvXMLImportPropertyMapper::~SvXMLImportPropertyMapper()
72 mxNextMapper = nullptr;
75 void SvXMLImportPropertyMapper::ChainImportMapper(
76 const rtl::Reference< SvXMLImportPropertyMapper>& rMapper )
78 // add map entries from rMapper to current map
79 maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
80 // rMapper uses the same map as 'this'
81 rMapper->maPropMapper = maPropMapper;
83 // set rMapper as last mapper in current chain
84 rtl::Reference< SvXMLImportPropertyMapper > xNext = mxNextMapper;
85 if( xNext.is())
87 while( xNext->mxNextMapper.is())
88 xNext = xNext->mxNextMapper;
89 xNext->mxNextMapper = rMapper;
91 else
92 mxNextMapper = rMapper;
94 // if rMapper was already chained, correct
95 // map pointer of successors
96 xNext = rMapper;
98 while( xNext->mxNextMapper.is())
100 xNext = xNext->mxNextMapper;
101 xNext->maPropMapper = maPropMapper;
105 /** fills the given itemset with the attributes in the given list */
106 void SvXMLImportPropertyMapper::importXML(
107 std::vector< XMLPropertyState >& rProperties,
108 const Reference< XFastAttributeList >& xAttrList,
109 const SvXMLUnitConverter& rUnitConverter,
110 const SvXMLNamespaceMap& rNamespaceMap,
111 sal_uInt32 nPropType,
112 sal_Int32 nStartIdx,
113 sal_Int32 nEndIdx ) const
115 Reference< XNameContainer > xAttrContainer;
117 if( -1 == nStartIdx )
118 nStartIdx = 0;
119 if( -1 == nEndIdx )
120 nEndIdx = maPropMapper->GetEntryCount();
122 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
124 sal_Int32 nToken = aIter.getToken();
125 if( IsTokenInNamespace(nToken, XML_NAMESPACE_XMLNS) )
126 continue;
128 const OUString aPrefix = SvXMLImport::getNamespacePrefixFromToken(nToken, &rNamespaceMap);
129 const OUString aNamespaceURI = SvXMLImport::getNamespaceURIFromToken(nToken);
130 OUString sAttrName = SvXMLImport::getNameFromToken( nToken );
131 if ( !aPrefix.isEmpty() )
132 sAttrName = aPrefix + SvXMLImport::aNamespaceSeparator + sAttrName;
134 const OUString sValue = aIter.toString();
136 importXMLAttribute(rProperties, rUnitConverter, rNamespaceMap,
137 nPropType, nStartIdx, nEndIdx, xAttrContainer,
138 sAttrName, aNamespaceURI, sValue);
141 const css::uno::Sequence< css::xml::Attribute > unknownAttribs = xAttrList->getUnknownAttributes();
142 for (const css::xml::Attribute& rAttribute : unknownAttribs)
144 int nSepIndex = rAttribute.Name.indexOf(SvXMLImport::aNamespaceSeparator);
145 if (nSepIndex != -1)
147 // If it's an unknown attribute in a known namespace, ignore it.
148 OUString aPrefix = rAttribute.Name.copy(0, nSepIndex);
149 auto nKey = rNamespaceMap.GetKeyByPrefix(aPrefix);
150 if (nKey != USHRT_MAX && !(nKey & XML_NAMESPACE_UNKNOWN_FLAG))
151 continue;
154 importXMLAttribute(rProperties, rUnitConverter, rNamespaceMap,
155 nPropType, nStartIdx, nEndIdx, xAttrContainer,
156 rAttribute.Name, rAttribute.NamespaceURL, rAttribute.Value);
159 finished( rProperties, nStartIdx, nEndIdx );
162 void SvXMLImportPropertyMapper::importXMLAttribute(
163 std::vector< XMLPropertyState >& rProperties,
164 const SvXMLUnitConverter& rUnitConverter,
165 const SvXMLNamespaceMap& rNamespaceMap,
166 const sal_uInt32 nPropType,
167 const sal_Int32 nStartIdx,
168 const sal_Int32 nEndIdx,
169 Reference< XNameContainer >& xAttrContainer,
170 const OUString& rAttrName,
171 const OUString& aNamespaceURI,
172 const OUString& sValue) const
174 OUString aLocalName, aPrefix, aNamespace;
175 sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName( rAttrName, &aPrefix,
176 &aLocalName, &aNamespace );
178 // index of actual property map entry
179 // This looks very strange, but it works well:
180 // If the start index is 0, the new value will become -1, and
181 // GetEntryIndex will start searching with position 0.
182 // Otherwise GetEntryIndex will start with the next position specified.
183 sal_Int32 nIndex = nStartIdx - 1;
184 sal_uInt32 nFlags = 0; // flags of actual property map entry
185 bool bFound = false;
187 // for better error reporting: this should be set true if no
188 // warning is needed
189 bool bNoWarning = false;
193 // find an entry for this attribute
194 nIndex = maPropMapper->GetEntryIndex( nPrefix, aLocalName,
195 nPropType, nIndex );
197 if( nIndex > -1 && nIndex < nEndIdx )
199 // create a XMLPropertyState with an empty value
201 nFlags = maPropMapper->GetEntryFlags( nIndex );
202 if( ( nFlags & MID_FLAG_ELEMENT_ITEM_IMPORT ) == 0 )
204 XMLPropertyState aNewProperty( nIndex );
205 sal_Int32 nReference = -1;
207 // if this is a multi attribute check if another attribute already set
208 // this any. If so use this as an initial value
209 if( ( nFlags & MID_FLAG_MERGE_PROPERTY ) != 0 )
211 const OUString aAPIName( maPropMapper->GetEntryAPIName( nIndex ) );
212 const sal_Int32 nSize = rProperties.size();
213 for( nReference = 0; nReference < nSize; nReference++ )
215 sal_Int32 nRefIdx = rProperties[nReference].mnIndex;
216 if( (nRefIdx != -1) && (nIndex != nRefIdx) &&
217 (maPropMapper->GetEntryAPIName( nRefIdx ) == aAPIName ))
219 aNewProperty = rProperties[nReference];
220 aNewProperty.mnIndex = nIndex;
221 break;
225 if( nReference == nSize )
226 nReference = -1;
229 bool bSet = false;
230 if( ( nFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) == 0 )
232 // let the XMLPropertySetMapper decide how to import the value
233 bSet = maPropMapper->importXML( sValue, aNewProperty,
234 rUnitConverter );
236 else
238 sal_uInt32 nOldSize = rProperties.size();
240 bSet = handleSpecialItem( aNewProperty, rProperties,
241 sValue, rUnitConverter,
242 rNamespaceMap );
244 // no warning if handleSpecialItem added properties
245 bNoWarning |= ( nOldSize != rProperties.size() );
248 // no warning if we found could set the item. This
249 // 'remembers' bSet across multi properties.
250 bNoWarning |= bSet;
252 // store the property in the given vector
253 if( bSet )
255 if( nReference == -1 )
256 rProperties.push_back( aNewProperty );
257 else
258 rProperties[nReference] = aNewProperty;
260 else
262 // warn about unknown value. Unless it's a
263 // multi property: Then we get another chance
264 // to set the value.
265 if( !bNoWarning &&
266 ((nFlags & MID_FLAG_MULTI_PROPERTY) == 0) )
268 m_rImport.SetError( XMLERROR_FLAG_WARNING |
269 XMLERROR_STYLE_ATTR_VALUE,
270 { rAttrName, sValue } );
274 bFound = true;
275 continue;
278 if( !bFound )
280 SAL_INFO_IF((XML_NAMESPACE_NONE != nPrefix) &&
281 !(XML_NAMESPACE_UNKNOWN_FLAG & nPrefix),
282 "xmloff.style",
283 "unknown attribute: \"" << rAttrName << "\"");
284 if( (XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) || (XML_NAMESPACE_NONE == nPrefix) )
286 if( !xAttrContainer.is() )
288 // add an unknown attribute container to the properties
289 Reference< XNameContainer > xNew( SvUnoAttributeContainer_CreateInstance(), UNO_QUERY );
290 xAttrContainer = xNew;
292 // find map entry and create new property state
293 if( -1 == nIndex )
295 switch( nPropType )
297 case XML_TYPE_PROP_CHART:
298 nIndex = maPropMapper->FindEntryIndex( "ChartUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
299 break;
300 case XML_TYPE_PROP_PARAGRAPH:
301 nIndex = maPropMapper->FindEntryIndex( "ParaUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
302 break;
303 case XML_TYPE_PROP_TEXT:
304 nIndex = maPropMapper->FindEntryIndex( "TextUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
305 break;
306 default:
307 break;
309 // other property type or property not found
310 if( -1 == nIndex )
311 nIndex = maPropMapper->FindEntryIndex( "UserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) );
314 // #106963#; use userdefined attribute only if it is in the specified property range
315 if( nIndex != -1 && nIndex >= nStartIdx && nIndex < nEndIdx)
317 XMLPropertyState aNewProperty( nIndex, Any(xAttrContainer) );
319 // push it on our stack so we export it later
320 rProperties.push_back( aNewProperty );
324 if( xAttrContainer.is() )
326 AttributeData aData;
327 aData.Type = GetXMLToken( XML_CDATA );
328 aData.Value = sValue;
329 OUString sName;
330 if( XML_NAMESPACE_NONE != nPrefix )
332 sName = rAttrName;
333 aData.Namespace = aNamespaceURI;
335 else
336 sName = aLocalName;
337 xAttrContainer->insertByName( sName, Any(aData) );
342 while( ( nIndex >= 0 && nIndex + 1 < nEndIdx ) && (( nFlags & MID_FLAG_MULTI_PROPERTY ) != 0 ) );
345 /** this method is called for every item that has the MID_FLAG_SPECIAL_ITEM_IMPORT flag set */
346 bool SvXMLImportPropertyMapper::handleSpecialItem(
347 XMLPropertyState& rProperty,
348 std::vector< XMLPropertyState >& rProperties,
349 const OUString& rValue,
350 const SvXMLUnitConverter& rUnitConverter,
351 const SvXMLNamespaceMap& rNamespaceMap ) const
353 OSL_ENSURE( mxNextMapper.is(), "unsupported special item in xml import" );
354 if( mxNextMapper.is() )
355 return mxNextMapper->handleSpecialItem( rProperty, rProperties, rValue,
356 rUnitConverter, rNamespaceMap );
357 else
358 return false;
361 void SvXMLImportPropertyMapper::FillPropertySequence(
362 const ::std::vector< XMLPropertyState >& rProperties,
363 css::uno::Sequence< css::beans::PropertyValue >& rValues )
364 const
366 sal_Int32 nCount = rProperties.size();
367 sal_Int32 nValueCount = 0;
368 rValues.realloc( nCount );
369 PropertyValue *pProps = rValues.getArray();
370 for( sal_Int32 i=0; i < nCount; i++ )
372 const XMLPropertyState& rProp = rProperties[i];
373 sal_Int32 nIdx = rProp.mnIndex;
374 if( nIdx == -1 )
375 continue;
376 pProps->Name = maPropMapper->GetEntryAPIName( nIdx );
377 if( !pProps->Name.isEmpty() )
379 pProps->Value = rProp.maValue;
380 ++pProps;
381 ++nValueCount;
384 if( nValueCount < nCount )
385 rValues.realloc( nValueCount );
388 void SvXMLImportPropertyMapper::CheckSpecialContext(
389 const ::std::vector< XMLPropertyState >& aProperties,
390 const css::uno::Reference< css::beans::XPropertySet >& rPropSet,
391 ContextID_Index_Pair* pSpecialContextIds ) const
393 OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
394 sal_Int32 nCount = aProperties.size();
396 for( sal_Int32 i=0; i < nCount; i++ )
398 const XMLPropertyState& rProp = aProperties[i];
399 sal_Int32 nIdx = rProp.mnIndex;
401 // disregard property state if it has an invalid index
402 if( -1 == nIdx )
403 continue;
405 const sal_Int32 nPropFlags = maPropMapper->GetEntryFlags( nIdx );
407 // handle no-property and special items
408 if( ( pSpecialContextIds != nullptr ) &&
409 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
410 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
412 // maybe it's one of our special context ids?
413 sal_Int16 nContextId = maPropMapper->GetEntryContextId(nIdx);
415 for ( sal_Int32 n = 0;
416 pSpecialContextIds[n].nContextID != -1;
417 n++ )
419 // found: set index in pSpecialContextIds array
420 if ( pSpecialContextIds[n].nContextID == nContextId )
422 pSpecialContextIds[n].nIndex = i;
423 break; // early out
431 bool SvXMLImportPropertyMapper::FillPropertySet(
432 const std::vector< XMLPropertyState >& aProperties,
433 const Reference< XPropertySet >& rPropSet,
434 ContextID_Index_Pair* pSpecialContextIds ) const
436 bool bSet = false;
438 Reference< XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
439 if (xTolPropSet.is())
440 bSet = FillTolerantMultiPropertySet_( aProperties, xTolPropSet, maPropMapper, m_rImport,
441 pSpecialContextIds );
443 if (!bSet)
445 // get property set info
446 Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo());
448 // check for multi-property set
449 Reference<XMultiPropertySet> xMultiPropSet( rPropSet, UNO_QUERY );
450 if ( xMultiPropSet.is() )
452 // Try XMultiPropertySet. If that fails, try the regular route.
453 bSet = FillMultiPropertySet_( aProperties, xMultiPropSet,
454 xInfo, maPropMapper,
455 pSpecialContextIds );
456 if ( !bSet )
457 bSet = FillPropertySet_( aProperties, rPropSet,
458 xInfo, maPropMapper, m_rImport,
459 pSpecialContextIds);
461 else
462 bSet = FillPropertySet_( aProperties, rPropSet, xInfo,
463 maPropMapper, m_rImport,
464 pSpecialContextIds );
467 return bSet;
470 bool SvXMLImportPropertyMapper::FillPropertySet_(
471 const std::vector<XMLPropertyState> & rProperties,
472 const Reference<XPropertySet> & rPropSet,
473 const Reference<XPropertySetInfo> & rPropSetInfo,
474 const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
475 SvXMLImport& rImport,
476 ContextID_Index_Pair* pSpecialContextIds )
478 OSL_ENSURE( rPropSet.is(), "need an XPropertySet" );
479 OSL_ENSURE( rPropSetInfo.is(), "need an XPropertySetInfo" );
481 // preliminaries
482 bool bSet = false;
483 sal_Int32 nCount = rProperties.size();
485 // iterate over property states that we want to set
486 for( sal_Int32 i=0; i < nCount; i++ )
488 const XMLPropertyState& rProp = rProperties[i];
489 sal_Int32 nIdx = rProp.mnIndex;
491 // disregard property state if it has an invalid index
492 if( -1 == nIdx )
493 continue;
495 const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
496 const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
498 if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
499 ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
500 rPropSetInfo->hasPropertyByName( rPropName ) ) )
502 // try setting the property
505 rPropSet->setPropertyValue( rPropName, rProp.maValue );
506 bSet = true;
508 catch ( const IllegalArgumentException& e )
510 // illegal value: check whether this property is
511 // allowed to throw this exception
512 if ( 0 == ( nPropFlags & MID_FLAG_PROPERTY_MAY_THROW ) )
514 Sequence<OUString> aSeq { rPropName };
515 rImport.SetError(
516 XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR,
517 aSeq, e.Message, nullptr );
520 catch ( const UnknownPropertyException& e )
522 // unknown property: This is always an error!
523 Sequence<OUString> aSeq { rPropName };
524 rImport.SetError(
525 XMLERROR_STYLE_PROP_UNKNOWN | XMLERROR_FLAG_ERROR,
526 aSeq, e.Message, nullptr );
528 catch ( const PropertyVetoException& e )
530 // property veto: this shouldn't happen
531 Sequence<OUString> aSeq { rPropName };
532 rImport.SetError(
533 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
534 aSeq, e.Message, nullptr );
536 catch ( const WrappedTargetException& e )
538 // wrapped target: this shouldn't happen either
539 Sequence<OUString> aSeq { rPropName };
540 rImport.SetError(
541 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
542 aSeq, e.Message, nullptr );
546 // handle no-property and special items
547 if( ( pSpecialContextIds != nullptr ) &&
548 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
549 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
551 // maybe it's one of our special context ids?
552 sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
554 for ( sal_Int32 n = 0;
555 pSpecialContextIds[n].nContextID != -1;
556 n++ )
558 // found: set index in pSpecialContextIds array
559 if ( pSpecialContextIds[n].nContextID == nContextId )
561 pSpecialContextIds[n].nIndex = i;
562 break; // early out
568 return bSet;
572 typedef std::pair<const OUString*, const Any* > PropertyPair;
574 namespace {
576 struct PropertyPairLessFunctor
578 bool operator()( const PropertyPair& a, const PropertyPair& b ) const
580 return (*a.first < *b.first);
586 void SvXMLImportPropertyMapper::PrepareForMultiPropertySet_(
587 const std::vector<XMLPropertyState> & rProperties,
588 const Reference<XPropertySetInfo> & rPropSetInfo,
589 const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
590 ContextID_Index_Pair* pSpecialContextIds,
591 Sequence<OUString>& rNames,
592 Sequence<Any>& rValues)
594 sal_Int32 nCount = rProperties.size();
596 // property pairs structure stores names + values of properties to be set.
597 std::vector<PropertyPair> aPropertyPairs;
598 aPropertyPairs.reserve( nCount );
600 // iterate over property states that we want to set
601 sal_Int32 i;
602 for( i = 0; i < nCount; i++ )
604 const XMLPropertyState& rProp = rProperties[i];
605 sal_Int32 nIdx = rProp.mnIndex;
607 // disregard property state if it has an invalid index
608 if( -1 == nIdx )
609 continue;
611 const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx );
612 const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx );
614 if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) &&
615 ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) ||
616 !rPropSetInfo.is() ||
617 rPropSetInfo->hasPropertyByName(rPropName) ) )
619 // save property into property pair structure
620 aPropertyPairs.emplace_back( &rPropName, &rProp.maValue );
623 // handle no-property and special items
624 if( ( pSpecialContextIds != nullptr ) &&
625 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) ||
626 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) )
628 // maybe it's one of our special context ids?
629 sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx);
630 for ( sal_Int32 n = 0;
631 pSpecialContextIds[n].nContextID != -1;
632 n++ )
634 // found: set index in pSpecialContextIds array
635 if ( pSpecialContextIds[n].nContextID == nContextId )
637 pSpecialContextIds[n].nIndex = i;
638 break; // early out
644 // We now need to construct the sequences and actually the set
645 // values.
647 // sort the property pairs
648 sort( aPropertyPairs.begin(), aPropertyPairs.end(),
649 PropertyPairLessFunctor());
651 // create sequences
652 rNames.realloc( aPropertyPairs.size() );
653 OUString* pNamesArray = rNames.getArray();
654 rValues.realloc( aPropertyPairs.size() );
655 Any* pValuesArray = rValues.getArray();
657 // copy values into sequences
658 i = 0;
659 for( const auto& rPropertyPair : aPropertyPairs )
661 pNamesArray[i] = *(rPropertyPair.first);
662 pValuesArray[i++] = *(rPropertyPair.second);
666 bool SvXMLImportPropertyMapper::FillMultiPropertySet_(
667 const std::vector<XMLPropertyState> & rProperties,
668 const Reference<XMultiPropertySet> & rMultiPropSet,
669 const Reference<XPropertySetInfo> & rPropSetInfo,
670 const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
671 ContextID_Index_Pair* pSpecialContextIds )
673 OSL_ENSURE( rMultiPropSet.is(), "Need multi property set. ");
674 OSL_ENSURE( rPropSetInfo.is(), "Need property set info." );
676 bool bSuccessful = false;
678 Sequence<OUString> aNames;
679 Sequence<Any> aValues;
681 PrepareForMultiPropertySet_(rProperties, rPropSetInfo, rPropMapper, pSpecialContextIds,
682 aNames, aValues);
684 // and, finally, try to set the values
687 rMultiPropSet->setPropertyValues( aNames, aValues );
688 bSuccessful = true;
690 catch ( ... )
692 OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
695 return bSuccessful;
698 bool SvXMLImportPropertyMapper::FillTolerantMultiPropertySet_(
699 const std::vector<XMLPropertyState> & rProperties,
700 const Reference<XTolerantMultiPropertySet> & rTolMultiPropSet,
701 const rtl::Reference<XMLPropertySetMapper> & rPropMapper,
702 SvXMLImport& rImport,
703 ContextID_Index_Pair* pSpecialContextIds )
705 OSL_ENSURE( rTolMultiPropSet.is(), "Need tolerant multi property set. ");
707 bool bSuccessful = false;
709 Sequence<OUString> aNames;
710 Sequence<Any> aValues;
712 PrepareForMultiPropertySet_(rProperties, Reference<XPropertySetInfo>(nullptr), rPropMapper, pSpecialContextIds,
713 aNames, aValues);
715 // and, finally, try to set the values
718 const Sequence< SetPropertyTolerantFailed > aResults(rTolMultiPropSet->setPropertyValuesTolerant( aNames, aValues ));
719 bSuccessful = !aResults.hasElements();
720 for( const auto& rResult : aResults)
722 Sequence<OUString> aSeq { rResult.Name };
723 OUString sMessage;
724 switch (rResult.Result)
726 case TolerantPropertySetResultType::UNKNOWN_PROPERTY :
727 sMessage = "UNKNOWN_PROPERTY";
728 break;
729 case TolerantPropertySetResultType::ILLEGAL_ARGUMENT :
730 sMessage = "ILLEGAL_ARGUMENT";
731 break;
732 case TolerantPropertySetResultType::PROPERTY_VETO :
733 sMessage = "PROPERTY_VETO";
734 break;
735 case TolerantPropertySetResultType::WRAPPED_TARGET :
736 sMessage = "WRAPPED_TARGET";
737 break;
739 rImport.SetError(
740 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR,
741 aSeq, sMessage, nullptr );
744 catch ( ... )
746 OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly.");
749 return bSuccessful;
752 void SvXMLImportPropertyMapper::finished(
753 std::vector< XMLPropertyState >& rProperties,
754 sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const
756 // nothing to do here
757 if( mxNextMapper.is() )
758 mxNextMapper->finished( rProperties, nStartIndex, nEndIndex );
761 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */