Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / ucb / source / sorter / sortdynres.cxx
blob66457efbab1053f2caac8123a0bb3a8b2ef869a2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <vector>
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;
36 using namespace cppu;
39 // The mutex to synchronize access to containers.
40 static osl::Mutex& getContainerMutex()
42 static osl::Mutex* pMutex = NULL;
43 if( !pMutex )
45 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
46 if( !pMutex )
48 static osl::Mutex aMutex;
49 pMutex = &aMutex;
53 return *pMutex;
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;
71 maOptions = aOptions;
72 mxCompFac = xCompFac;
73 m_xContext = rxContext;
75 mpOne = NULL;
76 mpTwo = NULL;
78 mbGotWelcome = false;
79 mbUseOne = true;
80 mbStatic = false;
84 SortedDynamicResultSet::~SortedDynamicResultSet()
86 mpOwnListener->impl_OwnerDies();
87 mxOwnListener.clear();
89 delete mpDisposeEventListeners;
91 mxOne.clear();
92 mxTwo.clear();
93 mxOriginal.clear();
95 mpOne = NULL;
96 mpTwo = NULL;
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 );
128 return aSNS;
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() )
140 EventObject aEvt;
141 aEvt.Source = static_cast< XComponent * >( this );
142 mpDisposeEventListeners->disposeAndClear( aEvt );
145 mxOne.clear();
146 mxTwo.clear();
147 mxOriginal.clear();
149 mpOne = NULL;
150 mpTwo = NULL;
151 mbUseOne = true;
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();
189 mbStatic = true;
191 if ( mxOriginal.is() )
193 mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() );
194 mxOne = mpOne;
195 mpOne->Initialize( maOptions, mxCompFac );
198 return mxOne;
202 void SAL_CALL
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 );
220 void SAL_CALL
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();
230 if( mbStatic )
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 );
249 return;
252 throw ServiceNotFoundException();
256 sal_Int16 SAL_CALL SortedDynamicResultSet::getCapabilities()
257 throw( RuntimeException, std::exception )
259 osl::Guard< osl::Mutex > aGuard( maMutex );
261 sal_Int16 nCaps = 0;
263 if ( mxOriginal.is() )
264 nCaps = mxOriginal->getCapabilities();
266 nCaps |= ContentResultSetCapability::SORTED;
268 return nCaps;
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
301 // from Old to New
302 if ( mbGotWelcome )
304 if ( mbUseOne )
306 mbUseOne = false;
307 mpTwo->CopyData( mpOne );
308 pCurSet = mpTwo;
310 else
312 mbUseOne = true;
313 mpOne->CopyData( mpTwo );
314 pCurSet = mpOne;
318 if (!pCurSet)
319 return;
321 Any aRet;
323 try {
324 aRet = pCurSet->getPropertyValue("IsRowCountFinal");
326 catch (const UnknownPropertyException&) {}
327 catch (const WrappedTargetException&) {}
329 long nOldCount = pCurSet->GetCount();
330 bool bWasFinal = false;
332 aRet >>= bWasFinal;
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 );
346 mxTwo = mpTwo;
347 mpOne = new SortedResultSet( aWelcome.New );
348 mxOne = mpOne;
349 mpOne->Initialize( maOptions, mxCompFac );
350 mbGotWelcome = true;
351 mbUseOne = true;
352 pCurSet = mpOne;
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 );
365 else
367 // throw RuntimeException();
369 break;
371 case ListActionType::INSERTED:
373 pCurSet->InsertNew( aAction.Position, aAction.Count );
374 bHasNew = true;
375 break;
377 case ListActionType::REMOVED:
379 pCurSet->Remove( aAction.Position,
380 aAction.Count,
381 &maActions );
382 break;
384 case ListActionType::MOVED:
386 long nOffset = 0;
387 if ( aAction.ActionInfo >>= nOffset )
389 pCurSet->Move( aAction.Position,
390 aAction.Count,
391 nOffset );
393 break;
395 case ListActionType::PROPERTIES_CHANGED:
397 pCurSet->SetChanged( aAction.Position, aAction.Count );
398 bHasModified = true;
399 break;
401 default: break;
405 if ( bHasModified )
406 pCurSet->ResortModified( &maActions );
408 if ( bHasNew )
409 pCurSet->ResortNew( &maActions );
411 // send the new actions with a notify to the listeners
412 SendNotify();
414 // check for propertyChangeEvents
415 pCurSet->CheckProperties( nOldCount, bWasFinal );
418 // XEventListener
420 void SortedDynamicResultSet::impl_disposing( const EventObject& )
421 throw( RuntimeException )
423 mxListener.clear();
424 mxOriginal.clear();
427 // private methods
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 ));
443 ListEvent aNewEvent;
444 aNewEvent.Changes = aActionList;
446 mxListener->notify( aNewEvent );
449 // clean up
450 maActions.Clear();
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 );
506 return aSNS;
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(
516 rxServiceMgr,
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 );
533 return xRet;
536 // EventList
538 void EventList::Clear()
540 for ( std::deque< ListAction* >::size_type i = 0;
541 i < maData.size(); ++i )
543 delete maData[i];
546 maData.clear();
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;
556 Insert( pAction );
559 // SortedDynamicResultSetListener
561 SortedDynamicResultSetListener::SortedDynamicResultSetListener(
562 SortedDynamicResultSet *mOwner )
564 mpOwner = mOwner;
568 SortedDynamicResultSetListener::~SortedDynamicResultSetListener()
572 // XEventListener ( base of XDynamicResultSetListener )
574 void SAL_CALL
575 SortedDynamicResultSetListener::disposing( const EventObject& Source )
576 throw( RuntimeException, std::exception )
578 osl::Guard< osl::Mutex > aGuard( maMutex );
580 if ( mpOwner )
581 mpOwner->impl_disposing( Source );
585 // XDynamicResultSetListener
587 void SAL_CALL
588 SortedDynamicResultSetListener::notify( const ListEvent& Changes )
589 throw( RuntimeException, std::exception )
591 osl::Guard< osl::Mutex > aGuard( maMutex );
593 if ( mpOwner )
594 mpOwner->impl_notify( Changes );
597 // own methods:
599 void SAL_CALL
600 SortedDynamicResultSetListener::impl_OwnerDies()
602 osl::Guard< osl::Mutex > aGuard( maMutex );
603 mpOwner = NULL;
606 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */