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 #include "vbadocumentproperties.hxx" 24 #include <cppuhelper/implbase1.hxx> 25 #include <cppuhelper/implbase3.hxx> 26 #include <com/sun/star/document/XDocumentInfoSupplier.hpp> 27 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 28 #include <com/sun/star/beans/NamedValue.hpp> 29 #include <com/sun/star/beans/XPropertyContainer.hpp> 30 #include <ooo/vba/word/WdBuiltInProperty.hpp> 31 #include <ooo/vba/office/MsoDocProperties.hpp> 32 #include <memory> 33 #include <boost/shared_ptr.hpp> 34 #include "wordvbahelper.hxx" 35 #include "fesh.hxx" 36 #include "docsh.hxx" 37 using namespace ::ooo::vba; 38 using namespace css; 39 40 sal_Int8 lcl_toMSOPropType( const uno::Type& aType ) throw ( lang::IllegalArgumentException ) 41 { 42 sal_Int16 msoType = office::MsoDocProperties::msoPropertyTypeString; 43 44 switch ( aType.getTypeClass() ) 45 { 46 case uno::TypeClass_BOOLEAN: 47 msoType = office::MsoDocProperties::msoPropertyTypeBoolean; 48 break; 49 case uno::TypeClass_FLOAT: 50 msoType = office::MsoDocProperties::msoPropertyTypeFloat; 51 break; 52 case uno::TypeClass_STRUCT: // Assume date 53 msoType = office::MsoDocProperties::msoPropertyTypeDate; 54 break; 55 case uno::TypeClass_BYTE: 56 case uno::TypeClass_SHORT: 57 case uno::TypeClass_LONG: 58 case uno::TypeClass_HYPER: 59 msoType = office::MsoDocProperties::msoPropertyTypeNumber; 60 break; 61 default: 62 throw lang::IllegalArgumentException(); 63 } 64 return msoType; 65 } 66 67 class PropertGetSetHelper 68 { 69 protected: 70 uno::Reference< frame::XModel > m_xModel; 71 uno::Reference< beans::XPropertySet > mxProps; 72 public: 73 PropertGetSetHelper( const uno::Reference< frame::XModel >& xModel ):m_xModel( xModel ) 74 { 75 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( m_xModel, uno::UNO_QUERY_THROW ); 76 mxProps.set( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW ); 77 } 78 virtual ~PropertGetSetHelper() {} 79 virtual uno::Any getPropertyValue( const rtl::OUString& rPropName ) = 0; 80 virtual void setPropertyValue( const rtl::OUString& rPropName, const uno::Any& aValue ) = 0; 81 virtual uno::Reference< beans::XPropertySet > getUnoProperties() { return mxProps; } 82 83 }; 84 85 class BuiltinPropertyGetSetHelper : public PropertGetSetHelper 86 { 87 public: 88 BuiltinPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :PropertGetSetHelper( xModel ) 89 { 90 } 91 virtual uno::Any getPropertyValue( const rtl::OUString& rPropName ) 92 { 93 if ( rPropName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("EditingDuration" ) ) ) ) 94 { 95 sal_Int32 nSecs = 0; 96 mxProps->getPropertyValue( rPropName ) >>= nSecs; 97 return uno::makeAny( nSecs/60 ); // minutes 98 } 99 return mxProps->getPropertyValue( rPropName ); 100 } 101 virtual void setPropertyValue( const rtl::OUString& rPropName, const uno::Any& aValue ) 102 { 103 mxProps->setPropertyValue( rPropName, aValue ); 104 } 105 }; 106 107 class CustomPropertyGetSetHelper : public BuiltinPropertyGetSetHelper 108 { 109 public: 110 CustomPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :BuiltinPropertyGetSetHelper( xModel ) 111 { 112 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( mxProps, uno::UNO_QUERY_THROW ); 113 uno::Reference< document::XDocumentProperties > xDocProp( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW ); 114 mxProps.set( xDocProp->getUserDefinedProperties(), uno::UNO_QUERY_THROW ); 115 } 116 }; 117 class StatisticPropertyGetSetHelper : public PropertGetSetHelper 118 { 119 SwDocShell* mpDocShell; 120 uno::Reference< beans::XPropertySet > mxModelProps; 121 public: 122 StatisticPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :PropertGetSetHelper( xModel ) , mpDocShell( NULL ) 123 { 124 mxModelProps.set( m_xModel, uno::UNO_QUERY_THROW ); 125 mpDocShell = word::getDocShell( xModel ); 126 } 127 virtual uno::Any getPropertyValue( const rtl::OUString& rPropName ) 128 { 129 uno::Sequence< beans::NamedValue > stats; 130 try 131 { 132 // Characters, ParagraphCount & WordCount are available from 133 // the model ( and addtionally these also update the statics object ) 134 //return mxProps->getPropertyValue( rPropName ); 135 return mxModelProps->getPropertyValue( rPropName ); 136 } 137 catch( uno::Exception& ) 138 { 139 OSL_TRACE("Got exception"); 140 } 141 uno::Any aReturn; 142 if ( rPropName.equals( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("LineCount")) ) ) // special processing needed 143 { 144 if ( mpDocShell ) 145 { 146 SwFEShell* pFEShell = mpDocShell->GetFEShell(); 147 if(pFEShell) 148 { 149 aReturn <<= pFEShell->GetLineCount(sal_False); 150 } 151 } 152 } 153 else 154 { 155 mxModelProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ParagraphCount") ) ) >>= stats; 156 mxProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DocumentStatistic") ) ) >>= stats; 157 158 sal_Int32 nLen = stats.getLength(); 159 bool bFound = false; 160 for ( sal_Int32 index = 0; index < nLen && !bFound ; ++index ) 161 { 162 if ( rPropName.equals( stats[ index ].Name ) ) 163 { 164 aReturn = stats[ index ].Value; 165 bFound = true; 166 } 167 } 168 if ( !bFound ) 169 throw uno::RuntimeException(); // bad Property 170 } 171 return aReturn; 172 } 173 174 virtual void setPropertyValue( const rtl::OUString& rPropName, const uno::Any& aValue ) 175 { 176 177 uno::Sequence< beans::NamedValue > stats; 178 mxProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DocumentStatistic") ) ) >>= stats; 179 180 sal_Int32 nLen = stats.getLength(); 181 for ( sal_Int32 index = 0; index < nLen; ++index ) 182 { 183 if ( rPropName.equals( stats[ index ].Name ) ) 184 { 185 stats[ index ].Value = aValue; 186 mxProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DocumentStatistic") ), uno::makeAny( stats ) ); 187 break; 188 } 189 } 190 } 191 }; 192 193 class DocPropInfo 194 { 195 public: 196 rtl::OUString msMSODesc; 197 rtl::OUString msOOOPropName; 198 boost::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper; 199 200 static DocPropInfo createDocPropInfo( const rtl::OUString& sDesc, const rtl::OUString& sPropName, boost::shared_ptr< PropertGetSetHelper >& rHelper ) 201 { 202 return createDocPropInfo( rtl::OUStringToOString( sDesc, RTL_TEXTENCODING_UTF8 ).getStr(), rtl::OUStringToOString( sPropName, RTL_TEXTENCODING_UTF8 ).getStr(), rHelper ); 203 } 204 205 static DocPropInfo createDocPropInfo( const sal_Char* sDesc, const sal_Char* sPropName, boost::shared_ptr< PropertGetSetHelper >& rHelper ) 206 { 207 DocPropInfo aItem; 208 aItem.msMSODesc = rtl::OUString::createFromAscii( sDesc ); 209 aItem.msOOOPropName = rtl::OUString::createFromAscii( sPropName ); 210 aItem.mpPropGetSetHelper = rHelper; 211 return aItem; 212 } 213 uno::Any getValue() 214 { 215 if ( mpPropGetSetHelper.get() ) 216 return mpPropGetSetHelper->getPropertyValue( msOOOPropName ); 217 return uno::Any(); 218 } 219 void setValue( const uno::Any& rValue ) 220 { 221 if ( mpPropGetSetHelper.get() ) 222 mpPropGetSetHelper->setPropertyValue( msOOOPropName, rValue ); 223 } 224 uno::Reference< beans::XPropertySet > getUnoProperties() 225 { 226 227 uno::Reference< beans::XPropertySet > xProps; 228 if ( mpPropGetSetHelper.get() ) 229 return mpPropGetSetHelper->getUnoProperties(); 230 return xProps; 231 } 232 }; 233 234 235 typedef std::hash_map< sal_Int32, DocPropInfo > MSOIndexToOODocPropInfo; 236 237 class BuiltInIndexHelper 238 { 239 MSOIndexToOODocPropInfo m_docPropInfoMap; 240 BuiltInIndexHelper(); 241 public: 242 BuiltInIndexHelper( const uno::Reference< frame::XModel >& xModel ) 243 { 244 boost::shared_ptr< PropertGetSetHelper > aStandardHelper( new BuiltinPropertyGetSetHelper( xModel ) ); 245 boost::shared_ptr< PropertGetSetHelper > aUsingStatsHelper( new StatisticPropertyGetSetHelper( xModel ) ); 246 247 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTitle ] = DocPropInfo::createDocPropInfo( "Title", "Title", aStandardHelper ); 248 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySubject ] = DocPropInfo::createDocPropInfo( "Subject", "Subject", aStandardHelper ); 249 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAuthor ] = DocPropInfo::createDocPropInfo( "Author", "Author", aStandardHelper ); 250 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyKeywords ] = DocPropInfo::createDocPropInfo( "Keywords", "Keywords", aStandardHelper ); 251 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyComments ] = DocPropInfo::createDocPropInfo( "Comments", "Description", aStandardHelper ); 252 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTemplate ] = DocPropInfo::createDocPropInfo( "Template", "Template", aStandardHelper ); 253 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLastAuthor ] = DocPropInfo::createDocPropInfo( "Last author", "ModifiedBy", aStandardHelper ); // doesn't seem to exist - throw or return nothing ? 254 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyRevision ] = DocPropInfo::createDocPropInfo( "Revision number", "EditingCycles", aStandardHelper ); // doesn't seem to exist - throw or return nothing ? 255 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAppName ] = DocPropInfo::createDocPropInfo( "Application name", "Generator", aStandardHelper ); // doesn't seem to exist - throw or return nothing ? 256 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastPrinted ] = DocPropInfo::createDocPropInfo( "Last print date", "PrintDate", aStandardHelper ); // doesn't seem to exist - throw or return nothing ? 257 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeCreated ] = DocPropInfo::createDocPropInfo( "Creation date", "CreationDate", aStandardHelper ); 258 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastSaved ] = DocPropInfo::createDocPropInfo( "Last save time", "ModifyDate", aStandardHelper ); 259 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyVBATotalEdit ] = DocPropInfo::createDocPropInfo( "Total editing time", "EditingDuration", aStandardHelper ); // Not sure if this is correct 260 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyPages ] = DocPropInfo::createDocPropInfo( "Number of pages", "PageCount", aUsingStatsHelper ); // special handling required ? 261 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyWords ] = DocPropInfo::createDocPropInfo( "Number of words", "WordCount", aUsingStatsHelper ); // special handling require ? 262 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharacters ] = DocPropInfo::createDocPropInfo( "Number of characters", "CharacterCount", aUsingStatsHelper ); // special handling required ? 263 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySecurity ] = DocPropInfo::createDocPropInfo( "Security", "", aStandardHelper ); // doesn't seem to exist 264 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCategory ] = DocPropInfo::createDocPropInfo( "Category", "Category", aStandardHelper ); // hacked in 265 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyFormat ] = DocPropInfo::createDocPropInfo( "Format", "", aStandardHelper ); // doesn't seem to exist 266 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyManager ] = DocPropInfo::createDocPropInfo( "Manager", "Manager", aStandardHelper ); // hacked in 267 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCompany ] = DocPropInfo::createDocPropInfo( "Company", "Company", aStandardHelper ); // hacked in 268 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyBytes ] = DocPropInfo::createDocPropInfo( "Number of bytes", "", aStandardHelper ); // doesn't seem to exist - size on disk exists ( for an already saved document ) perhaps it will do ( or we need something else ) 269 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLines ] = DocPropInfo::createDocPropInfo( "Number of lines", "LineCount", aUsingStatsHelper ); // special handling 270 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyParas ] = DocPropInfo::createDocPropInfo( "Number of paragraphs", "ParagraphCount", aUsingStatsHelper ); // special handling 271 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySlides ] = DocPropInfo::createDocPropInfo( "Number of slides", "" , aStandardHelper ); // doesn't seem to exist 272 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyNotes ] = DocPropInfo::createDocPropInfo( "Number of notes", "", aStandardHelper ); // doesn't seem to exist 273 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHiddenSlides ] = DocPropInfo::createDocPropInfo("Number of hidden Slides", "", aStandardHelper ); // doesn't seem to exist 274 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyMMClips ] = DocPropInfo::createDocPropInfo( "Number of multimedia clips", "", aStandardHelper ); // doesn't seem to exist 275 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHyperlinkBase ] = DocPropInfo::createDocPropInfo( "Hyperlink base", "AutoloadURL", aStandardHelper ); 276 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharsWSpaces ] = DocPropInfo::createDocPropInfo( "Number of characters (with spaces)", "", aStandardHelper ); // doesn't seem to be supported 277 } 278 279 MSOIndexToOODocPropInfo& getDocPropInfoMap() { return m_docPropInfoMap; } 280 }; 281 282 283 typedef InheritedHelperInterfaceImpl1< ooo::vba::XDocumentProperty > SwVbaDocumentProperty_BASE; 284 285 class SwVbaBuiltInDocumentProperty : public SwVbaDocumentProperty_BASE 286 { 287 protected: 288 DocPropInfo mPropInfo; 289 public: 290 SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ); 291 // XDocumentProperty 292 virtual void SAL_CALL Delete( ) throw (script::BasicErrorException, uno::RuntimeException); 293 virtual ::rtl::OUString SAL_CALL getName( ) throw (script::BasicErrorException, uno::RuntimeException); 294 virtual void SAL_CALL setName( const ::rtl::OUString& Name ) throw (script::BasicErrorException, uno::RuntimeException); 295 virtual ::sal_Int8 SAL_CALL getType( ) throw (script::BasicErrorException, uno::RuntimeException); 296 virtual void SAL_CALL setType( ::sal_Int8 Type ) throw (script::BasicErrorException, uno::RuntimeException); 297 virtual ::sal_Bool SAL_CALL getLinkToContent( ) throw (script::BasicErrorException, uno::RuntimeException); 298 virtual void SAL_CALL setLinkToContent( ::sal_Bool LinkToContent ) throw (script::BasicErrorException, uno::RuntimeException); 299 virtual uno::Any SAL_CALL getValue( ) throw (script::BasicErrorException, uno::RuntimeException); 300 virtual void SAL_CALL setValue( const uno::Any& Value ) throw (script::BasicErrorException, uno::RuntimeException); 301 virtual rtl::OUString SAL_CALL getLinkSource( ) throw (script::BasicErrorException, uno::RuntimeException); 302 virtual void SAL_CALL setLinkSource( const rtl::OUString& LinkSource ) throw (script::BasicErrorException, uno::RuntimeException); 303 //XDefaultProperty 304 virtual ::rtl::OUString SAL_CALL getDefaultPropertyName( ) throw (uno::RuntimeException) { return rtl::OUString::createFromAscii("Value"); } 305 // XHelperInterface 306 virtual rtl::OUString& getServiceImplName(); 307 virtual uno::Sequence<rtl::OUString> getServiceNames(); 308 }; 309 310 class SwVbaCustomDocumentProperty : public SwVbaBuiltInDocumentProperty 311 { 312 public: 313 314 SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ); 315 316 virtual ::sal_Bool SAL_CALL getLinkToContent( ) throw (script::BasicErrorException, uno::RuntimeException); 317 virtual void SAL_CALL setLinkToContent( ::sal_Bool LinkToContent ) throw (script::BasicErrorException, uno::RuntimeException); 318 319 virtual rtl::OUString SAL_CALL getLinkSource( ) throw (script::BasicErrorException, uno::RuntimeException); 320 virtual void SAL_CALL setLinkSource( const rtl::OUString& LinkSource ) throw (script::BasicErrorException, uno::RuntimeException); 321 virtual void SAL_CALL Delete( ) throw (script::BasicErrorException, uno::RuntimeException); 322 virtual void SAL_CALL setName( const ::rtl::OUString& Name ) throw (script::BasicErrorException, uno::RuntimeException); 323 virtual void SAL_CALL setType( ::sal_Int8 Type ) throw (script::BasicErrorException, uno::RuntimeException); 324 325 }; 326 327 328 SwVbaCustomDocumentProperty::SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaBuiltInDocumentProperty( xParent, xContext, rInfo ) 329 { 330 } 331 332 sal_Bool 333 SwVbaCustomDocumentProperty::getLinkToContent( ) throw (script::BasicErrorException, uno::RuntimeException) 334 { 335 // #FIXME we need to store the link content somewhere 336 return sal_False; 337 } 338 339 void 340 SwVbaCustomDocumentProperty::setLinkToContent( sal_Bool /*bLinkContent*/ ) throw (script::BasicErrorException, uno::RuntimeException) 341 { 342 } 343 344 rtl::OUString 345 SwVbaCustomDocumentProperty::getLinkSource( ) throw (script::BasicErrorException, uno::RuntimeException) 346 { 347 // #FIXME we need to store the link content somewhere 348 return rtl::OUString();; 349 } 350 351 void 352 SwVbaCustomDocumentProperty::setLinkSource( const rtl::OUString& /*rsLinkContent*/ ) throw (script::BasicErrorException, uno::RuntimeException) 353 { 354 // #FIXME we need to store the link source somewhere 355 } 356 357 void SAL_CALL 358 SwVbaCustomDocumentProperty::setName( const ::rtl::OUString& /*Name*/ ) throw (script::BasicErrorException, uno::RuntimeException) 359 { 360 // setName on existing property ? 361 // #FIXME 362 // do we need to delete existing property and create a new one? 363 } 364 365 void SAL_CALL 366 SwVbaCustomDocumentProperty::setType( ::sal_Int8 /*Type*/ ) throw (script::BasicErrorException, uno::RuntimeException) 367 { 368 // setType, do we need to do a conversion? 369 // #FIXME the underlying value needs to be changed to the new type 370 } 371 372 void SAL_CALL 373 SwVbaCustomDocumentProperty::Delete( ) throw (script::BasicErrorException, uno::RuntimeException) 374 { 375 uno::Reference< beans::XPropertyContainer > xContainer( mPropInfo.getUnoProperties(), uno::UNO_QUERY_THROW ); 376 xContainer->removeProperty( getName() ); 377 } 378 379 SwVbaBuiltInDocumentProperty::SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaDocumentProperty_BASE( xParent, xContext ), mPropInfo( rInfo ) 380 { 381 } 382 383 void SAL_CALL 384 SwVbaBuiltInDocumentProperty::Delete( ) throw (script::BasicErrorException, uno::RuntimeException) 385 { 386 // not valid for Builtin 387 throw uno::RuntimeException(); 388 } 389 390 ::rtl::OUString SAL_CALL 391 SwVbaBuiltInDocumentProperty::getName( ) throw (script::BasicErrorException, uno::RuntimeException) 392 { 393 return mPropInfo.msMSODesc; 394 } 395 396 void SAL_CALL 397 SwVbaBuiltInDocumentProperty::setName( const rtl::OUString& ) throw (script::BasicErrorException, uno::RuntimeException) 398 { 399 // not valid for Builtin 400 throw uno::RuntimeException(); 401 } 402 403 ::sal_Int8 SAL_CALL 404 SwVbaBuiltInDocumentProperty::getType( ) throw (script::BasicErrorException, uno::RuntimeException) 405 { 406 return lcl_toMSOPropType( getValue().getValueType() ); 407 } 408 409 void SAL_CALL 410 SwVbaBuiltInDocumentProperty::setType( ::sal_Int8 /*Type*/ ) throw (script::BasicErrorException, uno::RuntimeException) 411 { 412 // not valid for Builtin 413 throw uno::RuntimeException(); 414 } 415 416 ::sal_Bool SAL_CALL 417 SwVbaBuiltInDocumentProperty::getLinkToContent( ) throw (script::BasicErrorException, uno::RuntimeException) 418 { 419 return sal_False; // built-in always false 420 } 421 422 void SAL_CALL 423 SwVbaBuiltInDocumentProperty::setLinkToContent( ::sal_Bool /*LinkToContent*/ ) throw (script::BasicErrorException, uno::RuntimeException) 424 { 425 // not valid for Builtin 426 throw uno::RuntimeException(); 427 } 428 429 uno::Any SAL_CALL 430 SwVbaBuiltInDocumentProperty::getValue( ) throw (script::BasicErrorException, uno::RuntimeException) 431 { 432 uno::Any aRet = mPropInfo.getValue(); 433 if ( !aRet.hasValue() ) 434 throw uno::RuntimeException(); 435 return aRet; 436 } 437 438 void SAL_CALL 439 SwVbaBuiltInDocumentProperty::setValue( const uno::Any& Value ) throw (script::BasicErrorException, uno::RuntimeException) 440 { 441 mPropInfo.setValue( Value ); 442 } 443 444 rtl::OUString SAL_CALL 445 SwVbaBuiltInDocumentProperty::getLinkSource( ) throw (script::BasicErrorException, uno::RuntimeException) 446 { 447 // not valid for Builtin 448 throw uno::RuntimeException(); 449 } 450 451 void SAL_CALL 452 SwVbaBuiltInDocumentProperty::setLinkSource( const rtl::OUString& /*LinkSource*/ ) throw (script::BasicErrorException, uno::RuntimeException) 453 { 454 // not valid for Builtin 455 throw uno::RuntimeException(); 456 } 457 458 rtl::OUString& 459 SwVbaBuiltInDocumentProperty::getServiceImplName() 460 { 461 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaBuiltinDocumentProperty") ); 462 return sImplName; 463 } 464 465 uno::Sequence<rtl::OUString> 466 SwVbaBuiltInDocumentProperty::getServiceNames() 467 { 468 static uno::Sequence< rtl::OUString > aServiceNames; 469 if ( aServiceNames.getLength() == 0 ) 470 { 471 aServiceNames.realloc( 1 ); 472 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.DocumentProperty" ) ); 473 } 474 return aServiceNames; 475 } 476 typedef ::cppu::WeakImplHelper3< com::sun::star::container::XIndexAccess 477 ,com::sun::star::container::XNameAccess 478 ,com::sun::star::container::XEnumerationAccess 479 > PropertiesImpl_BASE; 480 481 typedef std::hash_map< sal_Int32, uno::Reference< XDocumentProperty > > DocProps; 482 483 typedef ::cppu::WeakImplHelper1< com::sun::star::container::XEnumeration > DocPropEnumeration_BASE; 484 class DocPropEnumeration : public DocPropEnumeration_BASE 485 { 486 DocProps mDocProps; 487 DocProps::iterator mIt; 488 public: 489 490 DocPropEnumeration( const DocProps& rProps ) : mDocProps( rProps ), mIt( mDocProps.begin() ) {} 491 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (uno::RuntimeException) 492 { 493 return mIt != mDocProps.end(); 494 } 495 virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 496 { 497 if ( !hasMoreElements() ) 498 throw container::NoSuchElementException(); 499 return uno::makeAny( mIt++->second ); 500 } 501 }; 502 503 typedef std::hash_map< rtl::OUString, uno::Reference< XDocumentProperty >, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > DocPropsByName; 504 505 class BuiltInPropertiesImpl : public PropertiesImpl_BASE 506 { 507 protected: 508 509 uno::Reference< XHelperInterface > m_xParent; 510 uno::Reference< uno::XComponentContext > m_xContext; 511 uno::Reference< frame::XModel > m_xModel; 512 uno::Reference< document::XDocumentInfo > m_xOOOBuiltIns; 513 514 DocProps mDocProps; 515 DocPropsByName mNamedDocProps; 516 517 public: 518 BuiltInPropertiesImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : m_xParent( xParent ), m_xContext( xContext ), m_xModel( xModel ) 519 { 520 BuiltInIndexHelper builtIns( m_xModel ); 521 for ( sal_Int32 index = word::WdBuiltInProperty::wdPropertyTitle; index <= word::WdBuiltInProperty::wdPropertyCharsWSpaces; ++index ) 522 { 523 mDocProps[ index ] = new SwVbaBuiltInDocumentProperty( xParent, xContext, builtIns.getDocPropInfoMap()[ index ] ); 524 mNamedDocProps[ mDocProps[ index ]->getName() ] = mDocProps[ index ]; 525 } 526 } 527 // XIndexAccess 528 virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException) 529 { 530 return mDocProps.size(); 531 } 532 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException ) 533 { 534 // correct the correct by the base class for 1 based indices 535 DocProps::iterator it = mDocProps.find( ++Index ); 536 if ( it == mDocProps.end() ) 537 throw lang::IndexOutOfBoundsException(); 538 return uno::makeAny( it->second ); 539 } 540 virtual uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 541 { 542 if ( !hasByName( aName ) ) 543 throw container::NoSuchElementException(); 544 DocPropsByName::iterator it = mNamedDocProps.find( aName ); 545 return uno::Any( it->second ); 546 547 } 548 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (uno::RuntimeException) 549 { 550 uno::Sequence< rtl::OUString > aNames( getCount() ); 551 rtl::OUString* pName = aNames.getArray(); 552 DocPropsByName::iterator it_end = mNamedDocProps.end(); 553 for( DocPropsByName::iterator it = mNamedDocProps.begin(); it != it_end; ++it, ++pName ) 554 *pName = it->first; 555 return aNames; 556 } 557 558 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException) 559 { 560 DocPropsByName::iterator it = mNamedDocProps.find( aName ); 561 if ( it == mNamedDocProps.end() ) 562 return sal_False; 563 return sal_True; 564 } 565 // XElementAccess 566 virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) 567 { 568 return XDocumentProperty::static_type(0); 569 } 570 virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) 571 { 572 return mDocProps.size() > 0; 573 } 574 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) throw (uno::RuntimeException) 575 { 576 return new DocPropEnumeration( mDocProps ); 577 } 578 }; 579 580 SwVbaBuiltinDocumentProperties::SwVbaBuiltinDocumentProperties( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : SwVbaDocumentproperties_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( new BuiltInPropertiesImpl( xParent, xContext, xModel ) ) ), m_xModel( xModel ) 581 { 582 } 583 584 uno::Reference< XDocumentProperty > SAL_CALL 585 SwVbaBuiltinDocumentProperties::Add( const ::rtl::OUString& /*Name*/, ::sal_Bool /*LinkToContent*/, ::sal_Int8 /*Type*/, const uno::Any& /*value*/, const uno::Any& /*LinkSource*/ ) throw (script::BasicErrorException, uno::RuntimeException) 586 { 587 throw uno::RuntimeException( 588 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("not supported for Builtin properties") ), uno::Reference< uno::XInterface >() ); 589 } 590 591 // XEnumerationAccess 592 uno::Type SAL_CALL 593 SwVbaBuiltinDocumentProperties::getElementType() throw (uno::RuntimeException) 594 { 595 return XDocumentProperty::static_type(0); 596 } 597 598 uno::Reference< container::XEnumeration > SAL_CALL 599 SwVbaBuiltinDocumentProperties::createEnumeration() throw (uno::RuntimeException) 600 { 601 uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW ); 602 return xEnumAccess->createEnumeration(); 603 } 604 605 // ScVbaCollectionBaseImpl 606 uno::Any 607 SwVbaBuiltinDocumentProperties::createCollectionObject( const uno::Any& aSource ) 608 { 609 // pass through 610 return aSource; 611 } 612 613 // XHelperInterface 614 rtl::OUString& 615 SwVbaBuiltinDocumentProperties::getServiceImplName() 616 { 617 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaBuiltinDocumentProperties") ); 618 return sImplName; 619 } 620 621 uno::Sequence<rtl::OUString> 622 SwVbaBuiltinDocumentProperties::getServiceNames() 623 { 624 static uno::Sequence< rtl::OUString > aServiceNames; 625 if ( aServiceNames.getLength() == 0 ) 626 { 627 aServiceNames.realloc( 1 ); 628 aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.DocumentProperties" ) ); 629 } 630 return aServiceNames; 631 } 632 633 class CustomPropertiesImpl : public PropertiesImpl_BASE 634 { 635 uno::Reference< XHelperInterface > m_xParent; 636 uno::Reference< uno::XComponentContext > m_xContext; 637 uno::Reference< frame::XModel > m_xModel; 638 uno::Reference< beans::XPropertySet > mxUserDefinedProp; 639 boost::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper; 640 public: 641 CustomPropertiesImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : m_xParent( xParent ), m_xContext( xContext ), m_xModel( xModel ) 642 { 643 // suck in the document( custom ) properties 644 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( m_xModel, uno::UNO_QUERY_THROW ); 645 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW ); 646 uno::Reference< document::XDocumentProperties > xDocProp( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW ); 647 mxUserDefinedProp.set( xDocProp->getUserDefinedProperties(), uno::UNO_QUERY_THROW ); 648 mpPropGetSetHelper.reset( new CustomPropertyGetSetHelper( m_xModel ) ); 649 }; 650 // XIndexAccess 651 virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException) 652 { 653 return mxUserDefinedProp->getPropertySetInfo()->getProperties().getLength(); 654 } 655 656 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException ) 657 { 658 uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties(); 659 if ( Index >= aProps.getLength() ) 660 throw lang::IndexOutOfBoundsException(); 661 // How to determine type e.g Date? ( com.sun.star.util.DateTime ) 662 DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aProps[ Index ].Name, aProps[ Index ].Name, mpPropGetSetHelper ); 663 return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) ); 664 } 665 666 virtual uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) 667 { 668 if ( !hasByName( aName ) ) 669 throw container::NoSuchElementException(); 670 671 DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aName, aName, mpPropGetSetHelper ); 672 return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) ); 673 } 674 675 virtual uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (uno::RuntimeException) 676 { 677 uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties(); 678 uno::Sequence< rtl::OUString > aNames( aProps.getLength() ); 679 rtl::OUString* pString = aNames.getArray(); 680 rtl::OUString* pEnd = ( pString + aNames.getLength() ); 681 beans::Property* pProp = aProps.getArray(); 682 for ( ; pString != pEnd; ++pString, ++pProp ) 683 *pString = pProp->Name; 684 return aNames; 685 } 686 687 virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException) 688 { 689 OSL_TRACE("hasByName(%s) returns %d", rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr(), mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName ) ); 690 return mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName ); 691 } 692 693 // XElementAccess 694 virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) 695 { 696 return XDocumentProperty::static_type(0); 697 } 698 699 virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException) 700 { 701 return getCount() > 0; 702 } 703 704 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) throw (uno::RuntimeException) 705 { 706 // create a map of properties ( the key doesn't matter ) 707 OSL_TRACE("Creating an enumeration"); 708 sal_Int32 key = 0; 709 sal_Int32 nElem = getCount(); 710 DocProps simpleDocPropSnapShot; 711 for ( ; key < nElem; ++key ) 712 simpleDocPropSnapShot[ key ].set( getByIndex( key ), uno::UNO_QUERY_THROW ); 713 OSL_TRACE("After creating the enumeration"); 714 return new DocPropEnumeration( simpleDocPropSnapShot ); 715 } 716 717 void addProp( const ::rtl::OUString& Name, ::sal_Int8 /*Type*/, const uno::Any& Value ) 718 { 719 sal_Int16 attributes = 128; 720 uno::Reference< beans::XPropertyContainer > xContainer( mxUserDefinedProp, uno::UNO_QUERY_THROW ); 721 // TODO fixme, perform the necessary Type Value conversions 722 xContainer->addProperty( Name, attributes, Value ); 723 } 724 725 }; 726 727 728 SwVbaCustomDocumentProperties::SwVbaCustomDocumentProperties( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : SwVbaBuiltinDocumentProperties( xParent, xContext, xModel ) 729 { 730 // replace the m_xIndexAccess implementation ( we need a virtual init ) 731 m_xIndexAccess.set( new CustomPropertiesImpl( xParent, xContext, xModel ) ); 732 m_xNameAccess.set( m_xIndexAccess, uno::UNO_QUERY_THROW ); 733 } 734 735 uno::Reference< XDocumentProperty > SAL_CALL 736 SwVbaCustomDocumentProperties::Add( const ::rtl::OUString& Name, ::sal_Bool LinkToContent, ::sal_Int8 Type, const uno::Any& Value, const uno::Any& LinkSource ) throw (script::BasicErrorException, uno::RuntimeException) 737 { 738 CustomPropertiesImpl* pCustomProps = dynamic_cast< CustomPropertiesImpl* > ( m_xIndexAccess.get() ); 739 uno::Reference< XDocumentProperty > xDocProp; 740 if ( pCustomProps ) 741 { 742 rtl::OUString sLinkSource; 743 pCustomProps->addProp( Name, Type, Value ); 744 745 xDocProp.set( m_xNameAccess->getByName( Name ), uno::UNO_QUERY_THROW ); 746 xDocProp->setLinkToContent( LinkToContent ); 747 748 if ( LinkSource >>= sLinkSource ) 749 xDocProp->setLinkSource( sLinkSource ); 750 } 751 return xDocProp; 752 } 753 754 // XHelperInterface 755 rtl::OUString& 756 SwVbaCustomDocumentProperties::getServiceImplName() 757 { 758 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaCustomDocumentProperties") ); 759 return sImplName; 760 } 761