1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 #include <com/sun/star/xml/AttributeData.hpp> 27 #include <com/sun/star/beans/XMultiPropertySet.hpp> 28 #include <com/sun/star/lang/IllegalArgumentException.hpp> 29 #include <com/sun/star/lang/WrappedTargetException.hpp> 30 #include <com/sun/star/beans/UnknownPropertyException.hpp> 31 #include <com/sun/star/beans/PropertyVetoException.hpp> 32 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp> 33 #include <rtl/ustrbuf.hxx> 34 #include <xmloff/xmlprmap.hxx> 35 #include <xmloff/nmspmap.hxx> 36 #include <xmloff/xmlimppr.hxx> 37 #include <xmloff/xmlimp.hxx> 38 39 #include "xmloff/unoatrcn.hxx" 40 #include "xmloff/xmlnmspe.hxx" 41 #include <xmloff/xmltoken.hxx> 42 #include "xmloff/xmlerror.hxx" 43 #include <tools/debug.hxx> 44 45 #include "xmloff/contextid.hxx" 46 47 // STL includes 48 #include <algorithm> 49 #include <functional> 50 #include <utility> 51 #include <vector> 52 53 using namespace ::com::sun::star::uno; 54 using namespace ::com::sun::star::beans; 55 using namespace ::com::sun::star::container; 56 using namespace ::com::sun::star::xml; 57 using namespace ::com::sun::star::xml::sax; 58 using ::rtl::OUString; 59 using ::rtl::OUStringBuffer; 60 61 using namespace ::std; 62 using namespace ::xmloff::token; 63 using ::com::sun::star::lang::IllegalArgumentException; 64 using ::com::sun::star::lang::WrappedTargetException; 65 using ::com::sun::star::beans::UnknownPropertyException; 66 using ::com::sun::star::beans::PropertyVetoException; 67 68 69 SvXMLImportPropertyMapper::SvXMLImportPropertyMapper( 70 const UniReference< XMLPropertySetMapper >& rMapper, 71 SvXMLImport& rImp ): 72 rImport(rImp), 73 maPropMapper ( rMapper ) 74 { 75 } 76 77 SvXMLImportPropertyMapper::~SvXMLImportPropertyMapper() 78 { 79 mxNextMapper = 0; 80 } 81 82 void SvXMLImportPropertyMapper::ChainImportMapper( 83 const UniReference< SvXMLImportPropertyMapper>& rMapper ) 84 { 85 // add map entries from rMapper to current map 86 maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() ); 87 // rMapper uses the same map as 'this' 88 rMapper->maPropMapper = maPropMapper; 89 90 // set rMapper as last mapper in current chain 91 UniReference< SvXMLImportPropertyMapper > xNext = mxNextMapper; 92 if( xNext.is()) 93 { 94 while( xNext->mxNextMapper.is()) 95 xNext = xNext->mxNextMapper; 96 xNext->mxNextMapper = rMapper; 97 } 98 else 99 mxNextMapper = rMapper; 100 101 // if rMapper was already chained, correct 102 // map pointer of successors 103 xNext = rMapper; 104 105 while( xNext->mxNextMapper.is()) 106 { 107 xNext = xNext->mxNextMapper; 108 xNext->maPropMapper = maPropMapper; 109 } 110 } 111 112 void SvXMLImportPropertyMapper::importXML( 113 vector< XMLPropertyState >& rProperties, 114 Reference< XAttributeList > xAttrList, 115 const SvXMLUnitConverter& rUnitConverter, 116 const SvXMLNamespaceMap& rNamespaceMap, 117 sal_uInt32 nPropType ) const 118 { 119 importXML( rProperties, xAttrList, rUnitConverter, rNamespaceMap, 120 nPropType,-1, -1 ); 121 } 122 123 /** fills the given itemset with the attributes in the given list */ 124 void SvXMLImportPropertyMapper::importXML( 125 vector< XMLPropertyState >& rProperties, 126 Reference< XAttributeList > xAttrList, 127 const SvXMLUnitConverter& rUnitConverter, 128 const SvXMLNamespaceMap& rNamespaceMap, 129 sal_uInt32 nPropType, 130 sal_Int32 nStartIdx, 131 sal_Int32 nEndIdx ) const 132 { 133 sal_Int16 nAttr = xAttrList->getLength(); 134 135 Reference< XNameContainer > xAttrContainer; 136 137 if( -1 == nStartIdx ) 138 nStartIdx = 0; 139 if( -1 == nEndIdx ) 140 nEndIdx = maPropMapper->GetEntryCount(); 141 for( sal_Int16 i=0; i < nAttr; i++ ) 142 { 143 const OUString& rAttrName = xAttrList->getNameByIndex( i ); 144 OUString aLocalName, aPrefix, aNamespace; 145 sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName( rAttrName, &aPrefix, 146 &aLocalName, &aNamespace ); 147 148 if( XML_NAMESPACE_XMLNS == nPrefix ) 149 continue; 150 151 const OUString& rValue = xAttrList->getValueByIndex( i ); 152 153 // index of actual property map entry 154 // This looks very strange, but it works well: 155 // If the start index is 0, the new value will become -1, and 156 // GetEntryIndex will start searching with position 0. 157 // Otherwise GetEntryIndex will start with the next position specified. 158 sal_Int32 nIndex = nStartIdx - 1; 159 sal_uInt32 nFlags = 0; // flags of actual property map entry 160 sal_Bool bFound = sal_False; 161 162 // for better error reporting: this should be set true if no 163 // warning is needed 164 sal_Bool bNoWarning = sal_False; 165 bool bAlienImport = false; 166 167 do 168 { 169 // find an entry for this attribute 170 nIndex = maPropMapper->GetEntryIndex( nPrefix, aLocalName, 171 nPropType, nIndex ); 172 173 if( nIndex > -1 && nIndex < nEndIdx ) 174 { 175 // create a XMLPropertyState with an empty value 176 177 nFlags = maPropMapper->GetEntryFlags( nIndex ); 178 if( (( nFlags & MID_FLAG_NO_PROPERTY ) == MID_FLAG_NO_PROPERTY) && (maPropMapper->GetEntryContextId( nIndex ) == CTF_ALIEN_ATTRIBUTE_IMPORT) ) 179 { 180 bAlienImport = true; 181 nIndex = -1; 182 } 183 else 184 { 185 if( ( nFlags & MID_FLAG_ELEMENT_ITEM_IMPORT ) == 0 ) 186 { 187 XMLPropertyState aNewProperty( nIndex ); 188 sal_Int32 nReference = -1; 189 190 // if this is a multi attribute check if another attribute already set 191 // this any. If so use this as a initial value 192 if( ( nFlags & MID_FLAG_MERGE_PROPERTY ) != 0 ) 193 { 194 const OUString aAPIName( maPropMapper->GetEntryAPIName( nIndex ) ); 195 const sal_Int32 nSize = rProperties.size(); 196 for( nReference = 0; nReference < nSize; nReference++ ) 197 { 198 sal_Int32 nRefIdx = rProperties[nReference].mnIndex; 199 if( (nRefIdx != -1) && (nIndex != nRefIdx) && 200 (maPropMapper->GetEntryAPIName( nRefIdx ) == aAPIName )) 201 { 202 aNewProperty = rProperties[nReference]; 203 aNewProperty.mnIndex = nIndex; 204 break; 205 } 206 } 207 208 if( nReference == nSize ) 209 nReference = -1; 210 } 211 212 sal_Bool bSet = sal_False; 213 if( ( nFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) == 0 ) 214 { 215 // let the XMLPropertySetMapper decide how to import the value 216 bSet = maPropMapper->importXML( rValue, aNewProperty, 217 rUnitConverter ); 218 } 219 else 220 { 221 sal_uInt32 nOldSize = rProperties.size(); 222 223 bSet = handleSpecialItem( aNewProperty, rProperties, 224 rValue, rUnitConverter, 225 rNamespaceMap ); 226 227 // no warning if handleSpecialItem added properties 228 bNoWarning |= ( nOldSize != rProperties.size() ); 229 } 230 231 // no warning if we found could set the item. This 232 // 'remembers' bSet across multi properties. 233 bNoWarning |= bSet; 234 235 // store the property in the given vector 236 if( bSet ) 237 { 238 if( nReference == -1 ) 239 rProperties.push_back( aNewProperty ); 240 else 241 rProperties[nReference] = aNewProperty; 242 } 243 else 244 { 245 // warn about unknown value. Unless it's a 246 // multi property: Then we get another chance 247 // to set the value. 248 if( !bNoWarning && 249 ((nFlags & MID_FLAG_MULTI_PROPERTY) == 0) ) 250 { 251 Sequence<OUString> aSeq(2); 252 aSeq[0] = rAttrName; 253 aSeq[1] = rValue; 254 rImport.SetError( XMLERROR_FLAG_WARNING | 255 XMLERROR_STYLE_ATTR_VALUE, 256 aSeq ); 257 } 258 } 259 } 260 bFound = sal_True; 261 continue; 262 } 263 } 264 265 if( !bFound ) 266 { 267 if( (XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) || (XML_NAMESPACE_NONE == nPrefix) || bAlienImport ) 268 { 269 OSL_ENSURE( XML_NAMESPACE_NONE == nPrefix || 270 (XML_NAMESPACE_UNKNOWN_FLAG & nPrefix) || 271 bAlienImport, 272 "unknown attribute - might be a new feature?" ); 273 if( !xAttrContainer.is() ) 274 { 275 // add an unknown attribute container to the properties 276 Reference< XNameContainer > xNew( SvUnoAttributeContainer_CreateInstance(), UNO_QUERY ); 277 xAttrContainer = xNew; 278 279 // find map entry and create new property state 280 if( -1 == nIndex ) 281 { 282 switch( nPropType ) 283 { 284 case XML_TYPE_PROP_CHART: 285 nIndex = maPropMapper->FindEntryIndex( "ChartUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) ); 286 break; 287 case XML_TYPE_PROP_PARAGRAPH: 288 nIndex = maPropMapper->FindEntryIndex( "ParaUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) ); 289 break; 290 case XML_TYPE_PROP_TEXT: 291 nIndex = maPropMapper->FindEntryIndex( "TextUserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) ); 292 break; 293 default: 294 break; 295 } 296 // other property type or property not found 297 if( -1 == nIndex ) 298 nIndex = maPropMapper->FindEntryIndex( "UserDefinedAttributes", XML_NAMESPACE_TEXT, GetXMLToken(XML_XMLNS) ); 299 } 300 301 // #106963#; use userdefined attribute only if it is in the specified property range 302 if( nIndex != -1 && nIndex >= nStartIdx && nIndex < nEndIdx) 303 { 304 Any aAny; 305 aAny <<= xAttrContainer; 306 XMLPropertyState aNewProperty( nIndex, aAny ); 307 308 // push it on our stack so we export it later 309 rProperties.push_back( aNewProperty ); 310 } 311 } 312 313 if( xAttrContainer.is() ) 314 { 315 AttributeData aData; 316 aData.Type = GetXMLToken( XML_CDATA ); 317 aData.Value = rValue; 318 319 OUStringBuffer sName; 320 if( XML_NAMESPACE_NONE != nPrefix ) 321 { 322 sName.append( aPrefix ); 323 sName.append( sal_Unicode(':') ); 324 aData.Namespace = aNamespace; 325 } 326 327 sName.append( aLocalName ); 328 329 Any aAny; 330 aAny <<= aData; 331 xAttrContainer->insertByName( sName.makeStringAndClear(), aAny ); 332 } 333 } 334 } 335 } 336 while( ( nIndex >= 0 ) && (( nFlags & MID_FLAG_MULTI_PROPERTY ) != 0 ) ); 337 } 338 339 finished( rProperties, nStartIdx, nEndIdx ); 340 341 // Have to do if we change from a vector to a list or something like that 342 /*std::vector <XMLPropertyState>::iterator aItr = rProperties.begin(); 343 while (aItr != rProperties.end()) 344 { 345 if (aItr->mnIndex == -1) 346 aItr = rProperties.erase(aItr); 347 else 348 aItr++; 349 }*/ 350 } 351 352 /** this method is called for every item that has the MID_FLAG_SPECIAL_ITEM_IMPORT flag set */ 353 sal_Bool SvXMLImportPropertyMapper::handleSpecialItem( 354 XMLPropertyState& rProperty, 355 vector< XMLPropertyState >& rProperties, 356 const OUString& rValue, 357 const SvXMLUnitConverter& rUnitConverter, 358 const SvXMLNamespaceMap& rNamespaceMap ) const 359 { 360 OSL_ENSURE( mxNextMapper.is(), "unsuported special item in xml import" ); 361 if( mxNextMapper.is() ) 362 return mxNextMapper->handleSpecialItem( rProperty, rProperties, rValue, 363 rUnitConverter, rNamespaceMap ); 364 else 365 return sal_False; 366 } 367 368 void SvXMLImportPropertyMapper::FillPropertySequence( 369 const ::std::vector< XMLPropertyState >& rProperties, 370 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rValues ) 371 const 372 { 373 sal_Int32 nCount = rProperties.size(); 374 sal_Int32 nValueCount = 0; 375 rValues.realloc( nCount ); 376 PropertyValue *pProps = rValues.getArray(); 377 for( sal_Int32 i=0; i < nCount; i++ ) 378 { 379 const XMLPropertyState& rProp = rProperties[i]; 380 sal_Int32 nIdx = rProp.mnIndex; 381 if( nIdx == -1 ) 382 continue; 383 pProps->Name = maPropMapper->GetEntryAPIName( nIdx ); 384 if( pProps->Name.getLength() ) 385 { 386 pProps->Value <<= rProp.maValue; 387 ++pProps; 388 ++nValueCount; 389 } 390 } 391 if( nValueCount < nCount ) 392 rValues.realloc( nValueCount ); 393 } 394 395 void SvXMLImportPropertyMapper::CheckSpecialContext( 396 const ::std::vector< XMLPropertyState >& aProperties, 397 const ::com::sun::star::uno::Reference< 398 ::com::sun::star::beans::XPropertySet > rPropSet, 399 _ContextID_Index_Pair* pSpecialContextIds ) const 400 { 401 OSL_ENSURE( rPropSet.is(), "need an XPropertySet" ); 402 sal_Int32 nCount = aProperties.size(); 403 404 Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo()); 405 406 for( sal_Int32 i=0; i < nCount; i++ ) 407 { 408 const XMLPropertyState& rProp = aProperties[i]; 409 sal_Int32 nIdx = rProp.mnIndex; 410 411 // disregard property state if it has an invalid index 412 if( -1 == nIdx ) 413 continue; 414 415 const sal_Int32 nPropFlags = maPropMapper->GetEntryFlags( nIdx ); 416 417 // handle no-property and special items 418 if( ( pSpecialContextIds != NULL ) && 419 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) || 420 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) ) 421 { 422 // maybe it's one of our special context ids? 423 sal_Int16 nContextId = maPropMapper->GetEntryContextId(nIdx); 424 425 for ( sal_Int32 n = 0; 426 pSpecialContextIds[n].nContextID != -1; 427 n++ ) 428 { 429 // found: set index in pSpecialContextIds array 430 if ( pSpecialContextIds[n].nContextID == nContextId ) 431 { 432 pSpecialContextIds[n].nIndex = i; 433 break; // early out 434 } 435 } 436 } 437 } 438 439 } 440 441 sal_Bool SvXMLImportPropertyMapper::FillPropertySet( 442 const vector< XMLPropertyState >& aProperties, 443 const Reference< XPropertySet > rPropSet, 444 _ContextID_Index_Pair* pSpecialContextIds ) const 445 { 446 sal_Bool bSet = sal_False; 447 448 Reference< XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY ); 449 if (xTolPropSet.is()) 450 bSet = _FillTolerantMultiPropertySet( aProperties, xTolPropSet, maPropMapper, rImport, 451 pSpecialContextIds ); 452 453 if (!bSet) 454 { 455 // get property set info 456 Reference< XPropertySetInfo > xInfo(rPropSet->getPropertySetInfo()); 457 458 // check for multi-property set 459 Reference<XMultiPropertySet> xMultiPropSet( rPropSet, UNO_QUERY ); 460 if ( xMultiPropSet.is() ) 461 { 462 // Try XMultiPropertySet. If that fails, try the regular route. 463 bSet = _FillMultiPropertySet( aProperties, xMultiPropSet, 464 xInfo, maPropMapper, 465 pSpecialContextIds ); 466 if ( !bSet ) 467 bSet = _FillPropertySet( aProperties, rPropSet, 468 xInfo, maPropMapper, rImport, 469 pSpecialContextIds); 470 } 471 else 472 bSet = _FillPropertySet( aProperties, rPropSet, xInfo, 473 maPropMapper, rImport, 474 pSpecialContextIds ); 475 } 476 477 return bSet; 478 } 479 480 sal_Bool SvXMLImportPropertyMapper::_FillPropertySet( 481 const vector<XMLPropertyState> & rProperties, 482 const Reference<XPropertySet> & rPropSet, 483 const Reference<XPropertySetInfo> & rPropSetInfo, 484 const UniReference<XMLPropertySetMapper> & rPropMapper, 485 SvXMLImport& rImport, 486 _ContextID_Index_Pair* pSpecialContextIds ) 487 { 488 OSL_ENSURE( rPropSet.is(), "need an XPropertySet" ); 489 OSL_ENSURE( rPropSetInfo.is(), "need an XPropertySetInfo" ); 490 491 // preliminaries 492 sal_Bool bSet = sal_False; 493 sal_Int32 nCount = rProperties.size(); 494 495 // iterate over property states that we want to set 496 for( sal_Int32 i=0; i < nCount; i++ ) 497 { 498 const XMLPropertyState& rProp = rProperties[i]; 499 sal_Int32 nIdx = rProp.mnIndex; 500 501 // disregard property state if it has an invalid index 502 if( -1 == nIdx ) 503 continue; 504 505 const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx ); 506 const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx ); 507 508 if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) && 509 ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) || 510 rPropSetInfo->hasPropertyByName( rPropName ) ) ) 511 { 512 // try setting the property 513 try 514 { 515 rPropSet->setPropertyValue( rPropName, rProp.maValue ); 516 bSet = sal_True; 517 } 518 catch ( IllegalArgumentException& e ) 519 { 520 // illegal value: check whether this property is 521 // allowed to throw this exception 522 if ( 0 == ( nPropFlags & MID_FLAG_PROPERTY_MAY_EXCEPT ) ) 523 { 524 Sequence<OUString> aSeq(1); 525 aSeq[0] = rPropName; 526 rImport.SetError( 527 XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR, 528 aSeq, e.Message, NULL ); 529 } 530 } 531 catch ( UnknownPropertyException& e ) 532 { 533 // unknown property: This is always an error! 534 Sequence<OUString> aSeq(1); 535 aSeq[0] = rPropName; 536 rImport.SetError( 537 XMLERROR_STYLE_PROP_UNKNOWN | XMLERROR_FLAG_ERROR, 538 aSeq, e.Message, NULL ); 539 } 540 catch ( PropertyVetoException& e ) 541 { 542 // property veto: this shouldn't happen 543 Sequence<OUString> aSeq(1); 544 aSeq[0] = rPropName; 545 rImport.SetError( 546 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR, 547 aSeq, e.Message, NULL ); 548 } 549 catch ( WrappedTargetException& e ) 550 { 551 // wrapped target: this shouldn't happen either 552 Sequence<OUString> aSeq(1); 553 aSeq[0] = rPropName; 554 rImport.SetError( 555 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR, 556 aSeq, e.Message, NULL ); 557 } 558 } 559 560 // handle no-property and special items 561 if( ( pSpecialContextIds != NULL ) && 562 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) || 563 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) ) 564 { 565 // maybe it's one of our special context ids? 566 sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx); 567 568 for ( sal_Int32 n = 0; 569 pSpecialContextIds[n].nContextID != -1; 570 n++ ) 571 { 572 // found: set index in pSpecialContextIds array 573 if ( pSpecialContextIds[n].nContextID == nContextId ) 574 { 575 pSpecialContextIds[n].nIndex = i; 576 break; // early out 577 } 578 } 579 } 580 } 581 582 return bSet; 583 } 584 585 586 587 typedef pair<const OUString*, const Any* > PropertyPair; 588 typedef vector<PropertyPair> PropertyPairs; 589 590 struct PropertyPairLessFunctor : 591 public binary_function<PropertyPair, PropertyPair, bool> 592 { 593 bool operator()( const PropertyPair& a, const PropertyPair& b ) const 594 { 595 return (*a.first < *b.first ? true : false); 596 } 597 }; 598 599 void SvXMLImportPropertyMapper::_PrepareForMultiPropertySet( 600 const vector<XMLPropertyState> & rProperties, 601 const Reference<XPropertySetInfo> & rPropSetInfo, 602 const UniReference<XMLPropertySetMapper> & rPropMapper, 603 _ContextID_Index_Pair* pSpecialContextIds, 604 Sequence<OUString>& rNames, 605 Sequence<Any>& rValues) 606 { 607 sal_Int32 nCount = rProperties.size(); 608 609 // property pairs structure stores names + values of properties to be set. 610 PropertyPairs aPropertyPairs; 611 aPropertyPairs.reserve( nCount ); 612 613 // iterate over property states that we want to set 614 sal_Int32 i; 615 for( i = 0; i < nCount; i++ ) 616 { 617 const XMLPropertyState& rProp = rProperties[i]; 618 sal_Int32 nIdx = rProp.mnIndex; 619 620 // disregard property state if it has an invalid index 621 if( -1 == nIdx ) 622 continue; 623 624 const OUString& rPropName = rPropMapper->GetEntryAPIName( nIdx ); 625 const sal_Int32 nPropFlags = rPropMapper->GetEntryFlags( nIdx ); 626 627 if ( ( 0 == ( nPropFlags & MID_FLAG_NO_PROPERTY ) ) && 628 ( ( 0 != ( nPropFlags & MID_FLAG_MUST_EXIST ) ) || 629 !rPropSetInfo.is() || 630 (rPropSetInfo.is() && rPropSetInfo->hasPropertyByName( rPropName )) ) ) 631 { 632 // save property into property pair structure 633 aPropertyPairs.push_back( PropertyPair( &rPropName, &rProp.maValue ) ); 634 } 635 636 // handle no-property and special items 637 if( ( pSpecialContextIds != NULL ) && 638 ( ( 0 != ( nPropFlags & MID_FLAG_NO_PROPERTY_IMPORT ) ) || 639 ( 0 != ( nPropFlags & MID_FLAG_SPECIAL_ITEM_IMPORT ) ) ) ) 640 { 641 // maybe it's one of our special context ids? 642 sal_Int16 nContextId = rPropMapper->GetEntryContextId(nIdx); 643 for ( sal_Int32 n = 0; 644 pSpecialContextIds[n].nContextID != -1; 645 n++ ) 646 { 647 // found: set index in pSpecialContextIds array 648 if ( pSpecialContextIds[n].nContextID == nContextId ) 649 { 650 pSpecialContextIds[n].nIndex = i; 651 break; // early out 652 } 653 } 654 } 655 } 656 657 // We now need to construct the sequences and actually the set 658 // values. 659 660 // sort the property pairs 661 sort( aPropertyPairs.begin(), aPropertyPairs.end(), 662 PropertyPairLessFunctor()); 663 664 // create sequences 665 rNames.realloc( aPropertyPairs.size() ); 666 OUString* pNamesArray = rNames.getArray(); 667 rValues.realloc( aPropertyPairs.size() ); 668 Any* pValuesArray = rValues.getArray(); 669 670 // copy values into sequences 671 i = 0; 672 for( PropertyPairs::iterator aIter = aPropertyPairs.begin(); 673 aIter != aPropertyPairs.end(); 674 ++aIter ) 675 { 676 pNamesArray[i] = *(aIter->first); 677 pValuesArray[i++] = *(aIter->second); 678 } 679 } 680 681 sal_Bool SvXMLImportPropertyMapper::_FillMultiPropertySet( 682 const vector<XMLPropertyState> & rProperties, 683 const Reference<XMultiPropertySet> & rMultiPropSet, 684 const Reference<XPropertySetInfo> & rPropSetInfo, 685 const UniReference<XMLPropertySetMapper> & rPropMapper, 686 _ContextID_Index_Pair* pSpecialContextIds ) 687 { 688 OSL_ENSURE( rMultiPropSet.is(), "Need multi property set. "); 689 OSL_ENSURE( rPropSetInfo.is(), "Need property set info." ); 690 691 sal_Bool bSuccessful = sal_False; 692 693 Sequence<OUString> aNames; 694 Sequence<Any> aValues; 695 696 _PrepareForMultiPropertySet(rProperties, rPropSetInfo, rPropMapper, pSpecialContextIds, 697 aNames, aValues); 698 699 // and, finally, try to set the values 700 try 701 { 702 rMultiPropSet->setPropertyValues( aNames, aValues ); 703 bSuccessful = sal_True; 704 } 705 catch ( ... ) 706 { 707 OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly."); 708 } 709 710 return bSuccessful; 711 } 712 713 sal_Bool SvXMLImportPropertyMapper::_FillTolerantMultiPropertySet( 714 const vector<XMLPropertyState> & rProperties, 715 const Reference<XTolerantMultiPropertySet> & rTolMultiPropSet, 716 const UniReference<XMLPropertySetMapper> & rPropMapper, 717 SvXMLImport& rImport, 718 _ContextID_Index_Pair* pSpecialContextIds ) 719 { 720 OSL_ENSURE( rTolMultiPropSet.is(), "Need tolerant multi property set. "); 721 722 sal_Bool bSuccessful = sal_False; 723 724 Sequence<OUString> aNames; 725 Sequence<Any> aValues; 726 727 _PrepareForMultiPropertySet(rProperties, Reference<XPropertySetInfo>(NULL), rPropMapper, pSpecialContextIds, 728 aNames, aValues); 729 730 // and, finally, try to set the values 731 try 732 { 733 Sequence< SetPropertyTolerantFailed > aResults(rTolMultiPropSet->setPropertyValuesTolerant( aNames, aValues )); 734 if (aResults.getLength() == 0) 735 bSuccessful = sal_True; 736 else 737 { 738 sal_Int32 nCount(aResults.getLength()); 739 for( sal_Int32 i = 0; i < nCount; ++i) 740 { 741 Sequence<OUString> aSeq(1); 742 aSeq[0] = aResults[i].Name; 743 rtl::OUString sMessage; 744 switch (aResults[i].Result) 745 { 746 case TolerantPropertySetResultType::UNKNOWN_PROPERTY : 747 sMessage = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("UNKNOWN_PROPERTY")); 748 break; 749 case TolerantPropertySetResultType::ILLEGAL_ARGUMENT : 750 sMessage = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ILLEGAL_ARGUMENT")); 751 break; 752 case TolerantPropertySetResultType::PROPERTY_VETO : 753 sMessage = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PROPERTY_VETO")); 754 break; 755 case TolerantPropertySetResultType::WRAPPED_TARGET : 756 sMessage = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WRAPPED_TARGET")); 757 break; 758 }; 759 rImport.SetError( 760 XMLERROR_STYLE_PROP_OTHER | XMLERROR_FLAG_ERROR, 761 aSeq, sMessage, NULL ); 762 } 763 } 764 } 765 catch ( ... ) 766 { 767 OSL_ENSURE(bSuccessful, "Exception caught; style may not be imported correctly."); 768 } 769 770 return bSuccessful; 771 } 772 773 void SvXMLImportPropertyMapper::finished( 774 vector< XMLPropertyState >& rProperties, 775 sal_Int32 nStartIndex, sal_Int32 nEndIndex ) const 776 { 777 // nothing to do here 778 if( mxNextMapper.is() ) 779 mxNextMapper->finished( rProperties, nStartIndex, nEndIndex ); 780 } 781