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