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 [begin, end] = asNonConstRange(stats);
342  auto pStat = std::find_if(begin, end,
343  [&rPropName](const beans::NamedValue& rStat) { return rPropName == rStat.Name; });
344  if (pStat != end)
345  {
346  pStat->Value = aValue;
347  m_xDocProps->setDocumentStatistics(stats);
348  }
349  }
350 };
351 
352 class DocPropInfo
353 {
354 public:
355  OUString msMSODesc;
356  OUString msOOOPropName;
357  std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
358 
359  static DocPropInfo createDocPropInfo( const OUString& sDesc, const OUString& sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
360  {
361  DocPropInfo aItem;
362  aItem.msMSODesc = sDesc;
363  aItem.msOOOPropName = sPropName;
364  aItem.mpPropGetSetHelper = rHelper;
365  return aItem;
366  }
367 
368  static DocPropInfo createDocPropInfo( const char* sDesc, const char* sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
369  {
370  return createDocPropInfo( OUString::createFromAscii( sDesc ), OUString::createFromAscii( sPropName ), rHelper );
371  }
373  {
374  if ( mpPropGetSetHelper )
375  return mpPropGetSetHelper->getPropertyValue( msOOOPropName );
376  return uno::Any();
377  }
378  void setValue( const uno::Any& rValue )
379  {
380  if ( mpPropGetSetHelper )
381  mpPropGetSetHelper->setPropertyValue( msOOOPropName, rValue );
382  }
383  uno::Reference< beans::XPropertySet > getUserDefinedProperties()
384  {
385  uno::Reference< beans::XPropertySet > xProps;
386  if ( mpPropGetSetHelper )
387  return mpPropGetSetHelper->getUserDefinedProperties();
388  return xProps;
389  }
390 };
391 
392 }
393 
394 typedef std::unordered_map< sal_Int32, DocPropInfo > MSOIndexToOODocPropInfo;
395 
396 namespace {
397 
398 class BuiltInIndexHelper
399 {
400  MSOIndexToOODocPropInfo m_docPropInfoMap;
401 
402 public:
403  explicit BuiltInIndexHelper( const uno::Reference< frame::XModel >& xModel )
404  {
405  auto aStandardHelper = std::make_shared<BuiltinPropertyGetSetHelper>( xModel );
406  auto aUsingStatsHelper = std::make_shared<StatisticPropertyGetSetHelper>( xModel );
407 
408  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTitle ] = DocPropInfo::createDocPropInfo( "Title", "Title", aStandardHelper );
409  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySubject ] = DocPropInfo::createDocPropInfo( "Subject", "Subject", aStandardHelper );
410  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAuthor ] = DocPropInfo::createDocPropInfo( "Author", "Author", aStandardHelper );
411  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyKeywords ] = DocPropInfo::createDocPropInfo( "Keywords", "Keywords", aStandardHelper );
412  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyComments ] = DocPropInfo::createDocPropInfo( "Comments", "Description", aStandardHelper );
413  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTemplate ] = DocPropInfo::createDocPropInfo( "Template", "Template", aStandardHelper );
414  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLastAuthor ] = DocPropInfo::createDocPropInfo( "Last author", "ModifiedBy", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
415  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyRevision ] = DocPropInfo::createDocPropInfo( "Revision number", "EditingCycles", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
416  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAppName ] = DocPropInfo::createDocPropInfo( "Application name", "Generator", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
417  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastPrinted ] = DocPropInfo::createDocPropInfo( "Last print date", "PrintDate", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
418  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeCreated ] = DocPropInfo::createDocPropInfo( "Creation date", "CreationDate", aStandardHelper );
419  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastSaved ] = DocPropInfo::createDocPropInfo( "Last save time", "ModifyDate", aStandardHelper );
420  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyVBATotalEdit ] = DocPropInfo::createDocPropInfo( "Total editing time", "EditingDuration", aStandardHelper ); // Not sure if this is correct
421  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyPages ] = DocPropInfo::createDocPropInfo( "Number of pages", "PageCount", aUsingStatsHelper ); // special handling required ?
422  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyWords ] = DocPropInfo::createDocPropInfo( "Number of words", "WordCount", aUsingStatsHelper ); // special handling require ?
423  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharacters ] = DocPropInfo::createDocPropInfo( "Number of characters", "CharacterCount", aUsingStatsHelper ); // special handling required ?
424  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySecurity ] = DocPropInfo::createDocPropInfo( "Security", "", aStandardHelper ); // doesn't seem to exist
425  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCategory ] = DocPropInfo::createDocPropInfo( "Category", "Category", aStandardHelper ); // hacked in
426  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyFormat ] = DocPropInfo::createDocPropInfo( "Format", "", aStandardHelper ); // doesn't seem to exist
427  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyManager ] = DocPropInfo::createDocPropInfo( "Manager", "Manager", aStandardHelper ); // hacked in
428  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCompany ] = DocPropInfo::createDocPropInfo( "Company", "Company", aStandardHelper ); // hacked in
429  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 )
430  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLines ] = DocPropInfo::createDocPropInfo( "Number of lines", "LineCount", aUsingStatsHelper ); // special handling
431  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyParas ] = DocPropInfo::createDocPropInfo( "Number of paragraphs", "ParagraphCount", aUsingStatsHelper ); // special handling
432  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySlides ] = DocPropInfo::createDocPropInfo( "Number of slides", "" , aStandardHelper ); // doesn't seem to exist
433  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyNotes ] = DocPropInfo::createDocPropInfo( "Number of notes", "", aStandardHelper ); // doesn't seem to exist
434  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHiddenSlides ] = DocPropInfo::createDocPropInfo("Number of hidden Slides", "", aStandardHelper ); // doesn't seem to exist
435  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyMMClips ] = DocPropInfo::createDocPropInfo( "Number of multimedia clips", "", aStandardHelper ); // doesn't seem to exist
436  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHyperlinkBase ] = DocPropInfo::createDocPropInfo( "Hyperlink base", "AutoloadURL", aStandardHelper );
437  m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharsWSpaces ] = DocPropInfo::createDocPropInfo( "Number of characters (with spaces)", "", aStandardHelper ); // doesn't seem to be supported
438  }
439 
440  MSOIndexToOODocPropInfo& getDocPropInfoMap() { return m_docPropInfoMap; }
441 };
442 
443 }
444 
446 
447 namespace {
448 
449 class SwVbaBuiltInDocumentProperty : public SwVbaDocumentProperty_BASE
450 {
451 protected:
452  DocPropInfo mPropInfo;
453 public:
454  SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo );
455  // XDocumentProperty
456  virtual void SAL_CALL Delete( ) override;
457  virtual OUString SAL_CALL getName( ) override;
458  virtual void SAL_CALL setName( const OUString& Name ) override;
459  virtual ::sal_Int8 SAL_CALL getType( ) override;
460  virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
461  virtual sal_Bool SAL_CALL getLinkToContent( ) override;
462  virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
463  virtual uno::Any SAL_CALL getValue( ) override;
464  virtual void SAL_CALL setValue( const uno::Any& Value ) override;
465  virtual OUString SAL_CALL getLinkSource( ) override;
466  virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
467  //XDefaultProperty
468  virtual OUString SAL_CALL getDefaultPropertyName( ) override { return "Value"; }
469  // XHelperInterface
470  virtual OUString getServiceImplName() override;
471  virtual uno::Sequence<OUString> getServiceNames() override;
472 };
473 
474 class SwVbaCustomDocumentProperty : public SwVbaBuiltInDocumentProperty
475 {
476 public:
477 
478  SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo );
479 
480  virtual sal_Bool SAL_CALL getLinkToContent( ) override;
481  virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
482 
483  virtual OUString SAL_CALL getLinkSource( ) override;
484  virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
485  virtual void SAL_CALL Delete( ) override;
486  virtual void SAL_CALL setName( const OUString& Name ) override;
487  virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
488 
489 };
490 
491 }
492 
493 SwVbaCustomDocumentProperty::SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaBuiltInDocumentProperty( xParent, xContext, rInfo )
494 {
495 }
496 
497 sal_Bool
498 SwVbaCustomDocumentProperty::getLinkToContent( )
499 {
500  // #FIXME we need to store the link content somewhere
501  return false;
502 }
503 
504 void
505 SwVbaCustomDocumentProperty::setLinkToContent( sal_Bool /*bLinkContent*/ )
506 {
507 }
508 
509 OUString
510 SwVbaCustomDocumentProperty::getLinkSource( )
511 {
512  // #FIXME we need to store the link content somewhere
513  return OUString();
514 }
515 
516 void
517 SwVbaCustomDocumentProperty::setLinkSource( const OUString& /*rsLinkContent*/ )
518 {
519  // #FIXME we need to store the link source somewhere
520 }
521 
522 void SAL_CALL
523 SwVbaCustomDocumentProperty::setName( const OUString& /*Name*/ )
524 {
525  // setName on existing property ?
526  // #FIXME
527  // do we need to delete existing property and create a new one?
528 }
529 
530 void SAL_CALL
531 SwVbaCustomDocumentProperty::setType( ::sal_Int8 /*Type*/ )
532 {
533  // setType, do we need to do a conversion?
534  // #FIXME the underlying value needs to be changed to the new type
535 }
536 
537 void SAL_CALL
538 SwVbaCustomDocumentProperty::Delete( )
539 {
540  uno::Reference< beans::XPropertyContainer > xContainer(
541  mPropInfo.getUserDefinedProperties(), uno::UNO_QUERY_THROW);
542  xContainer->removeProperty( getName() );
543 }
544 
545 SwVbaBuiltInDocumentProperty::SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaDocumentProperty_BASE( xParent, xContext ), mPropInfo( rInfo )
546 {
547 }
548 
549 void SAL_CALL
550 SwVbaBuiltInDocumentProperty::Delete( )
551 {
552  // not valid for Builtin
553  throw uno::RuntimeException();
554 }
555 
556 OUString SAL_CALL
557 SwVbaBuiltInDocumentProperty::getName( )
558 {
559  return mPropInfo.msMSODesc;
560 }
561 
562 void SAL_CALL
563 SwVbaBuiltInDocumentProperty::setName( const OUString& )
564 {
565  // not valid for Builtin
566  throw uno::RuntimeException();
567 }
568 
569 ::sal_Int8 SAL_CALL
570 SwVbaBuiltInDocumentProperty::getType( )
571 {
572  return lcl_toMSOPropType( getValue().getValueType() );
573 }
574 
575 void SAL_CALL
576 SwVbaBuiltInDocumentProperty::setType( ::sal_Int8 /*Type*/ )
577 {
578  // not valid for Builtin
579  throw uno::RuntimeException();
580 }
581 
582 sal_Bool SAL_CALL
583 SwVbaBuiltInDocumentProperty::getLinkToContent( )
584 {
585  return false; // built-in always false
586 }
587 
588 void SAL_CALL
589 SwVbaBuiltInDocumentProperty::setLinkToContent( sal_Bool /*LinkToContent*/ )
590 {
591  // not valid for Builtin
592  throw uno::RuntimeException();
593 }
594 
595 uno::Any SAL_CALL
596 SwVbaBuiltInDocumentProperty::getValue( )
597 {
598  uno::Any aRet = mPropInfo.getValue();
599  if ( !aRet.hasValue() )
600  throw uno::RuntimeException();
601  return aRet;
602 }
603 
604 void SAL_CALL
605 SwVbaBuiltInDocumentProperty::setValue( const uno::Any& Value )
606 {
607  mPropInfo.setValue( Value );
608 }
609 
610 OUString SAL_CALL
611 SwVbaBuiltInDocumentProperty::getLinkSource( )
612 {
613  // not valid for Builtin
614  throw uno::RuntimeException();
615 }
616 
617 void SAL_CALL
618 SwVbaBuiltInDocumentProperty::setLinkSource( const OUString& /*LinkSource*/ )
619 {
620  // not valid for Builtin
621  throw uno::RuntimeException();
622 }
623 
624 OUString
625 SwVbaBuiltInDocumentProperty::getServiceImplName()
626 {
627  return "SwVbaBuiltinDocumentProperty";
628 }
629 
630 uno::Sequence<OUString>
631 SwVbaBuiltInDocumentProperty::getServiceNames()
632 {
633  static uno::Sequence< OUString > const aServiceNames
634  {
635  "ooo.vba.word.DocumentProperty"
636  };
637  return aServiceNames;
638 }
639 typedef ::cppu::WeakImplHelper< css::container::XIndexAccess
640  ,css::container::XNameAccess
641  ,css::container::XEnumerationAccess
643 
644 typedef std::unordered_map< sal_Int32, uno::Reference< XDocumentProperty > > DocProps;
645 
646 namespace {
647 
648 class DocPropEnumeration : public ::cppu::WeakImplHelper< css::container::XEnumeration >
649 {
650  DocProps mDocProps;
651  DocProps::iterator mIt;
652 public:
653 
654  explicit DocPropEnumeration( DocProps&& rProps ) : mDocProps( std::move(rProps) ), mIt( mDocProps.begin() ) {}
655  virtual sal_Bool SAL_CALL hasMoreElements( ) override
656  {
657  return mIt != mDocProps.end();
658  }
659  virtual uno::Any SAL_CALL nextElement( ) override
660  {
661  if ( !hasMoreElements() )
662  throw container::NoSuchElementException();
663  return uno::makeAny( mIt++->second );
664  }
665 };
666 
667 }
668 
669 typedef std::unordered_map< OUString, uno::Reference< XDocumentProperty > > DocPropsByName;
670 
671 namespace {
672 
673 class BuiltInPropertiesImpl : public PropertiesImpl_BASE
674 {
675 protected:
676 
677  uno::Reference< frame::XModel > m_xModel;
678 
679  DocProps mDocProps;
680  DocPropsByName mNamedDocProps;
681 
682  public:
683  BuiltInPropertiesImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : m_xModel( xModel )
684  {
685  BuiltInIndexHelper builtIns( m_xModel );
686  for ( sal_Int32 index = word::WdBuiltInProperty::wdPropertyTitle; index <= word::WdBuiltInProperty::wdPropertyCharsWSpaces; ++index )
687  {
688  mDocProps[ index ] = new SwVbaBuiltInDocumentProperty( xParent, xContext, builtIns.getDocPropInfoMap()[ index ] );
689  mNamedDocProps[ mDocProps[ index ]->getName() ] = mDocProps[ index ];
690  }
691  }
692 // XIndexAccess
693  virtual ::sal_Int32 SAL_CALL getCount( ) override
694  {
695  return mDocProps.size();
696  }
697  virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
698  {
699  // correct the correct by the base class for 1 based indices
700  DocProps::iterator it = mDocProps.find( ++Index );
701  if ( it == mDocProps.end() )
702  throw lang::IndexOutOfBoundsException();
703  return uno::makeAny( it->second );
704  }
705  virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
706  {
707  if ( !hasByName( aName ) )
708  throw container::NoSuchElementException();
709  DocPropsByName::iterator it = mNamedDocProps.find( aName );
710  return uno::Any( it->second );
711 
712  }
713  virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
714  {
715  uno::Sequence< OUString > aNames( getCount() );
716  OUString* pName = aNames.getArray();
717  for (const auto& rEntry : mNamedDocProps)
718  {
719  *pName = rEntry.first;
720  ++pName;
721  }
722  return aNames;
723  }
724 
725  virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
726  {
727  DocPropsByName::iterator it = mNamedDocProps.find( aName );
728  if ( it == mNamedDocProps.end() )
729  return false;
730  return true;
731  }
732 // XElementAccess
733  virtual uno::Type SAL_CALL getElementType( ) override
734  {
736  }
737  virtual sal_Bool SAL_CALL hasElements( ) override
738  {
739  return !mDocProps.empty();
740  }
741  virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
742  {
743  return new DocPropEnumeration( std::unordered_map(mDocProps) );
744  }
745 };
746 
747 }
748 
749 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 ) ) )
750 {
751 }
752 
753 uno::Reference< XDocumentProperty > SAL_CALL
754 SwVbaBuiltinDocumentProperties::Add( const OUString& /*Name*/, sal_Bool /*LinkToContent*/, ::sal_Int8 /*Type*/, const uno::Any& /*value*/, const uno::Any& /*LinkSource*/ )
755 {
756  throw uno::RuntimeException( "not supported for Builtin properties" );
757 }
758 
759 // XEnumerationAccess
760 uno::Type SAL_CALL
762 {
764 }
765 
766 uno::Reference< container::XEnumeration > SAL_CALL
768 {
769  uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
770  return xEnumAccess->createEnumeration();
771 }
772 
773 // ScVbaCollectionBaseImpl
774 uno::Any
776 {
777  // pass through
778  return aSource;
779 }
780 
781 // XHelperInterface
782 OUString
784 {
785  return "SwVbaBuiltinDocumentProperties";
786 }
787 
788 uno::Sequence<OUString>
790 {
791  static uno::Sequence< OUString > const aServiceNames
792  {
793  "ooo.vba.word.DocumentProperties"
794  };
795  return aServiceNames;
796 }
797 
798 namespace {
799 
800 class CustomPropertiesImpl : public PropertiesImpl_BASE
801 {
802  uno::Reference< XHelperInterface > m_xParent;
803  uno::Reference< uno::XComponentContext > m_xContext;
804  uno::Reference< frame::XModel > m_xModel;
805  uno::Reference< beans::XPropertySet > mxUserDefinedProp;
806  std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
807 public:
808  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 )
809  {
810  // suck in the document( custom ) properties
811  mpPropGetSetHelper = std::make_shared<CustomPropertyGetSetHelper>( m_xModel );
812  mxUserDefinedProp.set(mpPropGetSetHelper->getUserDefinedProperties(),
813  uno::UNO_SET_THROW);
814  };
815  // XIndexAccess
816  virtual ::sal_Int32 SAL_CALL getCount( ) override
817  {
818  return mxUserDefinedProp->getPropertySetInfo()->getProperties().getLength();
819  }
820 
821  virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
822  {
823  uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
824  if ( Index >= aProps.getLength() )
825  throw lang::IndexOutOfBoundsException();
826  // How to determine type e.g Date? ( com.sun.star.util.DateTime )
827  DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aProps[ Index ].Name, aProps[ Index ].Name, mpPropGetSetHelper );
828  return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
829  }
830 
831  virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
832  {
833  if ( !hasByName( aName ) )
834  throw container::NoSuchElementException();
835 
836  DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aName, aName, mpPropGetSetHelper );
837  return uno::makeAny( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
838  }
839 
840  virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
841  {
842  const uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
843  uno::Sequence< OUString > aNames( aProps.getLength() );
844  std::transform(aProps.begin(), aProps.end(), aNames.getArray(),
845  [](const beans::Property& rProp) -> OUString { return rProp.Name; });
846  return aNames;
847  }
848 
849  virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
850  {
851  SAL_INFO("sw.vba", "hasByName(" << aName << ") returns " << mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName ) );
852  return mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName );
853  }
854 
855  // XElementAccess
856  virtual uno::Type SAL_CALL getElementType( ) override
857  {
859  }
860 
861  virtual sal_Bool SAL_CALL hasElements( ) override
862  {
863  return getCount() > 0;
864  }
865 
866  virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
867  {
868  // create a map of properties ( the key doesn't matter )
869  SAL_INFO("sw.vba", "Creating an enumeration");
870  sal_Int32 key = 0;
871  sal_Int32 nElem = getCount();
872  DocProps simpleDocPropSnapShot;
873  for ( ; key < nElem; ++key )
874  simpleDocPropSnapShot[ key ].set( getByIndex( key ), uno::UNO_QUERY_THROW );
875  SAL_INFO("sw.vba", "After creating the enumeration");
876  return new DocPropEnumeration( std::move(simpleDocPropSnapShot) );
877  }
878 
879  void addProp( const OUString& Name, const uno::Any& Value )
880  {
881  uno::Reference< beans::XPropertyContainer > xContainer( mxUserDefinedProp, uno::UNO_QUERY_THROW );
882  // TODO fixme, perform the necessary Type Value conversions
883  xContainer->addProperty( Name, sal_Int16(128), Value );
884  }
885 
886 };
887 
888 }
889 
890 SwVbaCustomDocumentProperties::SwVbaCustomDocumentProperties( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : SwVbaBuiltinDocumentProperties( xParent, xContext, xModel )
891 {
892  // replace the m_xIndexAccess implementation ( we need a virtual init )
893  m_xIndexAccess.set( new CustomPropertiesImpl( xParent, xContext, xModel ) );
894  m_xNameAccess.set( m_xIndexAccess, uno::UNO_QUERY_THROW );
895 }
896 
897 uno::Reference< XDocumentProperty > SAL_CALL
898 SwVbaCustomDocumentProperties::Add( const OUString& Name, sal_Bool LinkToContent, ::sal_Int8 /*Type*/, const uno::Any& Value, const uno::Any& LinkSource )
899 {
900  CustomPropertiesImpl* pCustomProps = dynamic_cast< CustomPropertiesImpl* > ( m_xIndexAccess.get() );
901  uno::Reference< XDocumentProperty > xDocProp;
902  if ( pCustomProps )
903  {
904  OUString sLinkSource;
905  pCustomProps->addProp( Name, Value );
906 
907  xDocProp.set( m_xNameAccess->getByName( Name ), uno::UNO_QUERY_THROW );
908  xDocProp->setLinkToContent( LinkToContent );
909 
910  if ( LinkSource >>= sLinkSource )
911  xDocProp->setLinkSource( sLinkSource );
912  }
913  return xDocProp;
914 }
915 
916 // XHelperInterface
917 OUString
919 {
920  return "SwVbaCustomDocumentProperties";
921 }
922 
923 /* 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:845
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
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
exports com.sun.star. container
Value
enumrange< T >::Iterator begin(enumrange< T >)
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
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
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
enumrange< T >::Iterator end(enumrange< T >)
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:1229
Reference< XComponentContext > m_xContext
struct _ADOIndex Index
void set(css::uno::UnoInterfaceReference const &value)