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