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