1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * Effective License of whole file:
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
22 * The Contents of this file are made available subject to the terms of
23 * the GNU Lesser General Public License Version 2.1
25 * Copyright: 2000 by Sun Microsystems, Inc.
27 * Contributor(s): Joerg Budischewski
29 * All parts contributed on or after August 2011:
31 * This Source Code Form is subject to the terms of the Mozilla Public
32 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
35 ************************************************************************/
37 #include <rtl/ustrbuf.hxx>
38 #include <com/sun/star/container/ElementExistException.hpp>
39 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <cppuhelper/implbase.hxx>
42 #include "pq_xcontainer.hxx"
43 #include "pq_statics.hxx"
44 #include "pq_tools.hxx"
46 using osl::MutexGuard
;
48 using com::sun::star::beans::XPropertySet
;
50 using com::sun::star::uno::Any
;
51 using com::sun::star::uno::makeAny
;
52 using com::sun::star::uno::Type
;
53 using com::sun::star::uno::XInterface
;
54 using com::sun::star::uno::Reference
;
55 using com::sun::star::uno::Sequence
;
56 using com::sun::star::uno::RuntimeException
;
58 using com::sun::star::container::NoSuchElementException
;
59 using com::sun::star::container::XEnumeration
;
60 using com::sun::star::container::XContainerListener
;
61 using com::sun::star::container::ContainerEvent
;
62 using com::sun::star::lang::IndexOutOfBoundsException
;
63 using com::sun::star::lang::XEventListener
;
66 namespace pq_sdbc_driver
69 class ReplacedBroadcaster
: public EventBroadcastHelper
71 ContainerEvent m_event
;
74 const Reference
< XInterface
> & source
,
75 const OUString
& name
,
76 const Any
& newElement
,
77 const OUString
& oldElement
) :
78 m_event( source
, makeAny( name
), newElement
, makeAny(oldElement
) )
81 virtual void fire( XEventListener
* listener
) const override
83 static_cast<XContainerListener
*>(listener
)->elementReplaced( m_event
);
85 virtual Type
getType() const override
87 return cppu::UnoType
<XContainerListener
>::get();
91 class InsertedBroadcaster
: public EventBroadcastHelper
94 ContainerEvent m_event
;
96 const Reference
< XInterface
> & source
,
97 const OUString
& name
,
98 const Any
& newElement
) :
99 m_event( source
, makeAny( name
), newElement
, Any() )
102 virtual void fire( XEventListener
* listener
) const override
104 static_cast<XContainerListener
*>(listener
)->elementInserted( m_event
);
107 virtual Type
getType() const override
109 return cppu::UnoType
<XContainerListener
>::get();
113 class RemovedBroadcaster
: public EventBroadcastHelper
116 ContainerEvent m_event
;
118 const Reference
< XInterface
> & source
,
119 const OUString
& name
) :
120 m_event( source
, makeAny( name
), Any(), Any() )
123 virtual void fire( XEventListener
* listener
) const override
125 static_cast<XContainerListener
*>(listener
)->elementRemoved( m_event
);
128 virtual Type
getType() const override
130 return cppu::UnoType
<XContainerListener
>::get();
134 Container::Container(
135 const ::rtl::Reference
< comphelper::RefCountedMutex
> & refMutex
,
136 const css::uno::Reference
< css::sdbc::XConnection
> & origin
,
137 ConnectionSettings
*pSettings
,
138 const OUString
&type
)
139 : ContainerBase( refMutex
->GetMutex() ),
140 m_xMutex( refMutex
),
141 m_pSettings( pSettings
),
147 Any
Container::getByName( const OUString
& aName
)
149 String2IntMap::const_iterator ii
= m_name2index
.find( aName
);
150 if( ii
== m_name2index
.end() )
152 throw NoSuchElementException(
153 "Element " + aName
+ " unknown in " + m_type
+ "-Container",
156 OSL_ASSERT( ii
->second
>= 0 && ii
->second
< static_cast<int>(m_values
.size()) );
157 return m_values
[ ii
->second
];
160 Sequence
< OUString
> Container::getElementNames( )
162 Sequence
< OUString
> ret( m_values
.size() );
163 for( const auto& [rName
, rIndex
] : m_name2index
)
165 // give element names in index order !
171 sal_Bool
Container::hasByName( const OUString
& aName
)
173 return m_name2index
.find( aName
) != m_name2index
.end();
176 Type
Container::getElementType( )
181 sal_Bool
Container::hasElements( )
183 return ! m_name2index
.empty();
186 Any
Container::getByIndex( sal_Int32 Index
)
188 if( Index
< 0 || Index
>= static_cast<sal_Int32
>(m_values
.size()) )
190 throw IndexOutOfBoundsException(
191 "Index " + OUString::number( Index
)
192 + " out of range for " + m_type
+ "-Container, expected 0 <= x <= "
193 + OUString::number(m_values
.size() -1),
196 return m_values
[Index
];
199 sal_Int32
Container::getCount()
201 return m_values
.size();
205 class ContainerEnumeration
: public ::cppu::WeakImplHelper
< XEnumeration
>
207 std::vector
< css::uno::Any
> m_vec
;
210 explicit ContainerEnumeration( const std::vector
< css::uno::Any
> &vec
)
217 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
;
218 virtual css::uno::Any SAL_CALL
nextElement( ) override
;
222 sal_Bool
ContainerEnumeration::hasMoreElements()
224 return static_cast<int>(m_vec
.size()) > m_index
+1;
227 css::uno::Any
ContainerEnumeration::nextElement()
229 if( ! hasMoreElements() )
231 throw NoSuchElementException(
232 "NoSuchElementException during enumeration", *this );
235 return m_vec
[m_index
];
238 Reference
< XEnumeration
> Container::createEnumeration( )
240 return new ContainerEnumeration( m_values
);
243 void Container::addRefreshListener(
244 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
246 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
249 void Container::removeRefreshListener(
250 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
252 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
255 void Container::disposing()
260 void Container::rename( const OUString
&oldName
, const OUString
&newName
)
264 osl::MutexGuard
guard ( m_xMutex
->GetMutex() );
265 String2IntMap::iterator ii
= m_name2index
.find( oldName
);
266 if( ii
!= m_name2index
.end() )
268 sal_Int32 nIndex
= ii
->second
;
269 newValue
= m_values
[nIndex
];
270 m_name2index
.erase( ii
);
271 m_name2index
[ newName
] = nIndex
;
274 fire( ReplacedBroadcaster( *this, newName
, newValue
, oldName
) );
275 fire( RefreshedBroadcaster( *this ) );
278 void Container::dropByName( const OUString
& elementName
)
280 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
281 String2IntMap::const_iterator ii
= m_name2index
.find( elementName
);
282 if( ii
== m_name2index
.end() )
284 throw css::container::NoSuchElementException(
285 "Column " + elementName
+ " is unknown in "
286 + m_type
+ " container, so it can't be dropped",
289 dropByIndex( ii
->second
);
292 void Container::dropByIndex( sal_Int32 index
)
294 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
295 if( index
< 0 || index
>=static_cast<sal_Int32
>(m_values
.size()) )
297 throw css::lang::IndexOutOfBoundsException(
298 "Index out of range (allowed 0 to "
299 + OUString::number(m_values
.size() -1)
300 + ", got " + OUString::number( index
)
306 String2IntMap::iterator ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
307 [&index
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== index
; });
308 if (ii
!= m_name2index
.end())
311 m_name2index
.erase( ii
);
314 for( int i
= index
+1 ; i
< static_cast<int>(m_values
.size()) ; i
++ )
316 m_values
[i
-1] = m_values
[i
];
318 // I know, this is expensive, but don't want to maintain another map ...
319 ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
320 [&i
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== i
; });
321 if (ii
!= m_name2index
.end())
326 m_values
.resize( m_values
.size() - 1 );
328 fire( RemovedBroadcaster( *this, name
) );
331 void Container::append(
332 const OUString
& name
,
333 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
336 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
338 if( hasByName( name
) )
340 throw css::container::ElementExistException(
341 "a " + m_type
+ " with name " + name
+ " already exists in this container",
345 int index
= m_values
.size();
346 m_values
.push_back( makeAny( descriptor
) );
347 m_name2index
[name
] = index
;
349 fire( InsertedBroadcaster( *this, name
, makeAny( descriptor
) ) );
352 void Container::appendByDescriptor(
353 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
355 append( extractStringProperty( descriptor
, getStatics().NAME
), descriptor
);
359 void Container::addContainerListener(
360 const css::uno::Reference
< css::container::XContainerListener
>& l
)
362 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
365 void Container::removeContainerListener(
366 const css::uno::Reference
< css::container::XContainerListener
>& l
)
368 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
372 void Container::fire( const EventBroadcastHelper
&helper
)
374 cppu::OInterfaceContainerHelper
*container
= rBHelper
.getContainer( helper
.getType() );
377 cppu::OInterfaceIteratorHelper
iterator( * container
);
378 while( iterator
.hasMoreElements() )
382 helper
.fire( static_cast<XEventListener
*>(iterator
.next()) );
384 catch ( css::uno::RuntimeException
& )
386 OSL_ENSURE( false, "exception caught" );
387 // loose coupling, a runtime exception shall not break anything
388 // TODO: log away as warning !
390 catch( css::uno::Exception
& )
392 OSL_ENSURE( false, "exception from listener flying through" );
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */