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