1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sortdynres.hxx>
23 #include <cppuhelper/interfacecontainer.hxx>
24 #include <com/sun/star/ucb/ContentResultSetCapability.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
27 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
28 #include <com/sun/star/ucb/XSourceInitialization.hpp>
30 //-----------------------------------------------------------------------------
31 using namespace com::sun::star::beans
;
32 using namespace com::sun::star::lang
;
33 using namespace com::sun::star::sdbc
;
34 using namespace com::sun::star::ucb
;
35 using namespace com::sun::star::uno
;
39 //=========================================================================
41 // The mutex to synchronize access to containers.
42 static osl::Mutex
& getContainerMutex()
44 static osl::Mutex
* pMutex
= NULL
;
47 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
50 static osl::Mutex aMutex
;
58 //=========================================================================
60 // SortedDynamicResultSet
62 //=========================================================================
64 SortedDynamicResultSet::SortedDynamicResultSet(
65 const Reference
< XDynamicResultSet
> &xOriginal
,
66 const Sequence
< NumberedSortingInfo
> &aOptions
,
67 const Reference
< XAnyCompareFactory
> &xCompFac
,
68 const Reference
< XComponentContext
> &rxContext
)
70 mpDisposeEventListeners
= NULL
;
71 mpOwnListener
= new SortedDynamicResultSetListener( this );
73 mxOwnListener
= Reference
< XDynamicResultSetListener
>( mpOwnListener
);
75 mxOriginal
= xOriginal
;
78 m_xContext
= rxContext
;
83 mbGotWelcome
= sal_False
;
88 //--------------------------------------------------------------------------
89 SortedDynamicResultSet::~SortedDynamicResultSet()
91 mpOwnListener
->impl_OwnerDies();
92 mxOwnListener
.clear();
94 delete mpDisposeEventListeners
;
104 //--------------------------------------------------------------------------
105 // XInterface methods.
106 //--------------------------------------------------------------------------
108 XINTERFACE_IMPL_4( SortedDynamicResultSet
,
111 XComponent
, /* base class of XDynamicResultSet */
114 //--------------------------------------------------------------------------
115 // XTypeProvider methods.
116 //--------------------------------------------------------------------------
118 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet
,
123 //--------------------------------------------------------------------------
124 // XServiceInfo methods.
125 //--------------------------------------------------------------------------
127 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet
,
128 OUString( "com.sun.star.comp.ucb.SortedDynamicResultSet" ),
129 OUString( DYNAMIC_RESULTSET_SERVICE_NAME
) );
131 //--------------------------------------------------------------------------
132 // XComponent methods.
133 //--------------------------------------------------------------------------
134 void SAL_CALL
SortedDynamicResultSet::dispose()
135 throw( RuntimeException
)
137 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
139 if ( mpDisposeEventListeners
&& mpDisposeEventListeners
->getLength() )
142 aEvt
.Source
= static_cast< XComponent
* >( this );
143 mpDisposeEventListeners
->disposeAndClear( aEvt
);
155 //--------------------------------------------------------------------------
156 void SAL_CALL
SortedDynamicResultSet::addEventListener(
157 const Reference
< XEventListener
>& Listener
)
158 throw( RuntimeException
)
160 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
162 if ( !mpDisposeEventListeners
)
163 mpDisposeEventListeners
=
164 new OInterfaceContainerHelper( getContainerMutex() );
166 mpDisposeEventListeners
->addInterface( Listener
);
169 //--------------------------------------------------------------------------
170 void SAL_CALL
SortedDynamicResultSet::removeEventListener(
171 const Reference
< XEventListener
>& Listener
)
172 throw( RuntimeException
)
174 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
176 if ( mpDisposeEventListeners
)
177 mpDisposeEventListeners
->removeInterface( Listener
);
180 //--------------------------------------------------------------------------
181 // XDynamicResultSet methods.
182 // ------------------------------------------------------------------------------
183 Reference
< XResultSet
> SAL_CALL
184 SortedDynamicResultSet::getStaticResultSet()
185 throw( ListenerAlreadySetException
, RuntimeException
)
187 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
189 if ( mxListener
.is() )
190 throw ListenerAlreadySetException();
194 if ( mxOriginal
.is() )
196 mpOne
= new SortedResultSet( mxOriginal
->getStaticResultSet() );
198 mpOne
->Initialize( maOptions
, mxCompFac
);
204 // ------------------------------------------------------------------------------
206 SortedDynamicResultSet::setListener( const Reference
< XDynamicResultSetListener
>& Listener
)
207 throw( ListenerAlreadySetException
, RuntimeException
)
209 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
211 if ( mxListener
.is() )
212 throw ListenerAlreadySetException();
214 addEventListener( Reference
< XEventListener
>::query( Listener
) );
216 mxListener
= Listener
;
218 if ( mxOriginal
.is() )
219 mxOriginal
->setListener( mxOwnListener
);
222 // ------------------------------------------------------------------------------
224 SortedDynamicResultSet::connectToCache(
225 const Reference
< XDynamicResultSet
> & xCache
)
226 throw( ListenerAlreadySetException
,
227 AlreadyInitializedException
,
228 ServiceNotFoundException
,
231 if( mxListener
.is() )
232 throw ListenerAlreadySetException();
235 throw ListenerAlreadySetException();
237 Reference
< XSourceInitialization
> xTarget( xCache
, UNO_QUERY
);
238 if( xTarget
.is() && m_xContext
.is() )
240 Reference
< XCachedDynamicResultSetStubFactory
> xStubFactory
;
243 xStubFactory
= CachedDynamicResultSetStubFactory::create( m_xContext
);
245 catch ( Exception
const & )
249 if( xStubFactory
.is() )
251 xStubFactory
->connectToCache(
252 this, xCache
, Sequence
< NumberedSortingInfo
> (), NULL
);
256 throw ServiceNotFoundException();
259 // ------------------------------------------------------------------------------
261 SortedDynamicResultSet::getCapabilities()
262 throw( RuntimeException
)
264 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
268 if ( mxOriginal
.is() )
269 nCaps
= mxOriginal
->getCapabilities();
271 nCaps
|= ContentResultSetCapability::SORTED
;
276 //--------------------------------------------------------------------------
277 // XDynamicResultSetListener methods.
278 // ------------------------------------------------------------------------------
280 /** In the first notify-call the listener gets the two
281 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
282 are implementations of the service <type>ContentResultSet</type>.
284 <p>The notified new <type>XResultSet</type> will stay valid after returning
285 notification. The old one will become invalid after returning notification.
287 <p>While in notify-call the listener is allowed to read old and new version,
288 except in the first call, where only the new Resultset is valid.
290 <p>The Listener is allowed to blockade this call, until he really want to go
291 to the new version. The only situation, where the listener has to return the
292 update call at once is, while he disposes his broadcaster or while he is
293 removing himsef as listener (otherwise you deadlock)!!!
296 SortedDynamicResultSet::impl_notify( const ListEvent
& Changes
)
297 throw( RuntimeException
)
299 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
301 sal_Bool bHasNew
= sal_False
;
302 sal_Bool bHasModified
= sal_False
;
304 SortedResultSet
*pCurSet
= NULL
;
306 // exchange mxNew and mxOld and immediately afterwards copy the tables
312 mbUseOne
= sal_False
;
313 mpTwo
->CopyData( mpOne
);
319 mpOne
->CopyData( mpTwo
);
327 aRet
= pCurSet
->getPropertyValue( OUString("IsRowCountFinal") );
329 catch (const UnknownPropertyException
&) {}
330 catch (const WrappedTargetException
&) {}
332 long nOldCount
= pCurSet
->GetCount();
333 sal_Bool bWasFinal
= false;
337 // handle the actions in the list
338 for ( long i
=0; i
<Changes
.Changes
.getLength(); i
++ )
340 const ListAction aAction
= Changes
.Changes
[i
];
341 switch ( aAction
.ListActionType
)
343 case ListActionType::WELCOME
:
345 WelcomeDynamicResultSetStruct aWelcome
;
346 if ( aAction
.ActionInfo
>>= aWelcome
)
348 mpTwo
= new SortedResultSet( aWelcome
.Old
);
350 mpOne
= new SortedResultSet( aWelcome
.New
);
352 mpOne
->Initialize( maOptions
, mxCompFac
);
353 mbGotWelcome
= sal_True
;
357 aWelcome
.Old
= mxTwo
;
358 aWelcome
.New
= mxOne
;
360 ListAction
*pWelcomeAction
= new ListAction
;
361 pWelcomeAction
->ActionInfo
<<= aWelcome
;
362 pWelcomeAction
->Position
= 0;
363 pWelcomeAction
->Count
= 0;
364 pWelcomeAction
->ListActionType
= ListActionType::WELCOME
;
366 maActions
.Insert( pWelcomeAction
);
370 // throw RuntimeException();
374 case ListActionType::INSERTED
:
376 pCurSet
->InsertNew( aAction
.Position
, aAction
.Count
);
380 case ListActionType::REMOVED
:
382 pCurSet
->Remove( aAction
.Position
,
387 case ListActionType::MOVED
:
390 if ( aAction
.ActionInfo
>>= nOffset
)
392 pCurSet
->Move( aAction
.Position
,
398 case ListActionType::PROPERTIES_CHANGED
:
400 pCurSet
->SetChanged( aAction
.Position
, aAction
.Count
);
401 bHasModified
= sal_True
;
409 pCurSet
->ResortModified( &maActions
);
412 pCurSet
->ResortNew( &maActions
);
414 // send the new actions with a notify to the listeners
417 // check for propertyChangeEvents
418 pCurSet
->CheckProperties( nOldCount
, bWasFinal
);
421 //-----------------------------------------------------------------
423 //-----------------------------------------------------------------
425 SortedDynamicResultSet::impl_disposing( const EventObject
& )
426 throw( RuntimeException
)
432 // ------------------------------------------------------------------------------
434 // ------------------------------------------------------------------------------
435 void SortedDynamicResultSet::SendNotify()
437 long nCount
= maActions
.Count();
439 if ( nCount
&& mxListener
.is() )
441 Sequence
< ListAction
> aActionList( maActions
.Count() );
442 ListAction
*pActionList
= aActionList
.getArray();
444 for ( long i
=0; i
<nCount
; i
++ )
446 pActionList
[ i
] = *(maActions
.GetAction( i
));
450 aNewEvent
.Changes
= aActionList
;
452 mxListener
->notify( aNewEvent
);
459 //=========================================================================
461 // SortedDynamicResultSetFactory
463 //=========================================================================
464 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
465 const Reference
< XComponentContext
> & rxContext
)
467 m_xContext
= rxContext
;
470 //--------------------------------------------------------------------------
471 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
475 //--------------------------------------------------------------------------
476 // XInterface methods.
477 //--------------------------------------------------------------------------
479 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory
,
482 XSortedDynamicResultSetFactory
);
484 //--------------------------------------------------------------------------
485 // XTypeProvider methods.
486 //--------------------------------------------------------------------------
488 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory
,
491 XSortedDynamicResultSetFactory
);
493 //--------------------------------------------------------------------------
494 // XServiceInfo methods.
495 //--------------------------------------------------------------------------
497 XSERVICEINFO_IMPL_1_CTX( SortedDynamicResultSetFactory
,
498 OUString( "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ),
499 OUString( DYNAMIC_RESULTSET_FACTORY_NAME
) );
501 //--------------------------------------------------------------------------
502 // Service factory implementation.
503 //--------------------------------------------------------------------------
505 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory
);
507 //--------------------------------------------------------------------------
508 // SortedDynamicResultSetFactory methods.
509 //--------------------------------------------------------------------------
510 Reference
< XDynamicResultSet
> SAL_CALL
511 SortedDynamicResultSetFactory::createSortedDynamicResultSet(
512 const Reference
< XDynamicResultSet
> & Source
,
513 const Sequence
< NumberedSortingInfo
> & Info
,
514 const Reference
< XAnyCompareFactory
> & CompareFactory
)
515 throw( RuntimeException
)
517 Reference
< XDynamicResultSet
> xRet
;
518 xRet
= new SortedDynamicResultSet( Source
, Info
, CompareFactory
, m_xContext
);
522 //=========================================================================
526 //=========================================================================
528 void EventList::Clear()
530 for ( std::deque
< ListAction
* >::size_type i
= 0;
531 i
< maData
.size(); ++i
)
539 //--------------------------------------------------------------------------
540 void EventList::AddEvent( long nType
, long nPos
, long nCount
)
542 ListAction
*pAction
= new ListAction
;
543 pAction
->Position
= nPos
;
544 pAction
->Count
= nCount
;
545 pAction
->ListActionType
= nType
;
550 //=================================================================
552 // SortedDynamicResultSetListener
554 //=================================================================
556 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
557 SortedDynamicResultSet
*mOwner
)
562 //-----------------------------------------------------------------
563 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
567 //-----------------------------------------------------------------
568 // XInterface methods.
569 //-----------------------------------------------------------------
571 XINTERFACE_IMPL_2( SortedDynamicResultSetListener
,
572 XEventListener
, /* base class of XDynamicResultSetListener */
573 XDynamicResultSetListener
);
575 //-----------------------------------------------------------------
576 // XEventListener ( base of XDynamicResultSetListener )
577 //-----------------------------------------------------------------
579 SortedDynamicResultSetListener::disposing( const EventObject
& Source
)
580 throw( RuntimeException
)
582 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
585 mpOwner
->impl_disposing( Source
);
588 //-----------------------------------------------------------------
589 // XDynamicResultSetListener
590 //-----------------------------------------------------------------
592 SortedDynamicResultSetListener::notify( const ListEvent
& Changes
)
593 throw( RuntimeException
)
595 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
598 mpOwner
->impl_notify( Changes
);
601 //-----------------------------------------------------------------
603 //-----------------------------------------------------------------
605 SortedDynamicResultSetListener::impl_OwnerDies()
607 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */