1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sortdynres.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
35 #include <sortdynres.hxx>
36 #include <cppuhelper/interfacecontainer.hxx>
37 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
38 #include <com/sun/star/ucb/ListActionType.hpp>
39 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
40 #include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp>
41 #include <com/sun/star/ucb/XSourceInitialization.hpp>
43 //-----------------------------------------------------------------------------
44 using namespace com::sun::star::beans
;
45 using namespace com::sun::star::lang
;
46 using namespace com::sun::star::sdbc
;
47 using namespace com::sun::star::ucb
;
48 using namespace com::sun::star::uno
;
52 //=========================================================================
54 // The mutex to synchronize access to containers.
55 static osl::Mutex
& getContainerMutex()
57 static osl::Mutex
* pMutex
= NULL
;
60 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
63 static osl::Mutex aMutex
;
71 //=========================================================================
73 // SortedDynamicResultSet
75 //=========================================================================
77 SortedDynamicResultSet::SortedDynamicResultSet(
78 const Reference
< XDynamicResultSet
> &xOriginal
,
79 const Sequence
< NumberedSortingInfo
> &aOptions
,
80 const Reference
< XAnyCompareFactory
> &xCompFac
,
81 const Reference
< XMultiServiceFactory
> &xSMgr
)
83 mpDisposeEventListeners
= NULL
;
84 mpOwnListener
= new SortedDynamicResultSetListener( this );
86 mxOwnListener
= Reference
< XDynamicResultSetListener
>( mpOwnListener
);
88 mxOriginal
= xOriginal
;
96 mbGotWelcome
= sal_False
;
101 //--------------------------------------------------------------------------
102 SortedDynamicResultSet::~SortedDynamicResultSet()
104 mpOwnListener
->impl_OwnerDies();
105 mxOwnListener
.clear();
107 delete mpDisposeEventListeners
;
117 //--------------------------------------------------------------------------
118 // XInterface methods.
119 //--------------------------------------------------------------------------
121 XINTERFACE_IMPL_4( SortedDynamicResultSet
,
124 XComponent
, /* base class of XDynamicResultSet */
127 //--------------------------------------------------------------------------
128 // XTypeProvider methods.
129 //--------------------------------------------------------------------------
131 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet
,
136 //--------------------------------------------------------------------------
137 // XServiceInfo methods.
138 //--------------------------------------------------------------------------
140 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet
,
141 OUString::createFromAscii(
142 "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
143 OUString::createFromAscii(
144 DYNAMIC_RESULTSET_SERVICE_NAME
) );
146 //--------------------------------------------------------------------------
147 // XComponent methods.
148 //--------------------------------------------------------------------------
149 void SAL_CALL
SortedDynamicResultSet::dispose()
150 throw( RuntimeException
)
152 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
154 if ( mpDisposeEventListeners
&& mpDisposeEventListeners
->getLength() )
157 aEvt
.Source
= static_cast< XComponent
* >( this );
158 mpDisposeEventListeners
->disposeAndClear( aEvt
);
170 //--------------------------------------------------------------------------
171 void SAL_CALL
SortedDynamicResultSet::addEventListener(
172 const Reference
< XEventListener
>& Listener
)
173 throw( RuntimeException
)
175 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
177 if ( !mpDisposeEventListeners
)
178 mpDisposeEventListeners
=
179 new OInterfaceContainerHelper( getContainerMutex() );
181 mpDisposeEventListeners
->addInterface( Listener
);
184 //--------------------------------------------------------------------------
185 void SAL_CALL
SortedDynamicResultSet::removeEventListener(
186 const Reference
< XEventListener
>& Listener
)
187 throw( RuntimeException
)
189 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
191 if ( mpDisposeEventListeners
)
192 mpDisposeEventListeners
->removeInterface( Listener
);
195 //--------------------------------------------------------------------------
196 // XDynamicResultSet methods.
197 // ------------------------------------------------------------------------------
198 Reference
< XResultSet
> SAL_CALL
199 SortedDynamicResultSet::getStaticResultSet()
200 throw( ListenerAlreadySetException
, RuntimeException
)
202 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
204 if ( mxListener
.is() )
205 throw ListenerAlreadySetException();
209 if ( mxOriginal
.is() )
211 mpOne
= new SortedResultSet( mxOriginal
->getStaticResultSet() );
213 mpOne
->Initialize( maOptions
, mxCompFac
);
219 // ------------------------------------------------------------------------------
221 SortedDynamicResultSet::setListener( const Reference
< XDynamicResultSetListener
>& Listener
)
222 throw( ListenerAlreadySetException
, RuntimeException
)
224 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
226 if ( mxListener
.is() )
227 throw ListenerAlreadySetException();
229 addEventListener( Reference
< XEventListener
>::query( Listener
) );
231 mxListener
= Listener
;
233 if ( mxOriginal
.is() )
234 mxOriginal
->setListener( mxOwnListener
);
237 // ------------------------------------------------------------------------------
239 SortedDynamicResultSet::connectToCache(
240 const Reference
< XDynamicResultSet
> & xCache
)
241 throw( ListenerAlreadySetException
,
242 AlreadyInitializedException
,
243 ServiceNotFoundException
,
246 if( mxListener
.is() )
247 throw ListenerAlreadySetException();
250 throw ListenerAlreadySetException();
252 Reference
< XSourceInitialization
> xTarget( xCache
, UNO_QUERY
);
253 if( xTarget
.is() && mxSMgr
.is() )
255 Reference
< XCachedDynamicResultSetStubFactory
> xStubFactory
;
258 xStubFactory
= Reference
< XCachedDynamicResultSetStubFactory
>(
259 mxSMgr
->createInstance(
260 OUString::createFromAscii(
261 "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ),
264 catch ( Exception
const & )
268 if( xStubFactory
.is() )
270 xStubFactory
->connectToCache(
271 this, xCache
, Sequence
< NumberedSortingInfo
> (), NULL
);
275 throw ServiceNotFoundException();
278 // ------------------------------------------------------------------------------
280 SortedDynamicResultSet::getCapabilities()
281 throw( RuntimeException
)
283 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
287 if ( mxOriginal
.is() )
288 nCaps
= mxOriginal
->getCapabilities();
290 nCaps
|= ContentResultSetCapability::SORTED
;
295 //--------------------------------------------------------------------------
296 // XDynamicResultSetListener methods.
297 // ------------------------------------------------------------------------------
299 /** In the first notify-call the listener gets the two
300 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
301 are implementations of the service <type>ContentResultSet</type>.
303 <p>The notified new <type>XResultSet</type> will stay valid after returning
304 notification. The old one will become invalid after returning notification.
306 <p>While in notify-call the listener is allowed to read old and new version,
307 except in the first call, where only the new Resultset is valid.
309 <p>The Listener is allowed to blockade this call, until he really want to go
310 to the new version. The only situation, where the listener has to return the
311 update call at once is, while he disposes his broadcaster or while he is
312 removing himsef as listener (otherwise you deadlock)!!!
315 SortedDynamicResultSet::impl_notify( const ListEvent
& Changes
)
316 throw( RuntimeException
)
318 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
320 sal_Bool bHasNew
= sal_False
;
321 sal_Bool bHasModified
= sal_False
;
323 SortedResultSet
*pCurSet
= NULL
;
325 // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old
331 mbUseOne
= sal_False
;
332 mpTwo
->CopyData( mpOne
);
338 mpOne
->CopyData( mpTwo
);
346 aRet
= pCurSet
->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) );
348 catch ( UnknownPropertyException
) {}
349 catch ( WrappedTargetException
) {}
351 long nOldCount
= pCurSet
->GetCount();
352 sal_Bool bWasFinal
= false;
356 // handle the actions in the list
357 for ( long i
=0; i
<Changes
.Changes
.getLength(); i
++ )
359 const ListAction aAction
= Changes
.Changes
[i
];
360 switch ( aAction
.ListActionType
)
362 case ListActionType::WELCOME
:
364 WelcomeDynamicResultSetStruct aWelcome
;
365 if ( aAction
.ActionInfo
>>= aWelcome
)
367 mpTwo
= new SortedResultSet( aWelcome
.Old
);
369 mpOne
= new SortedResultSet( aWelcome
.New
);
371 mpOne
->Initialize( maOptions
, mxCompFac
);
372 mbGotWelcome
= sal_True
;
376 aWelcome
.Old
= mxTwo
;
377 aWelcome
.New
= mxOne
;
379 ListAction
*pWelcomeAction
= new ListAction
;
380 pWelcomeAction
->ActionInfo
<<= aWelcome
;
381 pWelcomeAction
->Position
= 0;
382 pWelcomeAction
->Count
= 0;
383 pWelcomeAction
->ListActionType
= ListActionType::WELCOME
;
385 maActions
.Insert( pWelcomeAction
);
389 // throw RuntimeException();
393 case ListActionType::INSERTED
:
395 pCurSet
->InsertNew( aAction
.Position
, aAction
.Count
);
399 case ListActionType::REMOVED
:
401 pCurSet
->Remove( aAction
.Position
,
406 case ListActionType::MOVED
:
409 if ( aAction
.ActionInfo
>>= nOffset
)
411 pCurSet
->Move( aAction
.Position
,
417 case ListActionType::PROPERTIES_CHANGED
:
419 pCurSet
->SetChanged( aAction
.Position
, aAction
.Count
);
420 bHasModified
= sal_True
;
428 pCurSet
->ResortModified( &maActions
);
431 pCurSet
->ResortNew( &maActions
);
433 // send the new actions with a notify to the listeners
436 // check for propertyChangeEvents
437 pCurSet
->CheckProperties( nOldCount
, bWasFinal
);
440 //-----------------------------------------------------------------
442 //-----------------------------------------------------------------
444 SortedDynamicResultSet::impl_disposing( const EventObject
& )
445 throw( RuntimeException
)
451 // ------------------------------------------------------------------------------
453 // ------------------------------------------------------------------------------
454 void SortedDynamicResultSet::SendNotify()
456 long nCount
= maActions
.Count();
458 if ( nCount
&& mxListener
.is() )
460 Sequence
< ListAction
> aActionList( maActions
.Count() );
461 ListAction
*pActionList
= aActionList
.getArray();
463 for ( long i
=0; i
<nCount
; i
++ )
465 pActionList
[ i
] = *(maActions
.GetAction( i
));
469 aNewEvent
.Changes
= aActionList
;
471 mxListener
->notify( aNewEvent
);
478 //=========================================================================
480 // SortedDynamicResultSetFactory
482 //=========================================================================
483 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
484 const Reference
< XMultiServiceFactory
> & rSMgr
)
489 //--------------------------------------------------------------------------
490 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
494 //--------------------------------------------------------------------------
495 // XInterface methods.
496 //--------------------------------------------------------------------------
498 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory
,
501 XSortedDynamicResultSetFactory
);
503 //--------------------------------------------------------------------------
504 // XTypeProvider methods.
505 //--------------------------------------------------------------------------
507 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory
,
510 XSortedDynamicResultSetFactory
);
512 //--------------------------------------------------------------------------
513 // XServiceInfo methods.
514 //--------------------------------------------------------------------------
516 XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory
,
517 OUString::createFromAscii(
518 "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
519 OUString::createFromAscii(
520 DYNAMIC_RESULTSET_FACTORY_NAME
) );
522 //--------------------------------------------------------------------------
523 // Service factory implementation.
524 //--------------------------------------------------------------------------
526 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory
);
528 //--------------------------------------------------------------------------
529 // SortedDynamicResultSetFactory methods.
530 //--------------------------------------------------------------------------
531 Reference
< XDynamicResultSet
> SAL_CALL
532 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
533 const Reference
< XDynamicResultSet
> & Source
,
534 const Sequence
< NumberedSortingInfo
> & Info
,
535 const Reference
< XAnyCompareFactory
> & CompareFactory
)
536 throw( RuntimeException
)
538 Reference
< XDynamicResultSet
> xRet
;
539 xRet
= new SortedDynamicResultSet( Source
, Info
, CompareFactory
, mxSMgr
);
543 //=========================================================================
547 //=========================================================================
549 void EventList::Clear()
551 for ( std::deque
< LISTACTION
* >::size_type i
= 0;
552 i
< maData
.size(); ++i
)
560 //--------------------------------------------------------------------------
561 void EventList::AddEvent( long nType
, long nPos
, long nCount
)
563 ListAction
*pAction
= new ListAction
;
564 pAction
->Position
= nPos
;
565 pAction
->Count
= nCount
;
566 pAction
->ListActionType
= nType
;
571 //=================================================================
573 // SortedDynamicResultSetListener
575 //=================================================================
577 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
578 SortedDynamicResultSet
*mOwner
)
583 //-----------------------------------------------------------------
584 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
588 //-----------------------------------------------------------------
589 // XInterface methods.
590 //-----------------------------------------------------------------
592 XINTERFACE_IMPL_2( SortedDynamicResultSetListener
,
593 XEventListener
, /* base class of XDynamicResultSetListener */
594 XDynamicResultSetListener
);
596 //-----------------------------------------------------------------
597 // XEventListener ( base of XDynamicResultSetListener )
598 //-----------------------------------------------------------------
600 SortedDynamicResultSetListener::disposing( const EventObject
& Source
)
601 throw( RuntimeException
)
603 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
606 mpOwner
->impl_disposing( Source
);
609 //-----------------------------------------------------------------
610 // XDynamicResultSetListener
611 //-----------------------------------------------------------------
613 SortedDynamicResultSetListener::notify( const ListEvent
& Changes
)
614 throw( RuntimeException
)
616 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
619 mpOwner
->impl_notify( Changes
);
622 //-----------------------------------------------------------------
624 //-----------------------------------------------------------------
626 SortedDynamicResultSetListener::impl_OwnerDies()
628 osl::Guard
< osl::Mutex
> aGuard( maMutex
);