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 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_extensions.hxx"
26 #include "submissionhandler.hxx"
27 #include "formmetadata.hxx"
28 #include "formstrings.hxx"
29 #include "handlerhelper.hxx"
30 
31 /** === begin UNO includes === **/
32 #include <com/sun/star/form/FormButtonType.hpp>
33 #include <com/sun/star/container/XNamed.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
36 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
37 /** === end UNO includes === **/
38 #include <tools/debug.hxx>
39 #include <rtl/ustrbuf.hxx>
40 
41 //------------------------------------------------------------------------
createRegistryInfo_SubmissionPropertyHandler()42 extern "C" void SAL_CALL createRegistryInfo_SubmissionPropertyHandler()
43 {
44     ::pcr::SubmissionPropertyHandler::registerImplementation();
45 }
46 
47 //........................................................................
48 namespace pcr
49 {
50 //........................................................................
51 
52     using namespace ::comphelper;
53     using namespace ::com::sun::star;
54     using namespace ::com::sun::star::uno;
55     using namespace ::com::sun::star::lang;
56     using namespace ::com::sun::star::beans;
57     using namespace ::com::sun::star::script;
58     using namespace ::com::sun::star::form;
59     using namespace ::com::sun::star::xforms;
60     using namespace ::com::sun::star::container;
61     using namespace ::com::sun::star::inspection;
62 
63 	//====================================================================
64 	//= SubmissionHelper
65 	//====================================================================
66 	//--------------------------------------------------------------------
SubmissionHelper(::osl::Mutex & _rMutex,const Reference<XPropertySet> & _rxIntrospectee,const Reference<frame::XModel> & _rxContextDocument)67     SubmissionHelper::SubmissionHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxIntrospectee, const Reference< frame::XModel >& _rxContextDocument )
68         :EFormsHelper( _rMutex, _rxIntrospectee, _rxContextDocument )
69     {
70         OSL_ENSURE( canTriggerSubmissions( _rxIntrospectee, _rxContextDocument ),
71             "SubmissionHelper::SubmissionHelper: you should not have instantiated me!" );
72     }
73 
74     //--------------------------------------------------------------------
canTriggerSubmissions(const Reference<XPropertySet> & _rxControlModel,const Reference<frame::XModel> & _rxContextDocument)75     bool SubmissionHelper::canTriggerSubmissions( const Reference< XPropertySet >& _rxControlModel,
76         const Reference< frame::XModel >& _rxContextDocument ) SAL_THROW(())
77     {
78         if ( !EFormsHelper::isEForm( _rxContextDocument ) )
79             return false;
80 
81         try
82         {
83             Reference< submission::XSubmissionSupplier > xSubmissionSupp( _rxControlModel, UNO_QUERY );
84             if ( xSubmissionSupp.is() )
85                 return true;
86         }
87         catch( const Exception& )
88         {
89         	OSL_ENSURE( sal_False, "SubmissionHelper::canTriggerSubmissions: caught an exception!" );
90         }
91         return false;
92     }
93 
94     //====================================================================
95 	//= SubmissionPropertyHandler
96 	//====================================================================
DBG_NAME(SubmissionPropertyHandler)97     DBG_NAME( SubmissionPropertyHandler )
98 	//--------------------------------------------------------------------
99     SubmissionPropertyHandler::SubmissionPropertyHandler( const Reference< XComponentContext >& _rxContext )
100         :EditPropertyHandler_Base( _rxContext )
101         ,OPropertyChangeListener( m_aMutex )
102         ,m_pPropChangeMultiplexer( NULL )
103     {
104         DBG_CTOR( SubmissionPropertyHandler, NULL );
105     }
106 
107 	//--------------------------------------------------------------------
~SubmissionPropertyHandler()108     SubmissionPropertyHandler::~SubmissionPropertyHandler( )
109     {
110         disposeAdapter();
111         DBG_DTOR( SubmissionPropertyHandler, NULL );
112     }
113 
114     //--------------------------------------------------------------------
getImplementationName_static()115     ::rtl::OUString SAL_CALL SubmissionPropertyHandler::getImplementationName_static(  ) throw (RuntimeException)
116     {
117         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.SubmissionPropertyHandler" ) );
118     }
119 
120     //--------------------------------------------------------------------
getSupportedServiceNames_static()121     Sequence< ::rtl::OUString > SAL_CALL SubmissionPropertyHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
122     {
123         Sequence< ::rtl::OUString > aSupported( 1 );
124         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.SubmissionPropertyHandler" ) );
125         return aSupported;
126     }
127 
128     //--------------------------------------------------------------------
getPropertyValue(const::rtl::OUString & _rPropertyName)129     Any SAL_CALL SubmissionPropertyHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
130     {
131         ::osl::MutexGuard aGuard( m_aMutex );
132         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
133 
134         OSL_ENSURE( m_pHelper.get(), "SubmissionPropertyHandler::getPropertyValue: inconsistency!" );
135             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
136 
137         Any aReturn;
138         try
139         {
140             switch ( nPropId )
141             {
142             case PROPERTY_ID_SUBMISSION_ID:
143             {
144                 Reference< submission::XSubmissionSupplier > xSubmissionSupp( m_xComponent, UNO_QUERY );
145                 OSL_ENSURE( xSubmissionSupp.is(), "SubmissionPropertyHandler::getPropertyValue: this should never happen ..." );
146                     // this handler is not intended for components which are no XSubmissionSupplier
147                 Reference< submission::XSubmission > xSubmission;
148                 if ( xSubmissionSupp.is() )
149                     xSubmission = xSubmissionSupp->getSubmission( );
150                 aReturn <<= xSubmission;
151             }
152             break;
153 
154             case PROPERTY_ID_XFORMS_BUTTONTYPE:
155             {
156                 FormButtonType eType = FormButtonType_PUSH;
157                 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eType );
158                 if ( ( eType != FormButtonType_PUSH ) && ( eType != FormButtonType_SUBMIT ) )
159                     eType = FormButtonType_PUSH;
160                 aReturn <<= eType;
161             }
162             break;
163 
164             default:
165                 DBG_ERROR( "SubmissionPropertyHandler::getPropertyValue: cannot handle this property!" );
166                 break;
167             }
168         }
169         catch( const Exception& )
170         {
171         	OSL_ENSURE( sal_False, "SubmissionPropertyHandler::getPropertyValue: caught an exception!" );
172         }
173 
174         return aReturn;
175     }
176 
177     //--------------------------------------------------------------------
setPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rValue)178     void SAL_CALL SubmissionPropertyHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
179     {
180         ::osl::MutexGuard aGuard( m_aMutex );
181         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
182 
183         OSL_ENSURE( m_pHelper.get(), "SubmissionPropertyHandler::setPropertyValue: inconsistency!" );
184             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
185 
186         try
187         {
188             switch ( nPropId )
189             {
190             case PROPERTY_ID_SUBMISSION_ID:
191             {
192                 Reference< submission::XSubmission > xSubmission;
193                 OSL_VERIFY( _rValue >>= xSubmission );
194 
195                 Reference< submission::XSubmissionSupplier > xSubmissionSupp( m_xComponent, UNO_QUERY );
196                 OSL_ENSURE( xSubmissionSupp.is(), "SubmissionPropertyHandler::setPropertyValue: this should never happen ..." );
197                     // this handler is not intended for components which are no XSubmissionSupplier
198                 if ( xSubmissionSupp.is() )
199                 {
200                     xSubmissionSupp->setSubmission( xSubmission );
201                     impl_setContextDocumentModified_nothrow();
202                 }
203             }
204             break;
205 
206             case PROPERTY_ID_XFORMS_BUTTONTYPE:
207                 m_xComponent->setPropertyValue( PROPERTY_BUTTONTYPE, _rValue );
208                 break;
209 
210             default:
211                 OSL_ENSURE( sal_False, "SubmissionPropertyHandler::setPropertyValue: cannot handle this id!" );
212             }
213         }
214         catch( const Exception& )
215         {
216         	OSL_ENSURE( sal_False, "SubmissionPropertyHandler::setPropertyValue: caught an exception!" );
217         }
218     }
219 
220     //--------------------------------------------------------------------
getActuatingProperties()221     Sequence< ::rtl::OUString > SAL_CALL SubmissionPropertyHandler::getActuatingProperties( ) throw (RuntimeException)
222     {
223         ::osl::MutexGuard aGuard( m_aMutex );
224         if ( !m_pHelper.get() )
225             return Sequence< ::rtl::OUString >();
226 
227         Sequence< ::rtl::OUString > aReturn( 1 );
228         aReturn[ 0 ] = PROPERTY_XFORMS_BUTTONTYPE;
229         return aReturn;
230     }
231 
232     //--------------------------------------------------------------------
getSupersededProperties()233     Sequence< ::rtl::OUString > SAL_CALL SubmissionPropertyHandler::getSupersededProperties( ) throw (RuntimeException)
234     {
235         ::osl::MutexGuard aGuard( m_aMutex );
236         if ( !m_pHelper.get() )
237             return Sequence< ::rtl::OUString >();
238 
239         Sequence< ::rtl::OUString > aReturn( 3 );
240         aReturn[ 0 ] = PROPERTY_TARGET_URL;
241         aReturn[ 1 ] = PROPERTY_TARGET_FRAME;
242         aReturn[ 2 ] = PROPERTY_BUTTONTYPE;
243         return aReturn;
244     }
245 
246     //--------------------------------------------------------------------
onNewComponent()247     void SubmissionPropertyHandler::onNewComponent()
248     {
249 	    if ( m_pPropChangeMultiplexer )
250 	    {
251 		    m_pPropChangeMultiplexer->dispose();
252 		    m_pPropChangeMultiplexer->release();
253 		    m_pPropChangeMultiplexer = NULL;
254 	    }
255 
256         EditPropertyHandler_Base::onNewComponent();
257 
258         Reference< frame::XModel > xDocument( impl_getContextDocument_nothrow() );
259         DBG_ASSERT( xDocument.is(), "SubmissionPropertyHandler::onNewComponent: no document!" );
260 
261         m_pHelper.reset();
262 
263         if ( SubmissionHelper::canTriggerSubmissions( m_xComponent, xDocument ) )
264         {
265             m_pHelper.reset( new SubmissionHelper( m_aMutex, m_xComponent, xDocument ) );
266 
267             m_pPropChangeMultiplexer = new OPropertyChangeMultiplexer( this, m_xComponent );
268             m_pPropChangeMultiplexer->acquire();
269             m_pPropChangeMultiplexer->addProperty( PROPERTY_BUTTONTYPE );
270         }
271     }
272 
273     //--------------------------------------------------------------------
doDescribeSupportedProperties() const274     Sequence< Property > SAL_CALL SubmissionPropertyHandler::doDescribeSupportedProperties() const
275     {
276         ::std::vector< Property > aProperties;
277         if ( m_pHelper.get() )
278         {
279             implAddPropertyDescription( aProperties, PROPERTY_SUBMISSION_ID, ::getCppuType( static_cast< Reference< submission::XSubmission > * >( NULL ) ) );
280             implAddPropertyDescription( aProperties, PROPERTY_XFORMS_BUTTONTYPE, ::getCppuType( static_cast< FormButtonType* >( NULL ) ) );
281         }
282         if ( aProperties.empty() )
283             return Sequence< Property >();
284         return Sequence< Property >( &(*aProperties.begin()), aProperties.size() );
285     }
286 
287     //--------------------------------------------------------------------
describePropertyLine(const::rtl::OUString & _rPropertyName,const Reference<XPropertyControlFactory> & _rxControlFactory)288     LineDescriptor SAL_CALL SubmissionPropertyHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
289         const Reference< XPropertyControlFactory >& _rxControlFactory )
290         throw (UnknownPropertyException, NullPointerException, RuntimeException)
291     {
292         ::osl::MutexGuard aGuard( m_aMutex );
293         if ( !_rxControlFactory.is() )
294             throw NullPointerException();
295         if ( !m_pHelper.get() )
296             RuntimeException();
297 
298         ::std::vector< ::rtl::OUString > aListEntries;
299         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
300         switch ( nPropId )
301         {
302         case PROPERTY_ID_SUBMISSION_ID:
303             const_cast< SubmissionHelper* >( m_pHelper.get() )->getAllElementUINames( EFormsHelper::Submission, aListEntries, false );
304             break;
305 
306         case PROPERTY_ID_XFORMS_BUTTONTYPE:
307         {
308             // available options are nearly the same as for the "normal" button type, but only the
309             // first two options
310             aListEntries = m_pInfoService->getPropertyEnumRepresentations( PROPERTY_ID_BUTTONTYPE );
311             aListEntries.resize( 2 );
312         }
313         break;
314 
315         default:
316             OSL_ENSURE( sal_False, "SubmissionPropertyHandler::describePropertyLine: cannot handle this id!" );
317             return LineDescriptor();
318         }
319 
320         LineDescriptor aDescriptor;
321         aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, aListEntries, sal_False, sal_True );
322         aDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( nPropId );
323         aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "General" ) );
324         aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
325         return aDescriptor;
326     }
327 
328     //--------------------------------------------------------------------
actuatingPropertyChanged(const::rtl::OUString & _rActuatingPropertyName,const Any & _rNewValue,const Any &,const Reference<XObjectInspectorUI> & _rxInspectorUI,sal_Bool)329     void SAL_CALL SubmissionPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool ) throw (NullPointerException, RuntimeException)
330     {
331         if ( !_rxInspectorUI.is() )
332             throw NullPointerException();
333 
334         ::osl::MutexGuard aGuard( m_aMutex );
335         PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) );
336         OSL_PRECOND( m_pHelper.get(), "SubmissionPropertyHandler::actuatingPropertyChanged: inconsistentcy!" );
337             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
338 
339         switch ( nActuatingPropId )
340         {
341         case PROPERTY_ID_XFORMS_BUTTONTYPE:
342         {
343             FormButtonType eType = FormButtonType_PUSH;
344             OSL_VERIFY( _rNewValue >>= eType );
345             _rxInspectorUI->enablePropertyUI( PROPERTY_SUBMISSION_ID, eType == FormButtonType_SUBMIT );
346         }
347         break;
348 
349         default:
350             OSL_ENSURE( sal_False, "SubmissionPropertyHandler::actuatingPropertyChanged: cannot handle this id!" );
351         }
352     }
353 
354     //--------------------------------------------------------------------
convertToPropertyValue(const::rtl::OUString & _rPropertyName,const Any & _rControlValue)355     Any SAL_CALL SubmissionPropertyHandler::convertToPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rControlValue ) throw (UnknownPropertyException, RuntimeException)
356     {
357         ::osl::MutexGuard aGuard( m_aMutex );
358         Any aPropertyValue;
359 
360         OSL_ENSURE( m_pHelper.get(), "SubmissionPropertyHandler::convertToPropertyValue: we have no SupportedProperties!" );
361         if ( !m_pHelper.get() )
362             return aPropertyValue;
363 
364         ::rtl::OUString sControlValue;
365         OSL_VERIFY( _rControlValue >>= sControlValue );
366 
367         PropertyId nPropId( m_pInfoService->getPropertyId( _rPropertyName ) );
368         switch ( nPropId )
369         {
370         case PROPERTY_ID_SUBMISSION_ID:
371         {
372             Reference< XSubmission > xSubmission( m_pHelper->getModelElementFromUIName( EFormsHelper::Submission, sControlValue ), UNO_QUERY );
373             aPropertyValue <<= xSubmission;
374         }
375         break;
376 
377         case PROPERTY_ID_XFORMS_BUTTONTYPE:
378         {
379             ::rtl::Reference< IPropertyEnumRepresentation > aEnumConversion(
380                 new DefaultEnumRepresentation( *m_pInfoService, ::getCppuType( static_cast< FormButtonType* >( NULL ) ), PROPERTY_ID_BUTTONTYPE ) );
381             // TODO/UNOize: make aEnumConversion a member?
382             aEnumConversion->getValueFromDescription( sControlValue, aPropertyValue );
383         }
384         break;
385 
386         default:
387             OSL_ENSURE( sal_False, "SubmissionPropertyHandler::convertToPropertyValue: cannot handle this id!" );
388         }
389 
390         return aPropertyValue;
391     }
392 
393     //--------------------------------------------------------------------
convertToControlValue(const::rtl::OUString & _rPropertyName,const Any & _rPropertyValue,const Type & _rControlValueType)394     Any SAL_CALL SubmissionPropertyHandler::convertToControlValue( const ::rtl::OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType ) throw (UnknownPropertyException, RuntimeException)
395     {
396         ::osl::MutexGuard aGuard( m_aMutex );
397         Any aControlValue;
398 
399         OSL_ENSURE( m_pHelper.get(), "SubmissionPropertyHandler::convertToControlValue: we have no SupportedProperties!" );
400         if ( !m_pHelper.get() )
401             return aControlValue;
402 
403         OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
404             "SubmissionPropertyHandler::convertToControlValue: all our controls should use strings for value exchange!" );
405         (void)_rControlValueType;
406 
407         PropertyId nPropId( m_pInfoService->getPropertyId( _rPropertyName ) );
408         switch ( nPropId )
409         {
410         case PROPERTY_ID_SUBMISSION_ID:
411         {
412             Reference< XPropertySet > xSubmission( _rPropertyValue, UNO_QUERY );
413             if ( xSubmission.is() )
414                 aControlValue <<= m_pHelper->getModelElementUIName( EFormsHelper::Submission, xSubmission );
415         }
416         break;
417 
418         case PROPERTY_ID_XFORMS_BUTTONTYPE:
419         {
420             ::rtl::Reference< IPropertyEnumRepresentation > aEnumConversion(
421                 new DefaultEnumRepresentation( *m_pInfoService, _rPropertyValue.getValueType(), PROPERTY_ID_BUTTONTYPE ) );
422             // TODO/UNOize: make aEnumConversion a member?
423             aControlValue <<= aEnumConversion->getDescriptionForValue( _rPropertyValue );
424         }
425         break;
426 
427         default:
428             OSL_ENSURE( sal_False, "SubmissionPropertyHandler::convertToControlValue: cannot handle this id!" );
429         }
430 
431         return aControlValue;
432     }
433 
434     //--------------------------------------------------------------------
_propertyChanged(const PropertyChangeEvent & _rEvent)435 	void SubmissionPropertyHandler::_propertyChanged( const PropertyChangeEvent& _rEvent ) throw(RuntimeException)
436     {
437         if ( _rEvent.PropertyName == PROPERTY_BUTTONTYPE )
438             firePropertyChange( PROPERTY_XFORMS_BUTTONTYPE, PROPERTY_ID_XFORMS_BUTTONTYPE, _rEvent.OldValue, _rEvent.NewValue );
439     }
440 
441 //........................................................................
442 } // namespace pcr
443 //........................................................................
444 
445