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>
39 #include <com/sun/star/sdbc/XRow.hpp>
40 #include <com/sun/star/sdbc/XParameters.hpp>
43 #include <cppuhelper/implbase1.hxx>
45 #include "pq_xcontainer.hxx"
46 #include "pq_statics.hxx"
47 #include "pq_tools.hxx"
49 using osl::MutexGuard
;
52 using com::sun::star::beans::XPropertySet
;
54 using com::sun::star::uno::Any
;
55 using com::sun::star::uno::makeAny
;
56 using com::sun::star::uno::UNO_QUERY
;
57 using com::sun::star::uno::Type
;
58 using com::sun::star::uno::XInterface
;
59 using com::sun::star::uno::Reference
;
60 using com::sun::star::uno::Sequence
;
61 using com::sun::star::uno::RuntimeException
;
63 using com::sun::star::container::NoSuchElementException
;
64 using com::sun::star::container::XEnumeration
;
65 using com::sun::star::container::XContainerListener
;
66 using com::sun::star::container::ContainerEvent
;
67 using com::sun::star::lang::IndexOutOfBoundsException
;
68 using com::sun::star::lang::XEventListener
;
70 using com::sun::star::lang::WrappedTargetException
;
72 using com::sun::star::sdbc::XRow
;
73 using com::sun::star::sdbc::XCloseable
;
74 using com::sun::star::sdbc::XStatement
;
75 using com::sun::star::sdbc::XResultSet
;
76 using com::sun::star::sdbc::XParameters
;
77 using com::sun::star::sdbc::XPreparedStatement
;
78 using com::sun::star::sdbcx::XDataDescriptorFactory
;
80 namespace pq_sdbc_driver
83 class ReplacedBroadcaster
: public EventBroadcastHelper
85 ContainerEvent m_event
;
88 const Reference
< XInterface
> & source
,
89 const OUString
& name
,
90 const Any
& newElement
,
91 const OUString
& oldElement
) :
92 m_event( source
, makeAny( name
), newElement
, makeAny(oldElement
) )
95 virtual void fire( XEventListener
* listener
) const SAL_OVERRIDE
97 ((XContainerListener
*)listener
)->elementReplaced( m_event
);
99 virtual Type
getType() const SAL_OVERRIDE
101 return getCppuType( (Reference
< XContainerListener
> *)0 );
105 class InsertedBroadcaster
: public EventBroadcastHelper
108 ContainerEvent m_event
;
110 const Reference
< XInterface
> & source
,
111 const OUString
& name
,
112 const Any
& newElement
) :
113 m_event( source
, makeAny( name
), newElement
, Any() )
116 virtual void fire( XEventListener
* listener
) const SAL_OVERRIDE
118 ((XContainerListener
*)listener
)->elementInserted( m_event
);
121 virtual Type
getType() const SAL_OVERRIDE
123 return getCppuType( (Reference
< XContainerListener
> *)0 );
127 class RemovedBroadcaster
: public EventBroadcastHelper
130 ContainerEvent m_event
;
132 const Reference
< XInterface
> & source
,
133 const OUString
& name
) :
134 m_event( source
, makeAny( name
), Any(), Any() )
137 virtual void fire( XEventListener
* listener
) const SAL_OVERRIDE
139 ((XContainerListener
*)listener
)->elementRemoved( m_event
);
142 virtual Type
getType() const SAL_OVERRIDE
144 return getCppuType( (Reference
< XContainerListener
> *)0 );
148 Container::Container(
149 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
150 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
151 ConnectionSettings
*pSettings
,
152 const OUString
&type
)
153 : ContainerBase( refMutex
->mutex
),
154 m_refMutex( refMutex
),
155 m_pSettings( pSettings
),
161 Any
Container::getByName( const OUString
& aName
)
162 throw (NoSuchElementException
,WrappedTargetException
,RuntimeException
, std::exception
)
164 String2IntMap::const_iterator ii
= m_name2index
.find( aName
);
165 if( ii
== m_name2index
.end() )
167 OUStringBuffer
buf(128);
168 buf
.appendAscii( "Element " );
170 buf
.appendAscii( " unknown in " );
171 buf
.append( m_type
);
172 buf
.appendAscii( "-Container" );
173 throw NoSuchElementException( buf
.makeStringAndClear() , *this );
175 OSL_ASSERT( ii
->second
>= 0 && ii
->second
< m_values
.getLength() );
176 return m_values
[ ii
->second
];
179 Sequence
< OUString
> Container::getElementNames( )
180 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
182 Sequence
< OUString
> ret( m_values
.getLength() );
183 for( String2IntMap::const_iterator ii
= m_name2index
.begin();
184 ii
!= m_name2index
.end() ;
187 // give element names in index order !
188 ret
[ii
->second
] = ii
->first
;
189 // ret[i] = ii->first;
194 sal_Bool
Container::hasByName( const OUString
& aName
)
195 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
197 return m_name2index
.find( aName
) != m_name2index
.end();
200 Type
Container::getElementType( )
201 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
206 sal_Bool
Container::hasElements( )
207 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
209 return ! m_name2index
.empty();
212 Any
Container::getByIndex( sal_Int32 Index
)
213 throw (::com::sun::star::lang::IndexOutOfBoundsException
,
214 ::com::sun::star::lang::WrappedTargetException
,
215 ::com::sun::star::uno::RuntimeException
, std::exception
)
217 if( Index
< 0 || Index
>= m_values
.getLength() )
219 OUStringBuffer
buf(128);
220 buf
.appendAscii( "Index " );
222 buf
.appendAscii(" out of range for " );
223 buf
.append( m_type
);
224 buf
.appendAscii("-Container, expected 0 <= x <= " );
225 buf
.append( (sal_Int32
) (m_values
.getLength() -1));
226 throw IndexOutOfBoundsException( buf
.makeStringAndClear(), *this );
228 return m_values
[Index
];
231 sal_Int32
Container::getCount()
232 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
234 return m_values
.getLength();
238 class ContainerEnumeration
: public ::cppu::WeakImplHelper1
< XEnumeration
>
240 com::sun::star::uno::Sequence
< com::sun::star::uno::Any
> m_vec
;
243 ContainerEnumeration( const com::sun::star::uno::Sequence
< com::sun::star::uno::Any
> &vec
)
250 virtual sal_Bool SAL_CALL
hasMoreElements( )
251 throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
252 virtual ::com::sun::star::uno::Any SAL_CALL
nextElement( )
253 throw (::com::sun::star::container::NoSuchElementException
,
254 ::com::sun::star::lang::WrappedTargetException
,
255 ::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
259 sal_Bool
ContainerEnumeration::hasMoreElements()
260 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
262 return m_vec
.getLength() > m_index
+1;
265 com::sun::star::uno::Any
ContainerEnumeration::nextElement()
266 throw (::com::sun::star::container::NoSuchElementException
,
267 ::com::sun::star::lang::WrappedTargetException
,
268 ::com::sun::star::uno::RuntimeException
, std::exception
)
270 if( ! hasMoreElements() )
272 throw NoSuchElementException(
273 "NoSuchElementException during enumeration", *this );
276 return m_vec
[m_index
];
279 Reference
< XEnumeration
> Container::createEnumeration( )
280 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
282 return new ContainerEnumeration( m_values
);
285 void Container::addRefreshListener(
286 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XRefreshListener
>& l
)
287 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
289 rBHelper
.addListener( getCppuType(&l
) , l
);
292 void Container::removeRefreshListener(
293 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XRefreshListener
>& l
)
294 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
296 rBHelper
.removeListener( getCppuType(&l
) , l
);
299 void Container::disposing()
304 void Container::rename( const OUString
&oldName
, const OUString
&newName
)
308 osl::MutexGuard
guard ( m_refMutex
->mutex
);
309 String2IntMap::iterator ii
= m_name2index
.find( oldName
);
310 if( ii
!= m_name2index
.end() )
312 sal_Int32 nIndex
= ii
->second
;
313 newValue
= m_values
[nIndex
];
314 m_name2index
.erase( ii
);
315 m_name2index
[ newName
] = nIndex
;
318 fire( ReplacedBroadcaster( *this, newName
, newValue
, oldName
) );
319 fire( RefreshedBroadcaster( *this ) );
322 void Container::dropByName( const OUString
& elementName
)
323 throw (::com::sun::star::sdbc::SQLException
,
324 ::com::sun::star::container::NoSuchElementException
,
325 ::com::sun::star::uno::RuntimeException
, std::exception
)
327 osl::MutexGuard
guard( m_refMutex
->mutex
);
328 String2IntMap::const_iterator ii
= m_name2index
.find( elementName
);
329 if( ii
== m_name2index
.end() )
331 OUStringBuffer
buf( 128 );
332 buf
.appendAscii( "Column " );
333 buf
.append( elementName
);
334 buf
.appendAscii( " is unknown in " );
335 buf
.append( m_type
);
336 // buf.appendAscii( " " );
337 // buf.append( m_schemaName );
338 // buf.appendAscii( "." );
339 // buf.append( m_tableName );
340 buf
.appendAscii( " container, so it can't be dropped" );
341 throw com::sun::star::container::NoSuchElementException(
342 buf
.makeStringAndClear(), *this );
344 dropByIndex( ii
->second
);
347 void Container::dropByIndex( sal_Int32 index
)
348 throw (::com::sun::star::sdbc::SQLException
,
349 ::com::sun::star::lang::IndexOutOfBoundsException
,
350 ::com::sun::star::uno::RuntimeException
, std::exception
)
352 osl::MutexGuard
guard( m_refMutex
->mutex
);
353 if( index
< 0 || index
>= m_values
.getLength() )
355 OUStringBuffer
buf( 128 );
356 buf
.appendAscii( "Index out of range (allowed 0 to " );
357 buf
.append((sal_Int32
)(m_values
.getLength() -1) );
358 buf
.appendAscii( ", got " );
360 buf
.appendAscii( ") in " );
361 buf
.append( m_type
);
362 throw com::sun::star::lang::IndexOutOfBoundsException(
363 buf
.makeStringAndClear(), *this );
367 for( String2IntMap::iterator ii
= m_name2index
.begin() ;
368 ii
!= m_name2index
.end() ;
371 if( ii
->second
== index
)
374 m_name2index
.erase( ii
);
379 for( int i
= index
+1 ; i
< m_values
.getLength() ; i
++ )
381 m_values
[i
-1] = m_values
[i
];
383 // I know, this is expensive, but don't want to maintain another map ...
384 for( String2IntMap::iterator ii
= m_name2index
.begin() ;
385 ii
!= m_name2index
.end() ;
388 if( ii
->second
== i
)
395 m_values
.realloc( m_values
.getLength() - 1 );
397 fire( RemovedBroadcaster( *this, name
) );
400 void Container::append(
401 const OUString
& name
,
402 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
>& descriptor
)
403 throw ( ::com::sun::star::container::ElementExistException
)
406 osl::MutexGuard
guard( m_refMutex
->mutex
);
408 if( hasByName( name
) )
410 OUStringBuffer
buf( 128 );
411 buf
.appendAscii( "a ");
412 buf
.append( m_type
);
413 buf
.appendAscii( " with name " );
415 buf
.appendAscii( " already exists in this container" );
416 throw com::sun::star::container::ElementExistException(
417 buf
.makeStringAndClear() , *this );
420 int index
= m_values
.getLength();
421 m_values
.realloc( m_values
.getLength() + 1 );
422 m_values
[index
] = makeAny( descriptor
);
423 m_name2index
[name
] = index
;
425 fire( InsertedBroadcaster( *this, name
, makeAny( descriptor
) ) );
428 void Container::appendByDescriptor(
429 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
>& descriptor
)
430 throw (::com::sun::star::sdbc::SQLException
,
431 ::com::sun::star::container::ElementExistException
,
432 ::com::sun::star::uno::RuntimeException
, std::exception
)
434 append( extractStringProperty( descriptor
, getStatics().NAME
), descriptor
);
438 void Container::addContainerListener(
439 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XContainerListener
>& l
)
440 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
442 rBHelper
.addListener( getCppuType(&l
) , l
);
445 void Container::removeContainerListener(
446 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XContainerListener
>& l
)
447 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
449 rBHelper
.removeListener( getCppuType(&l
) , l
);
453 void Container::fire( const EventBroadcastHelper
&helper
)
455 Reference
< ::com::sun::star::util::XRefreshListener
> l
;
456 cppu::OInterfaceContainerHelper
*container
= rBHelper
.getContainer( helper
.getType() );
459 cppu::OInterfaceIteratorHelper
iterator( * container
);
460 while( iterator
.hasMoreElements() )
464 helper
.fire( (XEventListener
* ) iterator
.next() );
466 catch ( com::sun::star::uno::RuntimeException
& )
468 OSL_ENSURE( false, "exception catched" );
469 // loose coupling, a runtime exception shall not break anything
470 // TODO: log away as warning !
472 catch( com::sun::star::uno::Exception
& )
474 OSL_ENSURE( false, "exception from listener flying through" );
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */