xref: /trunk/main/ucb/source/sorter/sortdynres.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_ucb.hxx"
30 
31 #include <vector>
32 #include <sortdynres.hxx>
33 #include <cppuhelper/interfacecontainer.hxx>
34 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
35 #include <com/sun/star/ucb/ListActionType.hpp>
36 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
37 #include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp>
38 #include <com/sun/star/ucb/XSourceInitialization.hpp>
39 
40 //-----------------------------------------------------------------------------
41 using namespace com::sun::star::beans;
42 using namespace com::sun::star::lang;
43 using namespace com::sun::star::sdbc;
44 using namespace com::sun::star::ucb;
45 using namespace com::sun::star::uno;
46 using namespace cppu;
47 using namespace rtl;
48 
49 //=========================================================================
50 
51 //  The mutex to synchronize access to containers.
52 static osl::Mutex& getContainerMutex()
53 {
54     static osl::Mutex* pMutex = NULL;
55     if( !pMutex )
56     {
57         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
58         if( !pMutex )
59         {
60             static osl::Mutex aMutex;
61             pMutex = &aMutex;
62         }
63     }
64 
65     return *pMutex;
66 }
67 
68 //=========================================================================
69 //
70 // SortedDynamicResultSet
71 //
72 //=========================================================================
73 
74 SortedDynamicResultSet::SortedDynamicResultSet(
75                         const Reference < XDynamicResultSet > &xOriginal,
76                         const Sequence < NumberedSortingInfo > &aOptions,
77                         const Reference < XAnyCompareFactory > &xCompFac,
78                         const Reference < XMultiServiceFactory > &xSMgr )
79 {
80     mpDisposeEventListeners = NULL;
81     mpOwnListener           = new SortedDynamicResultSetListener( this );
82 
83     mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener );
84 
85     mxOriginal  = xOriginal;
86     maOptions   = aOptions;
87     mxCompFac   = xCompFac;
88     mxSMgr      = xSMgr;
89 
90     mpOne = NULL;
91     mpTwo = NULL;
92 
93     mbGotWelcome    = sal_False;
94     mbUseOne        = sal_True;
95     mbStatic        = sal_False;
96 }
97 
98 //--------------------------------------------------------------------------
99 SortedDynamicResultSet::~SortedDynamicResultSet()
100 {
101     mpOwnListener->impl_OwnerDies();
102     mxOwnListener.clear();
103 
104     delete mpDisposeEventListeners;
105 
106     mxOne.clear();
107     mxTwo.clear();
108     mxOriginal.clear();
109 
110     mpOne = NULL;
111     mpTwo = NULL;
112 }
113 
114 //--------------------------------------------------------------------------
115 // XInterface methods.
116 //--------------------------------------------------------------------------
117 
118 XINTERFACE_IMPL_4( SortedDynamicResultSet,
119                    XTypeProvider,
120                    XServiceInfo,
121                    XComponent,      /* base class of XDynamicResultSet */
122                    XDynamicResultSet );
123 
124 //--------------------------------------------------------------------------
125 // XTypeProvider methods.
126 //--------------------------------------------------------------------------
127 
128 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet,
129                       XTypeProvider,
130                       XServiceInfo,
131                       XDynamicResultSet );
132 
133 //--------------------------------------------------------------------------
134 // XServiceInfo methods.
135 //--------------------------------------------------------------------------
136 
137 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet,
138                                OUString::createFromAscii(
139                                 "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
140                                OUString::createFromAscii(
141                                 DYNAMIC_RESULTSET_SERVICE_NAME ) );
142 
143 //--------------------------------------------------------------------------
144 // XComponent methods.
145 //--------------------------------------------------------------------------
146 void SAL_CALL SortedDynamicResultSet::dispose()
147     throw( RuntimeException )
148 {
149     osl::Guard< osl::Mutex > aGuard( maMutex );
150 
151     if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() )
152     {
153         EventObject aEvt;
154         aEvt.Source = static_cast< XComponent * >( this );
155         mpDisposeEventListeners->disposeAndClear( aEvt );
156     }
157 
158     mxOne.clear();
159     mxTwo.clear();
160     mxOriginal.clear();
161 
162     mpOne = NULL;
163     mpTwo = NULL;
164     mbUseOne = sal_True;
165 }
166 
167 //--------------------------------------------------------------------------
168 void SAL_CALL SortedDynamicResultSet::addEventListener(
169                             const Reference< XEventListener >& Listener )
170     throw( RuntimeException )
171 {
172     osl::Guard< osl::Mutex > aGuard( maMutex );
173 
174     if ( !mpDisposeEventListeners )
175         mpDisposeEventListeners =
176                     new OInterfaceContainerHelper( getContainerMutex() );
177 
178     mpDisposeEventListeners->addInterface( Listener );
179 }
180 
181 //--------------------------------------------------------------------------
182 void SAL_CALL SortedDynamicResultSet::removeEventListener(
183                             const Reference< XEventListener >& Listener )
184     throw( RuntimeException )
185 {
186     osl::Guard< osl::Mutex > aGuard( maMutex );
187 
188     if ( mpDisposeEventListeners )
189         mpDisposeEventListeners->removeInterface( Listener );
190 }
191 
192 //--------------------------------------------------------------------------
193 // XDynamicResultSet methods.
194 // ------------------------------------------------------------------------------
195 Reference< XResultSet > SAL_CALL
196 SortedDynamicResultSet::getStaticResultSet()
197     throw( ListenerAlreadySetException, RuntimeException )
198 {
199     osl::Guard< osl::Mutex > aGuard( maMutex );
200 
201     if ( mxListener.is() )
202         throw ListenerAlreadySetException();
203 
204     mbStatic = sal_True;
205 
206     if ( mxOriginal.is() )
207     {
208         mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
209         mxOne = mpOne;
210         mpOne->Initialize( maOptions, mxCompFac );
211     }
212 
213     return mxOne;
214 }
215 
216 // ------------------------------------------------------------------------------
217 void SAL_CALL
218 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener )
219     throw( ListenerAlreadySetException, RuntimeException )
220 {
221     osl::Guard< osl::Mutex > aGuard( maMutex );
222 
223     if ( mxListener.is() )
224         throw ListenerAlreadySetException();
225 
226     addEventListener( Reference< XEventListener >::query( Listener ) );
227 
228     mxListener = Listener;
229 
230     if ( mxOriginal.is() )
231         mxOriginal->setListener( mxOwnListener );
232 }
233 
234 // ------------------------------------------------------------------------------
235 void SAL_CALL
236 SortedDynamicResultSet::connectToCache(
237         const Reference< XDynamicResultSet > & xCache )
238         throw( ListenerAlreadySetException,
239                AlreadyInitializedException,
240                ServiceNotFoundException,
241                RuntimeException )
242 {
243     if( mxListener.is() )
244         throw ListenerAlreadySetException();
245 
246     if( mbStatic )
247         throw ListenerAlreadySetException();
248 
249     Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
250     if( xTarget.is() && mxSMgr.is() )
251     {
252         Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
253         try
254         {
255             xStubFactory = Reference< XCachedDynamicResultSetStubFactory >(
256                 mxSMgr->createInstance(
257                     OUString::createFromAscii(
258                         "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ),
259                 UNO_QUERY );
260         }
261         catch ( Exception const & )
262         {
263         }
264 
265         if( xStubFactory.is() )
266         {
267             xStubFactory->connectToCache(
268                   this, xCache, Sequence< NumberedSortingInfo > (), NULL );
269             return;
270         }
271     }
272     throw ServiceNotFoundException();
273 }
274 
275 // ------------------------------------------------------------------------------
276 sal_Int16 SAL_CALL
277 SortedDynamicResultSet::getCapabilities()
278     throw( RuntimeException )
279 {
280     osl::Guard< osl::Mutex > aGuard( maMutex );
281 
282     sal_Int16 nCaps = 0;
283 
284     if ( mxOriginal.is() )
285         nCaps = mxOriginal->getCapabilities();
286 
287     nCaps |= ContentResultSetCapability::SORTED;
288 
289     return nCaps;
290 }
291 
292 //--------------------------------------------------------------------------
293 // XDynamicResultSetListener methods.
294 // ------------------------------------------------------------------------------
295 
296 /** In the first notify-call the listener gets the two
297  <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
298  are implementations of the service <type>ContentResultSet</type>.
299 
300  <p>The notified new <type>XResultSet</type> will stay valid after returning
301  notification. The old one will become invalid after returning notification.
302 
303  <p>While in notify-call the listener is allowed to read old and new version,
304  except in the first call, where only the new Resultset is valid.
305 
306  <p>The Listener is allowed to blockade this call, until he really want to go
307  to the new version. The only situation, where the listener has to return the
308  update call at once is, while he disposes his broadcaster or while he is
309  removing himsef as listener (otherwise you deadlock)!!!
310 */
311 void SAL_CALL
312 SortedDynamicResultSet::impl_notify( const ListEvent& Changes )
313     throw( RuntimeException )
314 {
315     osl::Guard< osl::Mutex > aGuard( maMutex );
316 
317     sal_Bool bHasNew = sal_False;
318     sal_Bool bHasModified = sal_False;
319 
320     SortedResultSet *pCurSet = NULL;
321 
322     // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old
323     // nach New kopieren
324     if ( mbGotWelcome )
325     {
326         if ( mbUseOne )
327         {
328             mbUseOne = sal_False;
329             mpTwo->CopyData( mpOne );
330             pCurSet = mpTwo;
331         }
332         else
333         {
334             mbUseOne = sal_True;
335             mpOne->CopyData( mpTwo );
336             pCurSet = mpOne;
337         }
338     }
339 
340     Any  aRet;
341 
342     try {
343         aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) );
344     }
345     catch ( UnknownPropertyException ) {}
346     catch ( WrappedTargetException ) {}
347 
348     long nOldCount = pCurSet->GetCount();
349     sal_Bool bWasFinal = false;
350 
351     aRet >>= bWasFinal;
352 
353     // handle the actions in the list
354     for ( long i=0; i<Changes.Changes.getLength(); i++ )
355     {
356         const ListAction aAction = Changes.Changes[i];
357         switch ( aAction.ListActionType )
358         {
359             case ListActionType::WELCOME:
360                 {
361                     WelcomeDynamicResultSetStruct aWelcome;
362                     if ( aAction.ActionInfo >>= aWelcome )
363                     {
364                         mpTwo = new SortedResultSet( aWelcome.Old );
365                         mxTwo = mpTwo;
366                         mpOne = new SortedResultSet( aWelcome.New );
367                         mxOne = mpOne;
368                         mpOne->Initialize( maOptions, mxCompFac );
369                         mbGotWelcome = sal_True;
370                         mbUseOne = sal_True;
371                         pCurSet = mpOne;
372 
373                         aWelcome.Old = mxTwo;
374                         aWelcome.New = mxOne;
375 
376                         ListAction *pWelcomeAction = new ListAction;
377                         pWelcomeAction->ActionInfo <<= aWelcome;
378                         pWelcomeAction->Position = 0;
379                         pWelcomeAction->Count = 0;
380                         pWelcomeAction->ListActionType = ListActionType::WELCOME;
381 
382                         maActions.Insert( pWelcomeAction );
383                     }
384                     else
385                     {
386                         // throw RuntimeException();
387                     }
388                     break;
389                 }
390             case ListActionType::INSERTED:
391                 {
392                     pCurSet->InsertNew( aAction.Position, aAction.Count );
393                     bHasNew = sal_True;
394                     break;
395                 }
396             case ListActionType::REMOVED:
397                 {
398                     pCurSet->Remove( aAction.Position,
399                                      aAction.Count,
400                                      &maActions );
401                     break;
402                 }
403             case ListActionType::MOVED:
404                 {
405                     long nOffset = 0;
406                     if ( aAction.ActionInfo >>= nOffset )
407                     {
408                         pCurSet->Move( aAction.Position,
409                                        aAction.Count,
410                                        nOffset );
411                     }
412                     break;
413                 }
414             case ListActionType::PROPERTIES_CHANGED:
415                 {
416                     pCurSet->SetChanged( aAction.Position, aAction.Count );
417                     bHasModified = sal_True;
418                     break;
419                 }
420             default: break;
421         }
422     }
423 
424     if ( bHasModified )
425         pCurSet->ResortModified( &maActions );
426 
427     if ( bHasNew )
428         pCurSet->ResortNew( &maActions );
429 
430     // send the new actions with a notify to the listeners
431     SendNotify();
432 
433     // check for propertyChangeEvents
434     pCurSet->CheckProperties( nOldCount, bWasFinal );
435 }
436 
437 //-----------------------------------------------------------------
438 // XEventListener
439 //-----------------------------------------------------------------
440 void SAL_CALL
441 SortedDynamicResultSet::impl_disposing( const EventObject& )
442     throw( RuntimeException )
443 {
444     mxListener.clear();
445     mxOriginal.clear();
446 }
447 
448 // ------------------------------------------------------------------------------
449 // private methods
450 // ------------------------------------------------------------------------------
451 void SortedDynamicResultSet::SendNotify()
452 {
453     long nCount = maActions.Count();
454 
455     if ( nCount && mxListener.is() )
456     {
457         Sequence< ListAction > aActionList( maActions.Count() );
458         ListAction *pActionList = aActionList.getArray();
459 
460         for ( long i=0; i<nCount; i++ )
461         {
462             pActionList[ i ] = *(maActions.GetAction( i ));
463         }
464 
465         ListEvent aNewEvent;
466         aNewEvent.Changes = aActionList;
467 
468         mxListener->notify( aNewEvent );
469     }
470 
471     // clean up
472     maActions.Clear();
473 }
474 
475 //=========================================================================
476 //
477 // SortedDynamicResultSetFactory
478 //
479 //=========================================================================
480 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
481                         const Reference< XMultiServiceFactory > & rSMgr )
482 {
483     mxSMgr = rSMgr;
484 }
485 
486 //--------------------------------------------------------------------------
487 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
488 {
489 }
490 
491 //--------------------------------------------------------------------------
492 // XInterface methods.
493 //--------------------------------------------------------------------------
494 
495 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory,
496                    XTypeProvider,
497                    XServiceInfo,
498                    XSortedDynamicResultSetFactory );
499 
500 //--------------------------------------------------------------------------
501 // XTypeProvider methods.
502 //--------------------------------------------------------------------------
503 
504 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory,
505                       XTypeProvider,
506                       XServiceInfo,
507                       XSortedDynamicResultSetFactory );
508 
509 //--------------------------------------------------------------------------
510 // XServiceInfo methods.
511 //--------------------------------------------------------------------------
512 
513 XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory,
514                      OUString::createFromAscii(
515                         "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
516                      OUString::createFromAscii(
517                         DYNAMIC_RESULTSET_FACTORY_NAME ) );
518 
519 //--------------------------------------------------------------------------
520 // Service factory implementation.
521 //--------------------------------------------------------------------------
522 
523 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory );
524 
525 //--------------------------------------------------------------------------
526 // SortedDynamicResultSetFactory methods.
527 //--------------------------------------------------------------------------
528 Reference< XDynamicResultSet > SAL_CALL
529 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
530                 const Reference< XDynamicResultSet > & Source,
531                 const Sequence< NumberedSortingInfo > & Info,
532                 const Reference< XAnyCompareFactory > & CompareFactory )
533     throw( RuntimeException )
534 {
535     Reference< XDynamicResultSet > xRet;
536     xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr );
537     return xRet;
538 }
539 
540 //=========================================================================
541 //
542 // EventList
543 //
544 //=========================================================================
545 
546 void EventList::Clear()
547 {
548     for ( std::deque< LISTACTION* >::size_type i = 0;
549           i < maData.size(); ++i )
550     {
551         delete maData[i];
552     }
553 
554     maData.clear();
555 }
556 
557 //--------------------------------------------------------------------------
558 void EventList::AddEvent( long nType, long nPos, long nCount )
559 {
560     ListAction *pAction = new ListAction;
561     pAction->Position = nPos;
562     pAction->Count = nCount;
563     pAction->ListActionType = nType;
564 
565     Insert( pAction );
566 }
567 
568 //=================================================================
569 //
570 // SortedDynamicResultSetListener
571 //
572 //=================================================================
573 
574 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
575                                 SortedDynamicResultSet *mOwner )
576 {
577     mpOwner = mOwner;
578 }
579 
580 //-----------------------------------------------------------------
581 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
582 {
583 }
584 
585 //-----------------------------------------------------------------
586 // XInterface methods.
587 //-----------------------------------------------------------------
588 
589 XINTERFACE_IMPL_2( SortedDynamicResultSetListener,
590                    XEventListener,  /* base class of XDynamicResultSetListener */
591                    XDynamicResultSetListener );
592 
593 //-----------------------------------------------------------------
594 // XEventListener ( base of XDynamicResultSetListener )
595 //-----------------------------------------------------------------
596 void SAL_CALL
597 SortedDynamicResultSetListener::disposing( const EventObject& Source )
598     throw( RuntimeException )
599 {
600     osl::Guard< osl::Mutex > aGuard( maMutex );
601 
602     if ( mpOwner )
603         mpOwner->impl_disposing( Source );
604 }
605 
606 //-----------------------------------------------------------------
607 // XDynamicResultSetListener
608 //-----------------------------------------------------------------
609 void SAL_CALL
610 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
611     throw( RuntimeException )
612 {
613     osl::Guard< osl::Mutex > aGuard( maMutex );
614 
615     if ( mpOwner )
616         mpOwner->impl_notify( Changes );
617 }
618 
619 //-----------------------------------------------------------------
620 // own methods:
621 //-----------------------------------------------------------------
622 void SAL_CALL
623 SortedDynamicResultSetListener::impl_OwnerDies()
624 {
625     osl::Guard< osl::Mutex > aGuard( maMutex );
626     mpOwner = NULL;
627 }
628 
629