1 /*************************************************************************
3 * $RCSfile: pq_xcontainer.cxx,v $
7 * last change: $Author: jbu $ $Date: 2007/01/07 13:50:38 $
9 * The Contents of this file are made available subject to the terms of
10 * either of the following licenses
12 * - GNU Lesser General Public License Version 2.1
13 * - Sun Industry Standards Source License Version 1.1
15 * Sun Microsystems Inc., October, 2000
17 * GNU Lesser General Public License Version 2.1
18 * =============================================
19 * Copyright 2000 by Sun Microsystems, Inc.
20 * 901 San Antonio Road, Palo Alto, CA 94303, USA
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License version 2.1, as published by the Free Software Foundation.
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
37 * Sun Industry Standards Source License Version 1.1
38 * =================================================
39 * The contents of this file are subject to the Sun Industry Standards
40 * Source License Version 1.1 (the "License"); You may not use this file
41 * except in compliance with the License. You may obtain a copy of the
42 * License at http://www.openoffice.org/license.html.
44 * Software provided under this License is provided on an "AS IS" basis,
45 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
46 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
47 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
48 * See the License for the specific provisions governing your rights and
49 * obligations concerning the Software.
51 * The Initial Developer of the Original Code is: Joerg Budischewski
53 * Copyright: 2000 by Sun Microsystems, Inc.
55 * All Rights Reserved.
57 * Contributor(s): Joerg Budischewski
60 ************************************************************************/
62 #include <rtl/ustrbuf.hxx>
64 #include <com/sun/star/sdbc/XRow.hpp>
65 #include <com/sun/star/sdbc/XParameters.hpp>
68 #include <cppuhelper/implbase1.hxx>
70 #include "pq_xcontainer.hxx"
71 #include "pq_statics.hxx"
72 #include "pq_tools.hxx"
74 using osl::MutexGuard
;
77 using rtl::OUStringBuffer
;
78 using rtl::OUStringToOString
;
80 using com::sun::star::beans::XPropertySet
;
82 using com::sun::star::uno::Any
;
83 using com::sun::star::uno::makeAny
;
84 using com::sun::star::uno::UNO_QUERY
;
85 using com::sun::star::uno::Type
;
86 using com::sun::star::uno::XInterface
;
87 using com::sun::star::uno::Reference
;
88 using com::sun::star::uno::Sequence
;
89 using com::sun::star::uno::RuntimeException
;
91 using com::sun::star::container::NoSuchElementException
;
92 using com::sun::star::container::XEnumeration
;
93 using com::sun::star::container::XContainerListener
;
94 using com::sun::star::container::ContainerEvent
;
95 using com::sun::star::lang::IndexOutOfBoundsException
;
96 using com::sun::star::lang::XEventListener
;
98 using com::sun::star::lang::WrappedTargetException
;
100 using com::sun::star::sdbc::XRow
;
101 using com::sun::star::sdbc::XCloseable
;
102 using com::sun::star::sdbc::XStatement
;
103 using com::sun::star::sdbc::XResultSet
;
104 using com::sun::star::sdbc::XParameters
;
105 using com::sun::star::sdbc::XPreparedStatement
;
106 using com::sun::star::sdbcx::XDataDescriptorFactory
;
108 namespace pq_sdbc_driver
110 #define ASCII_STR(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
113 class ReplacedBroadcaster
: public EventBroadcastHelper
115 ContainerEvent m_event
;
118 const Reference
< XInterface
> & source
,
119 const rtl::OUString
& name
,
120 const Any
& newElement
,
121 const rtl::OUString
& oldElement
) :
122 m_event( source
, makeAny( name
), newElement
, makeAny(oldElement
) )
125 virtual void fire( XEventListener
* listener
) const
127 ((XContainerListener
*)listener
)->elementReplaced( m_event
);
129 virtual Type
getType() const
131 return getCppuType( (Reference
< XContainerListener
> *)0 );
135 class InsertedBroadcaster
: public EventBroadcastHelper
138 ContainerEvent m_event
;
140 const Reference
< XInterface
> & source
,
141 const rtl::OUString
& name
,
142 const Any
& newElement
) :
143 m_event( source
, makeAny( name
), newElement
, Any() )
146 virtual void fire( XEventListener
* listener
) const
148 ((XContainerListener
*)listener
)->elementInserted( m_event
);
151 virtual Type
getType() const
153 return getCppuType( (Reference
< XContainerListener
> *)0 );
157 class RemovedBroadcaster
: public EventBroadcastHelper
160 ContainerEvent m_event
;
162 const Reference
< XInterface
> & source
,
163 const rtl::OUString
& name
) :
164 m_event( source
, makeAny( name
), Any(), Any() )
167 virtual void fire( XEventListener
* listener
) const
169 ((XContainerListener
*)listener
)->elementRemoved( m_event
);
172 virtual Type
getType() const
174 return getCppuType( (Reference
< XContainerListener
> *)0 );
178 Container::Container(
179 const ::rtl::Reference
< RefCountedMutex
> & refMutex
,
180 const ::com::sun::star::uno::Reference
< com::sun::star::sdbc::XConnection
> & origin
,
181 ConnectionSettings
*pSettings
,
182 const ::rtl::OUString
&type
)
183 : ContainerBase( refMutex
->mutex
),
184 m_refMutex( refMutex
),
185 m_pSettings( pSettings
),
191 Any
Container::getByName( const ::rtl::OUString
& aName
)
192 throw (NoSuchElementException
,WrappedTargetException
,RuntimeException
)
194 String2IntMap::const_iterator ii
= m_name2index
.find( aName
);
195 if( ii
== m_name2index
.end() )
197 OUStringBuffer
buf(128);
198 buf
.appendAscii( "Element " );
200 buf
.appendAscii( " unknown in " );
201 buf
.append( m_type
);
202 buf
.appendAscii( "-Container" );
203 throw NoSuchElementException( buf
.makeStringAndClear() , *this );
205 OSL_ASSERT( ii
->second
>= 0 && ii
->second
< m_values
.getLength() );
206 return m_values
[ ii
->second
];
209 Sequence
< OUString
> Container::getElementNames( )
210 throw (::com::sun::star::uno::RuntimeException
)
212 Sequence
< OUString
> ret( m_values
.getLength() );
213 for( String2IntMap::const_iterator ii
= m_name2index
.begin();
214 ii
!= m_name2index
.end() ;
217 // give element names in index order !
218 ret
[ii
->second
] = ii
->first
;
219 // ret[i] = ii->first;
224 sal_Bool
Container::hasByName( const ::rtl::OUString
& aName
)
225 throw (::com::sun::star::uno::RuntimeException
)
227 return m_name2index
.find( aName
) != m_name2index
.end();
230 Type
Container::getElementType( )
231 throw (::com::sun::star::uno::RuntimeException
)
236 sal_Bool
Container::hasElements( )
237 throw (::com::sun::star::uno::RuntimeException
)
239 return ! m_name2index
.empty();
242 Any
Container::getByIndex( sal_Int32 Index
)
243 throw (::com::sun::star::lang::IndexOutOfBoundsException
,
244 ::com::sun::star::lang::WrappedTargetException
,
245 ::com::sun::star::uno::RuntimeException
)
247 if( Index
< 0 || Index
>= m_values
.getLength() )
249 OUStringBuffer
buf(128);
250 buf
.appendAscii( "Index " );
252 buf
.appendAscii(" out of range for " );
253 buf
.append( m_type
);
254 buf
.appendAscii("-Container, expected 0 <= x <= " );
255 buf
.append( (sal_Int32
) (m_values
.getLength() -1));
256 throw IndexOutOfBoundsException( buf
.makeStringAndClear(), *this );
258 return m_values
[Index
];
261 sal_Int32
Container::getCount()
262 throw (::com::sun::star::uno::RuntimeException
)
264 return m_values
.getLength();
268 class ContainerEnumeration
: public ::cppu::WeakImplHelper1
< XEnumeration
>
270 com::sun::star::uno::Sequence
< com::sun::star::uno::Any
> m_vec
;
273 ContainerEnumeration( const com::sun::star::uno::Sequence
< com::sun::star::uno::Any
> &vec
)
280 virtual sal_Bool SAL_CALL
hasMoreElements( )
281 throw (::com::sun::star::uno::RuntimeException
);
282 virtual ::com::sun::star::uno::Any SAL_CALL
nextElement( )
283 throw (::com::sun::star::container::NoSuchElementException
,
284 ::com::sun::star::lang::WrappedTargetException
,
285 ::com::sun::star::uno::RuntimeException
);
289 sal_Bool
ContainerEnumeration::hasMoreElements()
290 throw (::com::sun::star::uno::RuntimeException
)
292 return m_vec
.getLength() > m_index
+1;
295 com::sun::star::uno::Any
ContainerEnumeration::nextElement()
296 throw (::com::sun::star::container::NoSuchElementException
,
297 ::com::sun::star::lang::WrappedTargetException
,
298 ::com::sun::star::uno::RuntimeException
)
300 if( ! hasMoreElements() )
302 throw NoSuchElementException(
303 ASCII_STR( "NoSuchElementException during enumeration" ), *this );
306 return m_vec
[m_index
];
309 Reference
< XEnumeration
> Container::createEnumeration( )
310 throw (::com::sun::star::uno::RuntimeException
)
312 return new ContainerEnumeration( m_values
);
315 void Container::addRefreshListener(
316 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XRefreshListener
>& l
)
317 throw (::com::sun::star::uno::RuntimeException
)
319 rBHelper
.addListener( getCppuType(&l
) , l
);
322 void Container::removeRefreshListener(
323 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XRefreshListener
>& l
)
324 throw (::com::sun::star::uno::RuntimeException
)
326 rBHelper
.removeListener( getCppuType(&l
) , l
);
329 void Container::disposing()
334 void Container::rename( const rtl::OUString
&oldName
, const rtl::OUString
&newName
)
338 osl::MutexGuard
guard ( m_refMutex
->mutex
);
339 String2IntMap::iterator ii
= m_name2index
.find( oldName
);
340 if( ii
!= m_name2index
.end() )
342 sal_Int32 nIndex
= ii
->second
;
343 newValue
= m_values
[nIndex
];
344 m_name2index
.erase( ii
);
345 m_name2index
[ newName
] = nIndex
;
346 newValue
= m_values
[nIndex
];
349 fire( ReplacedBroadcaster( *this, newName
, newValue
, oldName
) );
350 fire( RefreshedBroadcaster( *this ) );
353 void Container::dropByName( const ::rtl::OUString
& elementName
)
354 throw (::com::sun::star::sdbc::SQLException
,
355 ::com::sun::star::container::NoSuchElementException
,
356 ::com::sun::star::uno::RuntimeException
)
358 osl::MutexGuard
guard( m_refMutex
->mutex
);
359 String2IntMap::const_iterator ii
= m_name2index
.find( elementName
);
360 if( ii
== m_name2index
.end() )
362 OUStringBuffer
buf( 128 );
363 buf
.appendAscii( "Column " );
364 buf
.append( elementName
);
365 buf
.appendAscii( " is unknown in " );
366 buf
.append( m_type
);
367 // buf.appendAscii( " " );
368 // buf.append( m_schemaName );
369 // buf.appendAscii( "." );
370 // buf.append( m_tableName );
371 buf
.appendAscii( " container, so it can't be dropped" );
372 throw com::sun::star::container::NoSuchElementException(
373 buf
.makeStringAndClear(), *this );
375 dropByIndex( ii
->second
);
378 void Container::dropByIndex( sal_Int32 index
)
379 throw (::com::sun::star::sdbc::SQLException
,
380 ::com::sun::star::lang::IndexOutOfBoundsException
,
381 ::com::sun::star::uno::RuntimeException
)
383 osl::MutexGuard
guard( m_refMutex
->mutex
);
384 if( index
< 0 || index
>= m_values
.getLength() )
386 OUStringBuffer
buf( 128 );
387 buf
.appendAscii( "Index out of range (allowed 0 to " );
388 buf
.append((sal_Int32
)(m_values
.getLength() -1) );
389 buf
.appendAscii( ", got " );
391 buf
.appendAscii( ") in " );
392 buf
.append( m_type
);
393 throw com::sun::star::lang::IndexOutOfBoundsException(
394 buf
.makeStringAndClear(), *this );
398 for( String2IntMap::iterator ii
= m_name2index
.begin() ;
399 ii
!= m_name2index
.end() ;
402 if( ii
->second
== index
)
405 m_name2index
.erase( ii
);
410 Any oldElement
= m_values
[index
];
411 for( int i
= index
+1 ; i
< m_values
.getLength() ; i
++ )
413 m_values
[i
-1] = m_values
[i
];
415 // I know, this is expensive, but don't want to maintain another map ...
416 for( String2IntMap::iterator ii
= m_name2index
.begin() ;
417 ii
!= m_name2index
.end() ;
420 if( ii
->second
== i
)
427 m_values
.realloc( m_values
.getLength() - 1 );
429 fire( RemovedBroadcaster( *this, name
) );
432 void Container::append(
433 const rtl::OUString
& name
,
434 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
>& descriptor
)
435 throw ( ::com::sun::star::container::ElementExistException
)
438 osl::MutexGuard
guard( m_refMutex
->mutex
);
440 if( hasByName( name
) )
442 OUStringBuffer
buf( 128 );
443 buf
.appendAscii( "a ");
444 buf
.append( m_type
);
445 buf
.appendAscii( " with name " );
447 buf
.appendAscii( " already exists in this container" );
448 throw com::sun::star::container::ElementExistException(
449 buf
.makeStringAndClear() , *this );
452 int index
= m_values
.getLength();
453 m_values
.realloc( m_values
.getLength() + 1 );
454 m_values
[index
] = makeAny( descriptor
);
455 m_name2index
[name
] = index
;
457 fire( InsertedBroadcaster( *this, name
, makeAny( descriptor
) ) );
460 void Container::appendByDescriptor(
461 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
>& descriptor
)
462 throw (::com::sun::star::sdbc::SQLException
,
463 ::com::sun::star::container::ElementExistException
,
464 ::com::sun::star::uno::RuntimeException
)
466 append( extractStringProperty( descriptor
, getStatics().NAME
), descriptor
);
470 void Container::addContainerListener(
471 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XContainerListener
>& l
)
472 throw (::com::sun::star::uno::RuntimeException
)
474 rBHelper
.addListener( getCppuType(&l
) , l
);
477 void Container::removeContainerListener(
478 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XContainerListener
>& l
)
479 throw (::com::sun::star::uno::RuntimeException
)
481 rBHelper
.removeListener( getCppuType(&l
) , l
);
485 void Container::fire( const EventBroadcastHelper
&helper
)
487 Reference
< ::com::sun::star::util::XRefreshListener
> l
;
488 cppu::OInterfaceContainerHelper
*container
= rBHelper
.getContainer( helper
.getType() );
491 cppu::OInterfaceIteratorHelper
iterator( * container
);
492 while( iterator
.hasMoreElements() )
496 helper
.fire( (XEventListener
* ) iterator
.next() );
498 catch ( com::sun::star::uno::RuntimeException
& e
)
500 OSL_ENSURE( 0, "exception catched" );
501 // loose coupling, a runtime exception shall not break anything
502 // TODO: log away as warning !
504 catch( com::sun::star::uno::Exception
& e
)
506 OSL_ENSURE( 0, "exception from listener flying through" );