1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_connectivity.hxx"
26 
27 #include <algorithm>
28 #include <stdio.h>
29 #include "connectivity/sdbcx/VCollection.hxx"
30 #include "connectivity/sdbcx/VDescriptor.hxx"
31 #include "connectivity/dbexception.hxx"
32 #include <comphelper/enumhelper.hxx>
33 #include <comphelper/container.hxx>
34 #include <comphelper/types.hxx>
35 #include <comphelper/property.hxx>
36 #include "TConnection.hxx"
37 #include <rtl/ustrbuf.hxx>
38 #include "resource/common_res.hrc"
39 #include "resource/sharedresources.hxx"
40 
41 using namespace connectivity::sdbcx;
42 using namespace connectivity;
43 using namespace comphelper;
44 using namespace ::cppu;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::sdbc;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::util;
51 
52 namespace
53 {
54 	template < typename T> class OHardRefMap : public connectivity::sdbcx::IObjectCollection
55 	{
56 		typedef ::std::multimap< ::rtl::OUString, T , ::comphelper::UStringMixLess> ObjectMap;
57 		typedef typename ObjectMap::iterator   ObjectIter;
58 		typedef typename ObjectMap::value_type ObjectEntry;
59 
60 	//	private:
61 		// this combination of map and vector is used to have a fast name and index access
62 		::std::vector< ObjectIter >				m_aElements;		// hold the iterators which point to map
63 		ObjectMap								m_aNameMap;			// hold the elements and a name
64 	public:
OHardRefMap(sal_Bool _bCase)65 		OHardRefMap(sal_Bool _bCase)
66 			: m_aNameMap(_bCase ? true : false)
67 		{
68 		}
~OHardRefMap()69         virtual ~OHardRefMap()
70         {
71         }
72 
reserve(size_t nLength)73 		virtual void reserve(size_t nLength)
74 		{
75 			m_aElements.reserve(nLength);
76 		}
77 		// -----------------------------------------------------------------------------
exists(const::rtl::OUString & _sName)78 		virtual bool exists(const ::rtl::OUString& _sName )
79 		{
80 			return m_aNameMap.find(_sName) != m_aNameMap.end();
81 		}
82 		// -----------------------------------------------------------------------------
empty()83 		virtual bool empty()
84 		{
85 			return m_aNameMap.empty();
86 		}
87 		// -----------------------------------------------------------------------------
swapAll()88 		virtual void swapAll()
89 		{
90 			::std::vector< ObjectIter >(m_aElements).swap(m_aElements);
91 			ObjectMap(m_aNameMap).swap(m_aNameMap);
92 		}
93 		// -----------------------------------------------------------------------------
swap()94 		virtual void swap()
95 		{
96 			::std::vector< ObjectIter >().swap(m_aElements);
97 
98 			OSL_ENSURE( m_aNameMap.empty(), "swap: what did disposeElements do?" );
99 			ObjectMap( m_aNameMap ).swap( m_aNameMap );
100 				// Note that it's /important/ to construct the new ObjectMap from m_aNameMap before
101 				// swapping. This way, it's ensured that the compare object held by these maps is preserved
102 				// during the swap. If we would not do this, the UStringMixLess instance which is used would be
103 				// default constructed (instead of being constructed from the same instance in m_aNameMap), and
104 				// it's case-sensitive flag would have an unpredictable value.
105 				// 2002-01-09 - #106589# - fs@openoffice.org
106 		}
107 		// -----------------------------------------------------------------------------
clear()108 		virtual void clear()
109 		{
110 			m_aElements.clear();
111 			m_aNameMap.clear();
112 		}
113 		// -----------------------------------------------------------------------------
insert(const::rtl::OUString & _sName,const ObjectType & _xObject)114 		virtual void insert(const ::rtl::OUString& _sName,const ObjectType& _xObject)
115 		{
116 			m_aElements.push_back(m_aNameMap.insert(m_aNameMap.begin(), ObjectEntry(_sName,_xObject)));
117 		}
118 		// -----------------------------------------------------------------------------
reFill(const TStringVector & _rVector)119 		virtual void reFill(const TStringVector &_rVector)
120 		{
121 			OSL_ENSURE(!m_aNameMap.size(),"OCollection::reFill: collection isn't empty");
122 			m_aElements.reserve(_rVector.size());
123 
124 			for(TStringVector::const_iterator i=_rVector.begin(); i != _rVector.end();++i)
125 				m_aElements.push_back(m_aNameMap.insert(m_aNameMap.begin(), ObjectEntry(*i,ObjectType())));
126 		}
127 		// -----------------------------------------------------------------------------
rename(const::rtl::OUString _sOldName,const::rtl::OUString _sNewName)128 		virtual bool rename(const ::rtl::OUString _sOldName,const ::rtl::OUString _sNewName)
129 		{
130 			bool bRet = false;
131 			ObjectIter aIter = m_aNameMap.find(_sOldName);
132 			if ( aIter != m_aNameMap.end() )
133 			{
134 				typename ::std::vector< ObjectIter >::iterator aFind = ::std::find(m_aElements.begin(),m_aElements.end(),aIter);
135 				if(m_aElements.end() != aFind)
136 				{
137 					(*aFind) = m_aNameMap.insert(m_aNameMap.begin(), ObjectEntry(_sNewName,(*aFind)->second));
138 					m_aNameMap.erase(aIter);
139 
140 					bRet = true;
141 				}
142 			}
143 			return bRet;
144 		}
145 		// -----------------------------------------------------------------------------
size()146 		virtual sal_Int32 size()
147 		{
148 			return static_cast<sal_Int32>(m_aNameMap.size());
149 		}
150 		// -----------------------------------------------------------------------------
getElementNames()151 		virtual Sequence< ::rtl::OUString > getElementNames()
152 		{
153 			Sequence< ::rtl::OUString > aNameList(m_aElements.size());
154 
155 			::rtl::OUString* pStringArray = aNameList.getArray();
156             typename ::std::vector< ObjectIter >::const_iterator aEnd = m_aElements.end();
157 			for(typename ::std::vector< ObjectIter >::const_iterator aIter = m_aElements.begin(); aIter != aEnd;++aIter,++pStringArray)
158 				*pStringArray = (*aIter)->first;
159 
160 			return aNameList;
161 		}
162 		// -----------------------------------------------------------------------------
getName(sal_Int32 _nIndex)163 		virtual ::rtl::OUString getName(sal_Int32 _nIndex)
164 		{
165 			return m_aElements[_nIndex]->first;
166 		}
167 		// -----------------------------------------------------------------------------
disposeAndErase(sal_Int32 _nIndex)168 		virtual void disposeAndErase(sal_Int32 _nIndex)
169 		{
170 			OSL_ENSURE(_nIndex >= 0 && _nIndex < static_cast<sal_Int32>(m_aElements.size()),"Illegal argument!");
171 			Reference<XComponent> xComp(m_aElements[_nIndex]->second.get(),UNO_QUERY);
172 			::comphelper::disposeComponent(xComp);
173 			m_aElements[_nIndex]->second = T();
174 
175 			::rtl::OUString sName = m_aElements[_nIndex]->first;
176 			m_aElements.erase(m_aElements.begin()+_nIndex);
177 			m_aNameMap.erase(sName);
178 		}
179 		// -----------------------------------------------------------------------------
disposeElements()180 		virtual void disposeElements()
181 		{
182 			for( ObjectIter aIter = m_aNameMap.begin(); aIter != m_aNameMap.end(); ++aIter)
183 			{
184 				Reference<XComponent> xComp(aIter->second.get(),UNO_QUERY);
185 				if ( xComp.is() )
186 				{
187 					::comphelper::disposeComponent(xComp);
188 					(*aIter).second = T();
189 				}
190 			}
191 			m_aElements.clear();
192 			m_aNameMap.clear();
193 		}
194 		// -----------------------------------------------------------------------------
findColumn(const::rtl::OUString & columnName)195 		virtual sal_Int32 findColumn( const ::rtl::OUString& columnName )
196 		{
197 			ObjectIter aIter = m_aNameMap.find(columnName);
198 			OSL_ENSURE(aIter != m_aNameMap.end(),"findColumn:: Illegal name!");
199 			return m_aElements.size() - (m_aElements.end() - ::std::find(m_aElements.begin(),m_aElements.end(),aIter));
200 		}
201 		// -----------------------------------------------------------------------------
findColumnAtIndex(sal_Int32 _nIndex)202 		virtual ::rtl::OUString findColumnAtIndex(  sal_Int32 _nIndex)
203 		{
204 			OSL_ENSURE(_nIndex >= 0 && _nIndex < static_cast<sal_Int32>(m_aElements.size()),"Illegal argument!");
205 			return m_aElements[_nIndex]->first;
206 		}
207 		// -----------------------------------------------------------------------------
getObject(sal_Int32 _nIndex)208 		virtual ObjectType getObject(sal_Int32 _nIndex)
209 		{
210 			OSL_ENSURE(_nIndex >= 0 && _nIndex < static_cast<sal_Int32>(m_aElements.size()),"Illegal argument!");
211 			return m_aElements[_nIndex]->second;
212 		}
213 		// -----------------------------------------------------------------------------
getObject(const::rtl::OUString & columnName)214 		virtual ObjectType getObject(const ::rtl::OUString& columnName)
215 		{
216 			return m_aNameMap.find(columnName)->second;
217 		}
218 		// -----------------------------------------------------------------------------
setObject(sal_Int32 _nIndex,const ObjectType & _xObject)219 		virtual void setObject(sal_Int32 _nIndex,const ObjectType& _xObject)
220 		{
221 			OSL_ENSURE(_nIndex >= 0 && _nIndex < static_cast<sal_Int32>(m_aElements.size()),"Illegal argument!");
222 			m_aElements[_nIndex]->second = _xObject;
223 		}
224 		// -----------------------------------------------------------------------------
isCaseSensitive() const225 		sal_Bool isCaseSensitive() const
226 		{
227 			return m_aNameMap.key_comp().isCaseSensitive();
228 		}
229 		// -----------------------------------------------------------------------------
230 	};
231 }
232 // -----------------------------------------------------------------------------
233 
234 IMPLEMENT_SERVICE_INFO(OCollection,"com.sun.star.sdbcx.VContainer" , "com.sun.star.sdbcx.Container")
235 
OCollection(::cppu::OWeakObject & _rParent,sal_Bool _bCase,::osl::Mutex & _rMutex,const TStringVector & _rVector,sal_Bool _bUseIndexOnly,sal_Bool _bUseHardRef)236 OCollection::OCollection(::cppu::OWeakObject& _rParent
237 						 , sal_Bool _bCase
238 						 , ::osl::Mutex& _rMutex
239 						 , const TStringVector &_rVector
240 						 , sal_Bool _bUseIndexOnly
241 						 , sal_Bool _bUseHardRef)
242                      :m_aContainerListeners(_rMutex)
243 					 ,m_aRefreshListeners(_rMutex)
244 					 ,m_rParent(_rParent)
245 					 ,m_rMutex(_rMutex)
246 					 ,m_bUseIndexOnly(_bUseIndexOnly)
247 {
248 	if ( _bUseHardRef )
249 	{
250 		m_pElements.reset(new OHardRefMap< ObjectType >(_bCase));
251 	}
252 	else
253 	{
254 		m_pElements.reset(new OHardRefMap< WeakReference< XPropertySet> >(_bCase));
255 	}
256 	m_pElements->reFill(_rVector);
257 }
258 // -------------------------------------------------------------------------
~OCollection()259 OCollection::~OCollection()
260 {
261 }
262 // -----------------------------------------------------------------------------
queryInterface(const Type & rType)263 Any SAL_CALL OCollection::queryInterface( const Type & rType ) throw (RuntimeException)
264 {
265 	if ( m_bUseIndexOnly && rType == ::getCppuType(static_cast< Reference< XNameAccess > *> (NULL)) )
266 	{
267 		return Any();
268 	}
269 	return OCollectionBase::queryInterface( rType );
270 }
271 // -----------------------------------------------------------------------------
getTypes()272 Sequence< Type > SAL_CALL OCollection::getTypes() throw (RuntimeException)
273 {
274 	if ( m_bUseIndexOnly )
275 	{
276 		Sequence< Type > aTypes(OCollectionBase::getTypes());
277 		Type* pBegin	= aTypes.getArray();
278 		Type* pEnd		= pBegin + aTypes.getLength();
279 
280 		::std::vector<Type> aOwnTypes;
281 		aOwnTypes.reserve(aTypes.getLength());
282 		Type aType = ::getCppuType(static_cast< Reference<XNameAccess> *>(NULL));
283 		for(;pBegin != pEnd; ++pBegin)
284 		{
285 			if ( *pBegin != aType )
286 				aOwnTypes.push_back(*pBegin);
287 		}
288 		Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0];
289 		return Sequence< Type >(pTypes,aOwnTypes.size());
290 	}
291 	return OCollectionBase::getTypes( );
292 }
293 // -------------------------------------------------------------------------
clear_NoDispose()294 void OCollection::clear_NoDispose()
295 {
296 	::osl::MutexGuard aGuard(m_rMutex);
297 
298 	m_pElements->clear();
299 	m_pElements->swapAll();
300 }
301 
302 // -------------------------------------------------------------------------
disposing(void)303 void OCollection::disposing(void)
304 {
305 	m_aContainerListeners.disposeAndClear(EventObject(static_cast<XTypeProvider*>(this)));
306 	m_aRefreshListeners.disposeAndClear(EventObject(static_cast<XTypeProvider*>(this)));
307 
308 	::osl::MutexGuard aGuard(m_rMutex);
309 
310 	disposeElements();
311 
312 	m_pElements->swap();
313 }
314 // -------------------------------------------------------------------------
getByIndex(sal_Int32 Index)315 Any SAL_CALL OCollection::getByIndex( sal_Int32 Index ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException)
316 {
317 	::osl::MutexGuard aGuard(m_rMutex);
318 	if (Index < 0 || Index >= m_pElements->size() )
319 		throw IndexOutOfBoundsException(::rtl::OUString::valueOf(Index),static_cast<XTypeProvider*>(this));
320 
321 	return makeAny(getObject(Index));
322 }
323 // -------------------------------------------------------------------------
getByName(const::rtl::OUString & aName)324 Any SAL_CALL OCollection::getByName( const ::rtl::OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException)
325 {
326 	::osl::MutexGuard aGuard(m_rMutex);
327 
328 	if ( !m_pElements->exists(aName) )
329     {
330         ::connectivity::SharedResources aResources;
331         const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(
332                 STR_NO_ELEMENT_NAME,
333                 "$name$", aName
334              ) );
335 		throw NoSuchElementException( sError, static_cast< XTypeProvider* >( this ) );
336     }
337 
338 	return makeAny(getObject(m_pElements->findColumn(aName)));
339 }
340 // -------------------------------------------------------------------------
getElementNames()341 Sequence< ::rtl::OUString > SAL_CALL OCollection::getElementNames(  ) throw(RuntimeException)
342 {
343 	::osl::MutexGuard aGuard(m_rMutex);
344 	return m_pElements->getElementNames();
345 }
346 // -------------------------------------------------------------------------
refresh()347 void SAL_CALL OCollection::refresh(  ) throw(RuntimeException)
348 {
349 	::osl::MutexGuard aGuard(m_rMutex);
350 
351 	disposeElements();
352 
353 	impl_refresh();
354 	EventObject aEvt(static_cast<XTypeProvider*>(this));
355     m_aRefreshListeners.notifyEach( &XRefreshListener::refreshed, aEvt );
356 }
357 // -----------------------------------------------------------------------------
reFill(const TStringVector & _rVector)358 void OCollection::reFill(const TStringVector &_rVector)
359 {
360 	m_pElements->reFill(_rVector);
361 }
362 // -------------------------------------------------------------------------
363 // XDataDescriptorFactory
createDataDescriptor()364 Reference< XPropertySet > SAL_CALL OCollection::createDataDescriptor(  ) throw(RuntimeException)
365 {
366 	::osl::MutexGuard aGuard(m_rMutex);
367 
368 	return createDescriptor();
369 }
370 // -----------------------------------------------------------------------------
getNameForObject(const ObjectType & _xObject)371 ::rtl::OUString OCollection::getNameForObject(const ObjectType& _xObject)
372 {
373     OSL_ENSURE(_xObject.is(),"OCollection::getNameForObject: Object is NULL!");
374     ::rtl::OUString sName;
375     _xObject->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sName;
376     return sName;
377 }
378 // -------------------------------------------------------------------------
379 // XAppend
appendByDescriptor(const Reference<XPropertySet> & descriptor)380 void SAL_CALL OCollection::appendByDescriptor( const Reference< XPropertySet >& descriptor ) throw(SQLException, ElementExistException, RuntimeException)
381 {
382 	::osl::ClearableMutexGuard aGuard(m_rMutex);
383 
384     ::rtl::OUString sName = getNameForObject( descriptor );
385 
386 	if ( m_pElements->exists(sName) )
387 		throw ElementExistException(sName,static_cast<XTypeProvider*>(this));
388 
389     ObjectType xNewlyCreated = appendObject( sName, descriptor );
390 	if ( !xNewlyCreated.is() )
391         throw RuntimeException();
392 
393     ODescriptor* pDescriptor = ODescriptor::getImplementation( xNewlyCreated );
394 	if ( pDescriptor )
395 		pDescriptor->setNew( sal_False );
396 
397     sName = getNameForObject( xNewlyCreated );
398 	if ( !m_pElements->exists( sName ) ) // this may happen when the drived class included it itself
399 		m_pElements->insert( sName, xNewlyCreated );
400 
401     // notify our container listeners
402 	ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(sName), makeAny(xNewlyCreated), Any());
403     aGuard.clear();
404     m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
405 }
406 // -------------------------------------------------------------------------
407 // XDrop
dropByName(const::rtl::OUString & elementName)408 void SAL_CALL OCollection::dropByName( const ::rtl::OUString& elementName ) throw(SQLException, NoSuchElementException, RuntimeException)
409 {
410 	::osl::MutexGuard aGuard(m_rMutex);
411 
412 	if ( !m_pElements->exists(elementName) )
413 		throw NoSuchElementException(elementName,static_cast<XTypeProvider*>(this));
414 
415 	dropImpl(m_pElements->findColumn(elementName));
416 }
417 // -------------------------------------------------------------------------
dropByIndex(sal_Int32 index)418 void SAL_CALL OCollection::dropByIndex( sal_Int32 index ) throw(SQLException, IndexOutOfBoundsException, RuntimeException)
419 {
420 	::osl::MutexGuard aGuard(m_rMutex);
421 	if(index <0 || index >= getCount())
422 		throw IndexOutOfBoundsException(::rtl::OUString::valueOf(index),static_cast<XTypeProvider*>(this));
423 
424 	dropImpl(index);
425 }
426 // -----------------------------------------------------------------------------
dropImpl(sal_Int32 _nIndex,sal_Bool _bReallyDrop)427 void OCollection::dropImpl(sal_Int32 _nIndex,sal_Bool _bReallyDrop)
428 {
429 	::rtl::OUString elementName = m_pElements->getName(_nIndex);
430 
431 	if ( _bReallyDrop )
432 		dropObject(_nIndex,elementName);
433 
434 	m_pElements->disposeAndErase(_nIndex);
435 
436 	// notify our container listeners
437 	notifyElementRemoved(elementName);
438 }
439 // -----------------------------------------------------------------------------
notifyElementRemoved(const::rtl::OUString & _sName)440 void OCollection::notifyElementRemoved(const ::rtl::OUString& _sName)
441 {
442 	ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_sName), Any(), Any());
443 	// note that xExistent may be empty, in case somebody removed the data source while it is not alive at this moment
444 	OInterfaceIteratorHelper aListenerLoop(m_aContainerListeners);
445 	while (aListenerLoop.hasMoreElements())
446 		static_cast<XContainerListener*>(aListenerLoop.next())->elementRemoved(aEvent);
447 }
448 // -------------------------------------------------------------------------
findColumn(const::rtl::OUString & columnName)449 sal_Int32 SAL_CALL OCollection::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException)
450 {
451 	if ( !m_pElements->exists(columnName) )
452     {
453         ::connectivity::SharedResources aResources;
454         const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(
455                             STR_UNKNOWN_COLUMN_NAME,
456                             "$columnname$", columnName
457                          ) );
458 		::dbtools::throwGenericSQLException(sError,static_cast< XIndexAccess*>(this));
459     }
460 
461 	return m_pElements->findColumn(columnName) + 1; // because columns start at one
462 }
463 // -------------------------------------------------------------------------
createEnumeration()464 Reference< XEnumeration > SAL_CALL OCollection::createEnumeration(  ) throw(RuntimeException)
465 {
466 	::osl::MutexGuard aGuard(m_rMutex);
467     return new OEnumerationByIndex( static_cast< XIndexAccess*>(this));
468 }
469 // -----------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & _rxListener)470 void SAL_CALL OCollection::addContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
471 {
472 	m_aContainerListeners.addInterface(_rxListener);
473 }
474 
475 //------------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & _rxListener)476 void SAL_CALL OCollection::removeContainerListener( const Reference< XContainerListener >& _rxListener ) throw(RuntimeException)
477 {
478 	m_aContainerListeners.removeInterface(_rxListener);
479 }
480 // -----------------------------------------------------------------------------
acquire()481 void SAL_CALL OCollection::acquire() throw()
482 {
483 	m_rParent.acquire();
484 }
485 // -----------------------------------------------------------------------------
release()486 void SAL_CALL OCollection::release() throw()
487 {
488 	m_rParent.release();
489 }
490 // -----------------------------------------------------------------------------
getElementType()491 Type SAL_CALL OCollection::getElementType(  ) throw(RuntimeException)
492 {
493 	return::getCppuType(static_cast< Reference< XPropertySet>*>(NULL));
494 }
495 // -----------------------------------------------------------------------------
hasElements()496 sal_Bool SAL_CALL OCollection::hasElements(  ) throw(RuntimeException)
497 {
498 	::osl::MutexGuard aGuard(m_rMutex);
499 	return !m_pElements->empty();
500 }
501 // -----------------------------------------------------------------------------
getCount()502 sal_Int32 SAL_CALL OCollection::getCount(  ) throw(RuntimeException)
503 {
504 	::osl::MutexGuard aGuard(m_rMutex);
505 	return m_pElements->size();
506 }
507 // -----------------------------------------------------------------------------
hasByName(const::rtl::OUString & aName)508 sal_Bool SAL_CALL OCollection::hasByName( const ::rtl::OUString& aName ) throw(RuntimeException)
509 {
510 	::osl::MutexGuard aGuard(m_rMutex);
511 	return m_pElements->exists(aName);
512 }
513 // -----------------------------------------------------------------------------
addRefreshListener(const Reference<XRefreshListener> & l)514 void SAL_CALL OCollection::addRefreshListener( const Reference< XRefreshListener >& l ) throw(RuntimeException)
515 {
516 	m_aRefreshListeners.addInterface(l);
517 }
518 // -----------------------------------------------------------------------------
removeRefreshListener(const Reference<XRefreshListener> & l)519 void SAL_CALL OCollection::removeRefreshListener( const Reference< XRefreshListener >& l ) throw(RuntimeException)
520 {
521 	m_aRefreshListeners.removeInterface(l);
522 }
523 // -----------------------------------------------------------------------------
insertElement(const::rtl::OUString & _sElementName,const ObjectType & _xElement)524 void OCollection::insertElement(const ::rtl::OUString& _sElementName,const ObjectType& _xElement)
525 {
526 	OSL_ENSURE(!m_pElements->exists(_sElementName),"Element already exists");
527 	if ( !m_pElements->exists(_sElementName) )
528 		m_pElements->insert(_sElementName,_xElement);
529 }
530 // -----------------------------------------------------------------------------
renameObject(const::rtl::OUString _sOldName,const::rtl::OUString _sNewName)531 void OCollection::renameObject(const ::rtl::OUString _sOldName,const ::rtl::OUString _sNewName)
532 {
533 	OSL_ENSURE(m_pElements->exists(_sOldName),"Element doesn't exist");
534 	OSL_ENSURE(!m_pElements->exists(_sNewName),"Element already exists");
535 	OSL_ENSURE(_sNewName.getLength(),"New name must not be empty!");
536 	OSL_ENSURE(_sOldName.getLength(),"New name must not be empty!");
537 
538 	if ( m_pElements->rename(_sOldName,_sNewName) )
539 	{
540 		ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(_sNewName), makeAny(m_pElements->getObject(_sNewName)),makeAny(_sOldName));
541 		// note that xExistent may be empty, in case somebody removed the data source while it is not alive at this moment
542 		OInterfaceIteratorHelper aListenerLoop(m_aContainerListeners);
543 		while (aListenerLoop.hasMoreElements())
544 			static_cast<XContainerListener*>(aListenerLoop.next())->elementReplaced(aEvent);
545 	}
546 }
547 // -----------------------------------------------------------------------------
getObject(sal_Int32 _nIndex)548 ObjectType OCollection::getObject(sal_Int32 _nIndex)
549 {
550 	ObjectType xName = m_pElements->getObject(_nIndex);
551 	if ( !xName.is() )
552 	{
553 		try
554 		{
555 			xName = createObject(m_pElements->getName(_nIndex));
556 		}
557 		catch(const SQLException& e)
558 		{
559 			try
560 			{
561 				dropImpl(_nIndex,sal_False);
562 			}
563 			catch(const Exception& )
564 			{
565 			}
566 			throw WrappedTargetException(e.Message,static_cast<XTypeProvider*>(this),makeAny(e));
567 		}
568 		m_pElements->setObject(_nIndex,xName);
569 	}
570 	return xName;
571 }
572 // -----------------------------------------------------------------------------
disposeElements()573 void OCollection::disposeElements()
574 {
575 	m_pElements->disposeElements();
576 }
577 // -----------------------------------------------------------------------------
createDescriptor()578 Reference< XPropertySet > OCollection::createDescriptor()
579 {
580 	OSL_ASSERT(!"Need to be overloaded when used!");
581 	throw SQLException();
582 }
583 // -----------------------------------------------------------------------------
cloneDescriptor(const ObjectType & _descriptor)584 ObjectType OCollection::cloneDescriptor( const ObjectType& _descriptor )
585 {
586 	ObjectType xNewDescriptor( createDescriptor() );
587 	::comphelper::copyProperties( _descriptor, xNewDescriptor );
588 	return xNewDescriptor;
589 }
590 // -----------------------------------------------------------------------------
appendObject(const::rtl::OUString &,const Reference<XPropertySet> & descriptor)591 ObjectType OCollection::appendObject( const ::rtl::OUString& /*_rForName*/, const Reference< XPropertySet >& descriptor )
592 {
593     return cloneDescriptor( descriptor );
594 }
595 // -----------------------------------------------------------------------------
dropObject(sal_Int32,const::rtl::OUString)596 void OCollection::dropObject(sal_Int32 /*_nPos*/,const ::rtl::OUString /*_sElementName*/)
597 {
598 }
599 // -----------------------------------------------------------------------------
600