LibreOffice Module sw (master)  1
vbadocumentproperties.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
20 #include <cppuhelper/implbase.hxx>
21 #include <sal/log.hxx>
22 #include <com/sun/star/document/XDocumentProperties.hpp>
23 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/beans/XPropertyContainer.hpp>
26 #include <ooo/vba/word/WdBuiltInProperty.hpp>
27 #include <ooo/vba/office/MsoDocProperties.hpp>
28 #include <tools/diagnose_ex.h>
29 #include <memory>
30 #include "wordvbahelper.hxx"
31 #include <fesh.hxx>
32 #include <docsh.hxx>
33 using namespace ::ooo::vba;
34 using namespace css;
35 
37 static sal_Int8 lcl_toMSOPropType( const uno::Type& aType )
38 {
39  sal_Int16 msoType = office::MsoDocProperties::msoPropertyTypeString;
40 
41  switch ( aType.getTypeClass() )
42  {
43  case uno::TypeClass_BOOLEAN:
44  msoType = office::MsoDocProperties::msoPropertyTypeBoolean;
45  break;
46  case uno::TypeClass_FLOAT:
47  msoType = office::MsoDocProperties::msoPropertyTypeFloat;
48  break;
49  case uno::TypeClass_STRUCT: // Assume date
50  msoType = office::MsoDocProperties::msoPropertyTypeDate;
51  break;
52  case uno::TypeClass_BYTE:
53  case uno::TypeClass_SHORT:
54  case uno::TypeClass_LONG:
55  case uno::TypeClass_HYPER:
56  msoType = office::MsoDocProperties::msoPropertyTypeNumber;
57  break;
58  default:
59  throw lang::IllegalArgumentException();
60  }
61  return msoType;
62 }
63 
64 namespace {
65 
66 class PropertGetSetHelper
67 {
68 protected:
69  uno::Reference< frame::XModel > m_xModel;
70  uno::Reference<document::XDocumentProperties> m_xDocProps;
71 public:
72  explicit PropertGetSetHelper( const uno::Reference< frame::XModel >& xModel ):m_xModel( xModel )
73  {
74  uno::Reference<document::XDocumentPropertiesSupplier> const
75  xDocPropSupp(m_xModel, uno::UNO_QUERY_THROW);
76  m_xDocProps.set(xDocPropSupp->getDocumentProperties(),
77  uno::UNO_SET_THROW);
78  }
79  virtual ~PropertGetSetHelper() {}
80  virtual uno::Any getPropertyValue( const OUString& rPropName ) = 0;
81  virtual void setPropertyValue( const OUString& rPropName, const uno::Any& aValue ) = 0;
82  uno::Reference< beans::XPropertySet > getUserDefinedProperties() {
83  return uno::Reference<beans::XPropertySet>(
84  m_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
85  }
86 
87 };
88 
89 class BuiltinPropertyGetSetHelper : public PropertGetSetHelper
90 {
91 public:
92  explicit BuiltinPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :PropertGetSetHelper( xModel )
93  {
94  }
95  virtual uno::Any getPropertyValue( const OUString& rPropName ) override
96  {
97  if ( rPropName == "EditingDuration" )
98  {
99  sal_Int32 const nSecs = m_xDocProps->getEditingDuration();
100  return uno::makeAny( nSecs/60 ); // minutes
101  }
102  else if ("Title" == rPropName)
103  {
104  return uno::makeAny(m_xDocProps->getTitle());
105  }
106  else if ("Subject" == rPropName)
107  {
108  return uno::makeAny(m_xDocProps->getSubject());
109  }
110  else if ("Author" == rPropName)
111  {
112  return uno::makeAny(m_xDocProps->getAuthor());
113  }
114  else if ("Keywords" == rPropName)
115  {
116  return uno::makeAny(m_xDocProps->getKeywords());
117  }
118  else if ("Description" == rPropName)
119  {
120  return uno::makeAny(m_xDocProps->getDescription());
121  }
122  else if ("Template" == rPropName)
123  {
124  return uno::makeAny(m_xDocProps->getTemplateName());
125  }
126  else if ("ModifiedBy" == rPropName)
127  {
128  return uno::makeAny(m_xDocProps->getModifiedBy());
129  }
130  else if ("Generator" == rPropName)
131  {
132  return uno::makeAny(m_xDocProps->getGenerator());
133  }
134  else if ("PrintDate" == rPropName)
135  {
136  return uno::makeAny(m_xDocProps->getPrintDate());
137  }
138  else if ("CreationDate" == rPropName)
139  {
140  return uno::makeAny(m_xDocProps->getCreationDate());
141  }
142  else if ("ModifyDate" == rPropName)
143  {
144  return uno::makeAny(m_xDocProps->getModificationDate());
145  }
146  else if ("AutoloadURL" == rPropName)
147  {
148  return uno::makeAny(m_xDocProps->getAutoloadURL());
149  }
150  else
151  {
152  // fall back to user-defined properties
153  return getUserDefinedProperties()->getPropertyValue(rPropName);
154  }
155  }
156  virtual void setPropertyValue( const OUString& rPropName, const uno::Any& aValue ) override
157  {
158  if ("EditingDuration" == rPropName)
159  {
160  sal_Int32 nMins = 0;
161  if (aValue >>= nMins)
162  {
163  m_xDocProps->setEditingDuration(nMins * 60); // convert minutes
164  }
165  }
166  else if ("Title" == rPropName)
167  {
168  OUString str;
169  if (aValue >>= str)
170  {
171  m_xDocProps->setTitle(str);
172  }
173  }
174  else if ("Subject" == rPropName)
175  {
176  OUString str;
177  if (aValue >>= str)
178  {
179  m_xDocProps->setSubject(str);
180  }
181  }
182  else if ("Author" == rPropName)
183  {
184  OUString str;
185  if (aValue >>= str)
186  {
187  m_xDocProps->setAuthor(str);
188  }
189  }
190  else if ("Keywords" == rPropName)
191  {
192  uno::Sequence<OUString> keywords;
193  if (aValue >>= keywords)
194  {
195  m_xDocProps->setKeywords(keywords);
196  }
197  }
198  else if ("Description" == rPropName)
199  {
200  OUString str;
201  if (aValue >>= str)
202  {
203  m_xDocProps->setDescription(str);
204  }
205  }
206  else if ("Template" == rPropName)
207  {
208  OUString str;
209  if (aValue >>= str)
210  {
211  m_xDocProps->setTemplateName(str);
212  }
213  }
214  else if ("ModifiedBy" == rPropName)
215  {
216  OUString str;
217  if (aValue >>= str)
218  {
219  m_xDocProps->setModifiedBy(str);
220  }
221  }
222  else if ("Generator" == rPropName)
223  {
224  OUString str;
225  if (aValue >>= str)
226  {
227  return m_xDocProps->setGenerator(str);
228  }
229  }
230  else if ("PrintDate" == rPropName)
231  {
232  util::DateTime dt;
233  if (aValue >>= dt)
234  {
235  m_xDocProps->setPrintDate(dt);
236  }
237  }
238  else if ("CreationDate" == rPropName)
239  {
240  util::DateTime dt;
241  if (aValue >>= dt)
242  {
243  m_xDocProps->setCreationDate(dt);
244  }
245  }
246  else if ("ModifyDate" == rPropName)
247  {
248  util::DateTime dt;
249  if (aValue >>= dt)
250  {
251  m_xDocProps->setModificationDate(dt);
252  }
253  }
254  else if ("AutoloadURL" == rPropName)
255  {
256  OUString str;
257  if (aValue >>= str)
258  {
259  m_xDocProps->setAutoloadURL(str);
260  }
261  }
262  else
263  {
264  // fall back to user-defined properties
265  getUserDefinedProperties()->setPropertyValue(rPropName, aValue);
266  }
267  }
268 };
269 
270 class CustomPropertyGetSetHelper : public BuiltinPropertyGetSetHelper
271 {
272 public:
273  explicit CustomPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :BuiltinPropertyGetSetHelper( xModel )
274  {
275  }
276  virtual uno::Any getPropertyValue( const OUString& rPropName ) override
277  {
278  return getUserDefinedProperties()->getPropertyValue(rPropName);
279  }
280  virtual void setPropertyValue(
281  const OUString& rPropName, const uno::Any& rValue) override
282  {
283  return getUserDefinedProperties()->setPropertyValue(rPropName, rValue);
284  }
285 };
286 
287 class StatisticPropertyGetSetHelper : public PropertGetSetHelper
288 {
289  SwDocShell* mpDocShell;
290  uno::Reference< beans::XPropertySet > mxModelProps;
291 public:
292  explicit StatisticPropertyGetSetHelper( const uno::Reference< frame::XModel >& xModel ) :PropertGetSetHelper( xModel ) , mpDocShell( nullptr )
293  {
294  mxModelProps.set( m_xModel, uno::UNO_QUERY_THROW );
295  mpDocShell = word::getDocShell( xModel );
296  }
297  virtual uno::Any getPropertyValue( const OUString& rPropName ) override
298  {
299  try
300  {
301  // Characters, ParagraphCount & WordCount are available from
302  // the model ( and additionally these also update the statics object )
303  return mxModelProps->getPropertyValue( rPropName );
304  }
305  catch (const uno::Exception&)
306  {
307  TOOLS_WARN_EXCEPTION("sw.vba", "");
308  }
309  uno::Any aReturn;
310  if ( rPropName == "LineCount" ) // special processing needed
311  {
312  if ( mpDocShell )
313  {
314  SwFEShell* pFEShell = mpDocShell->GetFEShell();
315  if(pFEShell)
316  {
317  aReturn <<= pFEShell->GetLineCount();
318  }
319  }
320  }
321  else
322  {
323  uno::Sequence< beans::NamedValue > const stats(
324  m_xDocProps->getDocumentStatistics());
325 
326  auto pStat = std::find_if(stats.begin(), stats.end(),
327  [&rPropName](const beans::NamedValue& rStat) { return rPropName == rStat.Name; });
328  if (pStat == stats.end())
329  throw uno::RuntimeException(); // bad Property
330 
331  aReturn = pStat->Value;
332  }
333  return aReturn;
334  }
335 
336  virtual void setPropertyValue( const OUString& rPropName, const uno::Any& aValue ) override
337  {
338  uno::Sequence< beans::NamedValue > stats(
339  m_xDocProps->getDocumentStatistics());
340 
341  auto pStat = std::find_if(stats.begin(), stats.end(),
342  [&rPropName](const beans::NamedValue& rStat) { return rPropName == rStat.Name; });
343  if (pStat != stats.end())
344  {
345  pStat->Value = aValue;
346  m_xDocProps->setDocumentStatistics(stats);
347  }
348  }
349 };
350 
351 class DocPropInfo
352 {
353 public:
354  OUString msMSODesc;
355  OUString msOOOPropName;
356  std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
357 
358  static DocPropInfo createDocPropInfo( const OUString& sDesc, const OUString& sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
359  {
360  DocPropInfo aItem;
361  aItem.msMSODesc = sDesc;
362  aItem.msOOOPropName = sPropName;
363  aItem.mpPropGetSetHelper = rHelper;
364  return aItem;
365  }
366 
367  static DocPropInfo createDocPropInfo( const char* sDesc, const char* sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
368  {
369  return createDocPropInfo( OUString::createFromAscii( sDesc ), OUString::createFromAscii( sPropName ), rHelper );
370  }
372  {
373  if ( mpPropGetSetHelper.get() )
374  return mpPropGetSetHelper->getPropertyValue( msOOOPropName );
375  return uno::Any();
376  }
377  void setValue( const uno::Any& rValue )
378  {
379  if ( mpPropGetSetHelper.get() )
380  mpPropGetSetHelper->setPropertyValue( msOOOPropName, rValue );
381  }
382  uno::Reference< beans::XPropertySet > getUserDefinedProperties()
383  {
384  uno::Reference< beans::XPropertySet > xProps;
385  if ( mpPropGetSetHelper.get() )
386  return mpPropGetSetHelper->getUserDefinedProperties();
387  return xProps;
388  }
389 };
390 
391 }
392 
393 typedef std::unordered_map< sal_Int32, DocPropInfo > MSOIndexToOODocPropInfo;
394 
395 namespace {
396 
397 class BuiltInIndexHelper
398 {
399  MSOIndexToOODocPropInfo m_docPropInfoMap;
400 
401 public:
402  explicit BuiltInIndexHelper( const uno::Reference< frame::XModel >& xModel )
403  {
404  auto aStandardHelper = std::make_shared<BuiltinPropertyGetSetHelper>( xModel );
405  auto aUsingStatsHelper = std::make_shared<StatisticPropertyGetSetHelper>( xModel );
406 
407  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTitle ] = DocPropInfo::createDocPropInfo( "Title", "Title", aStandardHelper );
408  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySubject ] = DocPropInfo::createDocPropInfo( "Subject", "Subject", aStandardHelper );
409  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAuthor ] = DocPropInfo::createDocPropInfo( "Author", "Author", aStandardHelper );
410  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyKeywords ] = DocPropInfo::createDocPropInfo( "Keywords", "Keywords", aStandardHelper );
411  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyComments ] = DocPropInfo::createDocPropInfo( "Comments", "Description", aStandardHelper );
412  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTemplate ] = DocPropInfo::createDocPropInfo( "Template", "Template", aStandardHelper );
413  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLastAuthor ] = DocPropInfo::createDocPropInfo( "Last author", "ModifiedBy", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
414  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyRevision ] = DocPropInfo::createDocPropInfo( "Revision number", "EditingCycles", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
415  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAppName ] = DocPropInfo::createDocPropInfo( "Application name", "Generator", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
416  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastPrinted ] = DocPropInfo::createDocPropInfo( "Last print date", "PrintDate", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
417  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeCreated ] = DocPropInfo::createDocPropInfo( "Creation date", "CreationDate", aStandardHelper );
418  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastSaved ] = DocPropInfo::createDocPropInfo( "Last save time", "ModifyDate", aStandardHelper );
419  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyVBATotalEdit ] = DocPropInfo::createDocPropInfo( "Total editing time", "EditingDuration", aStandardHelper ); // Not sure if this is correct
420  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyPages ] = DocPropInfo::createDocPropInfo( "Number of pages", "PageCount", aUsingStatsHelper ); // special handling required ?
421  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyWords ] = DocPropInfo::createDocPropInfo( "Number of words", "WordCount", aUsingStatsHelper ); // special handling require ?
422  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharacters ] = DocPropInfo::createDocPropInfo( "Number of characters", "CharacterCount", aUsingStatsHelper ); // special handling required ?
423  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySecurity ] = DocPropInfo::createDocPropInfo( "Security", "", aStandardHelper ); // doesn't seem to exist
424  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCategory ] = DocPropInfo::createDocPropInfo( "Category", "Category", aStandardHelper ); // hacked in
425  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyFormat ] = DocPropInfo::createDocPropInfo( "Format", "", aStandardHelper ); // doesn't seem to exist
426  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyManager ] = DocPropInfo::createDocPropInfo( "Manager", "Manager", aStandardHelper ); // hacked in
427  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCompany ] = DocPropInfo::createDocPropInfo( "Company", "Company", aStandardHelper ); // hacked in
428  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 )
429  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLines ] = DocPropInfo::createDocPropInfo( "Number of lines", "LineCount", aUsingStatsHelper ); // special handling
430  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyParas ] = DocPropInfo::createDocPropInfo( "Number of paragraphs", "ParagraphCount", aUsingStatsHelper ); // special handling
431  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySlides ] = DocPropInfo::createDocPropInfo( "Number of slides", "" , aStandardHelper ); // doesn't seem to exist
432  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyNotes ] = DocPropInfo::createDocPropInfo( "Number of notes", "", aStandardHelper ); // doesn't seem to exist
433  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHiddenSlides ] = DocPropInfo::createDocPropInfo("Number of hidden Slides", "", aStandardHelper ); // doesn't seem to exist
434  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyMMClips ] = DocPropInfo::createDocPropInfo( "Number of multimedia clips", "", aStandardHelper ); // doesn't seem to exist
435  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHyperlinkBase ] = DocPropInfo::createDocPropInfo( "Hyperlink base", "AutoloadURL", aStandardHelper );
436  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharsWSpaces ] = DocPropInfo::createDocPropInfo( "Number of characters (with spaces)", "", aStandardHelper ); // doesn't seem to be supported
437  }
438 
439  MSOIndexToOODocPropInfo& getDocPropInfoMap() { return m_docPropInfoMap; }
440 };
441 
442 }
443 
445 
446 namespace {
447 
448 class SwVbaBuiltInDocumentProperty : public SwVbaDocumentProperty_BASE
449 {
450 protected:
451  DocPropInfo mPropInfo;
452 public:
453  SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo );
454  // XDocumentProperty
455  virtual void SAL_CALL Delete( ) override;
456  virtual OUString SAL_CALL getName( ) override;
457  virtual void SAL_CALL setName( const OUString& Name ) override;
458  virtual ::sal_Int8 SAL_CALL getType( ) override;
459  virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
460  virtual sal_Bool SAL_CALL getLinkToContent( ) override;
461  virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
462  virtual uno::Any SAL_CALL getValue( ) override;
463  virtual void SAL_CALL setValue( const uno::Any& Value ) override;
464  virtual OUString SAL_CALL getLinkSource( ) override;
465  virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
466  //XDefaultProperty
467  virtual OUString SAL_CALL getDefaultPropertyName( ) override { return "Value"; }
468  // XHelperInterface
469  virtual OUString getServiceImplName() override;
470  virtual uno::Sequence<OUString> getServiceNames() override;
471 };
472 
473 class SwVbaCustomDocumentProperty : public SwVbaBuiltInDocumentProperty
474 {
475 public:
476 
477  SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo );
478 
479  virtual sal_Bool SAL_CALL getLinkToContent( ) override;
480  virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
481 
482  virtual OUString SAL_CALL getLinkSource( ) override;
483  virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
484  virtual void SAL_CALL Delete( ) override;
485  virtual void SAL_CALL setName( const OUString& Name ) override;
486  virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
487 
488 };
489 
490 }
491 
492 SwVbaCustomDocumentProperty::SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaBuiltInDocumentProperty( xParent, xContext, rInfo )
493 {
494 }
495 
496 sal_Bool
497 SwVbaCustomDocumentProperty::getLinkToContent( )
498 {
499  // #FIXME we need to store the link content somewhere
500  return false;
501 }
502 
503 void
504 SwVbaCustomDocumentProperty::setLinkToContent( sal_Bool /*bLinkContent*/ )
505 {
506 }
507 
508 OUString
509 SwVbaCustomDocumentProperty::getLinkSource( )
510 {
511  // #FIXME we need to store the link content somewhere
512  return OUString();
513 }
514 
515 void
516 SwVbaCustomDocumentProperty::setLinkSource( const OUString& /*rsLinkContent*/ )
517 {
518  // #FIXME we need to store the link source somewhere
519 }
520 
521 void SAL_CALL
522 SwVbaCustomDocumentProperty::setName( const OUString& /*Name*/ )
523 {
524  // setName on existing property ?
525  // #FIXME
526  // do we need to delete existing property and create a new one?
527 }
528 
529 void SAL_CALL
530 SwVbaCustomDocumentProperty::setType( ::sal_Int8 /*Type*/ )
531 {
532  // setType, do we need to do a conversion?
533  // #FIXME the underlying value needs to be changed to the new type
534 }
535 
536 void SAL_CALL
537 SwVbaCustomDocumentProperty::Delete( )
538 {
539  uno::Reference< beans::XPropertyContainer > xContainer(
540  mPropInfo.getUserDefinedProperties(), uno::UNO_QUERY_THROW);
541  xContainer->removeProperty( getName() );
542 }
543 
544 SwVbaBuiltInDocumentProperty::SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaDocumentProperty_BASE( xParent, xContext ), mPropInfo( rInfo )
545 {
546 }
547 
548 void SAL_CALL
549 SwVbaBuiltInDocumentProperty::Delete( )
550 {
551  // not valid for Builtin
552  throw uno::RuntimeException();
553 }
554 
555 OUString SAL_CALL
556 SwVbaBuiltInDocumentProperty::getName( )
557 {
558  return mPropInfo.msMSODesc;
559 }
560 
561 void SAL_CALL
562 SwVbaBuiltInDocumentProperty::setName( const OUString& )
563 {
564  // not valid for Builtin
565  throw uno::RuntimeException();
566 }
567 
568 ::sal_Int8 SAL_CALL
569 SwVbaBuiltInDocumentProperty::getType( )
570 {
571  return lcl_toMSOPropType( getValue().getValueType() );
572 }
573 
574 void SAL_CALL
575 SwVbaBuiltInDocumentProperty::setType( ::sal_Int8 /*Type*/ )
576 {
577  // not valid for Builtin
578  throw uno::RuntimeException();
579 }
580 
581 sal_Bool SAL_CALL
582 SwVbaBuiltInDocumentProperty::getLinkToContent( )
583 {
584  return false; // built-in always false
585 }
586 
587 void SAL_CALL
588 SwVbaBuiltInDocumentProperty::setLinkToContent( sal_Bool /*LinkToContent*/ )
589 {
590  // not valid for Builtin
591  throw uno::RuntimeException();
592 }
593 
594 uno::Any SAL_CALL
595 SwVbaBuiltInDocumentProperty::getValue( )
596 {
597  uno::Any aRet = mPropInfo.getValue();
598  if ( !aRet.hasValue() )
599  throw uno::RuntimeException();
600  return aRet;
601 }
602 
603 void SAL_CALL
604 SwVbaBuiltInDocumentProperty::setValue( const uno::Any& Value )
605 {
606  mPropInfo.setValue( Value );
607 }
608 
609 OUString SAL_CALL
610 SwVbaBuiltInDocumentProperty::getLinkSource( )
611 {
612  // not valid for Builtin
613  throw uno::RuntimeException();
614 }
615 
616 void SAL_CALL
617 SwVbaBuiltInDocumentProperty::setLinkSource( const OUString& /*LinkSource*/ )
618 {
619  // not valid for Builtin
620  throw uno::RuntimeException();
621 }
622 
623 OUString
624 SwVbaBuiltInDocumentProperty::getServiceImplName()
625 {
626  return "SwVbaBuiltinDocumentProperty";
627 }
628 
629 uno::Sequence<OUString>
630 SwVbaBuiltInDocumentProperty::getServiceNames()
631 {
632  static uno::Sequence< OUString > const aServiceNames
633  {
634  "ooo.vba.word.DocumentProperty"
635  };
636  return aServiceNames;
637 }
638 typedef ::cppu::WeakImplHelper< css::container::XIndexAccess
639  ,css::container::XNameAccess
640  ,css::container::XEnumerationAccess
642 
643 typedef std::unordered_map< sal_Int32, uno::Reference< XDocumentProperty > > DocProps;
644 
645 namespace {
646 
647 class DocPropEnumeration : public ::cppu::WeakImplHelper< css::container::XEnumeration >
648 {
649  DocProps mDocProps;
650  DocProps::iterator mIt;
651 public:
652 
653  explicit DocPropEnumeration( const DocProps& rProps ) : mDocProps( rProps ), mIt( mDocProps.begin() ) {}
654  virtual sal_Bool SAL_CALL hasMoreElements( ) override
655  {
656  return mIt != mDocProps.end();
657  }
658  virtual uno::Any SAL_CALL nextElement( ) override
659  {
660  if ( !hasMoreElements() )
661  throw container::NoSuchElementException();
662  return uno::makeAny( mIt++->second );
663  }
664 };
665 
666 }
667 
668 typedef std::unordered_map< OUString, uno::Reference< XDocumentProperty > > DocPropsByName;
669 
670 namespace {
671 
672 class BuiltInPropertiesImpl : public PropertiesImpl_BASE
673 {
674 protected:
675 
676  uno::Reference< frame::XModel > m_xModel;
677 
678  DocProps mDocProps;
679  DocPropsByName mNamedDocProps;
680 
681  public:
682  BuiltInPropertiesImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : m_xModel( xModel )
683  {
684  BuiltInIndexHelper builtIns( m_xModel );
685  for ( sal_Int32 index = word::WdBuiltInProperty::wdPropertyTitle; index <= word::WdBuiltInProperty::wdPropertyCharsWSpaces; ++index )
686  {
687  mDocProps[ index ] = new SwVbaBuiltInDocumentProperty( xParent, xContext, builtIns.getDocPropInfoMap()[ index ] );
688  mNamedDocProps[ mDocProps[ index ]->getName() ] = mDocProps[ index ];
689  }
690  }
691 // XIndexAccess
692  virtual ::sal_Int32 SAL_CALL getCount( ) override
693  {
694  return mDocProps.size();
695  }
696  virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
697  {
698  // correct the correct by the base class for 1 based indices
699  DocProps::iterator it = mDocProps.find( ++Index );
700  if ( it == mDocProps.end() )
701  throw lang::IndexOutOfBoundsException();
702  return uno::makeAny( it->second );
703  }
704  virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
705  {
706  if ( !hasByName( aName ) )
707  throw container::NoSuchElementException();
708  DocPropsByName::iterator it = mNamedDocProps.find( aName );
709  return uno::Any( it->second );
710 
711  }
712  virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
713  {
714  uno::Sequence< OUString > aNames( getCount() );
715  OUString* pName = aNames.getArray();
716  for (const auto& rEntry : mNamedDocProps)
717  {
718  *pName = rEntry.first;
719  ++pName;
720  }
721  return aNames;
722  }
723 
724  virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
725  {
726  DocPropsByName::iterator it = mNamedDocProps.find( aName );
727  if ( it == mNamedDocProps.end() )
728  return false;
729  return true;
730  }
731 // XElementAccess
732  virtual uno::Type SAL_CALL getElementType( ) override
733  {
735  }
736  virtual sal_Bool SAL_CALL hasElements( ) override
737  {
738  return !mDocProps.empty();
739  }
740  virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
741  {
742  return new DocPropEnumeration( mDocProps );
743  }
744 };
745 
746 }
747 
748 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 ) ) )
749 {
750 }
751 
752 uno::Reference< XDocumentProperty > SAL_CALL
753 SwVbaBuiltinDocumentProperties::Add( const OUString& /*Name*/, sal_Bool /*LinkToContent*/, ::sal_Int8 /*Type*/, const uno::Any& /*value*/, const uno::Any& /*LinkSource*/ )
754 {
755  throw uno::RuntimeException( "not supported for Builtin properties" );
756 }
757 
758 // XEnumerationAccess
759 uno::Type SAL_CALL
761 {
763 }
764 
765 uno::Reference< container::XEnumeration > SAL_CALL
767 {
768  uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
769  return xEnumAccess->createEnumeration();
770 }
771 
772 // ScVbaCollectionBaseImpl
773 uno::Any
775 {
776  // pass through
777  return aSource;
778 }
779 
780 // XHelperInterface
781 OUString
783 {
784  return "SwVbaBuiltinDocumentProperties";
785 }
786 
787 uno::Sequence<OUString>
789 {
790  static uno::Sequence< OUString > const aServiceNames
791  {
792  "ooo.vba.word.DocumentProperties"
793  };
794  return aServiceNames;
795 }
796 
797 namespace {
798 
799 class CustomPropertiesImpl : public PropertiesImpl_BASE
800 {
801  uno::Reference< XHelperInterface > m_xParent;
802  uno::Reference< uno::XComponentContext > m_xContext;
803  uno::Reference< frame::XModel > m_xModel;
804  uno::Reference< beans::XPropertySet > mxUserDefinedProp;
805  std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
806 public:
807  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 )
808  {
809  // suck in the document( custom ) properties
810  mpPropGetSetHelper = std::make_shared<CustomPropertyGetSetHelper>( m_xModel );
811  mxUserDefinedProp.set(mpPropGetSetHelper->getUserDefinedProperties(),
812  uno::UNO_SET_THROW);
813  };
814  // XIndexAccess
815  virtual ::sal_Int32 SAL_CALL getCount( ) override
816  {
817  return mxUserDefinedProp->getPropertySetInfo()->getProperties().getLength();
818  }
819 
820  virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
821  {
822  uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
823  if ( Index >= aProps.getLength() )
824  throw lang::IndexOutOfBoundsException();
825  // How to determine type e.g Date? ( com.sun.star.util.DateTime )
826  DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aProps[ Index ].Name, aProps[ Index ].Name, mpPropGetSetHelper );
827  return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
828  }
829 
830  virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
831  {
832  if ( !hasByName( aName ) )
833  throw container::NoSuchElementException();
834 
835  DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aName, aName, mpPropGetSetHelper );
836  return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
837  }
838 
839  virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
840  {
841  uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
842  uno::Sequence< OUString > aNames( aProps.getLength() );
843  std::transform(aProps.begin(), aProps.end(), aNames.begin(),
844  [](const beans::Property& rProp) -> OUString { return rProp.Name; });
845  return aNames;
846  }
847 
848  virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
849  {
850  SAL_INFO("sw.vba", "hasByName(" << aName << ") returns " << mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName ) );
851  return mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName );
852  }
853 
854  // XElementAccess
855  virtual uno::Type SAL_CALL getElementType( ) override
856  {
858  }
859 
860  virtual sal_Bool SAL_CALL hasElements( ) override
861  {
862  return getCount() > 0;
863  }
864 
865  virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
866  {
867  // create a map of properties ( the key doesn't matter )
868  SAL_INFO("sw.vba", "Creating an enumeration");
869  sal_Int32 key = 0;
870  sal_Int32 nElem = getCount();
871  DocProps simpleDocPropSnapShot;
872  for ( ; key < nElem; ++key )
873  simpleDocPropSnapShot[ key ].set( getByIndex( key ), uno::UNO_QUERY_THROW );
874  SAL_INFO("sw.vba", "After creating the enumeration");
875  return new DocPropEnumeration( simpleDocPropSnapShot );
876  }
877 
878  void addProp( const OUString& Name, const uno::Any& Value )
879  {
880  uno::Reference< beans::XPropertyContainer > xContainer( mxUserDefinedProp, uno::UNO_QUERY_THROW );
881  // TODO fixme, perform the necessary Type Value conversions
882  xContainer->addProperty( Name, sal_Int16(128), Value );
883  }
884 
885 };
886 
887 }
888 
889 SwVbaCustomDocumentProperties::SwVbaCustomDocumentProperties( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : SwVbaBuiltinDocumentProperties( xParent, xContext, xModel )
890 {
891  // replace the m_xIndexAccess implementation ( we need a virtual init )
892  m_xIndexAccess.set( new CustomPropertiesImpl( xParent, xContext, xModel ) );
893  m_xNameAccess.set( m_xIndexAccess, uno::UNO_QUERY_THROW );
894 }
895 
896 uno::Reference< XDocumentProperty > SAL_CALL
897 SwVbaCustomDocumentProperties::Add( const OUString& Name, sal_Bool LinkToContent, ::sal_Int8 /*Type*/, const uno::Any& Value, const uno::Any& LinkSource )
898 {
899  CustomPropertiesImpl* pCustomProps = dynamic_cast< CustomPropertiesImpl* > ( m_xIndexAccess.get() );
900  uno::Reference< XDocumentProperty > xDocProp;
901  if ( pCustomProps )
902  {
903  OUString sLinkSource;
904  pCustomProps->addProp( Name, Value );
905 
906  xDocProp.set( m_xNameAccess->getByName( Name ), uno::UNO_QUERY_THROW );
907  xDocProp->setLinkToContent( LinkToContent );
908 
909  if ( LinkSource >>= sLinkSource )
910  xDocProp->setLinkSource( sLinkSource );
911  }
912  return xDocProp;
913 }
914 
915 // XHelperInterface
916 OUString
918 {
919  return "SwVbaCustomDocumentProperties";
920 }
921 
922 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unordered_map< OUString, uno::Reference< XDocumentProperty > > DocPropsByName
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
Type
InheritedHelperInterfaceWeakImpl< ooo::vba::XDocumentProperty > SwVbaDocumentProperty_BASE
Reference< frame::XModel > m_xModel
virtual OUString getServiceImplName() override
sal_uInt16 GetLineCount()
Definition: editsh.cxx:842
bool hasValue()
static sal_Int8 lcl_toMSOPropType(const uno::Type &aType)
virtual css::uno::Reference< ::ooo::vba::XDocumentProperty > SAL_CALL Add(const OUString &Name, sal_Bool LinkToContent,::sal_Int8 Type, const css::uno::Any &Value, const css::uno::Any &LinkSource) override
bool getType(BSTR name, Type &type)
css::uno::Reference< css::container::XIndexAccess > m_xIndexAccess
signed char sal_Int8
virtual css::uno::Type SAL_CALL getElementType() override
css::beans::Optional< css::uno::Any > getValue(OUString const &id)
SwVbaCustomDocumentProperties(const css::uno::Reference< ov::XHelperInterface > &xParent, const css::uno::Reference< css::uno::XComponentContext > &xContext, const css::uno::Reference< css::frame::XModel > &xDocument)
Reference
Sequence< OUString > aServiceNames
OUString Name
::cppu::WeakImplHelper< css::container::XIndexAccess,css::container::XNameAccess,css::container::XEnumerationAccess > PropertiesImpl_BASE
Value
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
virtual css::uno::Sequence< OUString > getServiceNames() override
virtual OUString getServiceImplName() override
virtual css::uno::Reference< ::ooo::vba::XDocumentProperty > SAL_CALL Add(const OUString &Name, sal_Bool LinkToContent,::sal_Int8 Type, const css::uno::Any &Value, const css::uno::Any &LinkSource) override
sal_uInt16 char * pName
#define TOOLS_WARN_EXCEPTION(area, stream)
std::unordered_map< sal_Int32, uno::Reference< XDocumentProperty > > DocProps
css::uno::Reference< css::container::XNameAccess > m_xNameAccess
unsigned char sal_Bool
Object Value
css::uno::Type const & get()
void setValue(Type type, object value)
virtual css::uno::Any createCollectionObject(const css::uno::Any &aSource) override
tuple index
bool setPropertyValue(uno::Sequence< beans::PropertyValue > &aProp, const OUString &aName, const uno::Any &aValue)
virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
std::unordered_map< sal_Int32, DocPropInfo > MSOIndexToOODocPropInfo
SwDocShell * getDocShell(const uno::Reference< frame::XModel > &xModel)
SwVbaBuiltinDocumentProperties(const css::uno::Reference< ov::XHelperInterface > &xParent, const css::uno::Reference< css::uno::XComponentContext > &xContext, const css::uno::Reference< css::frame::XModel > &xDocument)
#define SAL_INFO(area, stream)
OUString aName
SwFEShell * GetFEShell()
For Core - it knows the DocShell but not the WrtShell!
Definition: docsh.cxx:1208
Reference< XComponentContext > m_xContext
struct _ADOIndex Index
void set(css::uno::UnoInterfaceReference const &value)