ITEM: Refactor ItemType
[LibreOffice.git] / sw / source / ui / vba / vbadocumentproperties.cxx
blob05471640e1af0322dff0631569935ab174fd50e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "vbadocumentproperties.hxx"
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 <comphelper/diagnose_ex.hxx>
29 #include <memory>
30 #include "wordvbahelper.hxx"
31 #include <fesh.hxx>
32 #include <docsh.hxx>
33 #include <unotxdoc.hxx>
34 #include <utility>
36 using namespace ::ooo::vba;
37 using namespace css;
39 /// @throws lang::IllegalArgumentException
40 static sal_Int8 lcl_toMSOPropType( const uno::Type& aType )
42 sal_Int16 msoType = office::MsoDocProperties::msoPropertyTypeString;
44 switch ( aType.getTypeClass() )
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();
64 return msoType;
67 namespace {
69 class PropertGetSetHelper
71 protected:
72 rtl::Reference< SwXTextDocument > m_xModel;
73 uno::Reference<document::XDocumentProperties> m_xDocProps;
74 public:
75 explicit PropertGetSetHelper( rtl::Reference< SwXTextDocument > xModel ) : m_xModel(std::move( xModel ))
77 m_xDocProps.set(m_xModel->getDocumentProperties(), uno::UNO_SET_THROW);
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);
89 class BuiltinPropertyGetSetHelper : public PropertGetSetHelper
91 public:
92 explicit BuiltinPropertyGetSetHelper( const rtl::Reference< SwXTextDocument >& xModel ) :PropertGetSetHelper( xModel )
95 virtual uno::Any getPropertyValue( const OUString& rPropName ) override
97 if ( rPropName == "EditingDuration" )
99 sal_Int32 const nSecs = m_xDocProps->getEditingDuration();
100 return uno::Any( nSecs/60 ); // minutes
102 else if ("Title" == rPropName)
104 return uno::Any(m_xDocProps->getTitle());
106 else if ("Subject" == rPropName)
108 return uno::Any(m_xDocProps->getSubject());
110 else if ("Author" == rPropName)
112 return uno::Any(m_xDocProps->getAuthor());
114 else if ("Keywords" == rPropName)
116 return uno::Any(m_xDocProps->getKeywords());
118 else if ("Description" == rPropName)
120 return uno::Any(m_xDocProps->getDescription());
122 else if ("Template" == rPropName)
124 return uno::Any(m_xDocProps->getTemplateName());
126 else if ("ModifiedBy" == rPropName)
128 return uno::Any(m_xDocProps->getModifiedBy());
130 else if ("Generator" == rPropName)
132 return uno::Any(m_xDocProps->getGenerator());
134 else if ("PrintDate" == rPropName)
136 return uno::Any(m_xDocProps->getPrintDate());
138 else if ("CreationDate" == rPropName)
140 return uno::Any(m_xDocProps->getCreationDate());
142 else if ("ModifyDate" == rPropName)
144 return uno::Any(m_xDocProps->getModificationDate());
146 else if ("AutoloadURL" == rPropName)
148 return uno::Any(m_xDocProps->getAutoloadURL());
150 else
152 // fall back to user-defined properties
153 return getUserDefinedProperties()->getPropertyValue(rPropName);
156 virtual void setPropertyValue( const OUString& rPropName, const uno::Any& aValue ) override
158 if ("EditingDuration" == rPropName)
160 sal_Int32 nMins = 0;
161 if (aValue >>= nMins)
163 m_xDocProps->setEditingDuration(nMins * 60); // convert minutes
166 else if ("Title" == rPropName)
168 OUString str;
169 if (aValue >>= str)
171 m_xDocProps->setTitle(str);
174 else if ("Subject" == rPropName)
176 OUString str;
177 if (aValue >>= str)
179 m_xDocProps->setSubject(str);
182 else if ("Author" == rPropName)
184 OUString str;
185 if (aValue >>= str)
187 m_xDocProps->setAuthor(str);
190 else if ("Keywords" == rPropName)
192 uno::Sequence<OUString> keywords;
193 if (aValue >>= keywords)
195 m_xDocProps->setKeywords(keywords);
198 else if ("Description" == rPropName)
200 OUString str;
201 if (aValue >>= str)
203 m_xDocProps->setDescription(str);
206 else if ("Template" == rPropName)
208 OUString str;
209 if (aValue >>= str)
211 m_xDocProps->setTemplateName(str);
214 else if ("ModifiedBy" == rPropName)
216 OUString str;
217 if (aValue >>= str)
219 m_xDocProps->setModifiedBy(str);
222 else if ("Generator" == rPropName)
224 OUString str;
225 if (aValue >>= str)
227 return m_xDocProps->setGenerator(str);
230 else if ("PrintDate" == rPropName)
232 util::DateTime dt;
233 if (aValue >>= dt)
235 m_xDocProps->setPrintDate(dt);
238 else if ("CreationDate" == rPropName)
240 util::DateTime dt;
241 if (aValue >>= dt)
243 m_xDocProps->setCreationDate(dt);
246 else if ("ModifyDate" == rPropName)
248 util::DateTime dt;
249 if (aValue >>= dt)
251 m_xDocProps->setModificationDate(dt);
254 else if ("AutoloadURL" == rPropName)
256 OUString str;
257 if (aValue >>= str)
259 m_xDocProps->setAutoloadURL(str);
262 else
264 // fall back to user-defined properties
265 getUserDefinedProperties()->setPropertyValue(rPropName, aValue);
270 class CustomPropertyGetSetHelper : public BuiltinPropertyGetSetHelper
272 public:
273 explicit CustomPropertyGetSetHelper( const rtl::Reference< SwXTextDocument >& xModel ) :BuiltinPropertyGetSetHelper( xModel )
276 virtual uno::Any getPropertyValue( const OUString& rPropName ) override
278 return getUserDefinedProperties()->getPropertyValue(rPropName);
280 virtual void setPropertyValue(
281 const OUString& rPropName, const uno::Any& rValue) override
283 return getUserDefinedProperties()->setPropertyValue(rPropName, rValue);
287 class StatisticPropertyGetSetHelper : public PropertGetSetHelper
289 SwDocShell* mpDocShell;
290 public:
291 explicit StatisticPropertyGetSetHelper( const rtl::Reference< SwXTextDocument >& xModel ) :PropertGetSetHelper( xModel ) , mpDocShell( nullptr )
293 mpDocShell = m_xModel->GetDocShell();
295 virtual uno::Any getPropertyValue( const OUString& rPropName ) override
299 // Characters, ParagraphCount & WordCount are available from
300 // the model ( and additionally these also update the statics object )
301 return m_xModel->getPropertyValue( rPropName );
303 catch (const uno::Exception&)
305 TOOLS_WARN_EXCEPTION("sw.vba", "");
307 uno::Any aReturn;
308 if ( rPropName == "LineCount" ) // special processing needed
310 if ( mpDocShell )
312 if (SwFEShell* pFEShell = mpDocShell->GetFEShell())
313 aReturn <<= pFEShell->GetLineCount();
316 else
318 uno::Sequence< beans::NamedValue > const stats(
319 m_xDocProps->getDocumentStatistics());
321 auto pStat = std::find_if(stats.begin(), stats.end(),
322 [&rPropName](const beans::NamedValue& rStat) { return rPropName == rStat.Name; });
323 if (pStat == stats.end())
324 throw uno::RuntimeException(); // bad Property
326 aReturn = pStat->Value;
328 return aReturn;
331 virtual void setPropertyValue( const OUString& rPropName, const uno::Any& aValue ) override
333 uno::Sequence< beans::NamedValue > stats(
334 m_xDocProps->getDocumentStatistics());
336 auto [begin, end] = asNonConstRange(stats);
337 auto pStat = std::find_if(begin, end,
338 [&rPropName](const beans::NamedValue& rStat) { return rPropName == rStat.Name; });
339 if (pStat != end)
341 pStat->Value = aValue;
342 m_xDocProps->setDocumentStatistics(stats);
347 class DocPropInfo
349 public:
350 OUString msMSODesc;
351 OUString msOOOPropName;
352 std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
354 static DocPropInfo createDocPropInfo( const OUString& sDesc, const OUString& sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
356 DocPropInfo aItem;
357 aItem.msMSODesc = sDesc;
358 aItem.msOOOPropName = sPropName;
359 aItem.mpPropGetSetHelper = rHelper;
360 return aItem;
363 static DocPropInfo createDocPropInfo( const char* sDesc, const char* sPropName, std::shared_ptr< PropertGetSetHelper > const & rHelper )
365 return createDocPropInfo( OUString::createFromAscii( sDesc ), OUString::createFromAscii( sPropName ), rHelper );
367 uno::Any getValue()
369 if ( mpPropGetSetHelper )
370 return mpPropGetSetHelper->getPropertyValue( msOOOPropName );
371 return uno::Any();
373 void setValue( const uno::Any& rValue )
375 if ( mpPropGetSetHelper )
376 mpPropGetSetHelper->setPropertyValue( msOOOPropName, rValue );
378 uno::Reference< beans::XPropertySet > getUserDefinedProperties()
380 uno::Reference< beans::XPropertySet > xProps;
381 if ( mpPropGetSetHelper )
382 return mpPropGetSetHelper->getUserDefinedProperties();
383 return xProps;
389 typedef std::unordered_map< sal_Int32, DocPropInfo > MSOIndexToOODocPropInfo;
391 namespace {
393 class BuiltInIndexHelper
395 MSOIndexToOODocPropInfo m_docPropInfoMap;
397 public:
398 explicit BuiltInIndexHelper( const rtl::Reference< SwXTextDocument >& xModel )
400 auto aStandardHelper = std::make_shared<BuiltinPropertyGetSetHelper>( xModel );
401 auto aUsingStatsHelper = std::make_shared<StatisticPropertyGetSetHelper>( xModel );
403 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTitle ] = DocPropInfo::createDocPropInfo( "Title", "Title", aStandardHelper );
404 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySubject ] = DocPropInfo::createDocPropInfo( "Subject", "Subject", aStandardHelper );
405 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAuthor ] = DocPropInfo::createDocPropInfo( "Author", "Author", aStandardHelper );
406 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyKeywords ] = DocPropInfo::createDocPropInfo( "Keywords", "Keywords", aStandardHelper );
407 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyComments ] = DocPropInfo::createDocPropInfo( "Comments", "Description", aStandardHelper );
408 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTemplate ] = DocPropInfo::createDocPropInfo( "Template", "Template", aStandardHelper );
409 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLastAuthor ] = DocPropInfo::createDocPropInfo( "Last author", "ModifiedBy", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
410 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyRevision ] = DocPropInfo::createDocPropInfo( "Revision number", "EditingCycles", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
411 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyAppName ] = DocPropInfo::createDocPropInfo( "Application name", "Generator", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
412 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastPrinted ] = DocPropInfo::createDocPropInfo( "Last print date", "PrintDate", aStandardHelper ); // doesn't seem to exist - throw or return nothing ?
413 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeCreated ] = DocPropInfo::createDocPropInfo( "Creation date", "CreationDate", aStandardHelper );
414 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyTimeLastSaved ] = DocPropInfo::createDocPropInfo( "Last save time", "ModifyDate", aStandardHelper );
415 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyVBATotalEdit ] = DocPropInfo::createDocPropInfo( "Total editing time", "EditingDuration", aStandardHelper ); // Not sure if this is correct
416 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyPages ] = DocPropInfo::createDocPropInfo( "Number of pages", "PageCount", aUsingStatsHelper ); // special handling required ?
417 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyWords ] = DocPropInfo::createDocPropInfo( "Number of words", "WordCount", aUsingStatsHelper ); // special handling require ?
418 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharacters ] = DocPropInfo::createDocPropInfo( "Number of characters", "CharacterCount", aUsingStatsHelper ); // special handling required ?
419 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySecurity ] = DocPropInfo::createDocPropInfo( "Security", "", aStandardHelper ); // doesn't seem to exist
420 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCategory ] = DocPropInfo::createDocPropInfo( "Category", "Category", aStandardHelper ); // hacked in
421 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyFormat ] = DocPropInfo::createDocPropInfo( "Format", "", aStandardHelper ); // doesn't seem to exist
422 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyManager ] = DocPropInfo::createDocPropInfo( "Manager", "Manager", aStandardHelper ); // hacked in
423 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCompany ] = DocPropInfo::createDocPropInfo( "Company", "Company", aStandardHelper ); // hacked in
424 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 )
425 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyLines ] = DocPropInfo::createDocPropInfo( "Number of lines", "LineCount", aUsingStatsHelper ); // special handling
426 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyParas ] = DocPropInfo::createDocPropInfo( "Number of paragraphs", "ParagraphCount", aUsingStatsHelper ); // special handling
427 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertySlides ] = DocPropInfo::createDocPropInfo( "Number of slides", "" , aStandardHelper ); // doesn't seem to exist
428 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyNotes ] = DocPropInfo::createDocPropInfo( "Number of notes", "", aStandardHelper ); // doesn't seem to exist
429 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHiddenSlides ] = DocPropInfo::createDocPropInfo("Number of hidden Slides", "", aStandardHelper ); // doesn't seem to exist
430 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyMMClips ] = DocPropInfo::createDocPropInfo( "Number of multimedia clips", "", aStandardHelper ); // doesn't seem to exist
431 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyHyperlinkBase ] = DocPropInfo::createDocPropInfo( "Hyperlink base", "AutoloadURL", aStandardHelper );
432 m_docPropInfoMap[ word::WdBuiltInProperty::wdPropertyCharsWSpaces ] = DocPropInfo::createDocPropInfo( "Number of characters (with spaces)", "", aStandardHelper ); // doesn't seem to be supported
435 MSOIndexToOODocPropInfo& getDocPropInfoMap() { return m_docPropInfoMap; }
440 typedef InheritedHelperInterfaceWeakImpl< ooo::vba::XDocumentProperty > SwVbaDocumentProperty_BASE;
442 namespace {
444 class SwVbaBuiltInDocumentProperty : public SwVbaDocumentProperty_BASE
446 protected:
447 DocPropInfo mPropInfo;
448 public:
449 SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, DocPropInfo rInfo );
450 // XDocumentProperty
451 virtual void SAL_CALL Delete( ) override;
452 virtual OUString SAL_CALL getName( ) override;
453 virtual void SAL_CALL setName( const OUString& Name ) override;
454 virtual ::sal_Int8 SAL_CALL getType( ) override;
455 virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
456 virtual sal_Bool SAL_CALL getLinkToContent( ) override;
457 virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
458 virtual uno::Any SAL_CALL getValue( ) override;
459 virtual void SAL_CALL setValue( const uno::Any& Value ) override;
460 virtual OUString SAL_CALL getLinkSource( ) override;
461 virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
462 //XDefaultProperty
463 virtual OUString SAL_CALL getDefaultPropertyName( ) override { return u"Value"_ustr; }
464 // XHelperInterface
465 virtual OUString getServiceImplName() override;
466 virtual uno::Sequence<OUString> getServiceNames() override;
469 class SwVbaCustomDocumentProperty : public SwVbaBuiltInDocumentProperty
471 public:
473 SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo );
475 virtual sal_Bool SAL_CALL getLinkToContent( ) override;
476 virtual void SAL_CALL setLinkToContent( sal_Bool LinkToContent ) override;
478 virtual OUString SAL_CALL getLinkSource( ) override;
479 virtual void SAL_CALL setLinkSource( const OUString& LinkSource ) override;
480 virtual void SAL_CALL Delete( ) override;
481 virtual void SAL_CALL setName( const OUString& Name ) override;
482 virtual void SAL_CALL setType( ::sal_Int8 Type ) override;
488 SwVbaCustomDocumentProperty::SwVbaCustomDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const DocPropInfo& rInfo ) : SwVbaBuiltInDocumentProperty( xParent, xContext, rInfo )
492 sal_Bool
493 SwVbaCustomDocumentProperty::getLinkToContent( )
495 // #FIXME we need to store the link content somewhere
496 return false;
499 void
500 SwVbaCustomDocumentProperty::setLinkToContent( sal_Bool /*bLinkContent*/ )
504 OUString
505 SwVbaCustomDocumentProperty::getLinkSource( )
507 // #FIXME we need to store the link content somewhere
508 return OUString();
511 void
512 SwVbaCustomDocumentProperty::setLinkSource( const OUString& /*rsLinkContent*/ )
514 // #FIXME we need to store the link source somewhere
517 void SAL_CALL
518 SwVbaCustomDocumentProperty::setName( const OUString& /*Name*/ )
520 // setName on existing property ?
521 // #FIXME
522 // do we need to delete existing property and create a new one?
525 void SAL_CALL
526 SwVbaCustomDocumentProperty::setType( ::sal_Int8 /*Type*/ )
528 // setType, do we need to do a conversion?
529 // #FIXME the underlying value needs to be changed to the new type
532 void SAL_CALL
533 SwVbaCustomDocumentProperty::Delete( )
535 uno::Reference< beans::XPropertyContainer > xContainer(
536 mPropInfo.getUserDefinedProperties(), uno::UNO_QUERY_THROW);
537 xContainer->removeProperty( getName() );
540 SwVbaBuiltInDocumentProperty::SwVbaBuiltInDocumentProperty( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, DocPropInfo rInfo ) : SwVbaDocumentProperty_BASE( xParent, xContext ), mPropInfo(std::move( rInfo ))
544 void SAL_CALL
545 SwVbaBuiltInDocumentProperty::Delete( )
547 // not valid for Builtin
548 throw uno::RuntimeException();
551 OUString SAL_CALL
552 SwVbaBuiltInDocumentProperty::getName( )
554 return mPropInfo.msMSODesc;
557 void SAL_CALL
558 SwVbaBuiltInDocumentProperty::setName( const OUString& )
560 // not valid for Builtin
561 throw uno::RuntimeException();
564 ::sal_Int8 SAL_CALL
565 SwVbaBuiltInDocumentProperty::getType( )
567 return lcl_toMSOPropType( getValue().getValueType() );
570 void SAL_CALL
571 SwVbaBuiltInDocumentProperty::setType( ::sal_Int8 /*Type*/ )
573 // not valid for Builtin
574 throw uno::RuntimeException();
577 sal_Bool SAL_CALL
578 SwVbaBuiltInDocumentProperty::getLinkToContent( )
580 return false; // built-in always false
583 void SAL_CALL
584 SwVbaBuiltInDocumentProperty::setLinkToContent( sal_Bool /*LinkToContent*/ )
586 // not valid for Builtin
587 throw uno::RuntimeException();
590 uno::Any SAL_CALL
591 SwVbaBuiltInDocumentProperty::getValue( )
593 uno::Any aRet = mPropInfo.getValue();
594 if ( !aRet.hasValue() )
595 throw uno::RuntimeException();
596 return aRet;
599 void SAL_CALL
600 SwVbaBuiltInDocumentProperty::setValue( const uno::Any& Value )
602 mPropInfo.setValue( Value );
605 OUString SAL_CALL
606 SwVbaBuiltInDocumentProperty::getLinkSource( )
608 // not valid for Builtin
609 throw uno::RuntimeException();
612 void SAL_CALL
613 SwVbaBuiltInDocumentProperty::setLinkSource( const OUString& /*LinkSource*/ )
615 // not valid for Builtin
616 throw uno::RuntimeException();
619 OUString
620 SwVbaBuiltInDocumentProperty::getServiceImplName()
622 return u"SwVbaBuiltinDocumentProperty"_ustr;
625 uno::Sequence<OUString>
626 SwVbaBuiltInDocumentProperty::getServiceNames()
628 static uno::Sequence< OUString > const aServiceNames
630 u"ooo.vba.word.DocumentProperty"_ustr
632 return aServiceNames;
634 typedef ::cppu::WeakImplHelper< css::container::XIndexAccess
635 ,css::container::XNameAccess
636 ,css::container::XEnumerationAccess
637 > PropertiesImpl_BASE;
639 typedef std::unordered_map< sal_Int32, uno::Reference< XDocumentProperty > > DocProps;
641 namespace {
643 class DocPropEnumeration : public ::cppu::WeakImplHelper< css::container::XEnumeration >
645 DocProps mDocProps;
646 DocProps::iterator mIt;
647 public:
649 explicit DocPropEnumeration( DocProps&& rProps ) : mDocProps( std::move(rProps) ), mIt( mDocProps.begin() ) {}
650 virtual sal_Bool SAL_CALL hasMoreElements( ) override
652 return mIt != mDocProps.end();
654 virtual uno::Any SAL_CALL nextElement( ) override
656 if ( !hasMoreElements() )
657 throw container::NoSuchElementException();
658 return uno::Any( mIt++->second );
664 typedef std::unordered_map< OUString, uno::Reference< XDocumentProperty > > DocPropsByName;
666 namespace {
668 class BuiltInPropertiesImpl : public PropertiesImpl_BASE
670 protected:
672 rtl::Reference< SwXTextDocument > m_xModel;
674 DocProps mDocProps;
675 DocPropsByName mNamedDocProps;
677 public:
678 BuiltInPropertiesImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, rtl::Reference< SwXTextDocument > xModel ) : m_xModel(std::move( xModel ))
680 BuiltInIndexHelper builtIns( m_xModel );
681 for ( sal_Int32 index = word::WdBuiltInProperty::wdPropertyTitle; index <= word::WdBuiltInProperty::wdPropertyCharsWSpaces; ++index )
683 mDocProps[ index ] = new SwVbaBuiltInDocumentProperty( xParent, xContext, builtIns.getDocPropInfoMap()[ index ] );
684 mNamedDocProps[ mDocProps[ index ]->getName() ] = mDocProps[ index ];
687 // XIndexAccess
688 virtual ::sal_Int32 SAL_CALL getCount( ) override
690 return mDocProps.size();
692 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
694 // correct the correct by the base class for 1 based indices
695 DocProps::iterator it = mDocProps.find( ++Index );
696 if ( it == mDocProps.end() )
697 throw lang::IndexOutOfBoundsException();
698 return uno::Any( it->second );
700 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
702 if ( !hasByName( aName ) )
703 throw container::NoSuchElementException();
704 DocPropsByName::iterator it = mNamedDocProps.find( aName );
705 return uno::Any( it->second );
708 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
710 uno::Sequence< OUString > aNames( getCount() );
711 OUString* pName = aNames.getArray();
712 for (const auto& rEntry : mNamedDocProps)
714 *pName = rEntry.first;
715 ++pName;
717 return aNames;
720 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
722 DocPropsByName::iterator it = mNamedDocProps.find( aName );
723 if ( it == mNamedDocProps.end() )
724 return false;
725 return true;
727 // XElementAccess
728 virtual uno::Type SAL_CALL getElementType( ) override
730 return cppu::UnoType<XDocumentProperty>::get();
732 virtual sal_Bool SAL_CALL hasElements( ) override
734 return !mDocProps.empty();
736 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
738 return new DocPropEnumeration( std::unordered_map(mDocProps) );
744 SwVbaBuiltinDocumentProperties::SwVbaBuiltinDocumentProperties(
745 const uno::Reference< XHelperInterface >& xParent,
746 const uno::Reference< uno::XComponentContext >& xContext,
747 const rtl::Reference< SwXTextDocument >& xModel )
748 : SwVbaDocumentproperties_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( new BuiltInPropertiesImpl( xParent, xContext, xModel ) ) )
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*/ )
755 throw uno::RuntimeException( u"not supported for Builtin properties"_ustr );
758 // XEnumerationAccess
759 uno::Type SAL_CALL
760 SwVbaBuiltinDocumentProperties::getElementType()
762 return cppu::UnoType<XDocumentProperty>::get();
765 uno::Reference< container::XEnumeration > SAL_CALL
766 SwVbaBuiltinDocumentProperties::createEnumeration()
768 uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
769 return xEnumAccess->createEnumeration();
772 // ScVbaCollectionBaseImpl
773 uno::Any
774 SwVbaBuiltinDocumentProperties::createCollectionObject( const uno::Any& aSource )
776 // pass through
777 return aSource;
780 // XHelperInterface
781 OUString
782 SwVbaBuiltinDocumentProperties::getServiceImplName()
784 return u"SwVbaBuiltinDocumentProperties"_ustr;
787 uno::Sequence<OUString>
788 SwVbaBuiltinDocumentProperties::getServiceNames()
790 static uno::Sequence< OUString > const aServiceNames
792 u"ooo.vba.word.DocumentProperties"_ustr
794 return aServiceNames;
797 namespace {
799 class CustomPropertiesImpl : public PropertiesImpl_BASE
801 uno::Reference< XHelperInterface > m_xParent;
802 uno::Reference< uno::XComponentContext > m_xContext;
803 rtl::Reference< SwXTextDocument > m_xModel;
804 uno::Reference< beans::XPropertySet > mxUserDefinedProp;
805 std::shared_ptr< PropertGetSetHelper > mpPropGetSetHelper;
806 public:
807 CustomPropertiesImpl( uno::Reference< XHelperInterface > xParent,
808 uno::Reference< uno::XComponentContext > xContext,
809 rtl::Reference< SwXTextDocument > xModel )
810 : m_xParent(std::move( xParent )),
811 m_xContext(std::move( xContext )),
812 m_xModel(std::move( xModel ))
814 // suck in the document( custom ) properties
815 mpPropGetSetHelper = std::make_shared<CustomPropertyGetSetHelper>( m_xModel );
816 mxUserDefinedProp.set(mpPropGetSetHelper->getUserDefinedProperties(),
817 uno::UNO_SET_THROW);
819 // XIndexAccess
820 virtual ::sal_Int32 SAL_CALL getCount( ) override
822 return mxUserDefinedProp->getPropertySetInfo()->getProperties().getLength();
825 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
827 uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
828 if ( Index >= aProps.getLength() )
829 throw lang::IndexOutOfBoundsException();
830 // How to determine type e.g Date? ( com.sun.star.util.DateTime )
831 DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aProps[ Index ].Name, aProps[ Index ].Name, mpPropGetSetHelper );
832 return uno::Any( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
835 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
837 if ( !hasByName( aName ) )
838 throw container::NoSuchElementException();
840 DocPropInfo aPropInfo = DocPropInfo::createDocPropInfo( aName, aName, mpPropGetSetHelper );
841 return uno::Any( uno::Reference< XDocumentProperty >( new SwVbaCustomDocumentProperty( m_xParent, m_xContext, aPropInfo ) ) );
844 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
846 const uno::Sequence< beans::Property > aProps = mxUserDefinedProp->getPropertySetInfo()->getProperties();
847 uno::Sequence< OUString > aNames( aProps.getLength() );
848 std::transform(aProps.begin(), aProps.end(), aNames.getArray(),
849 [](const beans::Property& rProp) -> OUString { return rProp.Name; });
850 return aNames;
853 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
855 SAL_INFO("sw.vba", "hasByName(" << aName << ") returns " << mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName ) );
856 return mxUserDefinedProp->getPropertySetInfo()->hasPropertyByName( aName );
859 // XElementAccess
860 virtual uno::Type SAL_CALL getElementType( ) override
862 return cppu::UnoType<XDocumentProperty>::get();
865 virtual sal_Bool SAL_CALL hasElements( ) override
867 return getCount() > 0;
870 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
872 // create a map of properties ( the key doesn't matter )
873 SAL_INFO("sw.vba", "Creating an enumeration");
874 sal_Int32 key = 0;
875 sal_Int32 nElem = getCount();
876 DocProps simpleDocPropSnapShot;
877 for ( ; key < nElem; ++key )
878 simpleDocPropSnapShot[ key ].set( getByIndex( key ), uno::UNO_QUERY_THROW );
879 SAL_INFO("sw.vba", "After creating the enumeration");
880 return new DocPropEnumeration( std::move(simpleDocPropSnapShot) );
883 void addProp( const OUString& Name, const uno::Any& Value )
885 uno::Reference< beans::XPropertyContainer > xContainer( mxUserDefinedProp, uno::UNO_QUERY_THROW );
886 // TODO fixme, perform the necessary Type Value conversions
887 xContainer->addProperty( Name, sal_Int16(128), Value );
894 SwVbaCustomDocumentProperties::SwVbaCustomDocumentProperties( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const rtl::Reference< SwXTextDocument >& xModel ) : SwVbaBuiltinDocumentProperties( xParent, xContext, xModel )
896 // replace the m_xIndexAccess implementation ( we need a virtual init )
897 m_xIndexAccess.set( new CustomPropertiesImpl( xParent, xContext, xModel ) );
898 m_xNameAccess.set( m_xIndexAccess, uno::UNO_QUERY_THROW );
901 uno::Reference< XDocumentProperty > SAL_CALL
902 SwVbaCustomDocumentProperties::Add( const OUString& Name, sal_Bool LinkToContent, ::sal_Int8 /*Type*/, const uno::Any& Value, const uno::Any& LinkSource )
904 CustomPropertiesImpl* pCustomProps = dynamic_cast< CustomPropertiesImpl* > ( m_xIndexAccess.get() );
905 uno::Reference< XDocumentProperty > xDocProp;
906 if ( pCustomProps )
908 OUString sLinkSource;
909 pCustomProps->addProp( Name, Value );
911 xDocProp.set( m_xNameAccess->getByName( Name ), uno::UNO_QUERY_THROW );
912 xDocProp->setLinkToContent( LinkToContent );
914 if ( LinkSource >>= sLinkSource )
915 xDocProp->setLinkSource( sLinkSource );
917 return xDocProp;
920 // XHelperInterface
921 OUString
922 SwVbaCustomDocumentProperties::getServiceImplName()
924 return u"SwVbaCustomDocumentProperties"_ustr;
927 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */