xref: /trunk/main/ucb/source/sorter/sortdynres.cxx (revision 2f86921c)
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.
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 
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 //--------------------------------------------------------------------------
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 //--------------------------------------------------------------------------
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 //--------------------------------------------------------------------------
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 //--------------------------------------------------------------------------
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
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
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
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
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
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
437 SortedDynamicResultSet::impl_disposing( const EventObject& )
438 	throw( RuntimeException )
439 {
440 	mxListener.clear();
441 	mxOriginal.clear();
442 }
443 
444 // ------------------------------------------------------------------------------
445 // private methods
446 // ------------------------------------------------------------------------------
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 //=========================================================================
476 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
477 						const Reference< XMultiServiceFactory > & rSMgr )
478 {
479 	mxSMgr = rSMgr;
480 }
481 
482 //--------------------------------------------------------------------------
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
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 
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 //--------------------------------------------------------------------------
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 
570 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
571 								SortedDynamicResultSet *mOwner )
572 {
573 	mpOwner = mOwner;
574 }
575 
576 //-----------------------------------------------------------------
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
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
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
619 SortedDynamicResultSetListener::impl_OwnerDies()
620 {
621 	osl::Guard< osl::Mutex > aGuard( maMutex );
622 	mpOwner = NULL;
623 }
624 
625