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/container/XNameContainer.hpp> 27 #include <com/sun/star/xml/AttributeData.hpp> 28 #include <com/sun/star/beans/XPropertySet.hpp> 29 #include <com/sun/star/beans/XPropertyState.hpp> 30 #include <com/sun/star/lang/XTypeProvider.hpp> 31 #include <com/sun/star/beans/XMultiPropertySet.hpp> 32 #include <com/sun/star/beans/XTolerantMultiPropertySet.hpp> 33 #include <com/sun/star/beans/TolerantPropertySetResultType.hpp> 34 #include <rtl/ustrbuf.hxx> 35 #include <list> 36 #include <hash_map> 37 38 #include <xmloff/xmlexppr.hxx> 39 #include <xmloff/xmltoken.hxx> 40 #include <xmloff/attrlist.hxx> 41 #include <xmloff/nmspmap.hxx> 42 #include "xmloff/xmlnmspe.hxx" 43 #include <xmloff/xmlexp.hxx> 44 #include <xmloff/xmlprmap.hxx> 45 #include <xmloff/PropertySetInfoHash.hxx> 46 #include <comphelper/stl_types.hxx> 47 48 #ifndef _SVSTDARR_USHORTS 49 #define _SVSTDARR_USHORTS 50 #include <svl/svstdarr.hxx> 51 #endif 52 53 using ::rtl::OUString; 54 using ::rtl::OUStringBuffer; 55 56 using namespace ::std; 57 using namespace ::com::sun::star; 58 using namespace ::com::sun::star::beans; 59 using namespace ::com::sun::star::uno; 60 using namespace ::com::sun::star::lang; 61 using namespace ::xmloff::token; 62 63 #define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT) 64 65 struct XMLPropTokens_Impl 66 { 67 sal_uInt16 nType; 68 XMLTokenEnum eToken; 69 }; 70 71 #define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES } 72 const sal_uInt16 MAX_PROP_TYPES = 73 (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) - 74 (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT); 75 76 static XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] = 77 { 78 ENTRY(CHART), 79 ENTRY(GRAPHIC), 80 ENTRY(TABLE), 81 ENTRY(TABLE_COLUMN), 82 ENTRY(TABLE_ROW), 83 ENTRY(TABLE_CELL), 84 ENTRY(LIST_LEVEL), 85 ENTRY(PARAGRAPH), 86 ENTRY(TEXT), 87 ENTRY(DRAWING_PAGE), 88 ENTRY(PAGE_LAYOUT), 89 ENTRY(HEADER_FOOTER), 90 ENTRY(RUBY), 91 ENTRY(SECTION) 92 }; 93 94 /////////////////////////////////////////////////////////////////////////////// 95 // 96 // public methods 97 // 98 99 /////////////////////////////////////////////////////////////////////////// 100 // 101 // Take all properties of the XPropertySet which are also found in the 102 // XMLPropertyMapEntry-array and which are not set to their default-value, 103 // if a state is available. 104 // 105 // After that I call the method 'ContextFilter'. 106 // 107 108 typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl; 109 110 class XMLPropertyStates_Impl 111 { 112 XMLPropertyStateList_Impl aPropStates; 113 XMLPropertyStateList_Impl::iterator aLastItr; 114 sal_uInt32 nCount; 115 public: 116 XMLPropertyStates_Impl(); 117 void AddPropertyState(const XMLPropertyState& rPropState); 118 void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector); 119 }; 120 121 XMLPropertyStates_Impl::XMLPropertyStates_Impl() : 122 aPropStates(), 123 nCount(0) 124 { 125 aLastItr = aPropStates.begin(); 126 } 127 128 void XMLPropertyStates_Impl::AddPropertyState( 129 const XMLPropertyState& rPropState) 130 { 131 XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin(); 132 sal_Bool bInserted(sal_False); 133 if (nCount) 134 { 135 if (aLastItr->mnIndex < rPropState.mnIndex) 136 aItr = ++aLastItr; 137 } 138 do 139 { 140 // TODO: one path required only 141 if (aItr == aPropStates.end()) 142 { 143 aLastItr = aPropStates.insert(aPropStates.end(), rPropState); 144 bInserted = sal_True; 145 nCount++; 146 } 147 else if (aItr->mnIndex > rPropState.mnIndex) 148 { 149 aLastItr = aPropStates.insert(aItr, rPropState); 150 bInserted = sal_True; 151 nCount++; 152 } 153 } 154 while(!bInserted && (aItr++ != aPropStates.end())); 155 } 156 157 void XMLPropertyStates_Impl::FillPropertyStateVector( 158 std::vector<XMLPropertyState>& rVector) 159 { 160 if (nCount) 161 { 162 rVector.resize(nCount, XMLPropertyState(-1)); 163 ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() ); 164 } 165 } 166 167 class FilterPropertyInfo_Impl 168 { 169 const rtl::OUString sApiName; 170 std::list<sal_uInt32> aIndexes; 171 sal_uInt32 nCount; 172 173 public: 174 175 FilterPropertyInfo_Impl( const rtl::OUString& rApiName, 176 const sal_uInt32 nIndex); 177 178 const OUString& GetApiName() const { return sApiName; } 179 std::list<sal_uInt32>& GetIndexes() { return aIndexes; } 180 181 void AddIndex( sal_uInt32 nIndex ) 182 { 183 aIndexes.push_back(nIndex); 184 nCount++; 185 } 186 187 // for sort 188 sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const 189 { 190 return (GetApiName() < rArg.GetApiName()); 191 } 192 }; 193 194 FilterPropertyInfo_Impl::FilterPropertyInfo_Impl( 195 const rtl::OUString& rApiName, 196 const sal_uInt32 nIndex ) : 197 sApiName( rApiName ), 198 aIndexes(), 199 nCount(1) 200 { 201 aIndexes.push_back(nIndex); 202 } 203 204 typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl; 205 206 // ---------------------------------------------------------------------------- 207 208 class FilterPropertiesInfo_Impl 209 { 210 sal_uInt32 nCount; 211 FilterPropertyInfoList_Impl aPropInfos; 212 FilterPropertyInfoList_Impl::iterator aLastItr; 213 214 Sequence <OUString> *pApiNames; 215 216 public: 217 FilterPropertiesInfo_Impl(); 218 ~FilterPropertiesInfo_Impl(); 219 220 void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex); 221 const uno::Sequence<OUString>& GetApiNames(); 222 void FillPropertyStateArray( 223 vector< XMLPropertyState >& rPropStates, 224 const Reference< XPropertySet >& xPropSet, 225 const UniReference< XMLPropertySetMapper >& maPropMapper, 226 const sal_Bool bDefault = sal_False); 227 sal_uInt32 GetPropertyCount() const { return nCount; } 228 }; 229 230 // ---------------------------------------------------------------------------- 231 232 typedef std::hash_map 233 < 234 PropertySetInfoKey, 235 FilterPropertiesInfo_Impl *, 236 PropertySetInfoHash, 237 PropertySetInfoHash 238 > 239 FilterOropertiesHashMap_Impl; 240 241 class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl 242 { 243 public: 244 ~FilterPropertiesInfos_Impl (); 245 }; 246 247 FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl () 248 { 249 FilterOropertiesHashMap_Impl::iterator aIter = begin(); 250 FilterOropertiesHashMap_Impl::iterator aEnd = end(); 251 while( aIter != aEnd ) 252 { 253 delete (*aIter).second; 254 (*aIter).second = 0; 255 ++aIter; 256 } 257 } 258 259 // ---------------------------------------------------------------------------- 260 261 FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() : 262 nCount(0), 263 aPropInfos(), 264 pApiNames( 0 ) 265 { 266 aLastItr = aPropInfos.begin(); 267 } 268 269 FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl() 270 { 271 delete pApiNames; 272 } 273 274 void FilterPropertiesInfo_Impl::AddProperty( 275 const rtl::OUString& rApiName, const sal_uInt32 nIndex) 276 { 277 aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex)); 278 nCount++; 279 280 OSL_ENSURE( !pApiNames, "perfomance warning: API names already retrieved" ); 281 if( pApiNames ) 282 { 283 delete pApiNames; 284 pApiNames = NULL; 285 } 286 } 287 const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames() 288 { 289 OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count"); 290 if( !pApiNames ) 291 { 292 // we have to do three things: 293 // 1) sort API names, 294 // 2) merge duplicates, 295 // 3) construct sequence 296 297 // sort names 298 aPropInfos.sort(); 299 300 // merge duplicates 301 if ( nCount > 1 ) 302 { 303 FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin(); 304 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end(); 305 FilterPropertyInfoList_Impl::iterator aCurrent = aOld; 306 aCurrent++; 307 308 while ( aCurrent != aEnd ) 309 { 310 // equal to next element? 311 if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) ) 312 { 313 // if equal: merge index lists 314 aOld->GetIndexes().merge( aCurrent->GetIndexes() ); 315 // erase element, and continue with next 316 aCurrent = aPropInfos.erase( aCurrent ); 317 nCount--; 318 } 319 else 320 { 321 // remember old element and continue with next 322 aOld = aCurrent; 323 aCurrent++; 324 } 325 } 326 } 327 328 // construct sequence 329 pApiNames = new Sequence < OUString >( nCount ); 330 OUString *pNames = pApiNames->getArray(); 331 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin(); 332 FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end(); 333 for ( ; aItr != aEnd; aItr++, pNames++) 334 *pNames = aItr->GetApiName(); 335 } 336 337 return *pApiNames; 338 } 339 340 void FilterPropertiesInfo_Impl::FillPropertyStateArray( 341 vector< XMLPropertyState >& rPropStates, 342 const Reference< XPropertySet >& rPropSet, 343 const UniReference< XMLPropertySetMapper >& rPropMapper, 344 const sal_Bool bDefault ) 345 { 346 XMLPropertyStates_Impl aPropStates; 347 348 const uno::Sequence<OUString>& rApiNames = GetApiNames(); 349 350 Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY ); 351 if (xTolPropSet.is()) 352 { 353 if (!bDefault) 354 { 355 Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames)); 356 sal_Int32 nResultCount(aResults.getLength()); 357 if (nResultCount > 0) 358 { 359 const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray(); 360 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin()); 361 XMLPropertyState aNewProperty( -1 ); 362 sal_uInt32 i = 0; 363 while (nResultCount > 0 && i < nCount) 364 { 365 if (pResults->Name == aPropIter->GetApiName()) 366 { 367 aNewProperty.mnIndex = -1; 368 aNewProperty.maValue = pResults->Value; 369 370 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin()); 371 aIndexItr != aPropIter->GetIndexes().end(); 372 ++aIndexItr ) 373 { 374 aNewProperty.mnIndex = *aIndexItr; 375 aPropStates.AddPropertyState( aNewProperty ); 376 } 377 ++pResults; 378 --nResultCount; 379 } 380 ++aPropIter; 381 ++i; 382 } 383 } 384 } 385 else 386 { 387 Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames)); 388 OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" ); 389 const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray(); 390 FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin()); 391 XMLPropertyState aNewProperty( -1 ); 392 sal_uInt32 nResultCount(aResults.getLength()); 393 OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" ); 394 for( sal_uInt32 i = 0; i < nResultCount; ++i ) 395 { 396 if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) && 397 ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE))) 398 { 399 aNewProperty.mnIndex = -1; 400 aNewProperty.maValue = pResults->Value; 401 402 for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin()); 403 aIndexItr != aPropIter->GetIndexes().end(); 404 ++aIndexItr ) 405 { 406 aNewProperty.mnIndex = *aIndexItr; 407 aPropStates.AddPropertyState( aNewProperty ); 408 } 409 } 410 ++pResults; 411 ++aPropIter; 412 } 413 } 414 } 415 else 416 { 417 Sequence < PropertyState > aStates; 418 const PropertyState *pStates = 0; 419 Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY ); 420 if( xPropState.is() ) 421 { 422 aStates = xPropState->getPropertyStates( rApiNames ); 423 pStates = aStates.getConstArray(); 424 } 425 426 Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY ); 427 if( xMultiPropSet.is() && !bDefault ) 428 { 429 Sequence < Any > aValues; 430 if( pStates ) 431 { 432 // step 1: get value count 433 sal_uInt32 nValueCount = 0; 434 sal_uInt32 i; 435 436 for( i = 0; i < nCount; ++i, ++pStates ) 437 { 438 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ ) 439 nValueCount++; 440 } 441 442 if( nValueCount ) 443 { 444 // step 2: collect property names 445 Sequence < OUString > aAPINames( nValueCount ); 446 OUString *pAPINames = aAPINames.getArray(); 447 448 ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters; 449 aPropIters.reserve( nValueCount ); 450 451 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin(); 452 OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!"); 453 454 pStates = aStates.getConstArray(); 455 i = 0; 456 while( i < nValueCount ) 457 { 458 if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ ) 459 { 460 *pAPINames++ = aItr->GetApiName(); 461 aPropIters.push_back( aItr ); 462 ++i; 463 } 464 ++aItr; 465 ++pStates; 466 } 467 468 aValues = xMultiPropSet->getPropertyValues( aAPINames ); 469 const Any *pValues = aValues.getConstArray(); 470 471 ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator 472 pPropIter = aPropIters.begin(); 473 474 XMLPropertyState aNewProperty( -1 ); 475 for( i = 0; i < nValueCount; i++ ) 476 { 477 aNewProperty.mnIndex = -1; 478 aNewProperty.maValue = *pValues; 479 480 const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() ); 481 for ( std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin(); 482 aIndexItr != rIndexes.end(); 483 ++aIndexItr 484 ) 485 { 486 aNewProperty.mnIndex = *aIndexItr; 487 aPropStates.AddPropertyState( aNewProperty ); 488 } 489 490 ++pPropIter; 491 ++pValues; 492 } 493 } 494 } 495 else 496 { 497 aValues = xMultiPropSet->getPropertyValues( rApiNames ); 498 const Any *pValues = aValues.getConstArray(); 499 500 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin(); 501 for(sal_uInt32 i = 0; i < nCount; i++ ) 502 { 503 // The value is stored in the PropertySet itself, add to list. 504 XMLPropertyState aNewProperty( -1 ); 505 aNewProperty.maValue = *pValues; 506 ++pValues; 507 for( std::list<sal_uInt32>::iterator aIndexItr = 508 aItr->GetIndexes().begin(); 509 aIndexItr != aItr->GetIndexes().end(); 510 aIndexItr++ ) 511 { 512 aNewProperty.mnIndex = *aIndexItr; 513 aPropStates.AddPropertyState( aNewProperty ); 514 } 515 aItr++; 516 } 517 } 518 } 519 else 520 { 521 FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin(); 522 for(sal_uInt32 i = 0; i < nCount; i++ ) 523 { 524 sal_Bool bDirectValue = 525 !pStates || *pStates == PropertyState_DIRECT_VALUE; 526 if( bDirectValue || bDefault ) 527 { 528 // The value is stored in the PropertySet itself, add to list. 529 sal_Bool bGotValue = sal_False; 530 XMLPropertyState aNewProperty( -1 ); 531 for( std::list<sal_uInt32>::const_iterator aIndexItr = 532 aItr->GetIndexes().begin(); 533 aIndexItr != aItr->GetIndexes().end(); 534 aIndexItr++ ) 535 { 536 if( bDirectValue || 537 (rPropMapper->GetEntryFlags( *aIndexItr ) & 538 MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 ) 539 { 540 try 541 { 542 if( !bGotValue ) 543 { 544 aNewProperty.maValue = 545 rPropSet->getPropertyValue( aItr->GetApiName() ); 546 bGotValue = sal_True; 547 } 548 aNewProperty.mnIndex = *aIndexItr; 549 aPropStates.AddPropertyState( aNewProperty ); 550 } 551 catch( UnknownPropertyException& ) 552 { 553 // might be a problem of getImplemenetationId 554 OSL_ENSURE( !this, "unknown property in getPropertyValue" ); 555 } 556 557 } 558 } 559 } 560 561 aItr++; 562 if( pStates ) 563 pStates++; 564 } 565 } 566 } 567 aPropStates.FillPropertyStateVector(rPropStates); 568 } 569 570 /////////////////////////////////////////////////////////////////////////////// 571 // 572 // ctor/dtor , class SvXMLExportPropertyMapper 573 // 574 575 SvXMLExportPropertyMapper::SvXMLExportPropertyMapper( 576 const UniReference< XMLPropertySetMapper >& rMapper ) : 577 pCache( 0 ), 578 maPropMapper( rMapper ) 579 { 580 } 581 582 SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper() 583 { 584 delete pCache; 585 mxNextMapper = 0; 586 } 587 588 void SvXMLExportPropertyMapper::ChainExportMapper( 589 const UniReference< SvXMLExportPropertyMapper>& rMapper ) 590 { 591 // add map entries from rMapper to current map 592 maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() ); 593 // rMapper uses the same map as 'this' 594 rMapper->maPropMapper = maPropMapper; 595 596 // set rMapper as last mapper in current chain 597 UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper; 598 if( xNext.is()) 599 { 600 while( xNext->mxNextMapper.is()) 601 xNext = xNext->mxNextMapper; 602 xNext->mxNextMapper = rMapper; 603 } 604 else 605 mxNextMapper = rMapper; 606 607 // if rMapper was already chained, correct 608 // map pointer of successors 609 xNext = rMapper; 610 611 while( xNext->mxNextMapper.is()) 612 { 613 xNext = xNext->mxNextMapper; 614 xNext->maPropMapper = maPropMapper; 615 } 616 } 617 618 619 vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter( 620 const Reference< XPropertySet > xPropSet, 621 const sal_Bool bDefault ) const 622 { 623 vector< XMLPropertyState > aPropStateArray; 624 625 // Retrieve XPropertySetInfo and XPropertyState 626 Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() ); 627 if( !xInfo.is() ) 628 return aPropStateArray; 629 630 sal_Int32 nProps = maPropMapper->GetEntryCount(); 631 632 FilterPropertiesInfo_Impl *pFilterInfo = 0; 633 634 Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY ); 635 Sequence< sal_Int8 > aImplId; 636 if( xTypeProv.is() ) 637 { 638 aImplId = xTypeProv->getImplementationId(); 639 if( aImplId.getLength() == 16 ) 640 { 641 if( pCache ) 642 { 643 // The key must not be created outside this block, because it 644 // keeps a reference to the property set info. 645 PropertySetInfoKey aKey( xInfo, aImplId ); 646 FilterPropertiesInfos_Impl::iterator aIter = 647 pCache->find( aKey ); 648 if( aIter != pCache->end() ) 649 pFilterInfo = (*aIter).second; 650 } 651 } 652 } 653 654 sal_Bool bDelInfo = sal_False; 655 if( !pFilterInfo ) 656 { 657 pFilterInfo = new FilterPropertiesInfo_Impl; 658 for( sal_Int32 i=0; i < nProps; i++ ) 659 { 660 // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..) 661 // Does the PropertySet contain name of mpEntries-array ? 662 const OUString& rAPIName = maPropMapper->GetEntryAPIName( i ); 663 const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i ); 664 if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) && 665 ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) || 666 xInfo->hasPropertyByName( rAPIName ) ) ) 667 { 668 const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() ); 669 const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport( 670 maPropMapper->GetEarliestODFVersionForExport( i ) ); 671 if( nCurrentVersion >= nEarliestODFVersionForExport 672 || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN 673 || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN ) 674 pFilterInfo->AddProperty(rAPIName, i); 675 } 676 } 677 678 if( xTypeProv.is() && aImplId.getLength() == 16 ) 679 { 680 // Check whether the property set info is destroyed if it is 681 // assigned to a weak reference only. If it is destroyed, then 682 // every instance of getPropertySetInfo returns a new object. 683 // Such property set infos must not be cached. 684 WeakReference < XPropertySetInfo > xWeakInfo( xInfo ); 685 xInfo = 0; 686 xInfo = xWeakInfo; 687 if( xInfo.is() ) 688 { 689 if( !pCache ) 690 ((SvXMLExportPropertyMapper *)this)->pCache = 691 new FilterPropertiesInfos_Impl; 692 PropertySetInfoKey aKey( xInfo, aImplId ); 693 (*pCache)[aKey] = pFilterInfo; 694 } 695 else 696 bDelInfo = sal_True; 697 } 698 else 699 { 700 OSL_ENSURE(sal_False, "here is no TypeProvider or the ImplId is wrong"); 701 bDelInfo = sal_True; 702 } 703 } 704 705 if( pFilterInfo->GetPropertyCount() ) 706 { 707 try 708 { 709 pFilterInfo->FillPropertyStateArray(aPropStateArray, 710 xPropSet, maPropMapper, 711 bDefault); 712 } 713 catch( UnknownPropertyException& ) 714 { 715 // might be a problem of getImplemenetationId 716 OSL_ENSURE( !this, "unknown property in getPropertyStates" ); 717 } 718 } 719 720 // Call centext-filter 721 if( !aPropStateArray.empty() ) 722 ContextFilter( aPropStateArray, xPropSet ); 723 724 // Have to do if we change from a vector to a list or something like that 725 /*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin(); 726 while (aItr != aPropStateArray.end()) 727 { 728 if (aItr->mnIndex == -1) 729 aItr = aPropStateArray.erase(aItr); 730 else 731 aItr++; 732 }*/ 733 734 if( bDelInfo ) 735 delete pFilterInfo; 736 737 return aPropStateArray; 738 } 739 740 void SvXMLExportPropertyMapper::ContextFilter( 741 vector< XMLPropertyState >& rProperties, 742 Reference< XPropertySet > rPropSet ) const 743 { 744 // Derived class could implement this. 745 if( mxNextMapper.is() ) 746 mxNextMapper->ContextFilter( rProperties, rPropSet ); 747 } 748 749 /////////////////////////////////////////////////////////////////////////// 750 // 751 // Compares two Sequences of XMLPropertyState: 752 // 1.Number of elements equal ? 753 // 2.Index of each element equal ? (So I know whether the propertynames are the same) 754 // 3.Value of each element equal ? 755 // 756 sal_Bool SvXMLExportPropertyMapper::Equals( 757 const vector< XMLPropertyState >& aProperties1, 758 const vector< XMLPropertyState >& aProperties2 ) const 759 { 760 sal_Bool bRet = sal_True; 761 sal_uInt32 nCount = aProperties1.size(); 762 763 if( nCount == aProperties2.size() ) 764 { 765 sal_uInt32 nIndex = 0; 766 while( bRet && nIndex < nCount ) 767 { 768 const XMLPropertyState& rProp1 = aProperties1[ nIndex ]; 769 const XMLPropertyState& rProp2 = aProperties2[ nIndex ]; 770 771 // Compare index. If equal, compare value 772 if( rProp1.mnIndex == rProp2.mnIndex ) 773 { 774 if( rProp1.mnIndex != -1 ) 775 { 776 // Now compare values 777 if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) & 778 XML_TYPE_BUILDIN_CMP ) != 0 ) 779 // simple type ( binary compare ) 780 bRet = ( rProp1.maValue == rProp2.maValue ); 781 else 782 // complex type ( ask for compare-function ) 783 bRet = maPropMapper->GetPropertyHandler( 784 rProp1.mnIndex )->equals( rProp1.maValue, 785 rProp2.maValue ); 786 } 787 } 788 else 789 bRet = sal_False; 790 791 nIndex++; 792 } 793 } 794 else 795 bRet = sal_False; 796 797 return bRet; 798 } 799 800 801 /** fills the given attribute list with the items in the given set 802 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList, 803 const ::std::vector< XMLPropertyState >& rProperties, 804 const SvXMLUnitConverter& rUnitConverter, 805 const SvXMLNamespaceMap& rNamespaceMap, 806 sal_uInt16 nFlags ) const 807 { 808 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap, 809 nFlags, 0, -1, -1 ); 810 } 811 812 813 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList, 814 const ::std::vector< XMLPropertyState >& rProperties, 815 const SvXMLUnitConverter& rUnitConverter, 816 const SvXMLNamespaceMap& rNamespaceMap, 817 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx, 818 sal_uInt16 nFlags ) const 819 { 820 _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap, 821 nFlags, 0, nPropMapStartIdx, nPropMapEndIdx ); 822 } 823 */ 824 825 826 void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList, 827 const XMLPropertyState& rProperty, 828 const SvXMLUnitConverter& rUnitConverter, 829 const SvXMLNamespaceMap& rNamespaceMap, 830 sal_uInt16 nFlags ) const 831 { 832 if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) & 833 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 ) 834 _exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap, 835 nFlags ); 836 } 837 838 void SvXMLExportPropertyMapper::exportXML( 839 SvXMLExport& rExport, 840 const ::std::vector< XMLPropertyState >& rProperties, 841 sal_uInt16 nFlags ) const 842 { 843 exportXML( rExport, rProperties, -1, -1, nFlags ); 844 } 845 846 void SvXMLExportPropertyMapper::exportXML( 847 SvXMLExport& rExport, 848 const ::std::vector< XMLPropertyState >& rProperties, 849 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx, 850 sal_uInt16 nFlags ) const 851 { 852 sal_uInt16 nPropTypeFlags = 0; 853 for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i ) 854 { 855 sal_uInt16 nPropType = aPropTokens[i].nType; 856 if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 ) 857 { 858 SvUShorts aIndexArray; 859 860 _exportXML( nPropType, nPropTypeFlags, 861 rExport.GetAttrList(), rProperties, 862 rExport.GetMM100UnitConverter(), 863 rExport.GetNamespaceMap(), 864 nFlags, &aIndexArray, 865 nPropMapStartIdx, nPropMapEndIdx ); 866 867 if( rExport.GetAttrList().getLength() > 0L || 868 (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 || 869 aIndexArray.Count() != 0 ) 870 { 871 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, 872 aPropTokens[i].eToken, 873 (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0, 874 sal_False ); 875 876 exportElementItems( rExport, rProperties, nFlags, aIndexArray ); 877 } 878 } 879 } 880 } 881 882 /** this method is called for every item that has the 883 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */ 884 void SvXMLExportPropertyMapper::handleSpecialItem( 885 SvXMLAttributeList& rAttrList, 886 const XMLPropertyState& rProperty, 887 const SvXMLUnitConverter& rUnitConverter, 888 const SvXMLNamespaceMap& rNamespaceMap, 889 const ::std::vector< XMLPropertyState > *pProperties, 890 sal_uInt32 nIdx ) const 891 { 892 OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" ); 893 if( mxNextMapper.is() ) 894 mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter, 895 rNamespaceMap, pProperties, nIdx ); 896 } 897 898 /** this method is called for every item that has the 899 MID_FLAG_ELEMENT_EXPORT flag set */ 900 void SvXMLExportPropertyMapper::handleElementItem( 901 SvXMLExport& rExport, 902 const XMLPropertyState& rProperty, 903 sal_uInt16 nFlags, 904 const ::std::vector< XMLPropertyState > *pProperties, 905 sal_uInt32 nIdx ) const 906 { 907 OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" ); 908 if( mxNextMapper.is() ) 909 mxNextMapper->handleElementItem( rExport, rProperty, nFlags, 910 pProperties, nIdx ); 911 } 912 913 /////////////////////////////////////////////////////////////////////////////// 914 // 915 // protected methods 916 // 917 918 /** fills the given attribute list with the items in the given set */ 919 void SvXMLExportPropertyMapper::_exportXML( 920 sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags, 921 SvXMLAttributeList& rAttrList, 922 const ::std::vector< XMLPropertyState >& rProperties, 923 const SvXMLUnitConverter& rUnitConverter, 924 const SvXMLNamespaceMap& rNamespaceMap, 925 sal_uInt16 nFlags, 926 SvUShorts* pIndexArray, 927 sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const 928 { 929 const sal_uInt32 nCount = rProperties.size(); 930 sal_uInt32 nIndex = 0; 931 932 if( -1 == nPropMapStartIdx ) 933 nPropMapStartIdx = 0; 934 if( -1 == nPropMapEndIdx ) 935 nPropMapEndIdx = maPropMapper->GetEntryCount(); 936 937 while( nIndex < nCount ) 938 { 939 sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex; 940 if( nPropMapIdx >= nPropMapStartIdx && 941 nPropMapIdx < nPropMapEndIdx )// valid entry? 942 { 943 sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx ); 944 sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags); 945 OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT), 946 "no prop type sepcified" ); 947 rPropTypeFlags |= (1 << nEPType); 948 if( nEPType == nPropType ) 949 { 950 // we have a valid map entry here, so lets use it... 951 if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 ) 952 { 953 // element items do not add any properties, 954 // we export it later 955 if( pIndexArray ) 956 pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() ); 957 } 958 else 959 { 960 _exportXML( rAttrList, rProperties[nIndex], rUnitConverter, 961 rNamespaceMap, nFlags, &rProperties, nIndex ); 962 } 963 } 964 } 965 966 nIndex++; 967 } 968 } 969 970 void SvXMLExportPropertyMapper::_exportXML( 971 SvXMLAttributeList& rAttrList, 972 const XMLPropertyState& rProperty, 973 const SvXMLUnitConverter& rUnitConverter, 974 const SvXMLNamespaceMap& rNamespaceMap, 975 sal_uInt16 /*nFlags*/, 976 const ::std::vector< XMLPropertyState > *pProperties, 977 sal_uInt32 nIdx ) const 978 { 979 OUString sCDATA( GetXMLToken(XML_CDATA) ); 980 981 if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) & 982 MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 ) 983 { 984 uno::Reference< container::XNameContainer > xAttrContainer; 985 if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() ) 986 { 987 SvXMLNamespaceMap *pNewNamespaceMap = 0; 988 const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap; 989 990 uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() ); 991 const OUString* pAttribName = aAttribNames.getConstArray(); 992 993 const sal_Int32 nCount = aAttribNames.getLength(); 994 995 OUStringBuffer sNameBuffer; 996 xml::AttributeData aData; 997 for( sal_Int32 i=0; i < nCount; i++, pAttribName++ ) 998 { 999 xAttrContainer->getByName( *pAttribName ) >>= aData; 1000 OUString sAttribName( *pAttribName ); 1001 1002 // extract namespace prefix from attribute name if it exists 1003 OUString sPrefix; 1004 const sal_Int32 nColonPos = 1005 pAttribName->indexOf( sal_Unicode(':') ); 1006 if( nColonPos != -1 ) 1007 sPrefix = pAttribName->copy( 0, nColonPos ); 1008 1009 if( sPrefix.getLength() ) 1010 { 1011 OUString sNamespace( aData.Namespace ); 1012 1013 // if the prefix isn't defined yet or has another meaning, 1014 // we have to redefine it now. 1015 sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix ); 1016 if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace ) 1017 { 1018 sal_Bool bAddNamespace = sal_False; 1019 if( USHRT_MAX == nKey ) 1020 { 1021 // The prefix is unused, so it is sufficient 1022 // to add it to the namespace map. 1023 bAddNamespace = sal_True; 1024 } 1025 else 1026 { 1027 // check if there is a prefix registered for the 1028 // namepsace URI 1029 nKey = pNamespaceMap->GetKeyByName( sNamespace ); 1030 if( XML_NAMESPACE_UNKNOWN == nKey ) 1031 { 1032 // There is no prefix for the namespace, so 1033 // we have to generate one and have to add it. 1034 sal_Int32 n=0; 1035 OUString sOrigPrefix( sPrefix ); 1036 do 1037 { 1038 sNameBuffer.append( sOrigPrefix ); 1039 sNameBuffer.append( ++n ); 1040 sPrefix = sNameBuffer.makeStringAndClear(); 1041 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix ); 1042 } 1043 while( nKey != USHRT_MAX ); 1044 1045 bAddNamespace = sal_True; 1046 } 1047 else 1048 { 1049 // If there is a prefix for the namespace, 1050 // we reuse that. 1051 sPrefix = pNamespaceMap->GetPrefixByKey( nKey ); 1052 } 1053 // In any case, the attribute name has to be adapted. 1054 sNameBuffer.append( sPrefix ); 1055 sNameBuffer.append( sal_Unicode(':') ); 1056 sNameBuffer.append( pAttribName->copy( nColonPos+1 ) ); 1057 sAttribName = sNameBuffer.makeStringAndClear(); 1058 } 1059 1060 if( bAddNamespace ) 1061 { 1062 if( !pNewNamespaceMap ) 1063 { 1064 pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap ); 1065 pNamespaceMap = pNewNamespaceMap; 1066 } 1067 pNewNamespaceMap->Add( sPrefix, sNamespace ); 1068 sNameBuffer.append( GetXMLToken(XML_XMLNS) ); 1069 sNameBuffer.append( sal_Unicode(':') ); 1070 sNameBuffer.append( sPrefix ); 1071 rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(), 1072 sNamespace ); 1073 } 1074 } 1075 } 1076 OUString sOldValue( rAttrList.getValueByName( sAttribName ) ); 1077 OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" ); 1078 OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out"); 1079 if( !sOldValue.getLength() ) 1080 rAttrList.AddAttribute( sAttribName, aData.Value ); 1081 } 1082 1083 delete pNewNamespaceMap; 1084 } 1085 else 1086 { 1087 handleSpecialItem( rAttrList, rProperty, rUnitConverter, 1088 rNamespaceMap, pProperties, nIdx ); 1089 } 1090 } 1091 else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) & 1092 MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 ) 1093 { 1094 OUString aValue; 1095 const OUString sName( rNamespaceMap.GetQNameByKey( 1096 maPropMapper->GetEntryNameSpace( rProperty.mnIndex ), 1097 maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) ); 1098 1099 sal_Bool bRemove = sal_False; 1100 if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) & 1101 MID_FLAG_MERGE_ATTRIBUTE ) != 0 ) 1102 { 1103 aValue = rAttrList.getValueByName( sName ); 1104 bRemove = sal_True; //aValue.getLength() != 0; 1105 } 1106 1107 if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) ) 1108 { 1109 if( bRemove ) 1110 rAttrList.RemoveAttribute( sName ); 1111 rAttrList.AddAttribute( sName, aValue ); 1112 } 1113 } 1114 } 1115 1116 void SvXMLExportPropertyMapper::exportElementItems( 1117 SvXMLExport& rExport, 1118 const ::std::vector< XMLPropertyState >& rProperties, 1119 sal_uInt16 nFlags, 1120 const SvUShorts& rIndexArray ) const 1121 { 1122 const sal_uInt16 nCount = rIndexArray.Count(); 1123 1124 sal_Bool bItemsExported = sal_False; 1125 OUString sWS( GetXMLToken(XML_WS) ); 1126 for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ ) 1127 { 1128 const sal_uInt16 nElement = rIndexArray.GetObject( nIndex ); 1129 1130 OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags( 1131 rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT), 1132 "wrong mid flag!" ); 1133 1134 rExport.IgnorableWhitespace(); 1135 handleElementItem( rExport, rProperties[nElement], 1136 nFlags, &rProperties, nElement ); 1137 bItemsExported = sal_True; 1138 } 1139 1140 if( bItemsExported ) 1141 rExport.IgnorableWhitespace(); 1142 } 1143