LibreOffice Module dbaccess (master) 1
sbamultiplex.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sbamultiplex.hxx>
22
23using namespace dbaui;
24
25// the listener multiplexers
26
27// XStatusListener
28SbaXStatusMultiplexer::SbaXStatusMultiplexer(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex)
29 :OSbaWeakSubObject(rSource)
31{
32}
33
34css::uno::Any SAL_CALL SbaXStatusMultiplexer::queryInterface(const css::uno::Type& _rType)
35{
36 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
37 if (!aReturn.hasValue())
38 aReturn = ::cppu::queryInterface(_rType,
39 static_cast< css::frame::XStatusListener* >(this),
40 static_cast< css::lang::XEventListener* >(static_cast< css::frame::XStatusListener* >(this))
41 );
42
43 return aReturn;
44}
45void SAL_CALL SbaXStatusMultiplexer::disposing(const css::lang::EventObject& )
46{
47}
48
49
50void SAL_CALL SbaXStatusMultiplexer::statusChanged(const css::frame::FeatureStateEvent& e)
51{
54 notifyEach( &XStatusListener::statusChanged, m_aLastKnownStatus );
55}
56
57// LoadListener
59 :OSbaWeakSubObject(rSource)
61{
62}
63
64css::uno::Any SAL_CALL SbaXLoadMultiplexer::queryInterface(const css::uno::Type& _rType)
65{
66 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
67 if (!aReturn.hasValue())
68 aReturn = ::cppu::queryInterface(_rType,
69 static_cast< css::form::XLoadListener* >(this),
70 static_cast< css::lang::XEventListener* >(static_cast< css::form::XLoadListener* >(this))
71 );
72
73 return aReturn;
74}
75void SAL_CALL SbaXLoadMultiplexer::disposing(const css::lang::EventObject& )
76{
77}
78
79void SAL_CALL SbaXLoadMultiplexer::loaded(const css::lang::EventObject& e)
80{
81 css::lang::EventObject aMulti(e);
82 aMulti.Source = &m_rParent;
83 notifyEach( &XLoadListener::loaded, aMulti );
84}
85void SAL_CALL SbaXLoadMultiplexer::unloaded(const css::lang::EventObject& e)
86{
87 css::lang::EventObject aMulti(e);
88 aMulti.Source = &m_rParent;
89 notifyEach( &XLoadListener::unloaded, aMulti );
90}
91
92void SAL_CALL SbaXLoadMultiplexer::unloading(const css::lang::EventObject& e)
93{
94 css::lang::EventObject aMulti(e);
95 aMulti.Source = &m_rParent;
96 notifyEach( &XLoadListener::unloading, aMulti );
97}
98
99void SAL_CALL SbaXLoadMultiplexer::reloading(const css::lang::EventObject& e)
100{
101 css::lang::EventObject aMulti(e);
102 aMulti.Source = &m_rParent;
103 notifyEach( &XLoadListener::reloading, aMulti );
104}
105
106void SAL_CALL SbaXLoadMultiplexer::reloaded(const css::lang::EventObject& e)
107{
108 css::lang::EventObject aMulti(e);
109 aMulti.Source = &m_rParent;
110 notifyEach( &XLoadListener::reloaded, aMulti );
111}
112
113
114// css::sdbc::XRowSetListener
116 :OSbaWeakSubObject(rSource)
118{
119}
120
121css::uno::Any SAL_CALL SbaXRowSetMultiplexer::queryInterface(const css::uno::Type& _rType)
122{
123 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
124 if (!aReturn.hasValue())
125 aReturn = ::cppu::queryInterface(_rType,
126 static_cast< css::sdbc::XRowSetListener* >(this),
127 static_cast< css::lang::XEventListener* >(static_cast< css::sdbc::XRowSetListener* >(this))
128 );
129
130 return aReturn;
131}
132void SAL_CALL SbaXRowSetMultiplexer::disposing(const css::lang::EventObject& )
133{
134}
135
136void SAL_CALL SbaXRowSetMultiplexer::cursorMoved(const css::lang::EventObject& e)
137{
138 css::lang::EventObject aMulti(e);
139 aMulti.Source = &m_rParent;
140 notifyEach( &XRowSetListener::cursorMoved, aMulti );
141}
142
143void SAL_CALL SbaXRowSetMultiplexer::rowChanged(const css::lang::EventObject& e)
144{
145 css::lang::EventObject aMulti(e);
146 aMulti.Source = &m_rParent;
147 notifyEach( &XRowSetListener::rowChanged, aMulti );
148}
149
150void SAL_CALL SbaXRowSetMultiplexer::rowSetChanged(const css::lang::EventObject& e)
151{
152 css::lang::EventObject aMulti(e);
153 aMulti.Source = &m_rParent;
154 notifyEach( &XRowSetListener::rowSetChanged, aMulti );
155}
156
157// css::sdb::XRowSetApproveListener
159 :OSbaWeakSubObject(rSource)
161{
162}
163
164css::uno::Any SAL_CALL SbaXRowSetApproveMultiplexer::queryInterface(const css::uno::Type& _rType)
165{
166 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
167 if (!aReturn.hasValue())
168 aReturn = ::cppu::queryInterface(_rType,
169 static_cast< css::sdb::XRowSetApproveListener* >(this),
170 static_cast< css::lang::XEventListener* >(static_cast< css::sdb::XRowSetApproveListener* >(this))
171 );
172
173 return aReturn;
174}
175void SAL_CALL SbaXRowSetApproveMultiplexer::disposing(const css::lang::EventObject& )
176{
177}
178
179sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveCursorMove(const css::lang::EventObject& e)
180{
181 css::lang::EventObject aMulti(e);
182 aMulti.Source = &m_rParent;
184 bool bResult = true;
185 while (bResult && aIt.hasMoreElements())
186 bResult = aIt.next()->approveCursorMove(aMulti);
187 return bResult;
188}
189
190sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveRowChange(const css::sdb::RowChangeEvent& e)
191{
192 css::sdb::RowChangeEvent aMulti(e);
193 aMulti.Source = &m_rParent;
195 bool bResult = true;
196 while (bResult && aIt.hasMoreElements())
197 bResult = aIt.next()->approveRowChange(aMulti);
198 return bResult;
199}
200
201sal_Bool SAL_CALL SbaXRowSetApproveMultiplexer::approveRowSetChange(const css::lang::EventObject& e)
202{
203 css::lang::EventObject aMulti(e);
204 aMulti.Source = &m_rParent;
206 bool bResult = true;
207 while (bResult && aIt.hasMoreElements())
208 bResult = aIt.next()->approveRowSetChange(aMulti);
209 return bResult;
210}
211
212// css::sdb::XSQLErrorListener
214 :OSbaWeakSubObject(rSource)
216{
217}
218
219css::uno::Any SAL_CALL SbaXSQLErrorMultiplexer::queryInterface(const css::uno::Type& _rType)
220{
221 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
222 if (!aReturn.hasValue())
223 aReturn = ::cppu::queryInterface(_rType,
224 static_cast< css::sdb::XSQLErrorListener* >(this),
225 static_cast< css::lang::XEventListener* >(static_cast< css::sdb::XSQLErrorListener* >(this))
226 );
227
228 return aReturn;
229}
230void SAL_CALL SbaXSQLErrorMultiplexer::disposing(const css::lang::EventObject& )
231{
232}
233
234void SAL_CALL SbaXSQLErrorMultiplexer::errorOccured(const css::sdb::SQLErrorEvent& e)
235{
236 css::sdb::SQLErrorEvent aMulti(e);
237 aMulti.Source = &m_rParent;
238 notifyEach( &XSQLErrorListener::errorOccured, aMulti );
239}
240
241// css::form::XDatabaseParameterListener
243 :OSbaWeakSubObject(rSource)
245{
246}
247
248css::uno::Any SAL_CALL SbaXParameterMultiplexer::queryInterface(const css::uno::Type& _rType)
249{
250 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
251 if (!aReturn.hasValue())
252 aReturn = ::cppu::queryInterface(_rType,
253 static_cast< css::form::XDatabaseParameterListener* >(this),
254 static_cast< css::lang::XEventListener* >(static_cast< css::form::XDatabaseParameterListener* >(this))
255 );
256
257 return aReturn;
258}
259void SAL_CALL SbaXParameterMultiplexer::disposing(const css::lang::EventObject& )
260{
261}
262
263sal_Bool SAL_CALL SbaXParameterMultiplexer::approveParameter(const css::form::DatabaseParameterEvent& e)
264{
265 css::form::DatabaseParameterEvent aMulti(e);
266 aMulti.Source = &m_rParent;
268 bool bResult = true;
269 while (bResult && aIt.hasMoreElements())
270 bResult = aIt.next()->approveParameter(aMulti);
271 return bResult;
272}
273
274// css::form::XSubmitListener
276 :OSbaWeakSubObject(rSource)
278{
279}
280
281css::uno::Any SAL_CALL SbaXSubmitMultiplexer::queryInterface(const css::uno::Type& _rType)
282{
283 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
284 if (!aReturn.hasValue())
285 aReturn = ::cppu::queryInterface(_rType,
286 static_cast< css::form::XSubmitListener* >(this),
287 static_cast< css::lang::XEventListener* >(static_cast< css::form::XSubmitListener* >(this))
288 );
289
290 return aReturn;
291}
292void SAL_CALL SbaXSubmitMultiplexer::disposing(const css::lang::EventObject& )
293{
294}
295
296
297
298sal_Bool SAL_CALL SbaXSubmitMultiplexer::approveSubmit(const css::lang::EventObject& e)
299{
300 css::lang::EventObject aMulti(e);
301 aMulti.Source = &m_rParent;
303 bool bResult = true;
304 while (bResult && aIt.hasMoreElements())
305 bResult = aIt.next()->approveSubmit(aMulti);
306 return bResult;
307}
308
309// css::form::XResetListener
311 :OSbaWeakSubObject(rSource)
313{
314}
315
316css::uno::Any SAL_CALL SbaXResetMultiplexer::queryInterface(const css::uno::Type& _rType)
317{
318 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
319 if (!aReturn.hasValue())
320 aReturn = ::cppu::queryInterface(_rType,
321 static_cast< css::form::XResetListener* >(this),
322 static_cast< css::lang::XEventListener* >(static_cast< css::form::XResetListener* >(this))
323 );
324
325 return aReturn;
326}
327void SAL_CALL SbaXResetMultiplexer::disposing(const css::lang::EventObject& )
328{
329}
330
331
332sal_Bool SAL_CALL SbaXResetMultiplexer::approveReset(const css::lang::EventObject& e)
333{
334 css::lang::EventObject aMulti(e);
335 aMulti.Source = &m_rParent;
337 bool bResult = true;
338 while (bResult && aIt.hasMoreElements())
339 bResult = aIt.next()->approveReset(aMulti);
340 return bResult;
341}
342
343void SAL_CALL SbaXResetMultiplexer::resetted(const css::lang::EventObject& e)
344{
345 css::lang::EventObject aMulti(e);
346 aMulti.Source = &m_rParent;
347 notifyEach( &XResetListener::resetted, aMulti );
348}
349
350// css::beans::XPropertyChangeListener
352 :OSbaWeakSubObject(rSource)
353 ,m_aListeners(rMutex)
354{
355}
356
357css::uno::Any SAL_CALL SbaXPropertyChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
358{
359 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
360 if (!aReturn.hasValue())
361 aReturn = ::cppu::queryInterface(_rType,
362 static_cast< css::beans::XPropertyChangeListener* >(this),
363 static_cast< css::lang::XEventListener* >(static_cast< css::beans::XPropertyChangeListener* >(this))
364 );
365
366 return aReturn;
367}
368void SAL_CALL SbaXPropertyChangeMultiplexer::disposing(const css::lang::EventObject& )
369{
370}
371void SAL_CALL SbaXPropertyChangeMultiplexer::propertyChange(const css::beans::PropertyChangeEvent& e)
372{
374 if (pListeners)
375 Notify(*pListeners, e);
376
377 /* do the notification for the unspecialized listeners, too */
378 pListeners = m_aListeners.getContainer(OUString());
379 if (pListeners)
380 Notify(*pListeners, e);
381}
382
384 const css::uno::Reference< css::beans::XPropertyChangeListener > & rListener)
385{
386 m_aListeners.addInterface(rName, rListener);
387}
388
390 const css::uno::Reference< css::beans::XPropertyChangeListener > & rListener)
391{
392 m_aListeners.removeInterface(rName, rListener);
393}
394
396{
397 css::lang::EventObject aEvt(m_rParent);
399}
400
402{
403 sal_Int32 nLen = 0;
404 const std::vector< OUString > aContained = m_aListeners.getContainedTypes();
405 for ( OUString const & s : aContained)
406 {
408 if (!pListeners)
409 continue;
410 nLen += pListeners->getLength();
411 }
412 return nLen;
413}
414
416{
417 css::beans::PropertyChangeEvent aMulti(e);
418 aMulti.Source = &m_rParent;
419 rListeners.notifyEach( &XPropertyChangeListener::propertyChange, aMulti );
420}
421
422// css::beans::XVetoableChangeListener
424 :OSbaWeakSubObject(rSource)
425 ,m_aListeners(rMutex)
426{
427}
428
429css::uno::Any SAL_CALL SbaXVetoableChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
430{
431 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
432 if (!aReturn.hasValue())
433 aReturn = ::cppu::queryInterface(_rType,
434 static_cast< css::beans::XVetoableChangeListener* >(this),
435 static_cast< css::lang::XEventListener* >(static_cast< css::beans::XVetoableChangeListener* >(this))
436 );
437
438 return aReturn;
439}
440void SAL_CALL SbaXVetoableChangeMultiplexer::disposing(const css::lang::EventObject& )
441{
442}
443void SAL_CALL SbaXVetoableChangeMultiplexer::vetoableChange(const css::beans::PropertyChangeEvent& e)
444{
446 if (pListeners)
447 Notify(*pListeners, e);
448
449 /* do the notification for the unspecialized listeners, too */
450 pListeners = m_aListeners.getContainer(OUString());
451 if (pListeners)
452 Notify(*pListeners, e);
453}
454
456 const css::uno::Reference< css::beans::XVetoableChangeListener > & rListener)
457{
458 m_aListeners.addInterface(rName, rListener);
459}
460
462 const css::uno::Reference< css::beans::XVetoableChangeListener > & rListener)
463{
464 m_aListeners.removeInterface(rName, rListener);
465}
466
468{
469 css::lang::EventObject aEvt(m_rParent);
471}
472
474{
475 sal_Int32 nLen = 0;
476 const std::vector< OUString > aContained = m_aListeners.getContainedTypes();
477 for ( OUString const & s : aContained)
478 {
480 if (!pListeners)
481 continue;
482 nLen += pListeners->getLength();
483 }
484 return nLen;
485}
486
488{
489 css::beans::PropertyChangeEvent aMulti(e);
490 aMulti.Source = &m_rParent;
491 rListeners.notifyEach( &XVetoableChangeListener::vetoableChange, aMulti );
492}
493
494// css::beans::XPropertiesChangeListener
496 :OSbaWeakSubObject(rSource)
498{
499}
500
501css::uno::Any SAL_CALL SbaXPropertiesChangeMultiplexer::queryInterface(const css::uno::Type& _rType)
502{
503 css::uno::Any aReturn = OSbaWeakSubObject::queryInterface(_rType);
504 if (!aReturn.hasValue())
505 aReturn = ::cppu::queryInterface(_rType,
506 static_cast< css::beans::XPropertiesChangeListener* >(this),
507 static_cast< css::lang::XEventListener* >(static_cast< css::beans::XPropertiesChangeListener* >(this))
508 );
509
510 return aReturn;
511}
512void SAL_CALL SbaXPropertiesChangeMultiplexer::disposing(const css::lang::EventObject& )
513{
514}
515
516void SbaXPropertiesChangeMultiplexer::propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent>& aEvts)
517{
518 // the SbaXPropertiesChangeMultiplexer doesn't care about the property names a listener logs on for, it simply
519 // forwards _all_ changes to _all_ listeners
520
521 css::uno::Sequence< css::beans::PropertyChangeEvent> aMulti(aEvts);
522 for (css::beans::PropertyChangeEvent & rEvent : asNonConstRange(aMulti))
523 rEvent.Source = &m_rParent;
524
525 notifyEach( &css::beans::XPropertiesChangeListener::propertiesChange, aMulti );
526}
527
528/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
css::uno::Reference< ListenerT > const & next()
sal_Int32 addInterface(const key &rKey, const css::uno::Reference< listener > &rListener)
sal_Int32 removeInterface(const key &rKey, const css::uno::Reference< listener > &rListener)
void disposeAndClear(const css::lang::EventObject &rEvt)
OInterfaceContainerHelper3< listener > * getContainer(const key &rKey) const
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) SAL_OVERRIDE
::cppu::OWeakObject & m_rParent
virtual void SAL_CALL unloading(const css::lang::EventObject &e) override
virtual void SAL_CALL loaded(const css::lang::EventObject &e) override
virtual void SAL_CALL reloading(const css::lang::EventObject &e) override
SbaXLoadMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL reloaded(const css::lang::EventObject &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual void SAL_CALL unloaded(const css::lang::EventObject &e) override
SbaXParameterMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual sal_Bool SAL_CALL approveParameter(const css::form::DatabaseParameterEvent &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
SbaXPropertiesChangeMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent > &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void removeInterface(const OUString &rName, const css::uno::Reference< css::beans::XPropertyChangeListener > &rListener)
SbaXPropertyChangeMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
void Notify(::comphelper::OInterfaceContainerHelper3< css::beans::XPropertyChangeListener > &rListeners, const css::beans::PropertyChangeEvent &e)
void addInterface(const OUString &rName, const css::uno::Reference< css::beans::XPropertyChangeListener > &rListener)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &e) override
virtual sal_Bool SAL_CALL approveReset(const css::lang::EventObject &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
SbaXResetMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL resetted(const css::lang::EventObject &e) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
SbaXRowSetApproveMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual sal_Bool SAL_CALL approveCursorMove(const css::lang::EventObject &e) override
virtual sal_Bool SAL_CALL approveRowChange(const css::sdb::RowChangeEvent &e) override
virtual sal_Bool SAL_CALL approveRowSetChange(const css::lang::EventObject &e) override
virtual void SAL_CALL cursorMoved(const css::lang::EventObject &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
SbaXRowSetMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL rowChanged(const css::lang::EventObject &e) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL rowSetChanged(const css::lang::EventObject &e) override
virtual void SAL_CALL errorOccured(const css::sdb::SQLErrorEvent &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
SbaXSQLErrorMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
css::frame::FeatureStateEvent m_aLastKnownStatus
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
SbaXSubmitMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual sal_Bool SAL_CALL approveSubmit(const css::lang::EventObject &e) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
void removeInterface(const OUString &rName, const css::uno::Reference< css::beans::XVetoableChangeListener > &rListener)
void addInterface(const OUString &rName, const css::uno::Reference< css::beans::XVetoableChangeListener > &rListener)
SbaXVetoableChangeMultiplexer(::cppu::OWeakObject &rSource, ::osl::Mutex &rMutex)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void Notify(::comphelper::OInterfaceContainerHelper3< css::beans::XVetoableChangeListener > &rListeners, const css::beans::PropertyChangeEvent &e)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &_rType) override
virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent &e) override
std::vector< Reference< css::datatransfer::clipboard::XClipboardListener > > m_aListeners
unsigned char sal_Bool