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 .
21 #include <sortdynres.hxx>
22 #include <cppuhelper/interfacecontainer.hxx>
23 #include <cppuhelper/supportsservice.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>
29 #include <ucbhelper/getcomponentcontext.hxx>
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 // The mutex to synchronize access to containers.
40 static osl::Mutex
& getContainerMutex()
42 static osl::Mutex
* pMutex
= NULL
;
45 osl::Guard
< osl::Mutex
> aGuard( osl::Mutex::getGlobalMutex() );
48 static osl::Mutex aMutex
;
57 // SortedDynamicResultSet
59 SortedDynamicResultSet::SortedDynamicResultSet(
60 const Reference
< XDynamicResultSet
> &xOriginal
,
61 const Sequence
< NumberedSortingInfo
> &aOptions
,
62 const Reference
< XAnyCompareFactory
> &xCompFac
,
63 const Reference
< XComponentContext
> &rxContext
)
65 mpDisposeEventListeners
= NULL
;
66 mpOwnListener
= new SortedDynamicResultSetListener( this );
68 mxOwnListener
= Reference
< XDynamicResultSetListener
>( mpOwnListener
);
70 mxOriginal
= xOriginal
;
73 m_xContext
= rxContext
;
84 SortedDynamicResultSet::~SortedDynamicResultSet()
86 mpOwnListener
->impl_OwnerDies();
87 mxOwnListener
.clear();
89 delete mpDisposeEventListeners
;
99 // XServiceInfo methods.
101 OUString SAL_CALL
SortedDynamicResultSet::getImplementationName()
102 throw( css::uno::RuntimeException
, std::exception
)
104 return getImplementationName_Static();
107 OUString
SortedDynamicResultSet::getImplementationName_Static()
109 return OUString( "com.sun.star.comp.ucb.SortedDynamicResultSet" );
112 sal_Bool SAL_CALL
SortedDynamicResultSet::supportsService( const OUString
& ServiceName
)
113 throw( css::uno::RuntimeException
, std::exception
)
115 return cppu::supportsService( this, ServiceName
);
118 css::uno::Sequence
< OUString
> SAL_CALL
SortedDynamicResultSet::getSupportedServiceNames()
119 throw( css::uno::RuntimeException
, std::exception
)
121 return getSupportedServiceNames_Static();
124 css::uno::Sequence
< OUString
> SortedDynamicResultSet::getSupportedServiceNames_Static()
126 css::uno::Sequence
< OUString
> aSNS( 1 );
127 aSNS
.getArray()[ 0 ] = OUString( DYNAMIC_RESULTSET_SERVICE_NAME
);
131 // XComponent methods.
133 void SAL_CALL
SortedDynamicResultSet::dispose()
134 throw( RuntimeException
, std::exception
)
136 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
138 if ( mpDisposeEventListeners
&& mpDisposeEventListeners
->getLength() )
141 aEvt
.Source
= static_cast< XComponent
* >( this );
142 mpDisposeEventListeners
->disposeAndClear( aEvt
);
154 void SAL_CALL
SortedDynamicResultSet::addEventListener(
155 const Reference
< XEventListener
>& Listener
)
156 throw( RuntimeException
, std::exception
)
158 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
160 if ( !mpDisposeEventListeners
)
161 mpDisposeEventListeners
=
162 new OInterfaceContainerHelper( getContainerMutex() );
164 mpDisposeEventListeners
->addInterface( Listener
);
167 void SAL_CALL
SortedDynamicResultSet::removeEventListener(
168 const Reference
< XEventListener
>& Listener
)
169 throw( RuntimeException
, std::exception
)
171 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
173 if ( mpDisposeEventListeners
)
174 mpDisposeEventListeners
->removeInterface( Listener
);
178 // XDynamicResultSet methods.
180 Reference
< XResultSet
> SAL_CALL
181 SortedDynamicResultSet::getStaticResultSet()
182 throw( ListenerAlreadySetException
, RuntimeException
, std::exception
)
184 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
186 if ( mxListener
.is() )
187 throw ListenerAlreadySetException();
191 if ( mxOriginal
.is() )
193 mpOne
= new SortedResultSet( mxOriginal
->getStaticResultSet() );
195 mpOne
->Initialize( maOptions
, mxCompFac
);
203 SortedDynamicResultSet::setListener( const Reference
< XDynamicResultSetListener
>& Listener
)
204 throw( ListenerAlreadySetException
, RuntimeException
, std::exception
)
206 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
208 if ( mxListener
.is() )
209 throw ListenerAlreadySetException();
211 addEventListener( Reference
< XEventListener
>::query( Listener
) );
213 mxListener
= Listener
;
215 if ( mxOriginal
.is() )
216 mxOriginal
->setListener( mxOwnListener
);
221 SortedDynamicResultSet::connectToCache( const Reference
< XDynamicResultSet
> & xCache
)
222 throw( ListenerAlreadySetException
,
223 AlreadyInitializedException
,
224 ServiceNotFoundException
,
225 RuntimeException
, std::exception
)
227 if( mxListener
.is() )
228 throw ListenerAlreadySetException();
231 throw ListenerAlreadySetException();
233 Reference
< XSourceInitialization
> xTarget( xCache
, UNO_QUERY
);
234 if( xTarget
.is() && m_xContext
.is() )
236 Reference
< XCachedDynamicResultSetStubFactory
> xStubFactory
;
239 xStubFactory
= CachedDynamicResultSetStubFactory::create( m_xContext
);
241 catch ( Exception
const & )
245 if( xStubFactory
.is() )
247 xStubFactory
->connectToCache(
248 this, xCache
, Sequence
< NumberedSortingInfo
> (), NULL
);
252 throw ServiceNotFoundException();
256 sal_Int16 SAL_CALL
SortedDynamicResultSet::getCapabilities()
257 throw( RuntimeException
, std::exception
)
259 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
263 if ( mxOriginal
.is() )
264 nCaps
= mxOriginal
->getCapabilities();
266 nCaps
|= ContentResultSetCapability::SORTED
;
272 // XDynamicResultSetListener methods.
275 /** In the first notify-call the listener gets the two
276 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s
277 are implementations of the service <type>ContentResultSet</type>.
279 <p>The notified new <type>XResultSet</type> will stay valid after returning
280 notification. The old one will become invalid after returning notification.
282 <p>While in notify-call the listener is allowed to read old and new version,
283 except in the first call, where only the new Resultset is valid.
285 <p>The Listener is allowed to blockade this call, until he really want to go
286 to the new version. The only situation, where the listener has to return the
287 update call at once is, while he disposes his broadcaster or while he is
288 removing himsef as listener (otherwise you deadlock)!!!
290 void SortedDynamicResultSet::impl_notify( const ListEvent
& Changes
)
291 throw( RuntimeException
)
293 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
295 bool bHasNew
= false;
296 bool bHasModified
= false;
298 SortedResultSet
*pCurSet
= NULL
;
300 // exchange mxNew and mxOld and immediately afterwards copy the tables
307 mpTwo
->CopyData( mpOne
);
313 mpOne
->CopyData( mpTwo
);
324 aRet
= pCurSet
->getPropertyValue("IsRowCountFinal");
326 catch (const UnknownPropertyException
&) {}
327 catch (const WrappedTargetException
&) {}
329 long nOldCount
= pCurSet
->GetCount();
330 bool bWasFinal
= false;
334 // handle the actions in the list
335 for ( long i
=0; i
<Changes
.Changes
.getLength(); i
++ )
337 const ListAction aAction
= Changes
.Changes
[i
];
338 switch ( aAction
.ListActionType
)
340 case ListActionType::WELCOME
:
342 WelcomeDynamicResultSetStruct aWelcome
;
343 if ( aAction
.ActionInfo
>>= aWelcome
)
345 mpTwo
= new SortedResultSet( aWelcome
.Old
);
347 mpOne
= new SortedResultSet( aWelcome
.New
);
349 mpOne
->Initialize( maOptions
, mxCompFac
);
354 aWelcome
.Old
= mxTwo
;
355 aWelcome
.New
= mxOne
;
357 ListAction
*pWelcomeAction
= new ListAction
;
358 pWelcomeAction
->ActionInfo
<<= aWelcome
;
359 pWelcomeAction
->Position
= 0;
360 pWelcomeAction
->Count
= 0;
361 pWelcomeAction
->ListActionType
= ListActionType::WELCOME
;
363 maActions
.Insert( pWelcomeAction
);
367 // throw RuntimeException();
371 case ListActionType::INSERTED
:
373 pCurSet
->InsertNew( aAction
.Position
, aAction
.Count
);
377 case ListActionType::REMOVED
:
379 pCurSet
->Remove( aAction
.Position
,
384 case ListActionType::MOVED
:
387 if ( aAction
.ActionInfo
>>= nOffset
)
389 pCurSet
->Move( aAction
.Position
,
395 case ListActionType::PROPERTIES_CHANGED
:
397 pCurSet
->SetChanged( aAction
.Position
, aAction
.Count
);
406 pCurSet
->ResortModified( &maActions
);
409 pCurSet
->ResortNew( &maActions
);
411 // send the new actions with a notify to the listeners
414 // check for propertyChangeEvents
415 pCurSet
->CheckProperties( nOldCount
, bWasFinal
);
420 void SortedDynamicResultSet::impl_disposing( const EventObject
& )
421 throw( RuntimeException
)
429 void SortedDynamicResultSet::SendNotify()
431 long nCount
= maActions
.Count();
433 if ( nCount
&& mxListener
.is() )
435 Sequence
< ListAction
> aActionList( maActions
.Count() );
436 ListAction
*pActionList
= aActionList
.getArray();
438 for ( long i
=0; i
<nCount
; i
++ )
440 pActionList
[ i
] = *(maActions
.GetAction( i
));
444 aNewEvent
.Changes
= aActionList
;
446 mxListener
->notify( aNewEvent
);
453 // SortedDynamicResultSetFactory
455 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory(
456 const Reference
< XComponentContext
> & rxContext
)
458 m_xContext
= rxContext
;
462 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory()
467 // XServiceInfo methods.
469 OUString SAL_CALL
SortedDynamicResultSetFactory::getImplementationName()
470 throw( css::uno::RuntimeException
, std::exception
)
472 return getImplementationName_Static();
475 OUString
SortedDynamicResultSetFactory::getImplementationName_Static()
477 return OUString( "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" );
480 sal_Bool SAL_CALL
SortedDynamicResultSetFactory::supportsService( const OUString
& ServiceName
)
481 throw( css::uno::RuntimeException
, std::exception
)
483 return cppu::supportsService( this, ServiceName
);
486 css::uno::Sequence
< OUString
> SAL_CALL
SortedDynamicResultSetFactory::getSupportedServiceNames()
487 throw( css::uno::RuntimeException
, std::exception
)
489 return getSupportedServiceNames_Static();
492 static css::uno::Reference
< css::uno::XInterface
> SAL_CALL
493 SortedDynamicResultSetFactory_CreateInstance( const css::uno::Reference
<
494 css::lang::XMultiServiceFactory
> & rSMgr
)
495 throw( css::uno::Exception
)
497 css::lang::XServiceInfo
* pX
= (css::lang::XServiceInfo
*)
498 new SortedDynamicResultSetFactory( ucbhelper::getComponentContext(rSMgr
) );
499 return css::uno::Reference
< css::uno::XInterface
>::query( pX
);
502 css::uno::Sequence
< OUString
> SortedDynamicResultSetFactory::getSupportedServiceNames_Static()
504 com::sun::star::uno::Sequence
< OUString
> aSNS( 1 );
505 aSNS
.getArray()[ 0 ] = OUString( DYNAMIC_RESULTSET_FACTORY_NAME
);
510 // Service factory implementation.
511 css::uno::Reference
< css::lang::XSingleServiceFactory
>
512 SortedDynamicResultSetFactory::createServiceFactory( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& rxServiceMgr
)
514 return css::uno::Reference
< css::lang::XSingleServiceFactory
>(
515 cppu::createOneInstanceFactory(
517 SortedDynamicResultSetFactory::getImplementationName_Static(),
518 SortedDynamicResultSetFactory_CreateInstance
,
519 SortedDynamicResultSetFactory::getSupportedServiceNames_Static() ) );
522 // SortedDynamicResultSetFactory methods.
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
, std::exception
)
531 Reference
< XDynamicResultSet
> xRet
;
532 xRet
= new SortedDynamicResultSet( Source
, Info
, CompareFactory
, m_xContext
);
538 void EventList::Clear()
540 for ( std::deque
< ListAction
* >::size_type i
= 0;
541 i
< maData
.size(); ++i
)
549 void EventList::AddEvent( sal_IntPtr nType
, sal_IntPtr nPos
, sal_IntPtr nCount
)
551 ListAction
*pAction
= new ListAction
;
552 pAction
->Position
= nPos
;
553 pAction
->Count
= nCount
;
554 pAction
->ListActionType
= nType
;
559 // SortedDynamicResultSetListener
561 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
562 SortedDynamicResultSet
*mOwner
)
568 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
572 // XEventListener ( base of XDynamicResultSetListener )
575 SortedDynamicResultSetListener::disposing( const EventObject
& Source
)
576 throw( RuntimeException
, std::exception
)
578 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
581 mpOwner
->impl_disposing( Source
);
585 // XDynamicResultSetListener
588 SortedDynamicResultSetListener::notify( const ListEvent
& Changes
)
589 throw( RuntimeException
, std::exception
)
591 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
594 mpOwner
->impl_notify( Changes
);
600 SortedDynamicResultSetListener::impl_OwnerDies()
602 osl::Guard
< osl::Mutex
> aGuard( maMutex
);
606 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */