xref: /trunk/main/forms/source/component/DatabaseForm.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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_forms.hxx"
26 
27 #include "componenttools.hxx"
28 #include "DatabaseForm.hxx"
29 #include "EventThread.hxx"
30 #include "frm_module.hxx"
31 #include "frm_resource.hrc"
32 #include "frm_resource.hxx"
33 #include "GroupManager.hxx"
34 #include "property.hrc"
35 #include "property.hxx"
36 #include "services.hxx"
37 
38 #include <com/sun/star/awt/XControlContainer.hpp>
39 #include <com/sun/star/awt/XTextComponent.hpp>
40 #include <com/sun/star/form/DataSelectionType.hpp>
41 #include <com/sun/star/form/FormComponentType.hpp>
42 #include <com/sun/star/form/TabulatorCycle.hpp>
43 #include <com/sun/star/frame/FrameSearchFlag.hpp>
44 #include <com/sun/star/frame/XDispatch.hpp>
45 #include <com/sun/star/frame/XDispatchProvider.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/io/XObjectInputStream.hpp>
48 #include <com/sun/star/io/XObjectOutputStream.hpp>
49 #include <com/sun/star/sdb/CommandType.hpp>
50 #include <com/sun/star/sdb/RowSetVetoException.hpp>
51 #include <com/sun/star/sdb/SQLContext.hpp>
52 #include <com/sun/star/sdb/XColumnUpdate.hpp>
53 #include <com/sun/star/sdbc/DataType.hpp>
54 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
55 #include <com/sun/star/sdbc/ResultSetType.hpp>
56 #include <com/sun/star/sdbc/XRowSet.hpp>
57 #include <com/sun/star/sdbcx/Privilege.hpp>
58 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
59 #include <com/sun/star/util/XCancellable.hpp>
60 #include <com/sun/star/util/XURLTransformer.hpp>
61 #include <com/sun/star/util/XModifiable2.hpp>
62 
63 #include <comphelper/basicio.hxx>
64 #include <comphelper/container.hxx>
65 #include <comphelper/enumhelper.hxx>
66 #include <comphelper/extract.hxx>
67 #include <comphelper/seqstream.hxx>
68 #include <comphelper/sequence.hxx>
69 #include <comphelper/stl_types.hxx>
70 #include <comphelper/uno3.hxx>
71 #include <connectivity/dbtools.hxx>
72 #include <cppuhelper/exc_hlp.hxx>
73 #include <cppuhelper/implbase2.hxx>
74 #include <osl/mutex.hxx>
75 #include <rtl/math.hxx>
76 #include <rtl/tencinfo.h>
77 #include <svl/inetstrm.hxx>
78 #include <svl/inettype.hxx>
79 #include <tools/debug.hxx>
80 #include <tools/diagnose_ex.h>
81 #include <tools/fsys.hxx>
82 #include <tools/inetmsg.hxx>
83 #include <tools/urlobj.hxx>
84 #include <unotools/ucblockbytes.hxx>
85 #include <unotools/ucbstreamhelper.hxx>
86 #include <vcl/svapp.hxx>
87 #include <vcl/timer.hxx>
88 #include <vos/mutex.hxx>
89 
90 #include <ctype.h>
91 #include <hash_map>
92 
93 // compatibility: DatabaseCursorType is dead, but for compatibility reasons we still have to write it ...
94 namespace com {
95 namespace sun {
96 namespace star {
97 namespace data {
98 
99 enum DatabaseCursorType
100 {
101     DatabaseCursorType_FORWARD = 0,
102     DatabaseCursorType_SNAPSHOT = 1,
103     DatabaseCursorType_KEYSET = 2,
104     DatabaseCursorType_DYNAMIC = 3,
105     DatabaseCursorType_MAKE_FIXED_SIZE = SAL_MAX_ENUM
106 };
107 
108 } } } }
109 
110 using namespace ::dbtools;
111 using namespace ::comphelper;
112 using namespace ::com::sun::star::uno;
113 using namespace ::com::sun::star::sdb;
114 using namespace ::com::sun::star::sdbc;
115 using namespace ::com::sun::star::sdbcx;
116 using namespace ::com::sun::star::beans;
117 using namespace ::com::sun::star::container;
118 using namespace ::com::sun::star::task;
119 using namespace ::com::sun::star::frame;
120 using namespace ::com::sun::star::form;
121 using namespace ::com::sun::star::awt;
122 using namespace ::com::sun::star::io;
123 using namespace ::com::sun::star::lang;
124 using namespace ::com::sun::star::data;
125 using namespace ::com::sun::star::util;
126 
127 //--------------------------------------------------------------------------
createRegistryInfo_ODatabaseForm()128 extern "C" void SAL_CALL createRegistryInfo_ODatabaseForm()
129 {
130     static ::frm::OMultiInstanceAutoRegistration< ::frm::ODatabaseForm > aAutoRegistration;
131 }
132 
133 //.........................................................................
134 namespace frm
135 {
136 //.........................................................................
137 
138 //==================================================================
139 //= DocumentModifyGuard
140 //==================================================================
141 class DocumentModifyGuard
142 {
143 public:
DocumentModifyGuard(const Reference<XInterface> & _rxFormComponent)144     DocumentModifyGuard( const Reference< XInterface >& _rxFormComponent )
145         :m_xDocumentModify( getXModel( _rxFormComponent ), UNO_QUERY )
146     {
147         impl_changeModifiableFlag_nothrow( false );
148     }
~DocumentModifyGuard()149     ~DocumentModifyGuard()
150     {
151         impl_changeModifiableFlag_nothrow( true );
152     }
153 
154 private:
impl_changeModifiableFlag_nothrow(const bool _enable)155     void    impl_changeModifiableFlag_nothrow( const bool _enable )
156     {
157         try
158         {
159             if ( m_xDocumentModify.is() )
160                 _enable ? m_xDocumentModify->enableSetModified() : m_xDocumentModify->disableSetModified();
161         }
162         catch( const Exception& )
163         {
164             DBG_UNHANDLED_EXCEPTION();
165         }
166     }
167 
168 private:
169     Reference< XModifiable2 >   m_xDocumentModify;
170 };
171 
172 //==================================================================
173 //= OFormSubmitResetThread
174 //=-----------------------------------------------------------------
175 //= submitting and resetting html-forms asynchronously
176 //==================================================================
177 
178 //------------------------------------------------------------------
179 class OFormSubmitResetThread: public OComponentEventThread
180 {
181 protected:
182 
183     // duplicate an event with respect to it's type
184     virtual EventObject *cloneEvent( const EventObject *pEvt ) const;
185 
186     // process an event. while processing the mutex isn't locked, and pCompImpl
187     // is made sure to remain valid
188     virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
189                                const EventObject* _pEvt,
190                                const Reference<XControl>& _rControl,
191                                sal_Bool _bSubmit);
192 
193 public:
194 
OFormSubmitResetThread(ODatabaseForm * pControl)195     OFormSubmitResetThread(ODatabaseForm* pControl) : OComponentEventThread(pControl) { }
196 };
197 
198 //------------------------------------------------------------------
cloneEvent(const EventObject * pEvt) const199 EventObject* OFormSubmitResetThread::cloneEvent(
200         const EventObject *pEvt ) const
201 {
202     return new ::com::sun::star::awt::MouseEvent( *(::com::sun::star::awt::MouseEvent *)pEvt );
203 }
204 
205 //------------------------------------------------------------------
processEvent(::cppu::OComponentHelper * pCompImpl,const EventObject * _pEvt,const Reference<XControl> & _rControl,sal_Bool _bSubmit)206 void OFormSubmitResetThread::processEvent(
207         ::cppu::OComponentHelper* pCompImpl,
208         const EventObject *_pEvt,
209         const Reference<XControl>& _rControl,
210         sal_Bool _bSubmit)
211 {
212     if (_bSubmit)
213         ((ODatabaseForm *)pCompImpl)->submit_impl(_rControl, *static_cast<const ::com::sun::star::awt::MouseEvent*>(_pEvt), true);
214     else
215         ((ODatabaseForm *)pCompImpl)->reset_impl(true);
216 }
217 
218 //==================================================================
219 //= ODatabaseForm
220 //==================================================================
221 
222 //------------------------------------------------------------------
Create(const Reference<XMultiServiceFactory> & _rxFactory)223 Reference< XInterface > SAL_CALL ODatabaseForm::Create( const Reference< XMultiServiceFactory >& _rxFactory )
224 {
225     return *( new ODatabaseForm( _rxFactory ) );
226 }
227 
228 //------------------------------------------------------------------------------
getImplementationId()229 Sequence<sal_Int8> SAL_CALL ODatabaseForm::getImplementationId()
230 {
231     return OImplementationIds::getImplementationId(getTypes());
232 }
233 
234 //------------------------------------------------------------------
getTypes()235 Sequence<Type> SAL_CALL ODatabaseForm::getTypes()
236 {
237     // ask the aggregate
238     Sequence<Type> aAggregateTypes;
239     Reference<XTypeProvider> xAggregateTypes;
240     if (query_aggregation(m_xAggregate, xAggregateTypes))
241         aAggregateTypes = xAggregateTypes->getTypes();
242 
243     Sequence< Type > aRet = concatSequences(
244         aAggregateTypes, ODatabaseForm_BASE1::getTypes(), OFormComponents::getTypes()
245     );
246     aRet = concatSequences( aRet, ODatabaseForm_BASE2::getTypes(), ODatabaseForm_BASE3::getTypes() );
247     return concatSequences( aRet, OPropertySetAggregationHelper::getTypes() );
248 }
249 
250 //------------------------------------------------------------------
queryAggregation(const Type & _rType)251 Any SAL_CALL ODatabaseForm::queryAggregation(const Type& _rType)
252 {
253     Any aReturn = ODatabaseForm_BASE1::queryInterface(_rType);
254     // our own interfaces
255     if (!aReturn.hasValue())
256     {
257         aReturn = ODatabaseForm_BASE2::queryInterface(_rType);
258         // property set related interfaces
259         if (!aReturn.hasValue())
260         {
261             aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
262 
263             // form component collection related interfaces
264             if (!aReturn.hasValue())
265             {
266                 aReturn = OFormComponents::queryAggregation(_rType);
267 
268                 // interfaces already present in the aggregate which we want to reroute
269                 // only available if we could create the aggregate
270                 if (!aReturn.hasValue() && m_xAggregateAsRowSet.is())
271                     aReturn = ODatabaseForm_BASE3::queryInterface(_rType);
272 
273                 // aggregate interfaces
274                 // (ask the aggregated object _after_ the OComponentHelper (base of OFormComponents),
275                 // so calls to the XComponent interface reach us and not the aggregation)
276                 if (!aReturn.hasValue() && m_xAggregate.is())
277                     aReturn = m_xAggregate->queryAggregation(_rType);
278             }
279         }
280     }
281 
282     return aReturn;
283 }
284 
285 DBG_NAME(ODatabaseForm);
286 //------------------------------------------------------------------
ODatabaseForm(const Reference<XMultiServiceFactory> & _rxFactory)287 ODatabaseForm::ODatabaseForm(const Reference<XMultiServiceFactory>& _rxFactory)
288     :OFormComponents(_rxFactory)
289     ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
290     ,OPropertyChangeListener(m_aMutex)
291     ,m_aLoadListeners(m_aMutex)
292     ,m_aRowSetApproveListeners(m_aMutex)
293     ,m_aRowSetListeners(m_aMutex)
294     ,m_aSubmitListeners(m_aMutex)
295     ,m_aErrorListeners(m_aMutex)
296     ,m_aResetListeners( *this, m_aMutex )
297     ,m_aPropertyBagHelper( *this )
298     ,m_pAggregatePropertyMultiplexer(NULL)
299     ,m_pGroupManager( NULL )
300     ,m_aParameterManager( m_aMutex, _rxFactory )
301     ,m_aFilterManager( _rxFactory )
302     ,m_pLoadTimer(NULL)
303     ,m_pThread(NULL)
304     ,m_nResetsPending(0)
305     ,m_nPrivileges(0)
306     ,m_bInsertOnly( sal_False )
307     ,m_eSubmitMethod(FormSubmitMethod_GET)
308     ,m_eSubmitEncoding(FormSubmitEncoding_URL)
309     ,m_eNavigation(NavigationBarMode_CURRENT)
310     ,m_bAllowInsert(sal_True)
311     ,m_bAllowUpdate(sal_True)
312     ,m_bAllowDelete(sal_True)
313     ,m_bLoaded(sal_False)
314     ,m_bSubForm(sal_False)
315     ,m_bForwardingConnection(sal_False)
316     ,m_bSharingConnection( sal_False )
317 {
318     DBG_CTOR( ODatabaseForm, NULL );
319     impl_construct();
320 }
321 
322 //------------------------------------------------------------------
ODatabaseForm(const ODatabaseForm & _cloneSource)323 ODatabaseForm::ODatabaseForm( const ODatabaseForm& _cloneSource )
324     :OFormComponents( _cloneSource )
325     ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
326     ,OPropertyChangeListener( m_aMutex )
327     ,ODatabaseForm_BASE1()
328     ,ODatabaseForm_BASE2()
329     ,ODatabaseForm_BASE3()
330     ,IPropertyBagHelperContext()
331     ,m_aLoadListeners( m_aMutex )
332     ,m_aRowSetApproveListeners( m_aMutex )
333     ,m_aRowSetListeners( m_aMutex )
334     ,m_aSubmitListeners( m_aMutex )
335     ,m_aErrorListeners( m_aMutex )
336     ,m_aResetListeners( *this, m_aMutex )
337     ,m_aPropertyBagHelper( *this )
338     ,m_pAggregatePropertyMultiplexer( NULL )
339     ,m_pGroupManager( NULL )
340     ,m_aParameterManager( m_aMutex, _cloneSource.m_xServiceFactory )
341     ,m_aFilterManager( _cloneSource.m_xServiceFactory )
342     ,m_pLoadTimer( NULL )
343     ,m_pThread( NULL )
344     ,m_nResetsPending( 0 )
345     ,m_nPrivileges( 0 )
346     ,m_bInsertOnly( _cloneSource.m_bInsertOnly )
347     ,m_aControlBorderColorFocus( _cloneSource.m_aControlBorderColorFocus )
348     ,m_aControlBorderColorMouse( _cloneSource.m_aControlBorderColorMouse )
349     ,m_aControlBorderColorInvalid( _cloneSource.m_aControlBorderColorInvalid )
350     ,m_aDynamicControlBorder( _cloneSource.m_aDynamicControlBorder )
351     ,m_sName( _cloneSource.m_sName )
352     ,m_aTargetURL( _cloneSource.m_aTargetURL )
353     ,m_aTargetFrame( _cloneSource.m_aTargetFrame )
354     ,m_eSubmitMethod( _cloneSource.m_eSubmitMethod )
355     ,m_eSubmitEncoding( _cloneSource.m_eSubmitEncoding )
356     ,m_eNavigation( _cloneSource.m_eNavigation )
357     ,m_bAllowInsert( _cloneSource.m_bAllowInsert )
358     ,m_bAllowUpdate( _cloneSource.m_bAllowUpdate )
359     ,m_bAllowDelete( _cloneSource.m_bAllowDelete )
360     ,m_bLoaded( sal_False )
361     ,m_bSubForm( sal_False )
362     ,m_bForwardingConnection( sal_False )
363     ,m_bSharingConnection( sal_False )
364 {
365     DBG_CTOR( ODatabaseForm, NULL );
366 
367     impl_construct();
368 
369     osl_incrementInterlockedCount( &m_refCount );
370     {
371         // our aggregated rowset itself is not cloneable, so simply copy the properties
372         ::comphelper::copyProperties( _cloneSource.m_xAggregateSet, m_xAggregateSet );
373 
374         // also care for the dynamic properties: If the clone source has properties which we do not have,
375         // then add them
376         try
377         {
378             Reference< XPropertySet > xSourceProps( const_cast< ODatabaseForm& >( _cloneSource ).queryAggregation(
379                 XPropertySet::static_type() ), UNO_QUERY_THROW );
380             Reference< XPropertySetInfo > xSourcePSI( xSourceProps->getPropertySetInfo(), UNO_SET_THROW );
381             Reference< XPropertyState > xSourcePropState( xSourceProps, UNO_QUERY );
382 
383             Reference< XPropertySetInfo > xDestPSI( getPropertySetInfo(), UNO_QUERY_THROW );
384 
385             Sequence< Property > aSourceProperties( xSourcePSI->getProperties() );
386             for (   const Property* pSourceProperty = aSourceProperties.getConstArray();
387                     pSourceProperty != aSourceProperties.getConstArray() + aSourceProperties.getLength();
388                     ++pSourceProperty
389                 )
390             {
391                 if ( xDestPSI->hasPropertyByName( pSourceProperty->Name ) )
392                     continue;
393 
394                 // the initial value passed to XPropertyContainer is also used as default, usually. So, try
395                 // to retrieve the default of the source property
396                 Any aInitialValue;
397                 if ( xSourcePropState.is() )
398                 {
399                     aInitialValue = xSourcePropState->getPropertyDefault( pSourceProperty->Name );
400                 }
401                 else
402                 {
403                     aInitialValue = xSourceProps->getPropertyValue( pSourceProperty->Name );
404                 }
405                 addProperty( pSourceProperty->Name, pSourceProperty->Attributes, aInitialValue );
406                 setPropertyValue( pSourceProperty->Name, xSourceProps->getPropertyValue( pSourceProperty->Name ) );
407             }
408         }
409         catch( const Exception& )
410         {
411             throw WrappedTargetException(
412                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not clone the given database form." ) ),
413                 *const_cast< ODatabaseForm* >( &_cloneSource ),
414                 ::cppu::getCaughtException()
415             );
416         }
417     }
418     osl_decrementInterlockedCount( &m_refCount );
419 }
420 
421 //------------------------------------------------------------------
impl_construct()422 void ODatabaseForm::impl_construct()
423 {
424     // aggregate a row set
425     increment(m_refCount);
426     {
427         m_xAggregate = Reference< XAggregation >( m_xServiceFactory->createInstance( SRV_SDB_ROWSET ), UNO_QUERY_THROW );
428         m_xAggregateAsRowSet.set( m_xAggregate, UNO_QUERY_THROW );
429         setAggregation( m_xAggregate );
430     }
431 
432     // listen for the properties, important for Parameters
433     if ( m_xAggregateSet.is() )
434     {
435         m_pAggregatePropertyMultiplexer = new OPropertyChangeMultiplexer(this, m_xAggregateSet, sal_False);
436         m_pAggregatePropertyMultiplexer->acquire();
437         m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_COMMAND);
438         m_pAggregatePropertyMultiplexer->addProperty(PROPERTY_ACTIVE_CONNECTION);
439     }
440 
441     {
442         Reference< XWarningsSupplier > xRowSetWarnings( m_xAggregate, UNO_QUERY );
443         m_aWarnings.setExternalWarnings( xRowSetWarnings );
444     }
445 
446     if ( m_xAggregate.is() )
447     {
448         m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
449     }
450 
451     {
452         m_aFilterManager.initialize( m_xAggregateSet );
453         m_aParameterManager.initialize( this, m_xAggregate );
454 
455         declareForwardedProperty( PROPERTY_ID_ACTIVE_CONNECTION );
456     }
457     decrement( m_refCount );
458 
459     m_pGroupManager = new OGroupManager( this );
460     m_pGroupManager->acquire();
461 }
462 
463 //------------------------------------------------------------------
~ODatabaseForm()464 ODatabaseForm::~ODatabaseForm()
465 {
466     DBG_DTOR(ODatabaseForm,NULL);
467 
468     m_pGroupManager->release();
469     m_pGroupManager = NULL;
470 
471     if (m_xAggregate.is())
472         m_xAggregate->setDelegator( NULL );
473 
474     m_aWarnings.setExternalWarnings( NULL );
475 
476     if (m_pAggregatePropertyMultiplexer)
477     {
478         m_pAggregatePropertyMultiplexer->dispose();
479         m_pAggregatePropertyMultiplexer->release();
480         m_pAggregatePropertyMultiplexer = NULL;
481     }
482 }
483 
484 //==============================================================================
485 // HTML tools
486 //------------------------------------------------------------------------
GetDataURLEncoded(const Reference<XControl> & SubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt)487 ::rtl::OUString ODatabaseForm::GetDataURLEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
488 {
489     return GetDataEncoded(true,SubmitButton,MouseEvt);
490 }
491 // -----------------------------------------------------------------------------
GetDataEncoded(bool _bURLEncoded,const Reference<XControl> & SubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt)492 ::rtl::OUString ODatabaseForm::GetDataEncoded(bool _bURLEncoded,const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
493 {
494     // Liste von successful Controls fuellen
495     HtmlSuccessfulObjList aSuccObjList;
496     FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
497 
498 
499     // Liste zu ::rtl::OUString zusammensetzen
500     ::rtl::OUStringBuffer aResult;
501     ::rtl::OUString aName;
502     ::rtl::OUString aValue;
503 
504     for (   HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin();
505             pSuccObj < aSuccObjList.end();
506             ++pSuccObj
507         )
508     {
509         aName = pSuccObj->aName;
510         aValue = pSuccObj->aValue;
511         if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE && aValue.getLength() )
512         {
513             // Bei File-URLs wird der Dateiname und keine URL uebertragen,
514             // weil Netscape dies so macht.
515             INetURLObject aURL;
516             aURL.SetSmartProtocol(INET_PROT_FILE);
517             aURL.SetSmartURL(aValue);
518             if( INET_PROT_FILE == aURL.GetProtocol() )
519                 aValue = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
520         }
521         Encode( aName );
522         Encode( aValue );
523 
524         aResult.append(aName);
525         aResult.append(sal_Unicode('='));
526         aResult.append(aValue);
527 
528         if (pSuccObj < aSuccObjList.end() - 1)
529         {
530             if ( _bURLEncoded )
531                 aResult.append(sal_Unicode('&'));
532             else
533                 aResult.appendAscii("\r\n");
534         }
535     }
536 
537 
538     aSuccObjList.clear();
539 
540     return aResult.makeStringAndClear();
541 }
542 
543 //==============================================================================
544 // HTML tools
545 //------------------------------------------------------------------------
GetDataTextEncoded(const Reference<XControl> & SubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt)546 ::rtl::OUString ODatabaseForm::GetDataTextEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
547 {
548     return GetDataEncoded(false,SubmitButton,MouseEvt);
549 }
550 
551 //------------------------------------------------------------------------
GetDataMultiPartEncoded(const Reference<XControl> & SubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt,::rtl::OUString & rContentType)552 Sequence<sal_Int8> ODatabaseForm::GetDataMultiPartEncoded(const Reference<XControl>& SubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt, ::rtl::OUString& rContentType)
553 {
554 
555     // Parent erzeugen
556     INetMIMEMessage aParent;
557     aParent.EnableAttachChild( INETMSG_MULTIPART_FORM_DATA );
558 
559 
560     // Liste von successful Controls fuellen
561     HtmlSuccessfulObjList aSuccObjList;
562     FillSuccessfulList( aSuccObjList, SubmitButton, MouseEvt );
563 
564 
565     // Liste zu ::rtl::OUString zusammensetzen
566     ::rtl::OUString aResult;
567     for (   HtmlSuccessfulObjListIterator pSuccObj = aSuccObjList.begin();
568             pSuccObj < aSuccObjList.end();
569             ++pSuccObj
570         )
571     {
572         if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_TEXT )
573             InsertTextPart( aParent, pSuccObj->aName, pSuccObj->aValue );
574         else if( pSuccObj->nRepresentation == SUCCESSFUL_REPRESENT_FILE )
575             InsertFilePart( aParent, pSuccObj->aName, pSuccObj->aValue );
576     }
577 
578 
579     // Liste loeschen
580     aSuccObjList.clear();
581 
582     // Fuer Parent MessageStream erzeugen
583     INetMIMEMessageStream aMessStream;
584     aMessStream.SetSourceMessage( &aParent );
585     aMessStream.GenerateHeader( sal_False );
586 
587     // MessageStream in SvStream kopieren
588     SvMemoryStream aMemStream;
589     char* pBuf = new char[1025];
590     int nRead;
591     while( (nRead = aMessStream.Read(pBuf, 1024)) > 0 )
592         aMemStream.Write( pBuf, nRead );
593     delete[] pBuf;
594 
595     aMemStream.Flush();
596     aMemStream.Seek( 0 );
597     void* pData = (void*)aMemStream.GetData();
598     sal_Int32 nLen = aMemStream.Seek(STREAM_SEEK_TO_END);
599 
600     rContentType = UniString(aParent.GetContentType());
601     return Sequence<sal_Int8>((sal_Int8*)pData, nLen);
602 }
603 
604 //------------------------------------------------------------------------
605 namespace
606 {
appendDigits(sal_Int32 _nNumber,sal_Int8 nDigits,::rtl::OUStringBuffer & _rOut)607     static void appendDigits( sal_Int32 _nNumber, sal_Int8 nDigits, ::rtl::OUStringBuffer& _rOut )
608     {
609         sal_Int32 nCurLen = _rOut.getLength();
610         _rOut.append( _nNumber );
611         while ( _rOut.getLength() - nCurLen < nDigits )
612             _rOut.insert( nCurLen, (sal_Unicode)'0' );
613     }
614 }
615 
616 //------------------------------------------------------------------------
AppendComponent(HtmlSuccessfulObjList & rList,const Reference<XPropertySet> & xComponentSet,const::rtl::OUString & rNamePrefix,const Reference<XControl> & rxSubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt)617 void ODatabaseForm::AppendComponent(HtmlSuccessfulObjList& rList, const Reference<XPropertySet>& xComponentSet, const ::rtl::OUString& rNamePrefix,
618                      const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt)
619 {
620     if (!xComponentSet.is())
621         return;
622 
623     // MIB 25.6.98: Geschachtelte Formulare abfangen ... oder muesste
624     // man sie submitten?
625     if (!hasProperty(PROPERTY_CLASSID, xComponentSet))
626         return;
627 
628     // Namen ermitteln
629     if (!hasProperty(PROPERTY_NAME, xComponentSet))
630         return;
631 
632     sal_Int16 nClassId = 0;
633     xComponentSet->getPropertyValue(PROPERTY_CLASSID) >>= nClassId;
634     ::rtl::OUString aName;
635     xComponentSet->getPropertyValue( PROPERTY_NAME ) >>= aName;
636     if( !aName.getLength() && nClassId != FormComponentType::IMAGEBUTTON)
637         return;
638     else    // Name um den Prefix erweitern
639         aName = rNamePrefix + aName;
640 
641     switch( nClassId )
642     {
643         // Buttons
644         case FormComponentType::COMMANDBUTTON:
645         {
646             // Es wird nur der gedrueckte Submit-Button ausgewertet
647             // MIB: Sofern ueberhaupt einer uebergeben wurde
648             if( rxSubmitButton.is() )
649             {
650                 Reference<XPropertySet>  xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
651                 if (xSubmitButtonComponent == xComponentSet && hasProperty(PROPERTY_LABEL, xComponentSet))
652                 {
653                     // <name>=<label>
654                     ::rtl::OUString aLabel;
655                     xComponentSet->getPropertyValue( PROPERTY_LABEL ) >>= aLabel;
656                     rList.push_back( HtmlSuccessfulObj(aName, aLabel) );
657                 }
658             }
659         } break;
660 
661         // ImageButtons
662         case FormComponentType::IMAGEBUTTON:
663         {
664             // Es wird nur der gedrueckte Submit-Button ausgewertet
665             // MIB: Sofern ueberhaupt einer uebergeben wurde
666             if( rxSubmitButton.is() )
667             {
668                 Reference<XPropertySet>  xSubmitButtonComponent(rxSubmitButton->getModel(), UNO_QUERY);
669                 if (xSubmitButtonComponent == xComponentSet)
670                 {
671                     // <name>.x=<pos.X>&<name>.y=<pos.Y>
672                     ::rtl::OUString aLhs = aName;
673                     ::rtl::OUString aRhs = ::rtl::OUString::valueOf( MouseEvt.X );
674 
675                     // nur wenn ein Name vorhanden ist, kann ein name.x
676                     aLhs += aName.getLength() ? UniString::CreateFromAscii(".x") : UniString::CreateFromAscii("x");
677                     rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) );
678 
679                     aLhs = aName;
680                     aRhs = ::rtl::OUString::valueOf( MouseEvt.Y );
681                     aLhs += aName.getLength() ? UniString::CreateFromAscii(".y") : UniString::CreateFromAscii("y");
682                     rList.push_back( HtmlSuccessfulObj(aLhs, aRhs) );
683 
684                 }
685             }
686         } break;
687 
688         // CheckBoxen / RadioButtons
689         case FormComponentType::CHECKBOX:
690         case FormComponentType::RADIOBUTTON:
691         {
692             // <name>=<refValue>
693             if( !hasProperty(PROPERTY_STATE, xComponentSet) )
694                 break;
695             sal_Int16 nChecked = 0;
696             xComponentSet->getPropertyValue( PROPERTY_STATE ) >>= nChecked;
697             if( nChecked != 1 )
698                 break;
699 
700             ::rtl::OUString aStrValue;
701             if( hasProperty(PROPERTY_REFVALUE, xComponentSet) )
702                 xComponentSet->getPropertyValue( PROPERTY_REFVALUE ) >>= aStrValue;
703 
704             rList.push_back( HtmlSuccessfulObj(aName, aStrValue) );
705         } break;
706 
707         // Edit
708         case FormComponentType::TEXTFIELD:
709         {
710             // <name>=<text>
711             if( !hasProperty(PROPERTY_TEXT, xComponentSet) )
712                 break;
713 
714             // MIB: Spezial-Behandlung fuer Multiline-Edit nur dann, wenn
715             // es auch ein Control dazu gibt.
716             Any aTmp = xComponentSet->getPropertyValue( PROPERTY_MULTILINE );
717             sal_Bool bMulti =   rxSubmitButton.is()
718                             && (aTmp.getValueType().getTypeClass() == TypeClass_BOOLEAN)
719                             && getBOOL(aTmp);
720             ::rtl::OUString sText;
721             if ( bMulti )   // Bei MultiLineEdit Text am Control abholen
722             {
723 
724                 Reference<XControlContainer>  xControlContainer(rxSubmitButton->getContext(), UNO_QUERY);
725                 if( !xControlContainer.is() ) break;
726 
727                 Sequence<Reference<XControl> > aControlSeq = xControlContainer->getControls();
728                 Reference<XControl>  xControl;
729                 Reference<XFormComponent>  xControlComponent;
730 
731                 // Richtiges Control suchen
732                 sal_Int32 i;
733                 for( i=0; i<aControlSeq.getLength(); i++ )
734                 {
735                     xControl = aControlSeq.getConstArray()[i];
736                     Reference<XPropertySet>  xModel(xControl->getModel(), UNO_QUERY);
737                     if (xModel == xComponentSet)
738                     {
739                         Reference<XTextComponent>  xTextComponent(xControl, UNO_QUERY);
740                         if( xTextComponent.is() )
741                             sText = xTextComponent->getText();
742                         break;
743                     }
744                 }
745                 // Control nicht gefunden oder nicht existent, (Edit im Grid)
746                 if (i == aControlSeq.getLength())
747                     xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
748             }
749             else
750                 xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= sText;
751 
752             rList.push_back( HtmlSuccessfulObj(aName, sText) );
753         } break;
754 
755         // ComboBox, Patternfield
756         case FormComponentType::COMBOBOX:
757         case FormComponentType::PATTERNFIELD:
758         {
759             // <name>=<text>
760             if( hasProperty(PROPERTY_TEXT, xComponentSet) )
761             {
762                 ::rtl::OUString aText;
763                 xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
764                 rList.push_back( HtmlSuccessfulObj(aName, aText) );
765             }
766         } break;
767         case FormComponentType::CURRENCYFIELD:
768         case FormComponentType::NUMERICFIELD:
769         {
770             // <name>=<wert> // wert wird als double mit Punkt als Decimaltrenner
771                              // kein Wert angegeben (NULL) -> wert leer
772             if( hasProperty(PROPERTY_VALUE, xComponentSet) )
773             {
774                 ::rtl::OUString aText;
775                 Any aVal  = xComponentSet->getPropertyValue( PROPERTY_VALUE );
776 
777                 double aDoubleVal = 0;
778                 if (aVal >>= aDoubleVal)
779                 {
780                     sal_Int16 nScale = 0;
781                     xComponentSet->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) >>= nScale;
782                     aText = ::rtl::math::doubleToUString(aDoubleVal, rtl_math_StringFormat_F, nScale, '.', sal_True);
783                 }
784                 rList.push_back( HtmlSuccessfulObj(aName, aText) );
785             }
786         }   break;
787         case FormComponentType::DATEFIELD:
788         {
789             // <name>=<wert> // Wert wird als Datum im Format (MM-DD-YYYY)
790                              // kein Wert angegeben (NULL) -> wert leer
791             if( hasProperty(PROPERTY_DATE, xComponentSet) )
792             {
793                 ::rtl::OUString aText;
794                 Any aVal  = xComponentSet->getPropertyValue( PROPERTY_DATE );
795                 sal_Int32 nInt32Val = 0;
796                 if (aVal >>= nInt32Val)
797                 {
798                     ::Date aDate( nInt32Val );
799                     ::rtl::OUStringBuffer aBuffer;
800                     appendDigits( aDate.GetMonth(), 2, aBuffer );
801                     aBuffer.append( (sal_Unicode)'-' );
802                     appendDigits( aDate.GetDay(), 2, aBuffer );
803                     aBuffer.append( (sal_Unicode)'-' );
804                     appendDigits( aDate.GetYear(), 4, aBuffer );
805                     aText = aBuffer.makeStringAndClear();
806                 }
807                 rList.push_back( HtmlSuccessfulObj(aName, aText) );
808             }
809         }   break;
810         case FormComponentType::TIMEFIELD:
811         {
812             // <name>=<wert> // Wert wird als Zeit im Format (HH:MM:SS) angegeben
813                              // kein Wert angegeben (NULL) -> wert leer
814             if( hasProperty(PROPERTY_TIME, xComponentSet) )
815             {
816                 ::rtl::OUString aText;
817                 Any aVal  = xComponentSet->getPropertyValue( PROPERTY_TIME );
818                 sal_Int32 nInt32Val = 0;
819                 if (aVal >>= nInt32Val)
820                 {
821                     ::Time aTime(nInt32Val);
822                     ::rtl::OUStringBuffer aBuffer;
823                     appendDigits( aTime.GetHour(), 2, aBuffer );
824                     aBuffer.append( (sal_Unicode)'-' );
825                     appendDigits( aTime.GetMin(), 2, aBuffer );
826                     aBuffer.append( (sal_Unicode)'-' );
827                     appendDigits( aTime.GetSec(), 2, aBuffer );
828                     aText = aBuffer.makeStringAndClear();
829                 }
830                 rList.push_back( HtmlSuccessfulObj(aName, aText) );
831             }
832         }   break;
833 
834         // starform
835         case FormComponentType::HIDDENCONTROL:
836         {
837 
838             // <name>=<value>
839             if( hasProperty(PROPERTY_HIDDEN_VALUE, xComponentSet) )
840             {
841                 ::rtl::OUString aText;
842                 xComponentSet->getPropertyValue( PROPERTY_HIDDEN_VALUE ) >>= aText;
843                 rList.push_back( HtmlSuccessfulObj(aName, aText) );
844             }
845         } break;
846 
847         // starform
848         case FormComponentType::FILECONTROL:
849         {
850             // <name>=<text>
851             if( hasProperty(PROPERTY_TEXT, xComponentSet) )
852             {
853 
854                 ::rtl::OUString aText;
855                 xComponentSet->getPropertyValue( PROPERTY_TEXT ) >>= aText;
856                 rList.push_back( HtmlSuccessfulObj(aName, aText, SUCCESSFUL_REPRESENT_FILE) );
857             }
858         } break;
859 
860         // starform
861         case FormComponentType::LISTBOX:
862         {
863 
864             // <name>=<Token0>&<name>=<Token1>&...&<name>=<TokenN> (Mehrfachselektion)
865             if (!hasProperty(PROPERTY_SELECT_SEQ, xComponentSet) ||
866                 !hasProperty(PROPERTY_STRINGITEMLIST, xComponentSet))
867                 break;
868 
869             // angezeigte Werte
870             Sequence< ::rtl::OUString > aVisibleList;
871             xComponentSet->getPropertyValue( PROPERTY_STRINGITEMLIST ) >>= aVisibleList;
872             sal_Int32 nStringCnt = aVisibleList.getLength();
873             const ::rtl::OUString* pStrings = aVisibleList.getConstArray();
874 
875             // Werte-Liste
876             Sequence< ::rtl::OUString > aValueList;
877             xComponentSet->getPropertyValue( PROPERTY_VALUE_SEQ ) >>= aValueList;
878             sal_Int32 nValCnt = aValueList.getLength();
879             const ::rtl::OUString* pVals = aValueList.getConstArray();
880 
881             // Selektion
882             Sequence<sal_Int16> aSelectList;
883             xComponentSet->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectList;
884             sal_Int32 nSelCount = aSelectList.getLength();
885             const sal_Int16* pSels = aSelectList.getConstArray();
886 
887             // Einfach- oder Mehrfach-Selektion
888             // Bei Einfach-Selektionen beruecksichtigt MT nur den ersten Eintrag
889             // in der Liste.
890             if (nSelCount > 1 && !getBOOL(xComponentSet->getPropertyValue(PROPERTY_MULTISELECTION)))
891                 nSelCount = 1;
892 
893             // Die Indizes in der Selektions-Liste koennen auch ungueltig sein,
894             // also muss man die gueltigen erstmal raussuchen um die Laenge
895             // der neuen Liste zu bestimmen.
896             sal_Int32 nCurCnt = 0;
897             sal_Int32 i;
898             for( i=0; i<nSelCount; ++i )
899             {
900                 if( pSels[i] < nStringCnt )
901                     ++nCurCnt;
902             }
903 
904             ::rtl::OUString aSubValue;
905             for(i=0; i<nCurCnt; ++i )
906             {
907                 sal_Int16  nSelPos = pSels[i];
908                 if (nSelPos < nValCnt && pVals[nSelPos].getLength())
909                 {
910                     aSubValue = pVals[nSelPos];
911                 }
912                 else
913                 {
914                     aSubValue = pStrings[nSelPos];
915                 }
916                 rList.push_back( HtmlSuccessfulObj(aName, aSubValue) );
917             }
918         } break;
919         case FormComponentType::GRIDCONTROL:
920         {
921             // Die einzelnen Spaltenwerte werden verschickt,
922             // der Name wird mit dem Prefix des Names des Grids erweitert
923             Reference<XIndexAccess>  xContainer(xComponentSet, UNO_QUERY);
924             if (!xContainer.is())
925                 break;
926 
927             aName += UniString('.');
928 
929             Reference<XPropertySet>  xSet;
930             sal_Int32 nCount = xContainer->getCount();
931             // we know already how many objects should be appended,
932             // so why not allocate the space for them
933             rList.reserve( nCount + rList.capacity() ); // not size()
934             for (sal_Int32 i = 0; i < nCount; ++i)
935             {
936                 xContainer->getByIndex(i) >>= xSet;
937                 if (xSet.is())
938                     AppendComponent(rList, xSet, aName, rxSubmitButton, MouseEvt);
939             }
940         }
941     }
942 }
943 
944 //------------------------------------------------------------------------
FillSuccessfulList(HtmlSuccessfulObjList & rList,const Reference<XControl> & rxSubmitButton,const::com::sun::star::awt::MouseEvent & MouseEvt)945 void ODatabaseForm::FillSuccessfulList( HtmlSuccessfulObjList& rList,
946     const Reference<XControl>& rxSubmitButton, const ::com::sun::star::awt::MouseEvent& MouseEvt )
947 {
948     // Liste loeschen
949     rList.clear();
950     // Ueber Components iterieren
951     Reference<XPropertySet>         xComponentSet;
952     ::rtl::OUString aPrefix;
953 
954     // we know already how many objects should be appended,
955     // so why not allocate the space for them
956     rList.reserve( getCount() );
957     for( sal_Int32 nIndex=0; nIndex < getCount(); nIndex++ )
958     {
959         getByIndex( nIndex ) >>= xComponentSet;
960         AppendComponent(rList, xComponentSet, aPrefix, rxSubmitButton, MouseEvt);
961     }
962 }
963 
964 //------------------------------------------------------------------------
Encode(::rtl::OUString & rString) const965 void ODatabaseForm::Encode( ::rtl::OUString& rString ) const
966 {
967     ::rtl::OUString aResult;
968 
969     // Immer ANSI #58641
970 //  rString.Convert(CHARSET_SYSTEM, CHARSET_ANSI);
971 
972 
973     // Zeilenendezeichen werden als CR dargestellt
974     UniString sConverter = rString;
975     sConverter.ConvertLineEnd( LINEEND_CR );
976     rString = sConverter;
977 
978 
979     // Jeden einzelnen Character ueberpruefen
980     sal_Int32 nStrLen = rString.getLength();
981     sal_Unicode nCharCode;
982     for( sal_Int32 nCurPos=0; nCurPos < nStrLen; ++nCurPos )
983     {
984         nCharCode = rString[nCurPos];
985 
986         // Behandlung fuer chars, die kein alphanumerisches Zeichen sind
987         // und CharacterCodes > 127
988         if( (!isalnum(nCharCode) && nCharCode != (sal_Unicode)' ') || nCharCode > 127 )
989         {
990             switch( nCharCode )
991             {
992                 case 13:    // CR
993                     aResult += ::rtl::OUString::createFromAscii("%0D%0A");  // Hex-Darstellung CR LF
994                     break;
995 
996 
997                 // Netscape Sonderbehandlung
998                 case 42:    // '*'
999                 case 45:    // '-'
1000                 case 46:    // '.'
1001                 case 64:    // '@'
1002                 case 95:    // '_'
1003                     aResult += UniString(nCharCode);
1004                     break;
1005 
1006                 default:
1007                 {
1008                     // In Hex umrechnen
1009                     short nHi = ((sal_Int16)nCharCode) / 16;
1010                     short nLo = ((sal_Int16)nCharCode) - (nHi*16);
1011                     if( nHi > 9 ) nHi += (int)'A'-10; else nHi += (int)'0';
1012                     if( nLo > 9 ) nLo += (int)'A'-10; else nLo += (int)'0';
1013                     aResult += UniString('%');
1014                     aResult += UniString((sal_Unicode)nHi);
1015                     aResult += UniString((sal_Unicode)nLo);
1016                 }
1017             }
1018         }
1019         else
1020             aResult += UniString(nCharCode);
1021     }
1022 
1023 
1024     // Spaces durch '+' ersetzen
1025     aResult = aResult.replace(' ', '+');
1026 
1027     rString = aResult;
1028 }
1029 
1030 //------------------------------------------------------------------------
InsertTextPart(INetMIMEMessage & rParent,const::rtl::OUString & rName,const::rtl::OUString & rData)1031 void ODatabaseForm::InsertTextPart( INetMIMEMessage& rParent, const ::rtl::OUString& rName,
1032     const ::rtl::OUString& rData )
1033 {
1034 
1035     // Part als Message-Child erzeugen
1036     INetMIMEMessage* pChild = new INetMIMEMessage();
1037 
1038 
1039     // Header
1040     ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii("form-data; name=\"");
1041     aContentDisp += rName;
1042     aContentDisp += UniString('\"');
1043     pChild->SetContentDisposition( aContentDisp );
1044     pChild->SetContentType( UniString::CreateFromAscii("text/plain") );
1045 
1046     rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding();
1047     const sal_Char* pBestMatchingEncoding = rtl_getBestMimeCharsetFromTextEncoding( eSystemEncoding );
1048     UniString aBestMatchingEncoding = UniString::CreateFromAscii( pBestMatchingEncoding );
1049     pChild->SetContentTransferEncoding(aBestMatchingEncoding);
1050 
1051     // Body
1052     SvMemoryStream* pStream = new SvMemoryStream;
1053     pStream->WriteLine( ByteString( UniString(rData), rtl_getTextEncodingFromMimeCharset(pBestMatchingEncoding) ) );
1054     pStream->Flush();
1055     pStream->Seek( 0 );
1056     pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) );
1057     rParent.AttachChild( *pChild );
1058 }
1059 
1060 //------------------------------------------------------------------------
InsertFilePart(INetMIMEMessage & rParent,const::rtl::OUString & rName,const::rtl::OUString & rFileName)1061 sal_Bool ODatabaseForm::InsertFilePart( INetMIMEMessage& rParent, const ::rtl::OUString& rName,
1062     const ::rtl::OUString& rFileName )
1063 {
1064     UniString aFileName( rFileName );
1065     UniString aContentType(UniString::CreateFromAscii(CONTENT_TYPE_STR_TEXT_PLAIN));
1066     SvStream *pStream = 0;
1067 
1068     if( aFileName.Len() )
1069     {
1070         // Bisher koennen wir nur File-URLs verarbeiten
1071         INetURLObject aURL;
1072         aURL.SetSmartProtocol(INET_PROT_FILE);
1073         aURL.SetSmartURL(rFileName);
1074         if( INET_PROT_FILE == aURL.GetProtocol() )
1075         {
1076             aFileName = INetURLObject::decode(aURL.PathToFileName(), '%', INetURLObject::DECODE_UNAMBIGUOUS);
1077             DirEntry aDirEntry( aFileName );
1078             if( aDirEntry.Exists() )
1079             {
1080                 pStream = ::utl::UcbStreamHelper::CreateStream(aFileName, STREAM_READ);
1081                 if (!pStream || (pStream->GetError() != ERRCODE_NONE))
1082                 {
1083                     delete pStream;
1084                     pStream = 0;
1085                 }
1086             }
1087             INetContentType eContentType = INetContentTypes::GetContentType4Extension(
1088                                                                 aDirEntry.GetExtension() );
1089             if (eContentType != CONTENT_TYPE_UNKNOWN)
1090                 aContentType = INetContentTypes::GetContentType(eContentType);
1091         }
1092     }
1093 
1094     // Wenn irgendetwas nicht geklappt hat, legen wir einen leeren
1095     // MemoryStream an
1096     if( !pStream )
1097         pStream = new SvMemoryStream;
1098 
1099 
1100     // Part als Message-Child erzeugen
1101     INetMIMEMessage* pChild = new INetMIMEMessage;
1102 
1103 
1104     // Header
1105     ::rtl::OUString aContentDisp = ::rtl::OUString::createFromAscii( "form-data; name=\"" );
1106     aContentDisp += rName;
1107     aContentDisp += UniString('\"');
1108     aContentDisp += ::rtl::OUString::createFromAscii("; filename=\"");
1109     aContentDisp += aFileName;
1110     aContentDisp += UniString('\"');
1111     pChild->SetContentDisposition( aContentDisp );
1112     pChild->SetContentType( aContentType );
1113     pChild->SetContentTransferEncoding( UniString(::rtl::OUString::createFromAscii("8bit")) );
1114 
1115 
1116     // Body
1117     pChild->SetDocumentLB( new SvLockBytes(pStream, sal_True) );
1118     rParent.AttachChild( *pChild );
1119 
1120     return sal_True;
1121 }
1122 
1123 //==============================================================================
1124 // internals
1125 //------------------------------------------------------------------------------
onError(const SQLErrorEvent & _rEvent)1126 void ODatabaseForm::onError( const SQLErrorEvent& _rEvent )
1127 {
1128     m_aErrorListeners.notifyEach( &XSQLErrorListener::errorOccured, _rEvent );
1129 }
1130 
1131 //------------------------------------------------------------------------------
onError(const SQLException & _rException,const::rtl::OUString & _rContextDescription)1132 void ODatabaseForm::onError( const SQLException& _rException, const ::rtl::OUString& _rContextDescription )
1133 {
1134     if ( !m_aErrorListeners.getLength() )
1135         return;
1136 
1137     SQLErrorEvent aEvent( *this, makeAny( prependErrorInfo( _rException, *this, _rContextDescription ) ) );
1138     onError( aEvent );
1139 }
1140 
1141 //------------------------------------------------------------------------------
updateParameterInfo()1142 void ODatabaseForm::updateParameterInfo()
1143 {
1144     m_aParameterManager.updateParameterInfo( m_aFilterManager );
1145 }
1146 
1147 //------------------------------------------------------------------------------
hasValidParent() const1148 bool ODatabaseForm::hasValidParent() const
1149 {
1150     // do we have to fill the parameters again?
1151     if (m_bSubForm)
1152     {
1153         Reference<XResultSet>  xResultSet(m_xParent, UNO_QUERY);
1154         if (!xResultSet.is())
1155         {
1156             DBG_ERROR("ODatabaseForm::hasValidParent() : no parent resultset !");
1157             return false;
1158         }
1159         try
1160         {
1161             Reference< XPropertySet >  xSet( m_xParent, UNO_QUERY );
1162             Reference< XLoadable > xLoad( m_xParent, UNO_QUERY );
1163             if  (   xLoad->isLoaded()
1164                 &&  (   xResultSet->isBeforeFirst()
1165                     ||  xResultSet->isAfterLast()
1166                     ||  getBOOL( xSet->getPropertyValue( PROPERTY_ISNEW ) )
1167                     )
1168                 )
1169                 // the parent form is loaded and on a "virtual" row -> not valid
1170                 return false;
1171         }
1172         catch(Exception&)
1173         {
1174             // parent could be forwardonly?
1175             return false;
1176         }
1177     }
1178     return true;
1179 }
1180 
1181 //------------------------------------------------------------------------------
fillParameters(::osl::ResettableMutexGuard & _rClearForNotifies,const Reference<XInteractionHandler> & _rxCompletionHandler)1182 bool ODatabaseForm::fillParameters( ::osl::ResettableMutexGuard& _rClearForNotifies, const Reference< XInteractionHandler >& _rxCompletionHandler )
1183 {
1184     // do we have to fill the parameters again?
1185     if ( !m_aParameterManager.isUpToDate() )
1186         updateParameterInfo();
1187 
1188     // is there a valid parent?
1189     if ( m_bSubForm && !hasValidParent() )
1190         return true;
1191 
1192     // ensure we're connected
1193     if ( !implEnsureConnection() )
1194         return false;
1195 
1196     if ( m_aParameterManager.isUpToDate() )
1197         return m_aParameterManager.fillParameterValues( _rxCompletionHandler, _rClearForNotifies );
1198 
1199     return true;
1200 }
1201 
1202 //------------------------------------------------------------------------------
saveInsertOnlyState()1203 void ODatabaseForm::saveInsertOnlyState( )
1204 {
1205     OSL_ENSURE( !m_aIgnoreResult.hasValue(), "ODatabaseForm::saveInsertOnlyState: overriding old value!" );
1206     m_aIgnoreResult = m_xAggregateSet->getPropertyValue( PROPERTY_INSERTONLY );
1207 }
1208 
1209 //------------------------------------------------------------------------------
restoreInsertOnlyState()1210 void ODatabaseForm::restoreInsertOnlyState( )
1211 {
1212     if ( m_aIgnoreResult.hasValue() )
1213     {
1214         m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, m_aIgnoreResult );
1215         m_aIgnoreResult = Any();
1216     }
1217 }
1218 
1219 //------------------------------------------------------------------------------
executeRowSet(::osl::ResettableMutexGuard & _rClearForNotifies,sal_Bool bMoveToFirst,const Reference<XInteractionHandler> & _rxCompletionHandler)1220 sal_Bool ODatabaseForm::executeRowSet(::osl::ResettableMutexGuard& _rClearForNotifies, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler)
1221 {
1222     if (!m_xAggregateAsRowSet.is())
1223         return sal_False;
1224 
1225     if (!fillParameters(_rClearForNotifies, _rxCompletionHandler))
1226         return sal_False;
1227 
1228     restoreInsertOnlyState( );
1229 
1230     // ensure the aggregated row set has the correct properties
1231     sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
1232 
1233     // if we have a parent, who is not positioned on a valid row
1234     // we can't be updatable!
1235     if (m_bSubForm && !hasValidParent())
1236     {
1237         nConcurrency = ResultSetConcurrency::READ_ONLY;
1238 
1239         // don't use any parameters if we don't have a valid parent
1240         m_aParameterManager.setAllParametersNull();
1241 
1242         // switch to "insert only" mode
1243         saveInsertOnlyState( );
1244         m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( sal_True ) );
1245     }
1246     else if (m_bAllowInsert || m_bAllowUpdate || m_bAllowDelete)
1247         nConcurrency = ResultSetConcurrency::UPDATABLE;
1248     else
1249         nConcurrency = ResultSetConcurrency::READ_ONLY;
1250 
1251     m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_CONCURRENCY, makeAny( (sal_Int32)nConcurrency ) );
1252     m_xAggregateSet->setPropertyValue( PROPERTY_RESULTSET_TYPE, makeAny( (sal_Int32)ResultSetType::SCROLL_SENSITIVE ) );
1253 
1254     sal_Bool bSuccess = sal_False;
1255     try
1256     {
1257         m_xAggregateAsRowSet->execute();
1258         bSuccess = sal_True;
1259     }
1260     catch( const RowSetVetoException& eVeto )
1261     {
1262         (void)eVeto;
1263     }
1264     catch(SQLException& eDb)
1265     {
1266         _rClearForNotifies.clear();
1267         if (m_sCurrentErrorContext.getLength())
1268             onError(eDb, m_sCurrentErrorContext);
1269         else
1270             onError(eDb, FRM_RES_STRING(RID_STR_READERROR));
1271         _rClearForNotifies.reset();
1272 
1273         restoreInsertOnlyState( );
1274     }
1275 
1276     if (bSuccess)
1277     {
1278         // adjust the privilege property
1279         //  m_nPrivileges;
1280         m_xAggregateSet->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
1281         if (!m_bAllowInsert)
1282             m_nPrivileges &= ~Privilege::INSERT;
1283         if (!m_bAllowUpdate)
1284             m_nPrivileges &= ~Privilege::UPDATE;
1285         if (!m_bAllowDelete)
1286             m_nPrivileges &= ~Privilege::DELETE;
1287 
1288         if (bMoveToFirst)
1289         {
1290             // the row set is positioned _before_ the first row (per definitionem), so move the set ...
1291             try
1292             {
1293                 // if we have an insert only rowset we move to the insert row
1294                 next();
1295                 if (((m_nPrivileges & Privilege::INSERT) == Privilege::INSERT)
1296                     && isAfterLast())
1297                 {
1298                     // move on the insert row of set
1299                     // resetting must be done later, after the load events have been posted
1300                     // see :moveToInsertRow and load , reload
1301                     Reference<XResultSetUpdate>  xUpdate;
1302                     if (query_aggregation( m_xAggregate, xUpdate))
1303                         xUpdate->moveToInsertRow();
1304                 }
1305             }
1306             catch(SQLException& eDB)
1307             {
1308                 _rClearForNotifies.clear();
1309                 if (m_sCurrentErrorContext.getLength())
1310                     onError(eDB, m_sCurrentErrorContext);
1311                 else
1312                     onError(eDB, FRM_RES_STRING(RID_STR_READERROR));
1313                 _rClearForNotifies.reset();
1314                 bSuccess = sal_False;
1315             }
1316         }
1317     }
1318     return bSuccess;
1319 }
1320 
1321 //------------------------------------------------------------------
disposing()1322 void ODatabaseForm::disposing()
1323 {
1324     if (m_pAggregatePropertyMultiplexer)
1325         m_pAggregatePropertyMultiplexer->dispose();
1326 
1327     if (m_bLoaded)
1328         unload();
1329 
1330     // cancel the submit/reset-thread
1331     {
1332         ::osl::MutexGuard aGuard( m_aMutex );
1333         if (m_pThread)
1334         {
1335             m_pThread->release();
1336             m_pThread = NULL;
1337         }
1338     }
1339 
1340     EventObject aEvt(static_cast<XWeak*>(this));
1341     m_aLoadListeners.disposeAndClear(aEvt);
1342     m_aRowSetApproveListeners.disposeAndClear(aEvt);
1343     m_aParameterManager.disposing( aEvt );
1344     m_aResetListeners.disposing();
1345     m_aSubmitListeners.disposeAndClear(aEvt);
1346     m_aErrorListeners.disposeAndClear(aEvt);
1347 
1348     m_aParameterManager.dispose();   // (to free any references it may have to me)
1349     m_aFilterManager.dispose();      // (dito)
1350 
1351     OFormComponents::disposing();
1352     OPropertySetAggregationHelper::disposing();
1353 
1354     // stop listening on the aggregate
1355     if (m_xAggregateAsRowSet.is())
1356         m_xAggregateAsRowSet->removeRowSetListener(this);
1357 
1358     // dispose the active connection
1359     Reference<XComponent>  xAggregationComponent;
1360     if (query_aggregation(m_xAggregate, xAggregationComponent))
1361         xAggregationComponent->dispose();
1362 
1363     m_aPropertyBagHelper.dispose();
1364 }
1365 
1366 //------------------------------------------------------------------------------
getConnection()1367 Reference< XConnection > ODatabaseForm::getConnection()
1368 {
1369     Reference< XConnection > xConn;
1370     m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConn;
1371     return xConn;
1372 }
1373 
1374 //------------------------------------------------------------------------------
getMutex()1375 ::osl::Mutex& ODatabaseForm::getMutex()
1376 {
1377     return m_aMutex;
1378 }
1379 
1380 //==============================================================================
1381 // property handling
1382 //------------------------------------------------------------------------------
describeFixedAndAggregateProperties(Sequence<Property> & _rProps,Sequence<Property> & _rAggregateProps) const1383 void ODatabaseForm::describeFixedAndAggregateProperties(
1384         Sequence< Property >& _rProps,
1385         Sequence< Property >& _rAggregateProps ) const
1386 {
1387     BEGIN_DESCRIBE_AGGREGATION_PROPERTIES(22, m_xAggregateSet)
1388         // we want to "override" the privileges, since we have additional "AllowInsert" etc. properties
1389         RemoveProperty( _rAggregateProps, PROPERTY_PRIVILEGES );
1390 
1391         // InsertOnly is also to be overridden, since we sometimes change it ourself
1392         RemoveProperty( _rAggregateProps, PROPERTY_INSERTONLY );
1393 
1394         // we remove and re-declare the DataSourceName property, 'cause we want it to be constrained, and the
1395         // original property of our aggregate isn't
1396         RemoveProperty( _rAggregateProps, PROPERTY_DATASOURCE );
1397 
1398         // for connection sharing, we need to override the ActiveConnection property, too
1399         RemoveProperty( _rAggregateProps, PROPERTY_ACTIVE_CONNECTION );
1400 
1401         // the Filter property is also overwritten, since we have some implicit filters
1402         // (e.g. the ones which result from linking master fields to detail fields
1403         // via column names instead of parameters)
1404         RemoveProperty( _rAggregateProps, PROPERTY_FILTER );
1405         RemoveProperty( _rAggregateProps, PROPERTY_APPLYFILTER );
1406 
1407         DECL_IFACE_PROP4(ACTIVE_CONNECTION, XConnection,                    BOUND, TRANSIENT, MAYBEVOID, CONSTRAINED);
1408         DECL_BOOL_PROP2 ( APPLYFILTER,                                      BOUND, MAYBEDEFAULT            );
1409         DECL_PROP1      ( NAME,             ::rtl::OUString,                BOUND                          );
1410         DECL_PROP1      ( MASTERFIELDS,     Sequence< ::rtl::OUString >,    BOUND                          );
1411         DECL_PROP1      ( DETAILFIELDS,     Sequence< ::rtl::OUString >,    BOUND                          );
1412         DECL_PROP2      ( DATASOURCE,       ::rtl::OUString,                BOUND, CONSTRAINED             );
1413         DECL_PROP3      ( CYCLE,            TabulatorCycle,                 BOUND, MAYBEVOID, MAYBEDEFAULT );
1414         DECL_PROP2      ( FILTER,           ::rtl::OUString,                BOUND, MAYBEDEFAULT            );
1415         DECL_BOOL_PROP2 ( INSERTONLY,                                       BOUND, MAYBEDEFAULT            );
1416         DECL_PROP1      ( NAVIGATION,       NavigationBarMode,              BOUND                          );
1417         DECL_BOOL_PROP1 ( ALLOWADDITIONS,                                   BOUND                          );
1418         DECL_BOOL_PROP1 ( ALLOWEDITS,                                       BOUND                          );
1419         DECL_BOOL_PROP1 ( ALLOWDELETIONS,                                   BOUND                          );
1420         DECL_PROP2      ( PRIVILEGES,       sal_Int32,                      TRANSIENT, READONLY            );
1421         DECL_PROP1      ( TARGET_URL,       ::rtl::OUString,                BOUND                          );
1422         DECL_PROP1      ( TARGET_FRAME,     ::rtl::OUString,                BOUND                          );
1423         DECL_PROP1      ( SUBMIT_METHOD,    FormSubmitMethod,               BOUND                          );
1424         DECL_PROP1      ( SUBMIT_ENCODING,  FormSubmitEncoding,             BOUND                          );
1425         DECL_BOOL_PROP3 ( DYNAMIC_CONTROL_BORDER,                           BOUND, MAYBEVOID, MAYBEDEFAULT );
1426         DECL_PROP3      ( CONTROL_BORDER_COLOR_FOCUS,   sal_Int32,          BOUND, MAYBEVOID, MAYBEDEFAULT );
1427         DECL_PROP3      ( CONTROL_BORDER_COLOR_MOUSE,   sal_Int32,          BOUND, MAYBEVOID, MAYBEDEFAULT );
1428         DECL_PROP3      ( CONTROL_BORDER_COLOR_INVALID, sal_Int32,          BOUND, MAYBEVOID, MAYBEDEFAULT );
1429     END_DESCRIBE_PROPERTIES();
1430 }
1431 
1432 //------------------------------------------------------------------------------
getPropertiesInterface()1433 Reference< XMultiPropertySet > ODatabaseForm::getPropertiesInterface()
1434 {
1435     return Reference< XMultiPropertySet >( *this, UNO_QUERY );
1436 }
1437 
1438 //------------------------------------------------------------------------------
getInfoHelper()1439 ::cppu::IPropertyArrayHelper& ODatabaseForm::getInfoHelper()
1440 {
1441     return m_aPropertyBagHelper.getInfoHelper();
1442 }
1443 
1444 //------------------------------------------------------------------------------
getPropertySetInfo()1445 Reference< XPropertySetInfo > ODatabaseForm::getPropertySetInfo()
1446 {
1447     return createPropertySetInfo( getInfoHelper() );
1448 }
1449 
1450 //--------------------------------------------------------------------
addProperty(const::rtl::OUString & _rName,::sal_Int16 _nAttributes,const Any & _rInitialValue)1451 void SAL_CALL ODatabaseForm::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue )
1452 {
1453     m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1454 }
1455 
1456 //--------------------------------------------------------------------
removeProperty(const::rtl::OUString & _rName)1457 void SAL_CALL ODatabaseForm::removeProperty( const ::rtl::OUString& _rName )
1458 {
1459     m_aPropertyBagHelper.removeProperty( _rName );
1460 }
1461 
1462 //--------------------------------------------------------------------
getPropertyValues()1463 Sequence< PropertyValue > SAL_CALL ODatabaseForm::getPropertyValues()
1464 {
1465     return m_aPropertyBagHelper.getPropertyValues();
1466 }
1467 
1468 //--------------------------------------------------------------------
setPropertyValues(const Sequence<PropertyValue> & _rProps)1469 void SAL_CALL ODatabaseForm::setPropertyValues( const Sequence< PropertyValue >& _rProps )
1470 {
1471     m_aPropertyBagHelper.setPropertyValues( _rProps );
1472 }
1473 
1474 //------------------------------------------------------------------------------
getWarnings()1475 Any SAL_CALL ODatabaseForm::getWarnings(  )
1476 {
1477     return m_aWarnings.getWarnings();
1478 }
1479 
1480 //------------------------------------------------------------------------------
clearWarnings()1481 void SAL_CALL ODatabaseForm::clearWarnings(  )
1482 {
1483     m_aWarnings.clearWarnings();
1484 }
1485 
1486 //------------------------------------------------------------------------------
createClone()1487 Reference< XCloneable > SAL_CALL ODatabaseForm::createClone(  )
1488 {
1489     ODatabaseForm* pClone = new ODatabaseForm( *this );
1490     osl_incrementInterlockedCount( &pClone->m_refCount );
1491     pClone->clonedFrom( *this );
1492     osl_decrementInterlockedCount( &pClone->m_refCount );
1493     return pClone;
1494 }
1495 
1496 //------------------------------------------------------------------------------
fire(sal_Int32 * pnHandles,const Any * pNewValues,const Any * pOldValues,sal_Int32 nCount,sal_Bool bVetoable)1497 void ODatabaseForm::fire( sal_Int32* pnHandles, const Any* pNewValues, const Any* pOldValues, sal_Int32 nCount, sal_Bool bVetoable )
1498 {
1499     // same as in getFastPropertyValue(sal_Int32) : if we're resetting currently don't fire any changes of the
1500     // IsModified property from sal_False to sal_True, as this is only temporary 'til the reset is done
1501     if (m_nResetsPending > 0)
1502     {
1503         // look for the PROPERTY_ID_ISMODIFIED
1504         sal_Int32 nPos = 0;
1505         for (nPos=0; nPos<nCount; ++nPos)
1506             if (pnHandles[nPos] == PROPERTY_ID_ISMODIFIED)
1507                 break;
1508 
1509         if ((nPos < nCount) && (pNewValues[nPos].getValueType().getTypeClass() == TypeClass_BOOLEAN) && getBOOL(pNewValues[nPos]))
1510         {   // yeah, we found it, and it changed to TRUE
1511             if (nPos == 0)
1512             {   // just cut the first element
1513                 ++pnHandles;
1514                 ++pNewValues;
1515                 ++pOldValues;
1516                 --nCount;
1517             }
1518             else if (nPos == nCount - 1)
1519                 // just cut the last element
1520                 --nCount;
1521             else
1522             {   // split into two base class calls
1523                 OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nPos, bVetoable);
1524                 ++nPos;
1525                 OPropertySetAggregationHelper::fire(pnHandles + nPos, pNewValues + nPos, pOldValues + nPos, nCount - nPos, bVetoable);
1526                 return;
1527             }
1528         }
1529     }
1530 
1531     OPropertySetAggregationHelper::fire(pnHandles, pNewValues, pOldValues, nCount, bVetoable);
1532 }
1533 
1534 //------------------------------------------------------------------------------
getFastPropertyValue(sal_Int32 nHandle)1535 Any SAL_CALL ODatabaseForm::getFastPropertyValue( sal_Int32 nHandle )
1536 {
1537     if ((nHandle == PROPERTY_ID_ISMODIFIED) && (m_nResetsPending > 0))
1538         return ::cppu::bool2any((sal_False));
1539         // don't allow the aggregate which is currently being reset to return a (temporary) "yes"
1540     else
1541         return OPropertySetAggregationHelper::getFastPropertyValue(nHandle);
1542 }
1543 
1544 //------------------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const1545 void ODatabaseForm::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
1546 {
1547     switch (nHandle)
1548     {
1549         case PROPERTY_ID_INSERTONLY:
1550             rValue <<= m_bInsertOnly;
1551             break;
1552 
1553         case PROPERTY_ID_FILTER:
1554             rValue <<= m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter );
1555             break;
1556 
1557         case PROPERTY_ID_APPLYFILTER:
1558             rValue <<= m_aFilterManager.isApplyPublicFilter();
1559             break;
1560 
1561         case PROPERTY_ID_DATASOURCE:
1562             rValue = m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE );
1563             break;
1564 
1565         case PROPERTY_ID_TARGET_URL:
1566             rValue <<= m_aTargetURL;
1567             break;
1568         case PROPERTY_ID_TARGET_FRAME:
1569             rValue <<= m_aTargetFrame;
1570             break;
1571         case PROPERTY_ID_SUBMIT_METHOD:
1572             rValue <<= m_eSubmitMethod;
1573             break;
1574         case PROPERTY_ID_SUBMIT_ENCODING:
1575             rValue <<= m_eSubmitEncoding;
1576             break;
1577         case PROPERTY_ID_NAME:
1578             rValue <<= m_sName;
1579             break;
1580         case PROPERTY_ID_MASTERFIELDS:
1581             rValue <<= m_aMasterFields;
1582             break;
1583         case PROPERTY_ID_DETAILFIELDS:
1584             rValue <<= m_aDetailFields;
1585             break;
1586         case PROPERTY_ID_CYCLE:
1587             rValue = m_aCycle;
1588             break;
1589         case PROPERTY_ID_NAVIGATION:
1590             rValue <<= m_eNavigation;
1591             break;
1592         case PROPERTY_ID_ALLOWADDITIONS:
1593             rValue <<= (sal_Bool)m_bAllowInsert;
1594             break;
1595         case PROPERTY_ID_ALLOWEDITS:
1596             rValue <<= (sal_Bool)m_bAllowUpdate;
1597             break;
1598         case PROPERTY_ID_ALLOWDELETIONS:
1599             rValue <<= (sal_Bool)m_bAllowDelete;
1600             break;
1601         case PROPERTY_ID_PRIVILEGES:
1602             rValue <<= (sal_Int32)m_nPrivileges;
1603             break;
1604         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1605             rValue = m_aDynamicControlBorder;
1606             break;
1607         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1608             rValue = m_aControlBorderColorFocus;
1609             break;
1610         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1611             rValue = m_aControlBorderColorMouse;
1612             break;
1613         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1614             rValue = m_aControlBorderColorInvalid;
1615             break;
1616         default:
1617             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1618                 m_aPropertyBagHelper.getDynamicFastPropertyValue( nHandle, rValue );
1619             else
1620                 OPropertySetAggregationHelper::getFastPropertyValue( rValue, nHandle );
1621             break;
1622     }
1623 }
1624 
1625 //------------------------------------------------------------------------------
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)1626 sal_Bool ODatabaseForm::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue,
1627                                                 sal_Int32 nHandle, const Any& rValue )
1628 {
1629     sal_Bool bModified(sal_False);
1630     switch (nHandle)
1631     {
1632         case PROPERTY_ID_INSERTONLY:
1633             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bInsertOnly );
1634             break;
1635 
1636         case PROPERTY_ID_FILTER:
1637             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ) );
1638             break;
1639 
1640         case PROPERTY_ID_APPLYFILTER:
1641             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aFilterManager.isApplyPublicFilter() );
1642             break;
1643 
1644         case PROPERTY_ID_DATASOURCE:
1645         {
1646             Any aAggregateProperty;
1647             getFastPropertyValue(aAggregateProperty, PROPERTY_ID_DATASOURCE);
1648             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, aAggregateProperty, ::getCppuType(static_cast<const ::rtl::OUString*>(NULL)));
1649         }
1650         break;
1651         case PROPERTY_ID_TARGET_URL:
1652             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetURL);
1653             break;
1654         case PROPERTY_ID_TARGET_FRAME:
1655             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTargetFrame);
1656             break;
1657         case PROPERTY_ID_SUBMIT_METHOD:
1658             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitMethod);
1659             break;
1660         case PROPERTY_ID_SUBMIT_ENCODING:
1661             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eSubmitEncoding);
1662             break;
1663         case PROPERTY_ID_NAME:
1664             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sName);
1665             break;
1666         case PROPERTY_ID_MASTERFIELDS:
1667             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aMasterFields);
1668             break;
1669         case PROPERTY_ID_DETAILFIELDS:
1670             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDetailFields);
1671             break;
1672         case PROPERTY_ID_CYCLE:
1673             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
1674             break;
1675         case PROPERTY_ID_NAVIGATION:
1676             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_eNavigation);
1677             break;
1678         case PROPERTY_ID_ALLOWADDITIONS:
1679             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowInsert);
1680             break;
1681         case PROPERTY_ID_ALLOWEDITS:
1682             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowUpdate);
1683             break;
1684         case PROPERTY_ID_ALLOWDELETIONS:
1685             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAllowDelete);
1686             break;
1687         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1688             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aDynamicControlBorder, ::getBooleanCppuType() );
1689             break;
1690         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1691             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorFocus, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1692             break;
1693         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1694             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorMouse, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1695             break;
1696         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1697             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_aControlBorderColorInvalid, getCppuType( static_cast< sal_Int32* >( NULL ) ) );
1698             break;
1699         default:
1700             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle ( nHandle ) )
1701                 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( nHandle, rValue, rConvertedValue, rOldValue );
1702             else
1703                 bModified = OPropertySetAggregationHelper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
1704             break;
1705     }
1706     return bModified;
1707 }
1708 
1709 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)1710 void ODatabaseForm::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
1711 {
1712     switch (nHandle)
1713     {
1714         case PROPERTY_ID_INSERTONLY:
1715             rValue >>= m_bInsertOnly;
1716             if ( m_aIgnoreResult.hasValue() )
1717                 m_aIgnoreResult <<= m_bInsertOnly;
1718             else
1719                 m_xAggregateSet->setPropertyValue( PROPERTY_INSERTONLY, makeAny( m_bInsertOnly ) );
1720             break;
1721 
1722         case PROPERTY_ID_FILTER:
1723         {
1724             ::rtl::OUString sNewFilter;
1725             rValue >>= sNewFilter;
1726             m_aFilterManager.setFilterComponent( FilterManager::fcPublicFilter, sNewFilter );
1727         }
1728         break;
1729 
1730         case PROPERTY_ID_APPLYFILTER:
1731         {
1732             sal_Bool bApply = sal_True;
1733             rValue >>= bApply;
1734             m_aFilterManager.setApplyPublicFilter( bApply );
1735         }
1736         break;
1737 
1738         case PROPERTY_ID_DATASOURCE:
1739         {
1740             Reference< XConnection > xSomeConnection;
1741             if ( ::dbtools::isEmbeddedInDatabase( getParent(), xSomeConnection ) )
1742                 throw PropertyVetoException();
1743 
1744             try
1745             {
1746                 m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, rValue);
1747             }
1748             catch(Exception&) { }
1749         }
1750         break;
1751         case PROPERTY_ID_TARGET_URL:
1752             rValue >>= m_aTargetURL;
1753             break;
1754         case PROPERTY_ID_TARGET_FRAME:
1755             rValue >>= m_aTargetFrame;
1756             break;
1757         case PROPERTY_ID_SUBMIT_METHOD:
1758             rValue >>= m_eSubmitMethod;
1759             break;
1760         case PROPERTY_ID_SUBMIT_ENCODING:
1761             rValue >>= m_eSubmitEncoding;
1762             break;
1763         case PROPERTY_ID_NAME:
1764             rValue >>= m_sName;
1765             break;
1766         case PROPERTY_ID_MASTERFIELDS:
1767             rValue >>= m_aMasterFields;
1768             invlidateParameters();
1769             break;
1770         case PROPERTY_ID_DETAILFIELDS:
1771             rValue >>= m_aDetailFields;
1772             invlidateParameters();
1773             break;
1774         case PROPERTY_ID_CYCLE:
1775             m_aCycle = rValue;
1776             break;
1777         case PROPERTY_ID_NAVIGATION:
1778             rValue >>= m_eNavigation;
1779             break;
1780         case PROPERTY_ID_ALLOWADDITIONS:
1781             m_bAllowInsert = getBOOL(rValue);
1782             break;
1783         case PROPERTY_ID_ALLOWEDITS:
1784             m_bAllowUpdate = getBOOL(rValue);
1785             break;
1786         case PROPERTY_ID_ALLOWDELETIONS:
1787             m_bAllowDelete = getBOOL(rValue);
1788             break;
1789         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1790             m_aDynamicControlBorder = rValue;
1791             break;
1792         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1793             m_aControlBorderColorFocus = rValue;
1794             break;
1795         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1796             m_aControlBorderColorMouse = rValue;
1797             break;
1798         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1799             m_aControlBorderColorInvalid = rValue;
1800             break;
1801 
1802         case PROPERTY_ID_ACTIVE_CONNECTION:
1803         {
1804             Reference< XConnection > xOuterConnection;
1805             if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
1806             {
1807                 if ( xOuterConnection != Reference< XConnection >( rValue, UNO_QUERY ) )
1808                     // somebody's trying to set a connection which is not equal the connection
1809                     // implied by the database we're embedded in
1810                     throw PropertyVetoException();
1811             }
1812             OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
1813             break;
1814         }
1815 
1816         default:
1817             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1818                 m_aPropertyBagHelper.setDynamicFastPropertyValue( nHandle, rValue );
1819             else
1820                 OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
1821             break;
1822     }
1823 }
1824 
1825 //------------------------------------------------------------------
forwardingPropertyValue(sal_Int32 _nHandle)1826 void SAL_CALL ODatabaseForm::forwardingPropertyValue( sal_Int32 _nHandle )
1827 {
1828     OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardingPropertyValue: unexpected property!" );
1829     if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
1830     {
1831         if ( m_bSharingConnection )
1832             stopSharingConnection( );
1833         m_bForwardingConnection = sal_True;
1834     }
1835 }
1836 
1837 //------------------------------------------------------------------
forwardedPropertyValue(sal_Int32 _nHandle,bool)1838 void SAL_CALL ODatabaseForm::forwardedPropertyValue( sal_Int32 _nHandle, bool /*_bSuccess*/ )
1839 {
1840     OSL_ENSURE( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION, "ODatabaseForm::forwardedPropertyValue: unexpected property!" );
1841     if ( _nHandle == PROPERTY_ID_ACTIVE_CONNECTION )
1842     {
1843         m_bForwardingConnection = sal_False;
1844     }
1845 }
1846 
1847 //==============================================================================
1848 // com::sun::star::beans::XPropertyState
1849 //------------------------------------------------------------------
getPropertyStateByHandle(sal_Int32 nHandle)1850 PropertyState ODatabaseForm::getPropertyStateByHandle(sal_Int32 nHandle)
1851 {
1852     PropertyState eState;
1853     switch (nHandle)
1854     {
1855         case PROPERTY_ID_NAVIGATION:
1856             return (NavigationBarMode_CURRENT == m_eNavigation) ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
1857 
1858         case PROPERTY_ID_CYCLE:
1859             eState = m_aCycle.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1860             break;
1861 
1862         case PROPERTY_ID_INSERTONLY:
1863             eState = m_bInsertOnly ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1864             break;
1865 
1866         case PROPERTY_ID_FILTER:
1867             if ( !m_aFilterManager.getFilterComponent( FilterManager::fcPublicFilter ).getLength() )
1868                 eState = PropertyState_DEFAULT_VALUE;
1869             else
1870                 eState = PropertyState_DIRECT_VALUE;
1871             break;
1872 
1873         case PROPERTY_ID_APPLYFILTER:
1874             eState = m_aFilterManager.isApplyPublicFilter() ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
1875             break;
1876 
1877         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1878             eState = m_aDynamicControlBorder.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1879             break;
1880 
1881         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1882             eState = m_aControlBorderColorFocus.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1883             break;
1884 
1885         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1886             eState = m_aControlBorderColorMouse.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1887             break;
1888 
1889         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1890             eState = m_aControlBorderColorInvalid.hasValue() ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1891             break;
1892 
1893         default:
1894             eState = OPropertySetAggregationHelper::getPropertyStateByHandle(nHandle);
1895     }
1896     return eState;
1897 }
1898 
1899 //------------------------------------------------------------------
setPropertyToDefaultByHandle(sal_Int32 nHandle)1900 void ODatabaseForm::setPropertyToDefaultByHandle(sal_Int32 nHandle)
1901 {
1902     switch (nHandle)
1903     {
1904         case PROPERTY_ID_INSERTONLY:
1905         case PROPERTY_ID_FILTER:
1906         case PROPERTY_ID_APPLYFILTER:
1907         case PROPERTY_ID_NAVIGATION:
1908         case PROPERTY_ID_CYCLE:
1909         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1910         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1911         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1912         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1913             setFastPropertyValue( nHandle, getPropertyDefaultByHandle( nHandle ) );
1914             break;
1915 
1916         default:
1917             OPropertySetAggregationHelper::setPropertyToDefaultByHandle(nHandle);
1918     }
1919 }
1920 
1921 //------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 nHandle) const1922 Any ODatabaseForm::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
1923 {
1924     Any aReturn;
1925     switch (nHandle)
1926     {
1927         case PROPERTY_ID_INSERTONLY:
1928         case PROPERTY_ID_DYNAMIC_CONTROL_BORDER:
1929             aReturn <<= sal_False;
1930             break;
1931 
1932         case PROPERTY_ID_FILTER:
1933             aReturn <<= ::rtl::OUString();
1934             break;
1935 
1936         case PROPERTY_ID_APPLYFILTER:
1937             aReturn <<= sal_True;
1938             break;
1939 
1940         case PROPERTY_ID_NAVIGATION:
1941             aReturn = makeAny(NavigationBarMode_CURRENT);
1942             break;
1943 
1944         case PROPERTY_ID_CYCLE:
1945         case PROPERTY_ID_CONTROL_BORDER_COLOR_FOCUS:
1946         case PROPERTY_ID_CONTROL_BORDER_COLOR_MOUSE:
1947         case PROPERTY_ID_CONTROL_BORDER_COLOR_INVALID:
1948             break;
1949 
1950         default:
1951             if ( m_aPropertyBagHelper.hasDynamicPropertyByHandle( nHandle ) )
1952                 m_aPropertyBagHelper.getDynamicPropertyDefaultByHandle( nHandle, aReturn );
1953             else
1954                 aReturn = OPropertySetAggregationHelper::getPropertyDefaultByHandle( nHandle );
1955             break;
1956     }
1957     return aReturn;
1958 }
1959 
1960 //==============================================================================
1961 // com::sun::star::form::XReset
1962 //------------------------------------------------------------------------------
reset()1963 void SAL_CALL ODatabaseForm::reset()
1964 {
1965     ::osl::ResettableMutexGuard aGuard(m_aMutex);
1966 
1967     if (isLoaded())
1968     {
1969         ::osl::MutexGuard aResetGuard(m_aResetSafety);
1970         ++m_nResetsPending;
1971         reset_impl(true);
1972         return;
1973     }
1974 
1975     if ( !m_aResetListeners.empty() )
1976     {
1977         ::osl::MutexGuard aResetGuard(m_aResetSafety);
1978         ++m_nResetsPending;
1979         // create an own thread if we have (approve-)reset-listeners (so the listeners can't do that much damage
1980         // to this thread which is probably the main one)
1981         if (!m_pThread)
1982         {
1983             m_pThread = new OFormSubmitResetThread(this);
1984             m_pThread->acquire();
1985             m_pThread->create();
1986         }
1987         EventObject aEvt;
1988         m_pThread->addEvent(&aEvt, sal_False);
1989     }
1990     else
1991     {
1992         // direct call without any approving by the listeners
1993         aGuard.clear();
1994 
1995         ::osl::MutexGuard aResetGuard(m_aResetSafety);
1996         ++m_nResetsPending;
1997         reset_impl(false);
1998     }
1999 }
2000 
2001 //-----------------------------------------------------------------------------
reset_impl(bool _bAproveByListeners)2002 void ODatabaseForm::reset_impl(bool _bAproveByListeners)
2003 {
2004     if ( _bAproveByListeners )
2005         if ( !m_aResetListeners.approveReset() )
2006             return;
2007 
2008     ::osl::ResettableMutexGuard aResetGuard(m_aResetSafety);
2009     // do we have a database connected form and stay on the insert row
2010     sal_Bool bInsertRow = sal_False;
2011     if (m_xAggregateSet.is())
2012         bInsertRow = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW));
2013     if (bInsertRow)
2014     {
2015         try
2016         {
2017             // Iterate through all columns and set the default value
2018             Reference< XColumnsSupplier > xColsSuppl( m_xAggregateSet, UNO_QUERY );
2019             Reference< XIndexAccess > xIndexCols( xColsSuppl->getColumns(), UNO_QUERY );
2020             for (sal_Int32 i = 0; i < xIndexCols->getCount(); ++i)
2021             {
2022                 Reference< XPropertySet > xColProps;
2023                 xIndexCols->getByIndex(i) >>= xColProps;
2024 
2025                 Reference< XColumnUpdate > xColUpdate( xColProps, UNO_QUERY );
2026                 if ( !xColUpdate.is() )
2027                     continue;
2028 
2029                 Reference< XPropertySetInfo > xPSI;
2030                 if ( xColProps.is() )
2031                     xPSI = xColProps->getPropertySetInfo( );
2032 
2033                 static const ::rtl::OUString PROPERTY_CONTROLDEFAULT( RTL_CONSTASCII_USTRINGPARAM( "ControlDefault" ) );
2034                 if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_CONTROLDEFAULT ) )
2035                 {
2036                     Any aDefault = xColProps->getPropertyValue( PROPERTY_CONTROLDEFAULT );
2037 
2038                     sal_Bool bReadOnly = sal_False;
2039                     if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
2040                         xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= bReadOnly;
2041 
2042                     if ( !bReadOnly )
2043                     {
2044                         try
2045                         {
2046                             if ( aDefault.hasValue() )
2047                                 xColUpdate->updateObject( aDefault );
2048                         }
2049                         catch(Exception&)
2050                         {
2051                             DBG_UNHANDLED_EXCEPTION();
2052                         }
2053                     }
2054                 }
2055             }
2056         }
2057         catch(Exception&)
2058         {
2059         }
2060 
2061         if (m_bSubForm)
2062         {
2063             Reference< XColumnsSupplier > xParentColSupp( m_xParent, UNO_QUERY );
2064             Reference< XNameAccess >      xParentCols;
2065             if ( xParentColSupp.is() )
2066                 xParentCols = xParentColSupp->getColumns();
2067 
2068             if ( xParentCols.is() && xParentCols->hasElements() && m_aMasterFields.getLength() )
2069             {
2070                 try
2071                 {
2072                     // analyze our parameters
2073                     if ( !m_aParameterManager.isUpToDate() )
2074                         updateParameterInfo();
2075 
2076                     m_aParameterManager.resetParameterValues( );
2077                 }
2078                 catch(const Exception&)
2079                 {
2080                     OSL_ENSURE(sal_False, "ODatabaseForm::reset_impl: could not initialize the master-detail-driven parameters!");
2081                 }
2082             }
2083         }
2084     }
2085 
2086     aResetGuard.clear();
2087     // iterate through all components. don't use an XIndexAccess as this will cause massive
2088     // problems with the count.
2089     Reference<XEnumeration>  xIter = createEnumeration();
2090     while (xIter->hasMoreElements())
2091     {
2092         Reference<XReset> xReset;
2093         xIter->nextElement() >>= xReset;
2094         if (xReset.is())
2095         {
2096             // TODO : all reset-methods have to be thread-safe
2097             xReset->reset();
2098         }
2099     }
2100 
2101     aResetGuard.reset();
2102     // ensure that the row isn't modified
2103     // (do this _before_ the listeners are notified ! their reaction (maybe asynchronous) may depend
2104     // on the modified state of the row
2105     // 21.02.00 - 73265 - FS)
2106     if (bInsertRow)
2107         m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any(sal_Bool(sal_False)));
2108 
2109     aResetGuard.clear();
2110     {
2111         m_aResetListeners.resetted();
2112     }
2113 
2114     aResetGuard.reset();
2115     // and again : ensure the row isn't modified
2116     // we already did this after we (and maybe our dependents) resetted the values, but the listeners may have changed the row, too
2117     if (bInsertRow)
2118         m_xAggregateSet->setPropertyValue(PROPERTY_ISMODIFIED, ::cppu::bool2any((sal_False)));
2119 
2120     --m_nResetsPending;
2121 }
2122 
2123 //-----------------------------------------------------------------------------
addResetListener(const Reference<XResetListener> & _rListener)2124 void SAL_CALL ODatabaseForm::addResetListener(const Reference<XResetListener>& _rListener)
2125 {
2126     m_aResetListeners.addTypedListener( _rListener );
2127 }
2128 
2129 //-----------------------------------------------------------------------------
removeResetListener(const Reference<XResetListener> & _rListener)2130 void SAL_CALL ODatabaseForm::removeResetListener(const Reference<XResetListener>& _rListener)
2131 {
2132     m_aResetListeners.removeTypedListener( _rListener );
2133 }
2134 
2135 //==============================================================================
2136 // com::sun::star::form::XSubmit
2137 //------------------------------------------------------------------------------
submit(const Reference<XControl> & Control,const::com::sun::star::awt::MouseEvent & MouseEvt)2138 void SAL_CALL ODatabaseForm::submit( const Reference<XControl>& Control,
2139                               const ::com::sun::star::awt::MouseEvent& MouseEvt )
2140 {
2141     {
2142         ::osl::MutexGuard aGuard(m_aMutex);
2143         // Sind Controls und eine Submit-URL vorhanden?
2144         if( !getCount() || !m_aTargetURL.getLength() )
2145             return;
2146     }
2147 
2148     ::osl::ClearableMutexGuard aGuard(m_aMutex);
2149     if (m_aSubmitListeners.getLength())
2150     {
2151         // create an own thread if we have (approve-)submit-listeners (so the listeners can't do that much damage
2152         // to this thread which is probably the main one)
2153         if (!m_pThread)
2154         {
2155             m_pThread = new OFormSubmitResetThread(this);
2156             m_pThread->acquire();
2157             m_pThread->create();
2158         }
2159         m_pThread->addEvent(&MouseEvt, Control, sal_True);
2160     }
2161     else
2162     {
2163         // direct call without any approving by the listeners
2164         aGuard.clear();
2165         submit_impl( Control, MouseEvt, true );
2166     }
2167 }
2168 // -----------------------------------------------------------------------------
lcl_dispatch(const Reference<XFrame> & xFrame,const Reference<XURLTransformer> & xTransformer,const::rtl::OUString & aURLStr,const::rtl::OUString & aReferer,const::rtl::OUString & aTargetName,const::rtl::OUString & aData,rtl_TextEncoding _eEncoding)2169 void lcl_dispatch(const Reference< XFrame >& xFrame,const Reference<XURLTransformer>& xTransformer,const ::rtl::OUString& aURLStr,const ::rtl::OUString& aReferer,const ::rtl::OUString& aTargetName
2170                   ,const ::rtl::OUString& aData,rtl_TextEncoding _eEncoding)
2171 {
2172     URL aURL;
2173     aURL.Complete = aURLStr;
2174     xTransformer->parseStrict(aURL);
2175 
2176     Reference< XDispatch >  xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2177         FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2178         FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2179 
2180     if (xDisp.is())
2181     {
2182         Sequence<PropertyValue> aArgs(2);
2183         aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer");
2184         aArgs.getArray()[0].Value <<= aReferer;
2185 
2186         // build a sequence from the to-be-submitted string
2187         ByteString a8BitData(aData.getStr(), (sal_uInt16)aData.getLength(), _eEncoding);
2188             // always ANSI #58641
2189         Sequence< sal_Int8 > aPostData((sal_Int8*)a8BitData.GetBuffer(), a8BitData.Len());
2190         Reference< XInputStream > xPostData = new SequenceInputStream(aPostData);
2191 
2192         aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("PostData");
2193         aArgs.getArray()[1].Value <<= xPostData;
2194 
2195         xDisp->dispatch(aURL, aArgs);
2196     } // if (xDisp.is())
2197 }
2198 //------------------------------------------------------------------------------
submit_impl(const Reference<XControl> & Control,const::com::sun::star::awt::MouseEvent & MouseEvt,bool _bAproveByListeners)2199 void ODatabaseForm::submit_impl(const Reference<XControl>& Control, const ::com::sun::star::awt::MouseEvent& MouseEvt, bool _bAproveByListeners)
2200 {
2201 
2202     if (_bAproveByListeners)
2203     {
2204         ::cppu::OInterfaceIteratorHelper aIter(m_aSubmitListeners);
2205         EventObject aEvt(static_cast<XWeak*>(this));
2206         sal_Bool bCanceled = sal_False;
2207         while (aIter.hasMoreElements() && !bCanceled)
2208         {
2209             if (!((XSubmitListener*)aIter.next())->approveSubmit(aEvt))
2210                 bCanceled = sal_True;
2211         }
2212 
2213         if (bCanceled)
2214             return;
2215     }
2216 
2217     FormSubmitEncoding eSubmitEncoding;
2218     FormSubmitMethod eSubmitMethod;
2219     ::rtl::OUString aURLStr;
2220     ::rtl::OUString aReferer;
2221     ::rtl::OUString aTargetName;
2222     Reference< XModel >  xModel;
2223     {
2224         ::vos::OGuard aGuard( Application::GetSolarMutex() );
2225         // starform->Forms
2226 
2227         Reference<XChild>  xParent(m_xParent, UNO_QUERY);
2228 
2229         if (xParent.is())
2230             xModel = getXModel(xParent->getParent());
2231 
2232         if (xModel.is())
2233             aReferer = xModel->getURL();
2234 
2235         // TargetItem
2236         aTargetName = m_aTargetFrame;
2237 
2238         eSubmitEncoding = m_eSubmitEncoding;
2239         eSubmitMethod = m_eSubmitMethod;
2240         aURLStr = m_aTargetURL;
2241     }
2242 
2243     if (!xModel.is())
2244         return;
2245     Reference< XFrame >  xFrame = xModel->getCurrentController()->getFrame();
2246     if (!xFrame.is())
2247         return;
2248 
2249     Reference<XURLTransformer>
2250         xTransformer(m_xServiceFactory->createInstance(
2251             ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY);
2252     DBG_ASSERT(xTransformer.is(), "ODatabaseForm::submit_impl : could not create an URL transformer !");
2253 
2254     // URL-Encoding
2255     if( eSubmitEncoding == FormSubmitEncoding_URL )
2256     {
2257         ::rtl::OUString aData;
2258         {
2259             ::vos::OGuard aGuard( Application::GetSolarMutex() );
2260             aData = GetDataURLEncoded( Control, MouseEvt );
2261         }
2262 
2263         URL aURL;
2264         // FormMethod GET
2265         if( eSubmitMethod == FormSubmitMethod_GET )
2266         {
2267             INetURLObject aUrlObj( aURLStr, INetURLObject::WAS_ENCODED );
2268             aUrlObj.SetParam( aData, INetURLObject::ENCODE_ALL );
2269             aURL.Complete = aUrlObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
2270             if (xTransformer.is())
2271                 xTransformer->parseStrict(aURL);
2272 
2273             Reference< XDispatch >  xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2274                     FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2275                     FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2276 
2277             if (xDisp.is())
2278             {
2279                 Sequence<PropertyValue> aArgs(1);
2280                 aArgs.getArray()->Name = ::rtl::OUString::createFromAscii("Referer");
2281                 aArgs.getArray()->Value <<= aReferer;
2282                 xDisp->dispatch(aURL, aArgs);
2283             }
2284         }
2285         // FormMethod POST
2286         else if( eSubmitMethod == FormSubmitMethod_POST )
2287         {
2288             lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,RTL_TEXTENCODING_MS_1252);
2289         }
2290     }
2291     else if( eSubmitEncoding == FormSubmitEncoding_MULTIPART )
2292     {
2293         URL aURL;
2294         aURL.Complete = aURLStr;
2295         xTransformer->parseStrict(aURL);
2296 
2297         Reference< XDispatch >  xDisp = Reference< XDispatchProvider > (xFrame,UNO_QUERY)->queryDispatch(aURL, aTargetName,
2298                 FrameSearchFlag::SELF | FrameSearchFlag::PARENT | FrameSearchFlag::CHILDREN |
2299                 FrameSearchFlag::SIBLINGS | FrameSearchFlag::CREATE | FrameSearchFlag::TASKS);
2300 
2301         if (xDisp.is())
2302         {
2303             ::rtl::OUString aContentType;
2304             Sequence<sal_Int8> aData;
2305             {
2306                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
2307                 aData = GetDataMultiPartEncoded(Control, MouseEvt, aContentType);
2308             }
2309             if (!aData.getLength())
2310                 return;
2311 
2312             Sequence<PropertyValue> aArgs(3);
2313             aArgs.getArray()[0].Name = ::rtl::OUString::createFromAscii("Referer");
2314             aArgs.getArray()[0].Value <<= aReferer;
2315             aArgs.getArray()[1].Name = ::rtl::OUString::createFromAscii("ContentType");
2316             aArgs.getArray()[1].Value <<= aContentType;
2317 
2318             // build a sequence from the to-be-submitted string
2319             Reference< XInputStream > xPostData = new SequenceInputStream(aData);
2320 
2321             aArgs.getArray()[2].Name = ::rtl::OUString::createFromAscii("PostData");
2322             aArgs.getArray()[2].Value <<= xPostData;
2323 
2324             xDisp->dispatch(aURL, aArgs);
2325         }
2326     }
2327     else if( eSubmitEncoding == FormSubmitEncoding_TEXT )
2328     {
2329         ::rtl::OUString aData;
2330         {
2331             ::vos::OGuard aGuard( Application::GetSolarMutex() );
2332             aData = GetDataTextEncoded( Reference<XControl> (), MouseEvt );
2333         }
2334 
2335         lcl_dispatch(xFrame,xTransformer,aURLStr,aReferer,aTargetName,aData,osl_getThreadTextEncoding());
2336     }
2337     else {
2338         DBG_ERROR("ODatabaseForm::submit_Impl : wrong encoding !");
2339     }
2340 
2341 }
2342 
2343 // XSubmit
2344 //------------------------------------------------------------------------------
addSubmitListener(const Reference<XSubmitListener> & _rListener)2345 void SAL_CALL ODatabaseForm::addSubmitListener(const Reference<XSubmitListener>& _rListener)
2346 {
2347     m_aSubmitListeners.addInterface(_rListener);
2348 }
2349 
2350 //------------------------------------------------------------------------------
removeSubmitListener(const Reference<XSubmitListener> & _rListener)2351 void SAL_CALL ODatabaseForm::removeSubmitListener(const Reference<XSubmitListener>& _rListener)
2352 {
2353     m_aSubmitListeners.removeInterface(_rListener);
2354 }
2355 
2356 //==============================================================================
2357 // com::sun::star::sdbc::XSQLErrorBroadcaster
2358 //------------------------------------------------------------------------------
addSQLErrorListener(const Reference<XSQLErrorListener> & _rListener)2359 void SAL_CALL ODatabaseForm::addSQLErrorListener(const Reference<XSQLErrorListener>& _rListener)
2360 {
2361     m_aErrorListeners.addInterface(_rListener);
2362 }
2363 
2364 //------------------------------------------------------------------------------
removeSQLErrorListener(const Reference<XSQLErrorListener> & _rListener)2365 void SAL_CALL ODatabaseForm::removeSQLErrorListener(const Reference<XSQLErrorListener>& _rListener)
2366 {
2367     m_aErrorListeners.removeInterface(_rListener);
2368 }
2369 
2370 //------------------------------------------------------------------------------
invlidateParameters()2371 void ODatabaseForm::invlidateParameters()
2372 {
2373     ::osl::MutexGuard aGuard(m_aMutex);
2374     m_aParameterManager.clearAllParameterInformation();
2375 }
2376 
2377 //==============================================================================
2378 // OChangeListener
2379 //------------------------------------------------------------------------------
_propertyChanged(const PropertyChangeEvent & evt)2380 void ODatabaseForm::_propertyChanged(const PropertyChangeEvent& evt)
2381 {
2382     if ((0 == evt.PropertyName.compareToAscii(PROPERTY_ACTIVE_CONNECTION)) && !m_bForwardingConnection)
2383     {
2384         // the rowset changed its active connection itself (without interaction from our side), so
2385         // we need to fire this event, too
2386         sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION;
2387         fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
2388     }
2389     else    // it was one of the statement relevant props
2390     {
2391         // if the statement has changed we have to delete the parameter info
2392         invlidateParameters();
2393     }
2394 }
2395 
2396 //==============================================================================
2397 // smartXChild
2398 //------------------------------------------------------------------------------
setParent(const InterfaceRef & Parent)2399 void SAL_CALL ODatabaseForm::setParent(const InterfaceRef& Parent)
2400 {
2401     // SYNCHRONIZED ----->
2402     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2403 
2404     Reference<XForm>  xParentForm(getParent(), UNO_QUERY);
2405     if (xParentForm.is())
2406     {
2407         try
2408         {
2409             Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
2410             xParentApprBroadcast->removeRowSetApproveListener( this );
2411 
2412             Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
2413             xParentLoadable->removeLoadListener( this );
2414 
2415             Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
2416             xParentProperties->removePropertyChangeListener( PROPERTY_ISNEW, this );
2417         }
2418         catch( const Exception& )
2419         {
2420             DBG_UNHANDLED_EXCEPTION();
2421         }
2422     }
2423 
2424     OFormComponents::setParent(Parent);
2425 
2426     xParentForm.set(getParent(), UNO_QUERY);
2427     if ( xParentForm.is() )
2428     {
2429         try
2430         {
2431             Reference< XRowSetApproveBroadcaster > xParentApprBroadcast( xParentForm, UNO_QUERY_THROW );
2432             xParentApprBroadcast->addRowSetApproveListener( this );
2433 
2434             Reference< XLoadable > xParentLoadable( xParentForm, UNO_QUERY_THROW );
2435             xParentLoadable->addLoadListener( this );
2436 
2437             Reference< XPropertySet > xParentProperties( xParentForm, UNO_QUERY_THROW );
2438             xParentProperties->addPropertyChangeListener( PROPERTY_ISNEW, this );
2439         }
2440         catch( const Exception& )
2441         {
2442             DBG_UNHANDLED_EXCEPTION();
2443         }
2444     }
2445 
2446     Reference< XPropertySet > xAggregateProperties( m_xAggregateSet );
2447     aGuard.clear();
2448     // <----- SYNCHRONIZED
2449 
2450     Reference< XConnection > xOuterConnection;
2451     sal_Bool bIsEmbedded = ::dbtools::isEmbeddedInDatabase( Parent, xOuterConnection );
2452 
2453     if ( bIsEmbedded )
2454         xAggregateProperties->setPropertyValue( PROPERTY_DATASOURCE, makeAny( ::rtl::OUString() ) );
2455 }
2456 
2457 //==============================================================================
2458 // smartXTabControllerModel
2459 //------------------------------------------------------------------------------
getGroupControl()2460 sal_Bool SAL_CALL ODatabaseForm::getGroupControl()
2461 {
2462     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2463 
2464     // Sollen Controls in einer TabOrder gruppe zusammengefasst werden?
2465     if (m_aCycle.hasValue())
2466     {
2467         sal_Int32 nCycle = 0;
2468         ::cppu::enum2int(nCycle, m_aCycle);
2469         return nCycle != TabulatorCycle_PAGE;
2470     }
2471 
2472     if (isLoaded() && getConnection().is())
2473         return sal_True;
2474 
2475     return sal_False;
2476 }
2477 
2478 //------------------------------------------------------------------------------
setControlModels(const Sequence<Reference<XControlModel>> & rControls)2479 void SAL_CALL ODatabaseForm::setControlModels(const Sequence<Reference<XControlModel> >& rControls)
2480 {
2481     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2482 
2483     // TabIndex in der Reihenfolge der Sequence setzen
2484     const Reference<XControlModel>* pControls = rControls.getConstArray();
2485     sal_Int16 nTabIndex = 1;
2486     sal_Int32 nCount = getCount();
2487     sal_Int32 nNewCount = rControls.getLength();
2488 
2489     // HiddenControls und Formulare werden nicht aufgefuehrt
2490     if (nNewCount <= nCount)
2491     {
2492         Any aElement;
2493         for (sal_Int32 i=0; i < nNewCount; ++i, ++pControls)
2494         {
2495             Reference<XFormComponent>  xComp(*pControls, UNO_QUERY);
2496             if (xComp.is())
2497             {
2498                 // suchen der Componente in der Liste
2499                 for (sal_Int32 j = 0; j < nCount; ++j)
2500                 {
2501                     Reference<XFormComponent> xElement;
2502                     ::cppu::extractInterface(xElement, getByIndex(j));
2503                     if (xComp == xElement)
2504                     {
2505                         Reference<XPropertySet>  xSet(xComp, UNO_QUERY);
2506                         if (xSet.is() && hasProperty(PROPERTY_TABINDEX, xSet))
2507                             xSet->setPropertyValue( PROPERTY_TABINDEX, makeAny(nTabIndex++) );
2508                         break;
2509                     }
2510                 }
2511             }
2512         }
2513     }
2514 }
2515 
2516 //------------------------------------------------------------------------------
getControlModels()2517 Sequence<Reference<XControlModel> > SAL_CALL ODatabaseForm::getControlModels()
2518 {
2519     ::osl::MutexGuard aGuard(m_aMutex);
2520     return m_pGroupManager->getControlModels();
2521 }
2522 
2523 //------------------------------------------------------------------------------
setGroup(const Sequence<Reference<XControlModel>> & _rGroup,const::rtl::OUString & Name)2524 void SAL_CALL ODatabaseForm::setGroup( const Sequence<Reference<XControlModel> >& _rGroup, const ::rtl::OUString& Name )
2525 {
2526     ::osl::MutexGuard aGuard(m_aMutex);
2527 
2528     // Die Controls werden gruppiert, indem ihr Name dem Namen des ersten
2529     // Controls der Sequenz angepasst wird
2530     const Reference<XControlModel>* pControls = _rGroup.getConstArray();
2531     Reference< XPropertySet > xSet;
2532     ::rtl::OUString sGroupName( Name );
2533 
2534     for( sal_Int32 i=0; i<_rGroup.getLength(); ++i, ++pControls )
2535     {
2536         xSet = xSet.query( *pControls );
2537         if ( !xSet.is() )
2538         {
2539             // can't throw an exception other than a RuntimeException (which would not be appropriate),
2540             // so we ignore (and only assert) this
2541             OSL_ENSURE( sal_False, "ODatabaseForm::setGroup: invalid arguments!" );
2542             continue;
2543         }
2544 
2545         if (!sGroupName.getLength())
2546             xSet->getPropertyValue(PROPERTY_NAME) >>= sGroupName;
2547         else
2548             xSet->setPropertyValue(PROPERTY_NAME, makeAny(sGroupName));
2549     }
2550 }
2551 
2552 //------------------------------------------------------------------------------
getGroupCount()2553 sal_Int32 SAL_CALL ODatabaseForm::getGroupCount()
2554 {
2555     ::osl::MutexGuard aGuard(m_aMutex);
2556     return m_pGroupManager->getGroupCount();
2557 }
2558 
2559 //------------------------------------------------------------------------------
getGroup(sal_Int32 nGroup,Sequence<Reference<XControlModel>> & _rGroup,::rtl::OUString & _rName)2560 void SAL_CALL ODatabaseForm::getGroup( sal_Int32 nGroup, Sequence<Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName )
2561 {
2562     ::osl::MutexGuard aGuard(m_aMutex);
2563     _rGroup.realloc(0);
2564     _rName = ::rtl::OUString();
2565 
2566     if ((nGroup < 0) || (nGroup >= m_pGroupManager->getGroupCount()))
2567         return;
2568     m_pGroupManager->getGroup( nGroup, _rGroup, _rName  );
2569 }
2570 
2571 //------------------------------------------------------------------------------
getGroupByName(const::rtl::OUString & Name,Sequence<Reference<XControlModel>> & _rGroup)2572 void SAL_CALL ODatabaseForm::getGroupByName(const ::rtl::OUString& Name, Sequence< Reference<XControlModel>  >& _rGroup)
2573 {
2574     ::osl::MutexGuard aGuard(m_aMutex);
2575     _rGroup.realloc(0);
2576     m_pGroupManager->getGroupByName( Name, _rGroup );
2577 }
2578 
2579 //==============================================================================
2580 // com::sun::star::lang::XEventListener
2581 //------------------------------------------------------------------------------
disposing(const EventObject & Source)2582 void SAL_CALL ODatabaseForm::disposing(const EventObject& Source)
2583 {
2584     // does the call come from the connection which we are sharing with our parent?
2585     if ( isSharingConnection() )
2586     {
2587         Reference< XConnection > xConnSource( Source.Source, UNO_QUERY );
2588         if ( xConnSource.is() )
2589         {
2590 #if OSL_DEBUG_LEVEL > 0
2591             Reference< XConnection > xActiveConn;
2592             m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xActiveConn;
2593             OSL_ENSURE( xActiveConn.get() == xConnSource.get(), "ODatabaseForm::disposing: where did this come from?" );
2594                 // there should be exactly one XConnection object we're listening at - our aggregate connection
2595 #endif
2596             disposingSharedConnection( xConnSource );
2597         }
2598     }
2599 
2600     OInterfaceContainer::disposing(Source);
2601 
2602     // does the disposing come from the aggregate ?
2603     if (m_xAggregate.is())
2604     {   // no -> forward it
2605         com::sun::star::uno::Reference<com::sun::star::lang::XEventListener> xListener;
2606         if (query_aggregation(m_xAggregate, xListener))
2607             xListener->disposing(Source);
2608     }
2609 }
2610 
2611 //------------------------------------------------------------------------------
impl_createLoadTimer()2612 void ODatabaseForm::impl_createLoadTimer()
2613 {
2614     OSL_PRECOND( m_pLoadTimer == NULL, "ODatabaseForm::impl_createLoadTimer: timer already exists!" );
2615     m_pLoadTimer = new Timer();
2616     m_pLoadTimer->SetTimeout(100);
2617     m_pLoadTimer->SetTimeoutHdl(LINK(this,ODatabaseForm,OnTimeout));
2618 }
2619 
2620 //==============================================================================
2621 // com::sun::star::form::XLoadListener
2622 //------------------------------------------------------------------------------
loaded(const EventObject &)2623 void SAL_CALL ODatabaseForm::loaded(const EventObject& /*aEvent*/)
2624 {
2625     {
2626         ::osl::MutexGuard aGuard( m_aMutex );
2627         Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW );
2628         xParentRowSet->addRowSetListener( this );
2629 
2630         impl_createLoadTimer();
2631     }
2632 
2633     load_impl( sal_True );
2634 }
2635 
2636 //------------------------------------------------------------------------------
unloading(const EventObject &)2637 void SAL_CALL ODatabaseForm::unloading(const EventObject& /*aEvent*/)
2638 {
2639     {
2640         // now stop the rowset listening if we are a subform
2641         ::osl::MutexGuard aGuard( m_aMutex );
2642 
2643         if ( m_pLoadTimer && m_pLoadTimer->IsActive() )
2644             m_pLoadTimer->Stop();
2645         DELETEZ( m_pLoadTimer );
2646 
2647         Reference< XRowSet > xParentRowSet( m_xParent, UNO_QUERY_THROW );
2648         xParentRowSet->removeRowSetListener( this );
2649     }
2650 
2651     unload();
2652 }
2653 
2654 //------------------------------------------------------------------------------
unloaded(const EventObject &)2655 void SAL_CALL ODatabaseForm::unloaded(const EventObject& /*aEvent*/)
2656 {
2657     // nothing to do
2658 }
2659 
2660 //------------------------------------------------------------------------------
reloading(const EventObject &)2661 void SAL_CALL ODatabaseForm::reloading(const EventObject& /*aEvent*/)
2662 {
2663     // now stop the rowset listening if we are a subform
2664     ::osl::MutexGuard aGuard(m_aMutex);
2665     Reference<XRowSet>  xParentRowSet(m_xParent, UNO_QUERY);
2666     if (xParentRowSet.is())
2667         xParentRowSet->removeRowSetListener(this);
2668 
2669     if (m_pLoadTimer && m_pLoadTimer->IsActive())
2670         m_pLoadTimer->Stop();
2671 }
2672 
2673 //------------------------------------------------------------------------------
reloaded(const EventObject &)2674 void SAL_CALL ODatabaseForm::reloaded(const EventObject& /*aEvent*/)
2675 {
2676     reload_impl(sal_True);
2677     {
2678         ::osl::MutexGuard aGuard(m_aMutex);
2679         Reference<XRowSet>  xParentRowSet(m_xParent, UNO_QUERY);
2680         if (xParentRowSet.is())
2681             xParentRowSet->addRowSetListener(this);
2682     }
2683 }
2684 
2685 //------------------------------------------------------------------------------
IMPL_LINK(ODatabaseForm,OnTimeout,void *,EMPTYARG)2686 IMPL_LINK( ODatabaseForm, OnTimeout, void*, EMPTYARG )
2687 {
2688     reload_impl(sal_True);
2689     return 1;
2690 }
2691 
2692 //==============================================================================
2693 // com::sun::star::form::XLoadable
2694 //------------------------------------------------------------------------------
load()2695 void SAL_CALL ODatabaseForm::load()
2696 {
2697     load_impl(sal_False);
2698 }
2699 
2700 //------------------------------------------------------------------------------
canShareConnection(const Reference<XPropertySet> & _rxParentProps)2701 sal_Bool ODatabaseForm::canShareConnection( const Reference< XPropertySet >& _rxParentProps )
2702 {
2703     // our own data source
2704     ::rtl::OUString sOwnDatasource;
2705     m_xAggregateSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= sOwnDatasource;
2706 
2707     // our parents data source
2708     ::rtl::OUString sParentDataSource;
2709     OSL_ENSURE( _rxParentProps.is() && _rxParentProps->getPropertySetInfo().is() && _rxParentProps->getPropertySetInfo()->hasPropertyByName( PROPERTY_DATASOURCE ),
2710         "ODatabaseForm::doShareConnection: invalid parent form!" );
2711     if ( _rxParentProps.is() )
2712         _rxParentProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sParentDataSource;
2713 
2714     sal_Bool bCanShareConnection = sal_False;
2715 
2716     // both rowsets share are connected to the same data source
2717     if ( sParentDataSource == sOwnDatasource )
2718     {
2719         if ( 0 != sParentDataSource.getLength() )
2720             // and it's really a data source name (not empty)
2721             bCanShareConnection = sal_True;
2722         else
2723         {   // the data source name is empty
2724             // -> ook for the URL
2725             ::rtl::OUString sParentURL;
2726             ::rtl::OUString sMyURL;
2727             _rxParentProps->getPropertyValue( PROPERTY_URL ) >>= sParentURL;
2728             m_xAggregateSet->getPropertyValue( PROPERTY_URL ) >>= sMyURL;
2729 
2730             bCanShareConnection = (sParentURL == sMyURL);
2731         }
2732     }
2733 
2734     if ( bCanShareConnection )
2735     {
2736         // check for the user/password
2737 
2738         // take the user property on the rowset (if any) into account
2739         ::rtl::OUString sParentUser, sParentPwd;
2740         _rxParentProps->getPropertyValue( PROPERTY_USER ) >>= sParentUser;
2741         _rxParentProps->getPropertyValue( PROPERTY_PASSWORD ) >>= sParentPwd;
2742 
2743         ::rtl::OUString sMyUser, sMyPwd;
2744         m_xAggregateSet->getPropertyValue( PROPERTY_USER ) >>= sMyUser;
2745         m_xAggregateSet->getPropertyValue( PROPERTY_PASSWORD ) >>= sMyPwd;
2746 
2747         bCanShareConnection =
2748                 ( sParentUser == sMyUser )
2749             &&  ( sParentPwd == sMyPwd );
2750     }
2751 
2752     return bCanShareConnection;
2753 }
2754 
2755 //------------------------------------------------------------------------------
doShareConnection(const Reference<XPropertySet> & _rxParentProps)2756 void ODatabaseForm::doShareConnection( const Reference< XPropertySet >& _rxParentProps )
2757 {
2758     // get the connection of the parent
2759     Reference< XConnection > xParentConn;
2760     _rxParentProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xParentConn;
2761     OSL_ENSURE( xParentConn.is(), "ODatabaseForm::doShareConnection: we're a valid sub-form, but the parent has no connection?!" );
2762 
2763     if ( xParentConn.is() )
2764     {
2765         // add as dispose listener to the connection
2766         Reference< XComponent > xParentConnComp( xParentConn, UNO_QUERY );
2767         OSL_ENSURE( xParentConnComp.is(), "ODatabaseForm::doShareConnection: invalid connection!" );
2768         xParentConnComp->addEventListener( static_cast< XLoadListener* >( this ) );
2769 
2770         // forward the connection to our own aggreagte
2771         m_bForwardingConnection = sal_True;
2772         m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xParentConn ) );
2773         m_bForwardingConnection = sal_False;
2774 
2775         m_bSharingConnection = sal_True;
2776     }
2777     else
2778         m_bSharingConnection = sal_False;
2779 }
2780 
2781 //------------------------------------------------------------------------------
disposingSharedConnection(const Reference<XConnection> &)2782 void ODatabaseForm::disposingSharedConnection( const Reference< XConnection >& /*_rxConn*/ )
2783 {
2784     stopSharingConnection();
2785 
2786     // TODO: we could think about whether or not to re-connect.
2787     unload( );
2788 }
2789 
2790 //------------------------------------------------------------------------------
stopSharingConnection()2791 void ODatabaseForm::stopSharingConnection( )
2792 {
2793     OSL_ENSURE( m_bSharingConnection, "ODatabaseForm::stopSharingConnection: invalid call!" );
2794 
2795     if ( m_bSharingConnection )
2796     {
2797         // get the connection
2798         Reference< XConnection > xSharedConn;
2799         m_xAggregateSet->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xSharedConn;
2800         OSL_ENSURE( xSharedConn.is(), "ODatabaseForm::stopSharingConnection: there's no conn!" );
2801 
2802         // remove ourself as event listener
2803         Reference< XComponent > xSharedConnComp( xSharedConn, UNO_QUERY );
2804         if ( xSharedConnComp.is() )
2805             xSharedConnComp->removeEventListener( static_cast< XLoadListener* >( this ) );
2806 
2807         // no need to dispose the conn: we're not the owner, this is our parent
2808         // (in addition, this method may be called if the connection is being disposed while we use it)
2809 
2810         // reset the property
2811         xSharedConn.clear();
2812         m_bForwardingConnection = sal_True;
2813         m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xSharedConn ) );
2814         m_bForwardingConnection = sal_False;
2815 
2816         // reset the flag
2817         m_bSharingConnection = sal_False;
2818     }
2819 }
2820 
2821 //------------------------------------------------------------------------------
implEnsureConnection()2822 sal_Bool ODatabaseForm::implEnsureConnection()
2823 {
2824     try
2825     {
2826         if ( getConnection( ).is() )
2827             // if our aggregate already has a connection, nothing needs to be done about it
2828             return sal_True;
2829 
2830         // see whether we're an embedded form
2831         Reference< XConnection > xOuterConnection;
2832         if ( ::dbtools::isEmbeddedInDatabase( getParent(), xOuterConnection ) )
2833         {
2834             m_xAggregateSet->setPropertyValue( PROPERTY_ACTIVE_CONNECTION, makeAny( xOuterConnection ) );
2835             return xOuterConnection.is();
2836         }
2837 
2838         m_bSharingConnection = sal_False;
2839 
2840         // if we're a sub form, we try to re-use the connection of our parent
2841         if (m_bSubForm)
2842         {
2843             OSL_ENSURE( Reference< XForm >( getParent(), UNO_QUERY ).is(),
2844                 "ODatabaseForm::implEnsureConnection: m_bSubForm is TRUE, but the parent is no form?" );
2845 
2846             Reference< XPropertySet > xParentProps( getParent(), UNO_QUERY );
2847 
2848             // can we re-use (aka share) the connection of the parent?
2849             if ( canShareConnection( xParentProps ) )
2850             {
2851                 // yep -> do it
2852                 doShareConnection( xParentProps );
2853                 // success?
2854                 if ( m_bSharingConnection )
2855                     // yes -> outta here
2856                     return sal_True;
2857             }
2858         }
2859 
2860         if (m_xAggregateSet.is())
2861         {
2862             Reference< XConnection >  xConnection = connectRowset(
2863                 Reference<XRowSet> (m_xAggregate, UNO_QUERY),
2864                 m_xServiceFactory,
2865                 sal_True    // set a calculated connection as ActiveConnection
2866             );
2867             return xConnection.is();
2868         }
2869     }
2870     catch(SQLException& eDB)
2871     {
2872         onError(eDB, FRM_RES_STRING(RID_STR_CONNECTERROR));
2873     }
2874     catch( Exception )
2875     {
2876         DBG_UNHANDLED_EXCEPTION();
2877     }
2878 
2879     return sal_False;
2880 }
2881 
2882 //------------------------------------------------------------------------------
load_impl(sal_Bool bCausedByParentForm,sal_Bool bMoveToFirst,const Reference<XInteractionHandler> & _rxCompletionHandler)2883 void ODatabaseForm::load_impl(sal_Bool bCausedByParentForm, sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler )
2884 {
2885     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2886 
2887     // are we already loaded?
2888     if (isLoaded())
2889         return;
2890 
2891     m_bSubForm = bCausedByParentForm;
2892 
2893     // if we don't have a connection, we are not intended to be a database form or the aggregate was not able
2894     // to establish a connection
2895     sal_Bool bConnected = implEnsureConnection();
2896 
2897     // we don't have to execute if we do not have a command to execute
2898     sal_Bool bExecute = bConnected && m_xAggregateSet.is() && getString(m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND)).getLength();
2899 
2900     // a database form always uses caching
2901     // we use starting fetchsize with at least 10 rows
2902     if (bConnected)
2903         m_xAggregateSet->setPropertyValue(PROPERTY_FETCHSIZE, makeAny((sal_Int32)40));
2904 
2905     // if we're loaded as sub form we got a "rowSetChanged" from the parent rowset _before_ we got the "loaded"
2906     // so we don't need to execute the statement again, this was already done
2907     // (and there were no relevant changes between these two listener calls, the "load" of a form is quite an
2908     // atomar operation.)
2909 
2910     sal_Bool bSuccess = sal_False;
2911     if (bExecute)
2912     {
2913         m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_LOADING_FORM);
2914         bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
2915     }
2916 
2917     if (bSuccess)
2918     {
2919         m_bLoaded = sal_True;
2920         aGuard.clear();
2921         EventObject aEvt(static_cast<XWeak*>(this));
2922         m_aLoadListeners.notifyEach( &XLoadListener::loaded, aEvt );
2923 
2924         // if we are on the insert row, we have to reset all controls
2925         // to set the default values
2926         if (bExecute && getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
2927             reset();
2928     }
2929 }
2930 
2931 //------------------------------------------------------------------------------
unload()2932 void SAL_CALL ODatabaseForm::unload()
2933 {
2934     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2935     if (!isLoaded())
2936         return;
2937 
2938     DELETEZ(m_pLoadTimer);
2939 
2940     aGuard.clear();
2941     EventObject aEvt(static_cast<XWeak*>(this));
2942     m_aLoadListeners.notifyEach( &XLoadListener::unloading, aEvt );
2943 
2944     if (m_xAggregateAsRowSet.is())
2945     {
2946         // we may have reset the InsertOnly property on the aggregate - restore it
2947         restoreInsertOnlyState( );
2948 
2949         // clear the parameters if there are any
2950         invlidateParameters();
2951 
2952         try
2953         {
2954             // close the aggregate
2955             Reference<XCloseable>  xCloseable;
2956             query_aggregation( m_xAggregate, xCloseable);
2957             aGuard.clear();
2958             if (xCloseable.is())
2959                 xCloseable->close();
2960         }
2961         catch( const SQLException& e )
2962         {
2963             (void)e;
2964         }
2965         aGuard.reset();
2966     }
2967 
2968     m_bLoaded = sal_False;
2969 
2970     // if the connection we used while we were loaded is only shared with our parent, we
2971     // reset it
2972     if ( isSharingConnection() )
2973         stopSharingConnection();
2974 
2975     aGuard.clear();
2976     m_aLoadListeners.notifyEach( &XLoadListener::unloaded, aEvt );
2977 }
2978 
2979 //------------------------------------------------------------------------------
reload()2980 void SAL_CALL ODatabaseForm::reload()
2981 {
2982     reload_impl(sal_True);
2983 }
2984 
2985 //------------------------------------------------------------------------------
reload_impl(sal_Bool bMoveToFirst,const Reference<XInteractionHandler> & _rxCompletionHandler)2986 void ODatabaseForm::reload_impl(sal_Bool bMoveToFirst, const Reference< XInteractionHandler >& _rxCompletionHandler )
2987 {
2988     ::osl::ResettableMutexGuard aGuard(m_aMutex);
2989     if (!isLoaded())
2990         return;
2991 
2992     DocumentModifyGuard aModifyGuard( *this );
2993         // ensures the document is not marked as "modified" just because we change some control's content during
2994         // reloading ...
2995 
2996     EventObject aEvent(static_cast<XWeak*>(this));
2997     {
2998         // only if there is no approve listener we can post the event at this time
2999         // otherwise see approveRowsetChange
3000         // the aprrovement is done by the aggregate
3001         if (!m_aRowSetApproveListeners.getLength())
3002         {
3003             ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
3004             aGuard.clear();
3005 
3006             while (aIter.hasMoreElements())
3007                 ((XLoadListener*)aIter.next())->reloading(aEvent);
3008 
3009             aGuard.reset();
3010         }
3011     }
3012 
3013     sal_Bool bSuccess = sal_True;
3014     try
3015     {
3016         m_sCurrentErrorContext = FRM_RES_STRING(RID_ERR_REFRESHING_FORM);
3017         bSuccess = executeRowSet(aGuard, bMoveToFirst, _rxCompletionHandler);
3018     }
3019     catch( const SQLException& e )
3020     {
3021         DBG_ERROR("ODatabaseForm::reload_impl : shouldn't executeRowSet catch this exception?");
3022         (void)e;
3023     }
3024 
3025     if (bSuccess)
3026     {
3027         ::cppu::OInterfaceIteratorHelper aIter(m_aLoadListeners);
3028         aGuard.clear();
3029         while (aIter.hasMoreElements())
3030             ((XLoadListener*)aIter.next())->reloaded(aEvent);
3031 
3032         // if we are on the insert row, we have to reset all controls
3033         // to set the default values
3034         if (getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ISNEW)))
3035             reset();
3036     }
3037     else
3038         m_bLoaded = sal_False;
3039 }
3040 
3041 //------------------------------------------------------------------------------
isLoaded()3042 sal_Bool SAL_CALL ODatabaseForm::isLoaded()
3043 {
3044     return m_bLoaded;
3045 }
3046 
3047 //------------------------------------------------------------------------------
addLoadListener(const Reference<XLoadListener> & aListener)3048 void SAL_CALL ODatabaseForm::addLoadListener(const Reference<XLoadListener>& aListener)
3049 {
3050     m_aLoadListeners.addInterface(aListener);
3051 }
3052 
3053 //------------------------------------------------------------------------------
removeLoadListener(const Reference<XLoadListener> & aListener)3054 void SAL_CALL ODatabaseForm::removeLoadListener(const Reference<XLoadListener>& aListener)
3055 {
3056     m_aLoadListeners.removeInterface(aListener);
3057 }
3058 
3059 //==============================================================================
3060 // com::sun::star::sdbc::XCloseable
3061 //==============================================================================
close()3062 void SAL_CALL ODatabaseForm::close()
3063 {
3064     // unload will close the aggregate
3065     unload();
3066 }
3067 
3068 //==============================================================================
3069 // com::sun::star::sdbc::XRowSetListener
3070 //------------------------------------------------------------------------------
cursorMoved(const EventObject &)3071 void SAL_CALL ODatabaseForm::cursorMoved(const EventObject& /*event*/)
3072 {
3073     // reload the subform with the new parameters of the parent
3074     // do this handling delayed to provide of execute too many SQL Statements
3075     ::osl::ResettableMutexGuard aGuard(m_aMutex);
3076 
3077     DBG_ASSERT( m_pLoadTimer, "ODatabaseForm::cursorMoved: how can this happen?!" );
3078     if ( !m_pLoadTimer )
3079         impl_createLoadTimer();
3080 
3081     if ( m_pLoadTimer->IsActive() )
3082         m_pLoadTimer->Stop();
3083 
3084     // and start the timer again
3085     m_pLoadTimer->Start();
3086 }
3087 
3088 //------------------------------------------------------------------------------
rowChanged(const EventObject &)3089 void SAL_CALL ODatabaseForm::rowChanged(const EventObject& /*event*/)
3090 {
3091     // ignore it
3092 }
3093 
3094 //------------------------------------------------------------------------------
rowSetChanged(const EventObject &)3095 void SAL_CALL ODatabaseForm::rowSetChanged(const EventObject& /*event*/)
3096 {
3097     // not interested in :
3098     // if our parent is an ODatabaseForm, too, then after this rowSetChanged we'll get a "reloaded"
3099     // or a "loaded" event.
3100     // If somebody gave us another parent which is an XRowSet but doesn't handle an execute as
3101     // "load" respectively "reload" ... can't do anything ....
3102 }
3103 
3104 //------------------------------------------------------------------------------
impl_approveRowChange_throw(const EventObject & _rEvent,const bool _bAllowSQLException,::osl::ClearableMutexGuard & _rGuard)3105 bool ODatabaseForm::impl_approveRowChange_throw( const EventObject& _rEvent, const bool _bAllowSQLException,
3106     ::osl::ClearableMutexGuard& _rGuard )
3107 {
3108     ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3109     _rGuard.clear();
3110     while ( aIter.hasMoreElements() )
3111     {
3112         Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3113         if ( !xListener.is() )
3114             continue;
3115 
3116         try
3117         {
3118             if ( !xListener->approveRowSetChange( _rEvent ) )
3119                 return false;
3120         }
3121         catch ( const DisposedException& e )
3122         {
3123             if ( e.Context == xListener )
3124                 aIter.remove();
3125         }
3126         catch ( const RuntimeException& ) { throw; }
3127         catch ( const SQLException& )
3128         {
3129             if ( _bAllowSQLException )
3130                 throw;
3131             DBG_UNHANDLED_EXCEPTION();
3132         }
3133         catch ( const Exception& )
3134         {
3135             DBG_UNHANDLED_EXCEPTION();
3136         }
3137     }
3138     return true;
3139 }
3140 
3141 //------------------------------------------------------------------------------
approveCursorMove(const EventObject & event)3142 sal_Bool SAL_CALL ODatabaseForm::approveCursorMove(const EventObject& event)
3143 {
3144     // is our aggregate calling?
3145     if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
3146     {
3147         // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
3148         // for XRowSetApproveBroadcaster-interface.
3149         // So we have to multiplex this approve request.
3150         ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3151         while ( aIter.hasMoreElements() )
3152         {
3153             Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3154             if ( !xListener.is() )
3155                 continue;
3156 
3157             try
3158             {
3159                 if ( !xListener->approveCursorMove( event ) )
3160                     return sal_False;
3161             }
3162             catch ( const DisposedException& e )
3163             {
3164                 if ( e.Context == xListener )
3165                     aIter.remove();
3166             }
3167             catch ( const RuntimeException& ) { throw; }
3168             catch ( const Exception& )
3169             {
3170                 DBG_UNHANDLED_EXCEPTION();
3171             }
3172         }
3173         return true;
3174     }
3175     else
3176     {
3177         // this is a call from our parent ...
3178         // a parent's cursor move will result in a re-execute of our own row-set, so we have to
3179         // ask our own RowSetChangesListeners, too
3180         ::osl::ClearableMutexGuard aGuard( m_aMutex );
3181         if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3182             return sal_False;
3183     }
3184     return sal_True;
3185 }
3186 
3187 //------------------------------------------------------------------------------
approveRowChange(const RowChangeEvent & event)3188 sal_Bool SAL_CALL ODatabaseForm::approveRowChange(const RowChangeEvent& event)
3189 {
3190     // is our aggregate calling?
3191     if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))
3192     {
3193         // Our aggregate doesn't have any ApproveRowSetListeners (expect ourself), as we re-routed the queryInterface
3194         // for XRowSetApproveBroadcaster-interface.
3195         // So we have to multiplex this approve request.
3196         ::cppu::OInterfaceIteratorHelper aIter( m_aRowSetApproveListeners );
3197         while ( aIter.hasMoreElements() )
3198         {
3199             Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aIter.next() ) );
3200             if ( !xListener.is() )
3201                 continue;
3202 
3203             try
3204             {
3205                 if ( !xListener->approveRowChange( event ) )
3206                     return false;
3207             }
3208             catch ( const DisposedException& e )
3209             {
3210                 if ( e.Context == xListener )
3211                     aIter.remove();
3212             }
3213             catch ( const RuntimeException& ) { throw; }
3214             catch ( const Exception& )
3215             {
3216                 DBG_UNHANDLED_EXCEPTION();
3217             }
3218         }
3219         return true;
3220     }
3221     return sal_True;
3222 }
3223 
3224 //------------------------------------------------------------------------------
approveRowSetChange(const EventObject & event)3225 sal_Bool SAL_CALL ODatabaseForm::approveRowSetChange(const EventObject& event)
3226 {
3227     if (event.Source == InterfaceRef(static_cast<XWeak*>(this)))    // ignore our aggregate as we handle this approve ourself
3228     {
3229         ::osl::ClearableMutexGuard aGuard( m_aMutex );
3230         bool bWasLoaded = isLoaded();
3231         if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3232             return sal_False;
3233 
3234         if ( bWasLoaded )
3235         {
3236             m_aLoadListeners.notifyEach( &XLoadListener::reloading, event );
3237         }
3238     }
3239     else
3240     {
3241         // this is a call from our parent ...
3242         // a parent's cursor move will result in a re-execute of our own row-set, so we have to
3243         // ask our own RowSetChangesListeners, too
3244         ::osl::ClearableMutexGuard aGuard( m_aMutex );
3245         if ( !impl_approveRowChange_throw( event, false, aGuard ) )
3246             return sal_False;
3247     }
3248     return sal_True;
3249 }
3250 
3251 //==============================================================================
3252 // com::sun::star::sdb::XRowSetApproveBroadcaster
3253 //------------------------------------------------------------------------------
addRowSetApproveListener(const Reference<XRowSetApproveListener> & _rListener)3254 void SAL_CALL ODatabaseForm::addRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener)
3255 {
3256     ::osl::ResettableMutexGuard aGuard(m_aMutex);
3257     m_aRowSetApproveListeners.addInterface(_rListener);
3258 
3259     // do we have to multiplex ?
3260     if (m_aRowSetApproveListeners.getLength() == 1)
3261     {
3262         Reference<XRowSetApproveBroadcaster>  xBroadcaster;
3263         if (query_aggregation( m_xAggregate, xBroadcaster))
3264         {
3265             Reference<XRowSetApproveListener>  xListener((XRowSetApproveListener*)this);
3266             xBroadcaster->addRowSetApproveListener(xListener);
3267         }
3268     }
3269 }
3270 
3271 //------------------------------------------------------------------------------
removeRowSetApproveListener(const Reference<XRowSetApproveListener> & _rListener)3272 void SAL_CALL ODatabaseForm::removeRowSetApproveListener(const Reference<XRowSetApproveListener>& _rListener)
3273 {
3274     ::osl::ResettableMutexGuard aGuard(m_aMutex);
3275     // do we have to remove the multiplex ?
3276     m_aRowSetApproveListeners.removeInterface(_rListener);
3277     if ( m_aRowSetApproveListeners.getLength() == 0 )
3278     {
3279         Reference<XRowSetApproveBroadcaster>  xBroadcaster;
3280         if (query_aggregation( m_xAggregate, xBroadcaster))
3281         {
3282             Reference<XRowSetApproveListener>  xListener((XRowSetApproveListener*)this);
3283             xBroadcaster->removeRowSetApproveListener(xListener);
3284         }
3285     }
3286 }
3287 
3288 //==============================================================================
3289 // com::sun:star::form::XDatabaseParameterBroadcaster
3290 //------------------------------------------------------------------------------
addDatabaseParameterListener(const Reference<XDatabaseParameterListener> & _rListener)3291 void SAL_CALL ODatabaseForm::addDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener)
3292 {
3293     m_aParameterManager.addParameterListener( _rListener );
3294 }
3295 //------------------------------------------------------------------------------
removeDatabaseParameterListener(const Reference<XDatabaseParameterListener> & _rListener)3296 void SAL_CALL ODatabaseForm::removeDatabaseParameterListener(const Reference<XDatabaseParameterListener>& _rListener)
3297 {
3298     m_aParameterManager.removeParameterListener( _rListener );
3299 }
3300 
3301 //------------------------------------------------------------------------------
addParameterListener(const Reference<XDatabaseParameterListener> & _rListener)3302 void SAL_CALL ODatabaseForm::addParameterListener(const Reference<XDatabaseParameterListener>& _rListener)
3303 {
3304     ODatabaseForm::addDatabaseParameterListener( _rListener );
3305 }
3306 
3307 //------------------------------------------------------------------------------
removeParameterListener(const Reference<XDatabaseParameterListener> & _rListener)3308 void SAL_CALL ODatabaseForm::removeParameterListener(const Reference<XDatabaseParameterListener>& _rListener)
3309 {
3310     ODatabaseForm::removeDatabaseParameterListener( _rListener );
3311 }
3312 
3313 //==============================================================================
3314 // com::sun::star::sdb::XCompletedExecution
3315 //------------------------------------------------------------------------------
executeWithCompletion(const Reference<XInteractionHandler> & _rxHandler)3316 void SAL_CALL ODatabaseForm::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler )
3317 {
3318     ::osl::ClearableMutexGuard aGuard(m_aMutex);
3319     // the difference between execute and load is, that we position on the first row in case of load
3320     // after execute we remain before the first row
3321     if (!isLoaded())
3322     {
3323         aGuard.clear();
3324         load_impl(sal_False, sal_False, _rxHandler);
3325     }
3326     else
3327     {
3328         EventObject event(static_cast< XWeak* >(this));
3329         if ( !impl_approveRowChange_throw( event, true, aGuard ) )
3330             return;
3331 
3332         // we're loaded and somebody want's to execute ourself -> this means a reload
3333         reload_impl(sal_False, _rxHandler);
3334     }
3335 }
3336 
3337 //==============================================================================
3338 // com::sun::star::sdbc::XRowSet
3339 //------------------------------------------------------------------------------
execute()3340 void SAL_CALL ODatabaseForm::execute()
3341 {
3342     ::osl::ResettableMutexGuard aGuard(m_aMutex);
3343     // if somebody calls an execute and we're not loaded we reroute this call to our load method.
3344 
3345     // the difference between execute and load is, that we position on the first row in case of load
3346     // after execute we remain before the first row
3347     if (!isLoaded())
3348     {
3349         aGuard.clear();
3350         load_impl(sal_False, sal_False);
3351     }
3352     else
3353     {
3354         EventObject event(static_cast< XWeak* >(this));
3355         if ( !impl_approveRowChange_throw( event, true, aGuard ) )
3356             return;
3357 
3358         // we're loaded and somebody want's to execute ourself -> this means a reload
3359         reload_impl(sal_False);
3360     }
3361 }
3362 
3363 //------------------------------------------------------------------------------
addRowSetListener(const Reference<XRowSetListener> & _rListener)3364 void SAL_CALL ODatabaseForm::addRowSetListener(const Reference<XRowSetListener>& _rListener)
3365 {
3366     if (m_xAggregateAsRowSet.is())
3367         m_xAggregateAsRowSet->addRowSetListener(_rListener);
3368 }
3369 
3370 //------------------------------------------------------------------------------
removeRowSetListener(const Reference<XRowSetListener> & _rListener)3371 void SAL_CALL ODatabaseForm::removeRowSetListener(const Reference<XRowSetListener>& _rListener)
3372 {
3373     if (m_xAggregateAsRowSet.is())
3374         m_xAggregateAsRowSet->removeRowSetListener(_rListener);
3375 }
3376 
3377 //==============================================================================
3378 // com::sun::star::sdbc::XResultSet
3379 //------------------------------------------------------------------------------
next()3380 sal_Bool SAL_CALL ODatabaseForm::next()
3381 {
3382     return m_xAggregateAsRowSet->next();
3383 }
3384 
3385 //------------------------------------------------------------------------------
isBeforeFirst()3386 sal_Bool SAL_CALL ODatabaseForm::isBeforeFirst()
3387 {
3388     return m_xAggregateAsRowSet->isBeforeFirst();
3389 }
3390 
3391 //------------------------------------------------------------------------------
isAfterLast()3392 sal_Bool SAL_CALL ODatabaseForm::isAfterLast()
3393 {
3394     return m_xAggregateAsRowSet->isAfterLast();
3395 }
3396 
3397 //------------------------------------------------------------------------------
isFirst()3398 sal_Bool SAL_CALL ODatabaseForm::isFirst()
3399 {
3400     return m_xAggregateAsRowSet->isFirst();
3401 }
3402 
3403 //------------------------------------------------------------------------------
isLast()3404 sal_Bool SAL_CALL ODatabaseForm::isLast()
3405 {
3406     return m_xAggregateAsRowSet->isLast();
3407 }
3408 
3409 //------------------------------------------------------------------------------
beforeFirst()3410 void SAL_CALL ODatabaseForm::beforeFirst()
3411 {
3412     m_xAggregateAsRowSet->beforeFirst();
3413 }
3414 
3415 //------------------------------------------------------------------------------
afterLast()3416 void SAL_CALL ODatabaseForm::afterLast()
3417 {
3418     m_xAggregateAsRowSet->afterLast();
3419 }
3420 
3421 //------------------------------------------------------------------------------
first()3422 sal_Bool SAL_CALL ODatabaseForm::first()
3423 {
3424     return m_xAggregateAsRowSet->first();
3425 }
3426 
3427 //------------------------------------------------------------------------------
last()3428 sal_Bool SAL_CALL ODatabaseForm::last()
3429 {
3430     return m_xAggregateAsRowSet->last();
3431 }
3432 
3433 //------------------------------------------------------------------------------
getRow()3434 sal_Int32 SAL_CALL ODatabaseForm::getRow()
3435 {
3436     return m_xAggregateAsRowSet->getRow();
3437 }
3438 
3439 //------------------------------------------------------------------------------
absolute(sal_Int32 row)3440 sal_Bool SAL_CALL ODatabaseForm::absolute(sal_Int32 row)
3441 {
3442     return m_xAggregateAsRowSet->absolute(row);
3443 }
3444 
3445 //------------------------------------------------------------------------------
relative(sal_Int32 rows)3446 sal_Bool SAL_CALL ODatabaseForm::relative(sal_Int32 rows)
3447 {
3448     return m_xAggregateAsRowSet->relative(rows);
3449 }
3450 
3451 //------------------------------------------------------------------------------
previous()3452 sal_Bool SAL_CALL ODatabaseForm::previous()
3453 {
3454     return m_xAggregateAsRowSet->previous();
3455 }
3456 
3457 //------------------------------------------------------------------------------
refreshRow()3458 void SAL_CALL ODatabaseForm::refreshRow()
3459 {
3460     m_xAggregateAsRowSet->refreshRow();
3461 }
3462 
3463 //------------------------------------------------------------------------------
rowUpdated()3464 sal_Bool SAL_CALL ODatabaseForm::rowUpdated()
3465 {
3466     return m_xAggregateAsRowSet->rowUpdated();
3467 }
3468 
3469 //------------------------------------------------------------------------------
rowInserted()3470 sal_Bool SAL_CALL ODatabaseForm::rowInserted()
3471 {
3472     return m_xAggregateAsRowSet->rowInserted();
3473 }
3474 
3475 //------------------------------------------------------------------------------
rowDeleted()3476 sal_Bool SAL_CALL ODatabaseForm::rowDeleted()
3477 {
3478     return m_xAggregateAsRowSet->rowDeleted();
3479 }
3480 
3481 //------------------------------------------------------------------------------
getStatement()3482 InterfaceRef SAL_CALL ODatabaseForm::getStatement()
3483 {
3484     return m_xAggregateAsRowSet->getStatement();
3485 }
3486 
3487 // com::sun::star::sdbc::XResultSetUpdate
3488 // exceptions during insert update and delete will be forwarded to the errorlistener
3489 //------------------------------------------------------------------------------
insertRow()3490 void SAL_CALL ODatabaseForm::insertRow()
3491 {
3492     try
3493     {
3494         Reference<XResultSetUpdate>  xUpdate;
3495         if (query_aggregation( m_xAggregate, xUpdate))
3496             xUpdate->insertRow();
3497     }
3498     catch( const RowSetVetoException& eVeto )
3499     {
3500         (void)eVeto;
3501         throw;
3502     }
3503     catch(SQLException& eDb)
3504     {
3505         onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
3506         throw;
3507     }
3508 }
3509 
3510 //------------------------------------------------------------------------------
updateRow()3511 void SAL_CALL ODatabaseForm::updateRow()
3512 {
3513     try
3514     {
3515         Reference<XResultSetUpdate>  xUpdate;
3516         if (query_aggregation( m_xAggregate, xUpdate))
3517             xUpdate->updateRow();
3518     }
3519     catch( const RowSetVetoException& eVeto )
3520     {
3521         (void)eVeto;
3522         throw;
3523     }
3524     catch(SQLException& eDb)
3525     {
3526         onError(eDb, FRM_RES_STRING(RID_STR_ERR_UPDATERECORD));
3527         throw;
3528     }
3529 }
3530 
3531 //------------------------------------------------------------------------------
deleteRow()3532 void SAL_CALL ODatabaseForm::deleteRow()
3533 {
3534     try
3535     {
3536         Reference<XResultSetUpdate>  xUpdate;
3537         if (query_aggregation( m_xAggregate, xUpdate))
3538             xUpdate->deleteRow();
3539     }
3540     catch( const RowSetVetoException& eVeto )
3541     {
3542         (void)eVeto;
3543         throw;
3544     }
3545     catch(SQLException& eDb)
3546     {
3547         onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORD));
3548         throw;
3549     }
3550 }
3551 
3552 //------------------------------------------------------------------------------
cancelRowUpdates()3553 void SAL_CALL ODatabaseForm::cancelRowUpdates()
3554 {
3555     try
3556     {
3557         Reference<XResultSetUpdate>  xUpdate;
3558         if (query_aggregation( m_xAggregate, xUpdate))
3559             xUpdate->cancelRowUpdates();
3560     }
3561     catch( const RowSetVetoException& eVeto )
3562     {
3563         (void)eVeto;
3564         throw;
3565     }
3566     catch(SQLException& eDb)
3567     {
3568         onError(eDb, FRM_RES_STRING(RID_STR_ERR_INSERTRECORD));
3569         throw;
3570     }
3571 }
3572 
3573 //------------------------------------------------------------------------------
moveToInsertRow()3574 void SAL_CALL ODatabaseForm::moveToInsertRow()
3575 {
3576     Reference<XResultSetUpdate>  xUpdate;
3577     if (query_aggregation( m_xAggregate, xUpdate))
3578     {
3579         // _always_ move to the insert row
3580         //
3581         // Formerly, the following line was conditioned with a "not is new", means we did not move the aggregate
3582         // to the insert row if it was already positioned there.
3583         //
3584         // This prevented the RowSet implementation from resetting it's column values. We, ourself, formerly
3585         // did this reset of columns in reset_impl, where we set every column to the ControlDefault, or, if this
3586         // was not present, to NULL. However, the problem with setting to NULL was #88888#, the problem with
3587         // _not_ setting to NULL (which was the original fix for #88888#) was #97955#.
3588         //
3589         // So now we
3590         // * move our aggregate to the insert row
3591         // * in reset_impl
3592         //   - set the control defaults into the columns if not void
3593         //   - do _not_ set the columns to NULL if no control default is set
3594         // This fixes both #88888# and #97955#
3595         //
3596         // Still, there is #72756#. During fixing this bug, DG introduced not calling the aggregate here. So
3597         // in theory, we re-introduced #72756#. But the bug described therein does not happen anymore, as the
3598         // preliminaries for it changed (no display of guessed values for new records with autoinc fields)
3599         //
3600         // BTW: the public Issuezilla bug for #97955# is #i2815#
3601         //
3602         // 16.04.2002 - 97955 - fs@openoffice.org
3603         xUpdate->moveToInsertRow();
3604 
3605         // then set the default values and the parameters given from the parent
3606         reset();
3607     }
3608 }
3609 
3610 //------------------------------------------------------------------------------
moveToCurrentRow()3611 void SAL_CALL ODatabaseForm::moveToCurrentRow()
3612 {
3613     Reference<XResultSetUpdate>  xUpdate;
3614     if (query_aggregation( m_xAggregate, xUpdate))
3615         xUpdate->moveToCurrentRow();
3616 }
3617 
3618 // com::sun::star::sdbcx::XDeleteRows
3619 //------------------------------------------------------------------------------
deleteRows(const Sequence<Any> & rows)3620 Sequence<sal_Int32> SAL_CALL ODatabaseForm::deleteRows(const Sequence<Any>& rows)
3621 {
3622     try
3623     {
3624         Reference<XDeleteRows>  xDelete;
3625         if (query_aggregation( m_xAggregate, xDelete))
3626             return xDelete->deleteRows(rows);
3627     }
3628     catch( const RowSetVetoException& eVeto )
3629     {
3630         (void)eVeto; // make compiler happy
3631         throw;
3632     }
3633     catch(SQLException& eDb)
3634     {
3635         onError(eDb, FRM_RES_STRING(RID_STR_ERR_DELETERECORDS));
3636         throw;
3637     }
3638 
3639     return Sequence< sal_Int32 >();
3640 }
3641 
3642 // com::sun::star::sdbc::XParameters
3643 //------------------------------------------------------------------------------
setNull(sal_Int32 parameterIndex,sal_Int32 sqlType)3644 void SAL_CALL ODatabaseForm::setNull(sal_Int32 parameterIndex, sal_Int32 sqlType)
3645 {
3646     m_aParameterManager.setNull(parameterIndex, sqlType);
3647 }
3648 
3649 //------------------------------------------------------------------------------
setObjectNull(sal_Int32 parameterIndex,sal_Int32 sqlType,const::rtl::OUString & typeName)3650 void SAL_CALL ODatabaseForm::setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName)
3651 {
3652     m_aParameterManager.setObjectNull(parameterIndex, sqlType, typeName);
3653 }
3654 
3655 //------------------------------------------------------------------------------
setBoolean(sal_Int32 parameterIndex,sal_Bool x)3656 void SAL_CALL ODatabaseForm::setBoolean(sal_Int32 parameterIndex, sal_Bool x)
3657 {
3658     m_aParameterManager.setBoolean(parameterIndex, x);
3659 }
3660 
3661 //------------------------------------------------------------------------------
setByte(sal_Int32 parameterIndex,sal_Int8 x)3662 void SAL_CALL ODatabaseForm::setByte(sal_Int32 parameterIndex, sal_Int8 x)
3663 {
3664     m_aParameterManager.setByte(parameterIndex, x);
3665 }
3666 
3667 //------------------------------------------------------------------------------
setShort(sal_Int32 parameterIndex,sal_Int16 x)3668 void SAL_CALL ODatabaseForm::setShort(sal_Int32 parameterIndex, sal_Int16 x)
3669 {
3670     m_aParameterManager.setShort(parameterIndex, x);
3671 }
3672 
3673 //------------------------------------------------------------------------------
setInt(sal_Int32 parameterIndex,sal_Int32 x)3674 void SAL_CALL ODatabaseForm::setInt(sal_Int32 parameterIndex, sal_Int32 x)
3675 {
3676     m_aParameterManager.setInt(parameterIndex, x);
3677 }
3678 
3679 //------------------------------------------------------------------------------
setLong(sal_Int32 parameterIndex,sal_Int64 x)3680 void SAL_CALL ODatabaseForm::setLong(sal_Int32 parameterIndex, sal_Int64 x)
3681 {
3682     m_aParameterManager.setLong(parameterIndex, x);
3683 }
3684 
3685 //------------------------------------------------------------------------------
setFloat(sal_Int32 parameterIndex,float x)3686 void SAL_CALL ODatabaseForm::setFloat(sal_Int32 parameterIndex, float x)
3687 {
3688     m_aParameterManager.setFloat(parameterIndex, x);
3689 }
3690 
3691 //------------------------------------------------------------------------------
setDouble(sal_Int32 parameterIndex,double x)3692 void SAL_CALL ODatabaseForm::setDouble(sal_Int32 parameterIndex, double x)
3693 {
3694     m_aParameterManager.setDouble(parameterIndex, x);
3695 }
3696 
3697 //------------------------------------------------------------------------------
setString(sal_Int32 parameterIndex,const::rtl::OUString & x)3698 void SAL_CALL ODatabaseForm::setString(sal_Int32 parameterIndex, const ::rtl::OUString& x)
3699 {
3700     m_aParameterManager.setString(parameterIndex, x);
3701 }
3702 
3703 //------------------------------------------------------------------------------
setBytes(sal_Int32 parameterIndex,const Sequence<sal_Int8> & x)3704 void SAL_CALL ODatabaseForm::setBytes(sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x)
3705 {
3706     m_aParameterManager.setBytes(parameterIndex, x);
3707 }
3708 
3709 //------------------------------------------------------------------------------
setDate(sal_Int32 parameterIndex,const::com::sun::star::util::Date & x)3710 void SAL_CALL ODatabaseForm::setDate(sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x)
3711 {
3712     m_aParameterManager.setDate(parameterIndex, x);
3713 }
3714 
3715 //------------------------------------------------------------------------------
setTime(sal_Int32 parameterIndex,const::com::sun::star::util::Time & x)3716 void SAL_CALL ODatabaseForm::setTime(sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x)
3717 {
3718     m_aParameterManager.setTime(parameterIndex, x);
3719 }
3720 
3721 //------------------------------------------------------------------------------
setTimestamp(sal_Int32 parameterIndex,const::com::sun::star::util::DateTime & x)3722 void SAL_CALL ODatabaseForm::setTimestamp(sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x)
3723 {
3724     m_aParameterManager.setTimestamp(parameterIndex, x);
3725 }
3726 
3727 //------------------------------------------------------------------------------
setBinaryStream(sal_Int32 parameterIndex,const Reference<XInputStream> & x,sal_Int32 length)3728 void SAL_CALL ODatabaseForm::setBinaryStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length)
3729 {
3730     m_aParameterManager.setBinaryStream(parameterIndex, x, length);
3731 }
3732 
3733 //------------------------------------------------------------------------------
setCharacterStream(sal_Int32 parameterIndex,const Reference<XInputStream> & x,sal_Int32 length)3734 void SAL_CALL ODatabaseForm::setCharacterStream(sal_Int32 parameterIndex, const Reference<XInputStream>& x, sal_Int32 length)
3735 {
3736     m_aParameterManager.setCharacterStream(parameterIndex, x, length);
3737 }
3738 
3739 //------------------------------------------------------------------------------
setObjectWithInfo(sal_Int32 parameterIndex,const Any & x,sal_Int32 targetSqlType,sal_Int32 scale)3740 void SAL_CALL ODatabaseForm::setObjectWithInfo(sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale)
3741 {
3742     m_aParameterManager.setObjectWithInfo(parameterIndex, x, targetSqlType, scale);
3743 }
3744 
3745 //------------------------------------------------------------------------------
setObject(sal_Int32 parameterIndex,const Any & x)3746 void SAL_CALL ODatabaseForm::setObject(sal_Int32 parameterIndex, const Any& x)
3747 {
3748     m_aParameterManager.setObject(parameterIndex, x);
3749 }
3750 
3751 //------------------------------------------------------------------------------
setRef(sal_Int32 parameterIndex,const Reference<XRef> & x)3752 void SAL_CALL ODatabaseForm::setRef(sal_Int32 parameterIndex, const Reference<XRef>& x)
3753 {
3754     m_aParameterManager.setRef(parameterIndex, x);
3755 }
3756 
3757 //------------------------------------------------------------------------------
setBlob(sal_Int32 parameterIndex,const Reference<XBlob> & x)3758 void SAL_CALL ODatabaseForm::setBlob(sal_Int32 parameterIndex, const Reference<XBlob>& x)
3759 {
3760     m_aParameterManager.setBlob(parameterIndex, x);
3761 }
3762 
3763 //------------------------------------------------------------------------------
setClob(sal_Int32 parameterIndex,const Reference<XClob> & x)3764 void SAL_CALL ODatabaseForm::setClob(sal_Int32 parameterIndex, const Reference<XClob>& x)
3765 {
3766     m_aParameterManager.setClob(parameterIndex, x);
3767 }
3768 
3769 //------------------------------------------------------------------------------
setArray(sal_Int32 parameterIndex,const Reference<XArray> & x)3770 void SAL_CALL ODatabaseForm::setArray(sal_Int32 parameterIndex, const Reference<XArray>& x)
3771 {
3772     m_aParameterManager.setArray(parameterIndex, x);
3773 }
3774 
3775 //------------------------------------------------------------------------------
clearParameters()3776 void SAL_CALL ODatabaseForm::clearParameters()
3777 {
3778     m_aParameterManager.clearParameters();
3779 }
3780 
3781 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)3782 void SAL_CALL ODatabaseForm::propertyChange( const PropertyChangeEvent& evt )
3783 {
3784     if ( evt.Source == m_xParent )
3785     {
3786         if ( evt.PropertyName == PROPERTY_ISNEW )
3787         {
3788             sal_Bool bCurrentIsNew( sal_False );
3789             OSL_VERIFY( evt.NewValue >>= bCurrentIsNew );
3790             if ( !bCurrentIsNew )
3791                 reload_impl( sal_True );
3792         }
3793         return;
3794     }
3795     OFormComponents::propertyChange( evt );
3796 }
3797 
3798 // com::sun::star::lang::XServiceInfo
3799 //------------------------------------------------------------------------------
getImplementationName_Static()3800 ::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName_Static()
3801 {
3802     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.forms.ODatabaseForm" ) );
3803 }
3804 
3805 //------------------------------------------------------------------------------
getCompatibleServiceNames_Static()3806 Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCompatibleServiceNames_Static()
3807 {
3808     Sequence< ::rtl::OUString > aServices( 1 );
3809     ::rtl::OUString* pServices = aServices.getArray();
3810 
3811     *pServices++ = FRM_COMPONENT_FORM;
3812 
3813     return aServices;
3814 }
3815 
3816 //------------------------------------------------------------------------------
getCurrentServiceNames_Static()3817 Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getCurrentServiceNames_Static()
3818 {
3819     Sequence< ::rtl::OUString > aServices( 5 );
3820     ::rtl::OUString* pServices = aServices.getArray();
3821 
3822     *pServices++ = FRM_SUN_FORMCOMPONENT;
3823     *pServices++ = ::rtl::OUString::createFromAscii("com.sun.star.form.FormComponents");
3824     *pServices++ = FRM_SUN_COMPONENT_FORM;
3825     *pServices++ = FRM_SUN_COMPONENT_HTMLFORM;
3826     *pServices++ = FRM_SUN_COMPONENT_DATAFORM;
3827 
3828     return aServices;
3829 }
3830 
3831 //------------------------------------------------------------------------------
getSupportedServiceNames_Static()3832 Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames_Static()
3833 {
3834     return ::comphelper::concatSequences(
3835         getCurrentServiceNames_Static(),
3836         getCompatibleServiceNames_Static()
3837     );
3838 }
3839 
3840 //------------------------------------------------------------------------------
getImplementationName()3841 ::rtl::OUString SAL_CALL ODatabaseForm::getImplementationName()
3842 {
3843     return getImplementationName_Static();
3844 }
3845 
3846 //------------------------------------------------------------------------------
getSupportedServiceNames()3847 Sequence< ::rtl::OUString > SAL_CALL ODatabaseForm::getSupportedServiceNames()
3848 {
3849     // the services of our aggregate
3850     Sequence< ::rtl::OUString > aServices;
3851     Reference< XServiceInfo > xInfo;
3852     if (query_aggregation(m_xAggregate, xInfo))
3853         aServices = xInfo->getSupportedServiceNames();
3854 
3855     // concat with out own services
3856     return ::comphelper::concatSequences(
3857         getCurrentServiceNames_Static(),
3858         aServices
3859     );
3860     // use getCurrentXXX instead of getSupportedXXX, because at runtime, we do not want to have
3861     // the compatible names
3862     // This is maily to be consistent with the implementation before fixing #97083#, though the
3863     // better solution _may_ be to return the compatible names at runtime, too
3864     // 04.03.2002 - fs@openoffice.org
3865 }
3866 
3867 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & ServiceName)3868 sal_Bool SAL_CALL ODatabaseForm::supportsService(const ::rtl::OUString& ServiceName)
3869 {
3870     Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
3871     const ::rtl::OUString* pArray = aSupported.getConstArray();
3872     for( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pArray )
3873         if( pArray->equals( ServiceName ) )
3874             return sal_True;
3875     return sal_False;
3876 }
3877 
3878 //==============================================================================
3879 // com::sun::star::io::XPersistObject
3880 //------------------------------------------------------------------------------
3881 
3882 const sal_uInt16 CYCLE              = 0x0001;
3883 const sal_uInt16 DONTAPPLYFILTER    = 0x0002;
3884 
3885 //------------------------------------------------------------------------------
getServiceName()3886 ::rtl::OUString ODatabaseForm::getServiceName()
3887 {
3888     return FRM_COMPONENT_FORM;  // old (non-sun) name for compatibility !
3889 }
3890 
3891 //------------------------------------------------------------------------------
write(const Reference<XObjectOutputStream> & _rxOutStream)3892 void SAL_CALL ODatabaseForm::write(const Reference<XObjectOutputStream>& _rxOutStream)
3893 {
3894     DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::write : only to be called if the aggregate exists !");
3895 
3896     // all children
3897     OFormComponents::write(_rxOutStream);
3898 
3899     // version
3900     _rxOutStream->writeShort(0x0003);
3901 
3902     // Name
3903     _rxOutStream << m_sName;
3904 
3905     ::rtl::OUString sDataSource;
3906     if (m_xAggregateSet.is())
3907         m_xAggregateSet->getPropertyValue(PROPERTY_DATASOURCE) >>= sDataSource;
3908     _rxOutStream << sDataSource;
3909 
3910     // former CursorSource
3911     ::rtl::OUString sCommand;
3912     if (m_xAggregateSet.is())
3913         m_xAggregateSet->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
3914     _rxOutStream << sCommand;
3915 
3916     // former MasterFields
3917     _rxOutStream << m_aMasterFields;
3918     // former DetailFields
3919     _rxOutStream << m_aDetailFields;
3920 
3921     // former DataSelectionType
3922     DataSelectionType eTranslated = DataSelectionType_TABLE;
3923     if (m_xAggregateSet.is())
3924     {
3925         sal_Int32 nCommandType = 0;
3926         m_xAggregateSet->getPropertyValue(PROPERTY_COMMANDTYPE) >>= nCommandType;
3927         switch (nCommandType)
3928         {
3929             case CommandType::TABLE : eTranslated = DataSelectionType_TABLE; break;
3930             case CommandType::QUERY : eTranslated = DataSelectionType_QUERY; break;
3931             case CommandType::COMMAND:
3932             {
3933                 sal_Bool bEscapeProcessing = getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_ESCAPE_PROCESSING));
3934                 eTranslated = bEscapeProcessing ? DataSelectionType_SQL : DataSelectionType_SQLPASSTHROUGH;
3935             }
3936             break;
3937             default : DBG_ERROR("ODatabaseForm::write : wrong CommandType !");
3938         }
3939     }
3940     _rxOutStream->writeShort((sal_Int16)eTranslated);           // former DataSelectionType
3941 
3942     // very old versions expect a CursorType here
3943     _rxOutStream->writeShort(DatabaseCursorType_KEYSET);
3944 
3945     _rxOutStream->writeBoolean(m_eNavigation != NavigationBarMode_NONE);
3946 
3947     // former DataEntry
3948     if (m_xAggregateSet.is())
3949         _rxOutStream->writeBoolean(getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_INSERTONLY)));
3950     else
3951         _rxOutStream->writeBoolean(sal_False);
3952 
3953     _rxOutStream->writeBoolean(m_bAllowInsert);
3954     _rxOutStream->writeBoolean(m_bAllowUpdate);
3955     _rxOutStream->writeBoolean(m_bAllowDelete);
3956 
3957     // HTML form stuff
3958     ::rtl::OUString sTmp = INetURLObject::decode( m_aTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS);
3959     _rxOutStream << sTmp;
3960     _rxOutStream->writeShort( (sal_Int16)m_eSubmitMethod );
3961     _rxOutStream->writeShort( (sal_Int16)m_eSubmitEncoding );
3962     _rxOutStream << m_aTargetFrame;
3963 
3964     // version 2 didn't know some options and the "default" state
3965     sal_Int32 nCycle = TabulatorCycle_RECORDS;
3966     if (m_aCycle.hasValue())
3967     {
3968         ::cppu::enum2int(nCycle, m_aCycle);
3969         if (m_aCycle == TabulatorCycle_PAGE)
3970                 // unknown in earlier versions
3971             nCycle = TabulatorCycle_RECORDS;
3972     }
3973     _rxOutStream->writeShort((sal_Int16) nCycle);
3974 
3975     _rxOutStream->writeShort((sal_Int16)m_eNavigation);
3976 
3977     ::rtl::OUString sFilter;
3978     ::rtl::OUString sOrder;
3979     if (m_xAggregateSet.is())
3980     {
3981         m_xAggregateSet->getPropertyValue(PROPERTY_FILTER) >>= sFilter;
3982         m_xAggregateSet->getPropertyValue(PROPERTY_SORT) >>= sOrder;
3983     }
3984     _rxOutStream << sFilter;
3985     _rxOutStream << sOrder;
3986 
3987 
3988     // version 3
3989     sal_uInt16 nAnyMask = 0;
3990     if (m_aCycle.hasValue())
3991         nAnyMask |= CYCLE;
3992 
3993     if (m_xAggregateSet.is() && !getBOOL(m_xAggregateSet->getPropertyValue(PROPERTY_APPLYFILTER)))
3994         nAnyMask |= DONTAPPLYFILTER;
3995 
3996     _rxOutStream->writeShort(nAnyMask);
3997 
3998     if (nAnyMask & CYCLE)
3999     {
4000         sal_Int32 nRealCycle = 0;
4001         ::cppu::enum2int(nRealCycle, m_aCycle);
4002         _rxOutStream->writeShort((sal_Int16)nRealCycle);
4003     }
4004 }
4005 
4006 //------------------------------------------------------------------------------
read(const Reference<XObjectInputStream> & _rxInStream)4007 void SAL_CALL ODatabaseForm::read(const Reference<XObjectInputStream>& _rxInStream)
4008 {
4009     DBG_ASSERT(m_xAggregateSet.is(), "ODatabaseForm::read : only to be called if the aggregate exists !");
4010 
4011     OFormComponents::read(_rxInStream);
4012 
4013     // version
4014     sal_uInt16 nVersion = _rxInStream->readShort();
4015 
4016     _rxInStream >> m_sName;
4017 
4018     ::rtl::OUString sAggregateProp;
4019     _rxInStream >> sAggregateProp;
4020     if (m_xAggregateSet.is())
4021         m_xAggregateSet->setPropertyValue(PROPERTY_DATASOURCE, makeAny(sAggregateProp));
4022     _rxInStream >> sAggregateProp;
4023     if (m_xAggregateSet.is())
4024         m_xAggregateSet->setPropertyValue(PROPERTY_COMMAND, makeAny(sAggregateProp));
4025 
4026     _rxInStream >> m_aMasterFields;
4027     _rxInStream >> m_aDetailFields;
4028 
4029     sal_Int16 nCursorSourceType = _rxInStream->readShort();
4030     sal_Int32 nCommandType = 0;
4031     switch ((DataSelectionType)nCursorSourceType)
4032     {
4033         case DataSelectionType_TABLE : nCommandType = CommandType::TABLE; break;
4034         case DataSelectionType_QUERY : nCommandType = CommandType::QUERY; break;
4035         case DataSelectionType_SQL:
4036         case DataSelectionType_SQLPASSTHROUGH:
4037         {
4038             nCommandType = CommandType::COMMAND;
4039             sal_Bool bEscapeProcessing = ((DataSelectionType)nCursorSourceType) != DataSelectionType_SQLPASSTHROUGH;
4040             m_xAggregateSet->setPropertyValue(PROPERTY_ESCAPE_PROCESSING, makeAny((sal_Bool)bEscapeProcessing));
4041         }
4042         break;
4043         default : DBG_ERROR("ODatabaseForm::read : wrong CommandType !");
4044     }
4045     if (m_xAggregateSet.is())
4046         m_xAggregateSet->setPropertyValue(PROPERTY_COMMANDTYPE, makeAny(nCommandType));
4047 
4048     // obsolete
4049     _rxInStream->readShort();
4050 
4051     // navigation mode was a boolean in version 1
4052     // war in der version 1 ein sal_Bool
4053     sal_Bool bNavigation = _rxInStream->readBoolean();
4054     if (nVersion == 1)
4055         m_eNavigation = bNavigation ? NavigationBarMode_CURRENT : NavigationBarMode_NONE;
4056 
4057     sal_Bool bInsertOnly = _rxInStream->readBoolean();
4058     if (m_xAggregateSet.is())
4059         m_xAggregateSet->setPropertyValue(PROPERTY_INSERTONLY, makeAny(bInsertOnly));
4060 
4061     m_bAllowInsert      = _rxInStream->readBoolean();
4062     m_bAllowUpdate      = _rxInStream->readBoolean();
4063     m_bAllowDelete      = _rxInStream->readBoolean();
4064 
4065     // HTML stuff
4066     ::rtl::OUString sTmp;
4067     _rxInStream >> sTmp;
4068     m_aTargetURL = INetURLObject::decode( sTmp, '%', INetURLObject::DECODE_UNAMBIGUOUS);
4069     m_eSubmitMethod     = (FormSubmitMethod)_rxInStream->readShort();
4070     m_eSubmitEncoding       = (FormSubmitEncoding)_rxInStream->readShort();
4071     _rxInStream >> m_aTargetFrame;
4072 
4073     if (nVersion > 1)
4074     {
4075         sal_Int32 nCycle = _rxInStream->readShort();
4076         m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
4077         m_eNavigation = (NavigationBarMode)_rxInStream->readShort();
4078 
4079         _rxInStream >> sAggregateProp;
4080         setPropertyValue(PROPERTY_FILTER, makeAny(sAggregateProp));
4081 
4082         _rxInStream >> sAggregateProp;
4083         if (m_xAggregateSet.is())
4084             m_xAggregateSet->setPropertyValue(PROPERTY_SORT, makeAny(sAggregateProp));
4085     }
4086 
4087     sal_uInt16 nAnyMask = 0;
4088     if (nVersion > 2)
4089     {
4090         nAnyMask = _rxInStream->readShort();
4091         if (nAnyMask & CYCLE)
4092         {
4093             sal_Int32 nCycle = _rxInStream->readShort();
4094             m_aCycle = ::cppu::int2enum(nCycle, ::getCppuType(static_cast<const TabulatorCycle*>(NULL)));
4095         }
4096         else
4097             m_aCycle.clear();
4098     }
4099     if (m_xAggregateSet.is())
4100         m_xAggregateSet->setPropertyValue(PROPERTY_APPLYFILTER, makeAny((sal_Bool)((nAnyMask & DONTAPPLYFILTER) == 0)));
4101 }
4102 
4103 //------------------------------------------------------------------------------
implInserted(const ElementDescription * _pElement)4104 void ODatabaseForm::implInserted( const ElementDescription* _pElement )
4105 {
4106     OFormComponents::implInserted( _pElement );
4107 
4108     Reference< XSQLErrorBroadcaster >   xBroadcaster( _pElement->xInterface, UNO_QUERY );
4109     Reference< XForm >                  xForm       ( _pElement->xInterface, UNO_QUERY );
4110 
4111     if ( xBroadcaster.is() && !xForm.is() )
4112     {   // the object is an error broadcaster, but no form itself -> add ourself as listener
4113         xBroadcaster->addSQLErrorListener( this );
4114     }
4115 }
4116 
4117 //------------------------------------------------------------------------------
implRemoved(const InterfaceRef & _rxObject)4118 void ODatabaseForm::implRemoved(const InterfaceRef& _rxObject)
4119 {
4120     OFormComponents::implRemoved( _rxObject );
4121 
4122     Reference<XSQLErrorBroadcaster>  xBroadcaster(_rxObject, UNO_QUERY);
4123     Reference<XForm>  xForm(_rxObject, UNO_QUERY);
4124     if (xBroadcaster.is() && !xForm.is())
4125     {   // the object is an error broadcaster, but no form itself -> remove ourself as listener
4126         xBroadcaster->removeSQLErrorListener(this);
4127     }
4128 }
4129 
4130 //------------------------------------------------------------------------------
errorOccured(const SQLErrorEvent & _rEvent)4131 void SAL_CALL ODatabaseForm::errorOccured(const SQLErrorEvent& _rEvent)
4132 {
4133     // give it to my own error listener
4134     onError(_rEvent);
4135     // TODO : think about extending the chain with an SQLContext object saying
4136     // "this was an error of one of my children"
4137 }
4138 
4139 // com::sun::star::container::XNamed
4140 //------------------------------------------------------------------------------
getName()4141 ::rtl::OUString SAL_CALL ODatabaseForm::getName()
4142 {
4143     ::rtl::OUString sReturn;
4144     OPropertySetHelper::getFastPropertyValue(PROPERTY_ID_NAME) >>= sReturn;
4145     return sReturn;
4146 }
4147 
4148 //------------------------------------------------------------------------------
setName(const::rtl::OUString & aName)4149 void SAL_CALL ODatabaseForm::setName(const ::rtl::OUString& aName)
4150 {
4151     setFastPropertyValue(PROPERTY_ID_NAME, makeAny(aName));
4152 }
4153 
4154 //.........................................................................
4155 }   // namespace frm
4156 //.........................................................................
4157