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