xref: /aoo41x/main/ucb/source/sorter/sortdynres.cxx (revision cdf0e10c)
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