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