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