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