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_ucbhelper.hxx"
26 
27 /**************************************************************************
28 								TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 #include <cppuhelper/interfacecontainer.hxx>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <ucbhelper/resultset.hxx>
35 #include <ucbhelper/resultsetmetadata.hxx>
36 
37 using namespace com::sun::star;
38 
39 //=========================================================================
40 
41 namespace ucbhelper_impl
42 {
43 
44 struct PropertyInfo
45 {
46 	const char*	pName;
47 	sal_Int32   nHandle;
48 	sal_Int16   nAttributes;
49 	const uno::Type& (*pGetCppuType)();
50 };
51 
52 static const uno::Type& sal_Int32_getCppuType()
53 {
54 	return getCppuType( static_cast< const sal_Int32 * >( 0 ) );
55 }
56 
57 static const uno::Type& sal_Bool_getCppuType()
58 {
59 	return getCppuBooleanType();
60 }
61 
62 static const PropertyInfo aPropertyTable[] =
63 {
64 	{ "IsRowCountFinal",
65 	  1000,
66 	  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
67 	  &sal_Bool_getCppuType
68 	},
69 	{ "RowCount",
70 	  1001,
71 	  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
72 	  &sal_Int32_getCppuType
73 	},
74 	{ 0,
75 	  0,
76 	  0,
77 	  0
78 	}
79 };
80 
81 #define RESULTSET_PROPERTY_COUNT 2
82 
83 //=========================================================================
84 //
85 // class PropertySetInfo
86 //
87 //=========================================================================
88 
89 class PropertySetInfo :
90 		public cppu::OWeakObject,
91         public lang::XTypeProvider,
92         public beans::XPropertySetInfo
93 {
94 	uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
95 	uno::Sequence< beans::Property >* 			 m_pProps;
96 
97 private:
98 	sal_Bool queryProperty(
99         const rtl::OUString& aName, beans::Property& rProp );
100 
101 public:
102 	PropertySetInfo(
103         const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
104         const PropertyInfo* pProps,
105         sal_Int32 nProps );
106 	virtual ~PropertySetInfo();
107 
108 	// XInterface
109 	XINTERFACE_DECL()
110 
111 	// XTypeProvider
112 	XTYPEPROVIDER_DECL()
113 
114 	// XPropertySetInfo
115     virtual uno::Sequence< beans::Property > SAL_CALL getProperties()
116 		throw( uno::RuntimeException );
117     virtual beans::Property SAL_CALL getPropertyByName(
118             const rtl::OUString& aName )
119 		throw( beans::UnknownPropertyException, uno::RuntimeException );
120     virtual sal_Bool SAL_CALL hasPropertyByName( const rtl::OUString& Name )
121 		throw( uno::RuntimeException );
122 };
123 
124 //=========================================================================
125 //
126 // PropertyChangeListenerContainer.
127 //
128 //=========================================================================
129 
130 struct equalStr_Impl
131 {
132 	bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const
133   	{
134 		return !!( s1 == s2 );
135 	}
136 };
137 
138 struct hashStr_Impl
139 {
140 	size_t operator()( const rtl::OUString& rName ) const
141 	{
142 		return rName.hashCode();
143 	}
144 };
145 
146 typedef cppu::OMultiTypeInterfaceContainerHelperVar
147 <
148 	rtl::OUString,
149 	hashStr_Impl,
150 	equalStr_Impl
151 > PropertyChangeListenerContainer;
152 
153 //=========================================================================
154 //
155 // class PropertyChangeListeners.
156 //
157 //=========================================================================
158 
159 class PropertyChangeListeners : public PropertyChangeListenerContainer
160 {
161 public:
162 	PropertyChangeListeners( osl::Mutex& rMtx )
163 	: PropertyChangeListenerContainer( rMtx ) {}
164 };
165 
166 } // namespace ucbhelper_impl
167 
168 using namespace ucbhelper_impl;
169 
170 namespace ucbhelper
171 {
172 
173 //=========================================================================
174 //
175 // struct ResultSet_Impl.
176 //
177 //=========================================================================
178 
179 struct ResultSet_Impl
180 {
181 	uno::Reference< lang::XMultiServiceFactory > 	m_xSMgr;
182 	uno::Reference< com::sun::star::ucb::XCommandEnvironment > 	m_xEnv;
183 	uno::Reference< beans::XPropertySetInfo >     	m_xPropSetInfo;
184 	uno::Reference< sdbc::XResultSetMetaData >   	m_xMetaData;
185 	uno::Sequence< beans::Property >              	m_aProperties;
186 	rtl::Reference< ResultSetDataSupplier >	        m_xDataSupplier;
187 	osl::Mutex						 	m_aMutex;
188 	cppu::OInterfaceContainerHelper* 	m_pDisposeEventListeners;
189 	PropertyChangeListeners*			m_pPropertyChangeListeners;
190 	sal_Int32						 	m_nPos;
191 	sal_Bool 						 	m_bWasNull;
192 	sal_Bool 						 	m_bAfterLast;
193 
194 	inline ResultSet_Impl(
195         const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
196         const uno::Sequence< beans::Property >& rProperties,
197         const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
198         const uno::Reference< com::sun::star::ucb::XCommandEnvironment >&
199             rxEnv );
200 	inline ~ResultSet_Impl();
201 };
202 
203 inline ResultSet_Impl::ResultSet_Impl(
204     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
205     const uno::Sequence< beans::Property >& rProperties,
206     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
207     const uno::Reference< com::sun::star::ucb::XCommandEnvironment >& rxEnv )
208 : m_xSMgr( rxSMgr ),
209   m_xEnv( rxEnv ),
210   m_aProperties( rProperties ),
211   m_xDataSupplier( rDataSupplier ),
212   m_pDisposeEventListeners( 0 ),
213   m_pPropertyChangeListeners( 0 ),
214   m_nPos( 0 ), // Position is one-based. Zero means: before first element.
215   m_bWasNull( sal_False ),
216   m_bAfterLast( sal_False )
217 {
218 }
219 
220 //=========================================================================
221 inline ResultSet_Impl::~ResultSet_Impl()
222 {
223 	delete m_pDisposeEventListeners;
224 	delete m_pPropertyChangeListeners;
225 }
226 
227 //=========================================================================
228 //=========================================================================
229 //
230 // ResultSet Implementation.
231 //
232 //=========================================================================
233 //=========================================================================
234 
235 ResultSet::ResultSet(
236     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
237     const uno::Sequence< beans::Property >& rProperties,
238     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier )
239 : m_pImpl( new ResultSet_Impl(
240                rxSMgr,
241                rProperties,
242                rDataSupplier,
243                uno::Reference< com::sun::star::ucb::XCommandEnvironment >() ) )
244 {
245 	rDataSupplier->m_pResultSet = this;
246 }
247 
248 //=========================================================================
249 ResultSet::ResultSet(
250     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
251     const uno::Sequence< beans::Property >& rProperties,
252     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
253     const uno::Reference< com::sun::star::ucb::XCommandEnvironment >& rxEnv )
254 : m_pImpl( new ResultSet_Impl( rxSMgr, rProperties, rDataSupplier, rxEnv ) )
255 {
256 	rDataSupplier->m_pResultSet = this;
257 }
258 
259 //=========================================================================
260 // virtual
261 ResultSet::~ResultSet()
262 {
263 	delete m_pImpl;
264 }
265 
266 //=========================================================================
267 //
268 // XInterface methods.
269 //
270 //=========================================================================
271 
272 XINTERFACE_IMPL_9( ResultSet,
273 				   lang::XTypeProvider,
274 				   lang::XServiceInfo,
275 				   lang::XComponent,
276 				   com::sun::star::ucb::XContentAccess,
277 				   sdbc::XResultSet,
278 				   sdbc::XResultSetMetaDataSupplier,
279 				   sdbc::XRow,
280 				   sdbc::XCloseable,
281 				   beans::XPropertySet );
282 
283 //=========================================================================
284 //
285 // XTypeProvider methods.
286 //
287 //=========================================================================
288 
289 XTYPEPROVIDER_IMPL_9( ResultSet,
290 					  lang::XTypeProvider,
291 				   	  lang::XServiceInfo,
292 					  lang::XComponent,
293 					  com::sun::star::ucb::XContentAccess,
294 					  sdbc::XResultSet,
295 					  sdbc::XResultSetMetaDataSupplier,
296 					  sdbc::XRow,
297 					  sdbc::XCloseable,
298 					  beans::XPropertySet );
299 
300 //=========================================================================
301 //
302 // XServiceInfo methods.
303 //
304 //=========================================================================
305 
306 XSERVICEINFO_NOFACTORY_IMPL_1( ResultSet,
307 		 		   rtl::OUString::createFromAscii( "ResultSet" ),
308 		 		   rtl::OUString::createFromAscii( RESULTSET_SERVICE_NAME ) );
309 
310 //=========================================================================
311 //
312 // XComponent methods.
313 //
314 //=========================================================================
315 
316 // virtual
317 void SAL_CALL ResultSet::dispose()
318 	throw( uno::RuntimeException )
319 {
320 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
321 
322 	if ( m_pImpl->m_pDisposeEventListeners &&
323 		 m_pImpl->m_pDisposeEventListeners->getLength() )
324 	{
325 		lang::EventObject aEvt;
326 		aEvt.Source = static_cast< lang::XComponent * >( this );
327 		m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
328 	}
329 
330 	if ( m_pImpl->m_pPropertyChangeListeners )
331 	{
332 		lang::EventObject aEvt;
333 		aEvt.Source = static_cast< beans::XPropertySet * >( this );
334 		m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
335 	}
336 
337 	m_pImpl->m_xDataSupplier->close();
338 }
339 
340 //=========================================================================
341 // virtual
342 void SAL_CALL ResultSet::addEventListener(
343         const uno::Reference< lang::XEventListener >& Listener )
344 	throw( uno::RuntimeException )
345 {
346 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
347 
348 	if ( !m_pImpl->m_pDisposeEventListeners )
349 		m_pImpl->m_pDisposeEventListeners =
350             new cppu::OInterfaceContainerHelper( m_pImpl->m_aMutex );
351 
352 	m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
353 }
354 
355 //=========================================================================
356 // virtual
357 void SAL_CALL ResultSet::removeEventListener(
358         const uno::Reference< lang::XEventListener >& Listener )
359 	throw( uno::RuntimeException )
360 {
361 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
362 
363 	if ( m_pImpl->m_pDisposeEventListeners )
364 		m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
365 }
366 
367 //=========================================================================
368 //
369 // XResultSetMetaDataSupplier methods.
370 //
371 //=========================================================================
372 
373 // virtual
374 uno::Reference< sdbc::XResultSetMetaData > SAL_CALL ResultSet::getMetaData()
375 	throw( sdbc::SQLException, uno::RuntimeException )
376 {
377 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
378 
379 	if ( !m_pImpl->m_xMetaData.is() )
380 		m_pImpl->m_xMetaData = new ResultSetMetaData( m_pImpl->m_xSMgr,
381 													  m_pImpl->m_aProperties );
382 
383 	return m_pImpl->m_xMetaData;
384 }
385 
386 //=========================================================================
387 //
388 // XResultSet methods.
389 //
390 //=========================================================================
391 
392 // virtual
393 sal_Bool SAL_CALL ResultSet::next()
394 	throw( sdbc::SQLException, uno::RuntimeException )
395 {
396 	// Note: Cursor is initially positioned before the first row.
397 	//       First call to 'next()' moves it to first row.
398 
399 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
400 
401 	if ( m_pImpl->m_bAfterLast )
402 	{
403 		m_pImpl->m_xDataSupplier->validate();
404 		return sal_False;
405 	}
406 
407 	// getResult works zero-based!
408 	if ( !m_pImpl->m_xDataSupplier->getResult( m_pImpl->m_nPos ) )
409 	{
410 		m_pImpl->m_bAfterLast = sal_True;
411 		m_pImpl->m_xDataSupplier->validate();
412 		return sal_False;
413 	}
414 
415 	m_pImpl->m_nPos++;
416 	m_pImpl->m_xDataSupplier->validate();
417 	return sal_True;
418 }
419 
420 //=========================================================================
421 // virtual
422 sal_Bool SAL_CALL ResultSet::isBeforeFirst()
423 	throw( sdbc::SQLException, uno::RuntimeException )
424 {
425 	if ( m_pImpl->m_bAfterLast )
426 	{
427 		m_pImpl->m_xDataSupplier->validate();
428 		return sal_False;
429 	}
430 
431 	// getResult works zero-based!
432 	if ( !m_pImpl->m_xDataSupplier->getResult( 0 ) )
433 	{
434 		m_pImpl->m_xDataSupplier->validate();
435 		return sal_False;
436 	}
437 
438 	m_pImpl->m_xDataSupplier->validate();
439 	return ( m_pImpl->m_nPos == 0 );
440 }
441 
442 //=========================================================================
443 // virtual
444 sal_Bool SAL_CALL ResultSet::isAfterLast()
445 	throw( sdbc::SQLException, uno::RuntimeException )
446 {
447 	m_pImpl->m_xDataSupplier->validate();
448 	return m_pImpl->m_bAfterLast;
449 }
450 
451 //=========================================================================
452 // virtual
453 sal_Bool SAL_CALL ResultSet::isFirst()
454 	throw( sdbc::SQLException, uno::RuntimeException )
455 {
456 	if ( m_pImpl->m_bAfterLast )
457 	{
458 		m_pImpl->m_xDataSupplier->validate();
459 		return sal_False;
460 	}
461 
462 	m_pImpl->m_xDataSupplier->validate();
463 	return ( m_pImpl->m_nPos == 1 );
464 }
465 
466 //=========================================================================
467 // virtual
468 sal_Bool SAL_CALL ResultSet::isLast()
469 	throw( sdbc::SQLException, uno::RuntimeException )
470 {
471 	if ( m_pImpl->m_bAfterLast )
472 	{
473 		m_pImpl->m_xDataSupplier->validate();
474 		return sal_False;
475 	}
476 
477 	sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
478 	if ( !nCount )
479 	{
480 		m_pImpl->m_xDataSupplier->validate();
481 		return sal_False;
482 	}
483 
484 	m_pImpl->m_xDataSupplier->validate();
485 	return ( m_pImpl->m_nPos == nCount );
486 }
487 
488 //=========================================================================
489 // virtual
490 void SAL_CALL ResultSet::beforeFirst()
491 	throw( sdbc::SQLException, uno::RuntimeException )
492 {
493 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
494 	m_pImpl->m_bAfterLast = sal_False;
495 	m_pImpl->m_nPos = 0;
496 	m_pImpl->m_xDataSupplier->validate();
497 }
498 
499 //=========================================================================
500 // virtual
501 void SAL_CALL ResultSet::afterLast()
502 	throw( sdbc::SQLException, uno::RuntimeException )
503 {
504 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
505 	m_pImpl->m_bAfterLast = sal_True;
506 	m_pImpl->m_xDataSupplier->validate();
507 }
508 
509 //=========================================================================
510 // virtual
511 sal_Bool SAL_CALL ResultSet::first()
512 	throw( sdbc::SQLException, uno::RuntimeException )
513 {
514 	// getResult works zero-based!
515 	if ( m_pImpl->m_xDataSupplier->getResult( 0 ) )
516 	{
517 		osl::MutexGuard aGuard( m_pImpl->m_aMutex );
518 		m_pImpl->m_bAfterLast = sal_False;
519 		m_pImpl->m_nPos = 1;
520 		m_pImpl->m_xDataSupplier->validate();
521 		return sal_True;
522 	}
523 
524 	m_pImpl->m_xDataSupplier->validate();
525 	return sal_False;
526 }
527 
528 //=========================================================================
529 // virtual
530 sal_Bool SAL_CALL ResultSet::last()
531 	throw( sdbc::SQLException, uno::RuntimeException )
532 {
533 	sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
534 	if ( nCount )
535 	{
536 		osl::MutexGuard aGuard( m_pImpl->m_aMutex );
537 		m_pImpl->m_bAfterLast = sal_False;
538 		m_pImpl->m_nPos = nCount;
539 		m_pImpl->m_xDataSupplier->validate();
540 		return sal_True;
541 	}
542 
543 	m_pImpl->m_xDataSupplier->validate();
544 	return sal_False;
545 }
546 
547 //=========================================================================
548 // virtual
549 sal_Int32 SAL_CALL ResultSet::getRow()
550 	throw( sdbc::SQLException, uno::RuntimeException )
551 {
552 	if ( m_pImpl->m_bAfterLast )
553 	{
554 		m_pImpl->m_xDataSupplier->validate();
555 		return 0;
556 	}
557 
558 	m_pImpl->m_xDataSupplier->validate();
559 	return m_pImpl->m_nPos;
560 }
561 
562 //=========================================================================
563 // virtual
564 sal_Bool SAL_CALL ResultSet::absolute( sal_Int32 row )
565 	throw( sdbc::SQLException, uno::RuntimeException )
566 {
567 /*
568 	If the row number is positive, the cursor moves to the given row number
569 	with respect to the beginning of the result set. The first row is row 1,
570 	the second is row 2, and so on.
571 
572 	If the given row number is negative, the cursor moves to an absolute row
573 	position with respect to the end of the result set. For example, calling
574 	absolaute( -1 ) positions the cursor on the last row, absolaute( -2 )
575 	indicates the next-to-last row, and so on.
576 
577 	An attempt to position the cursor beyond the first/last row in the result
578 	set leaves the cursor before/after the first/last row, respectively.
579 
580 	Calling absolute( 1 ) is the same as calling first().
581 
582     Calling absolute( -1 ) is the same as calling last().
583 */
584 	if ( row < 0 )
585 	{
586 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
587 
588 		if ( ( row * -1 ) > nCount )
589 		{
590 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
591 			m_pImpl->m_bAfterLast = sal_False;
592 			m_pImpl->m_nPos = 0;
593 			m_pImpl->m_xDataSupplier->validate();
594 			return sal_False;
595 		}
596 		else // |row| <= nCount
597 		{
598 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
599 			m_pImpl->m_bAfterLast = sal_False;
600 			m_pImpl->m_nPos = ( nCount + row + 1 );
601 			m_pImpl->m_xDataSupplier->validate();
602 			return sal_True;
603 		}
604 	}
605 	else if ( row == 0 )
606 	{
607 	    // @throws SQLException
608 		//		... if row is 0 ...
609 		throw sdbc::SQLException();
610 	}
611 	else // row > 0
612 	{
613 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
614 
615 		if ( row <= nCount )
616 		{
617 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
618 			m_pImpl->m_bAfterLast = sal_False;
619 			m_pImpl->m_nPos = row;
620 			m_pImpl->m_xDataSupplier->validate();
621 			return sal_True;
622 		}
623 		else // row > nCount
624 		{
625 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
626 			m_pImpl->m_bAfterLast = sal_True;
627 			m_pImpl->m_xDataSupplier->validate();
628 			return sal_False;
629 		}
630 	}
631 
632 	// unreachable...
633 }
634 
635 //=========================================================================
636 // virtual
637 sal_Bool SAL_CALL ResultSet::relative( sal_Int32 rows )
638 	throw( sdbc::SQLException, uno::RuntimeException )
639 {
640 /*
641 	Attempting to move beyond the first/last row in the result set
642 	positions the cursor before/after the the first/last row.
643 
644 	Calling relative( 0 ) is valid, but does not change the cursor position.
645 
646     Calling relative( 1 ) is different from calling next() because it makes
647 	sense to call next() when there is no current row, for example,	when
648 	the cursor is positioned before the first row or after the last	row of
649 	the result set.
650 */
651 	if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
652 	{
653 		// "No current row".
654 		throw sdbc::SQLException();
655 	}
656 
657 	if ( rows < 0 )
658 	{
659 		if ( ( m_pImpl->m_nPos + rows ) > 0 )
660 		{
661 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
662 			m_pImpl->m_bAfterLast = sal_False;
663 			m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
664 			m_pImpl->m_xDataSupplier->validate();
665 			return sal_True;
666 		}
667 		else
668 		{
669 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
670 			m_pImpl->m_bAfterLast = sal_False;
671 			m_pImpl->m_nPos = 0;
672 			m_pImpl->m_xDataSupplier->validate();
673 			return sal_False;
674 		}
675 	}
676 	else if ( rows == 0 )
677 	{
678 		// nop.
679 		m_pImpl->m_xDataSupplier->validate();
680 		return sal_True;
681 	}
682 	else // rows > 0
683 	{
684 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
685 		if ( ( m_pImpl->m_nPos + rows ) <= nCount )
686 		{
687 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
688 			m_pImpl->m_bAfterLast = sal_False;
689 			m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
690 			m_pImpl->m_xDataSupplier->validate();
691 			return sal_True;
692 		}
693 		else
694 		{
695 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
696 			m_pImpl->m_bAfterLast = sal_True;
697 			m_pImpl->m_xDataSupplier->validate();
698 			return sal_False;
699 		}
700 	}
701 
702 	// unreachable...
703 }
704 
705 //=========================================================================
706 // virtual
707 sal_Bool SAL_CALL ResultSet::previous()
708 	throw( sdbc::SQLException, uno::RuntimeException )
709 {
710 /*
711 	previous() is not the same as relative( -1 ) because it makes sense
712 	to call previous() when there is no current row.
713 */
714 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
715 
716 	if ( m_pImpl->m_bAfterLast )
717 	{
718 		m_pImpl->m_bAfterLast = sal_False;
719 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
720 		m_pImpl->m_nPos = nCount;
721 	}
722 	else if ( m_pImpl->m_nPos )
723 		m_pImpl->m_nPos--;
724 
725 	if ( m_pImpl->m_nPos )
726 	{
727 		m_pImpl->m_xDataSupplier->validate();
728 		return sal_True;
729 	}
730 
731 	m_pImpl->m_xDataSupplier->validate();
732 	return sal_False;
733 }
734 
735 //=========================================================================
736 // virtual
737 void SAL_CALL ResultSet::refreshRow()
738 	throw( sdbc::SQLException, uno::RuntimeException )
739 {
740 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
741 	if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
742 		return;
743 
744 	m_pImpl->m_xDataSupplier->releasePropertyValues( m_pImpl->m_nPos );
745 	m_pImpl->m_xDataSupplier->validate();
746 }
747 
748 //=========================================================================
749 // virtual
750 sal_Bool SAL_CALL ResultSet::rowUpdated()
751 	throw( sdbc::SQLException, uno::RuntimeException )
752 {
753 	m_pImpl->m_xDataSupplier->validate();
754 	return sal_False;
755 }
756 
757 //=========================================================================
758 // virtual
759 sal_Bool SAL_CALL ResultSet::rowInserted()
760 	throw( sdbc::SQLException, uno::RuntimeException )
761 {
762 	m_pImpl->m_xDataSupplier->validate();
763 	return sal_False;
764 }
765 
766 //=========================================================================
767 // virtual
768 sal_Bool SAL_CALL ResultSet::rowDeleted()
769 	throw( sdbc::SQLException, uno::RuntimeException )
770 {
771 	m_pImpl->m_xDataSupplier->validate();
772 	return sal_False;
773 }
774 
775 //=========================================================================
776 // virtual
777 uno::Reference< uno::XInterface > SAL_CALL ResultSet::getStatement()
778 	throw( sdbc::SQLException, uno::RuntimeException )
779 {
780 /*
781 	returns the Statement that produced this ResultSet object. If the
782 	result set was generated some other way, ... this method returns null.
783 */
784 	m_pImpl->m_xDataSupplier->validate();
785 	return uno::Reference< uno::XInterface >();
786 }
787 
788 //=========================================================================
789 //
790 // XRow methods.
791 //
792 //=========================================================================
793 
794 // virtual
795 sal_Bool SAL_CALL ResultSet::wasNull()
796 	throw( sdbc::SQLException, uno::RuntimeException )
797 {
798 	// This method can not be implemented correctly!!! Imagine different
799 	// threads doing a getXYZ - wasNull calling sequence on the same
800 	// implementation object...
801 
802 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
803 	{
804 		uno::Reference< sdbc::XRow > xValues
805 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
806 														m_pImpl->m_nPos - 1 );
807 		if ( xValues.is() )
808 		{
809 			m_pImpl->m_xDataSupplier->validate();
810 			return xValues->wasNull();
811 		}
812 	}
813 
814 	m_pImpl->m_xDataSupplier->validate();
815 	return m_pImpl->m_bWasNull;
816 }
817 
818 //=========================================================================
819 // virtual
820 rtl::OUString SAL_CALL ResultSet::getString( sal_Int32 columnIndex )
821 	throw( sdbc::SQLException, uno::RuntimeException )
822 {
823 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
824 	{
825 		uno::Reference< sdbc::XRow > xValues
826 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
827 														m_pImpl->m_nPos - 1 );
828 		if ( xValues.is() )
829 		{
830 			m_pImpl->m_bWasNull = sal_False;
831 			m_pImpl->m_xDataSupplier->validate();
832 			return xValues->getString( columnIndex );
833 		}
834 	}
835 
836 	m_pImpl->m_bWasNull = sal_True;
837 	m_pImpl->m_xDataSupplier->validate();
838 	return rtl::OUString();
839 }
840 
841 //=========================================================================
842 // virtual
843 sal_Bool SAL_CALL ResultSet::getBoolean( sal_Int32 columnIndex )
844 	throw( sdbc::SQLException, uno::RuntimeException )
845 {
846 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
847 	{
848 		uno::Reference< sdbc::XRow > xValues
849 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
850 														m_pImpl->m_nPos - 1 );
851 		if ( xValues.is() )
852 		{
853 			m_pImpl->m_bWasNull = sal_False;
854 			m_pImpl->m_xDataSupplier->validate();
855 			return xValues->getBoolean( columnIndex );
856 		}
857 	}
858 
859 	m_pImpl->m_bWasNull = sal_True;
860 	m_pImpl->m_xDataSupplier->validate();
861 	return sal_False;
862 }
863 
864 //=========================================================================
865 // virtual
866 sal_Int8 SAL_CALL ResultSet::getByte( sal_Int32 columnIndex )
867 	throw( sdbc::SQLException, uno::RuntimeException )
868 {
869 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
870 	{
871 		uno::Reference< sdbc::XRow > xValues
872 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
873 														m_pImpl->m_nPos - 1 );
874 		if ( xValues.is() )
875 		{
876 			m_pImpl->m_bWasNull = sal_False;
877 			m_pImpl->m_xDataSupplier->validate();
878 			return xValues->getByte( columnIndex );
879 		}
880 	}
881 
882 	m_pImpl->m_bWasNull = sal_True;
883 	m_pImpl->m_xDataSupplier->validate();
884 	return 0;
885 }
886 
887 //=========================================================================
888 // virtual
889 sal_Int16 SAL_CALL ResultSet::getShort( sal_Int32 columnIndex )
890 	throw( sdbc::SQLException, uno::RuntimeException )
891 {
892 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
893 	{
894 		uno::Reference< sdbc::XRow > xValues
895 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
896 														m_pImpl->m_nPos - 1 );
897 		if ( xValues.is() )
898 		{
899 			m_pImpl->m_bWasNull = sal_False;
900 			m_pImpl->m_xDataSupplier->validate();
901 			return xValues->getShort( columnIndex );
902 		}
903 	}
904 
905 	m_pImpl->m_bWasNull = sal_True;
906 	m_pImpl->m_xDataSupplier->validate();
907 	return 0;
908 }
909 
910 //=========================================================================
911 // virtual
912 sal_Int32 SAL_CALL ResultSet::getInt( sal_Int32 columnIndex )
913 	throw( sdbc::SQLException, uno::RuntimeException )
914 {
915 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
916 	{
917 		uno::Reference< sdbc::XRow > xValues
918 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
919 														m_pImpl->m_nPos - 1 );
920 		if ( xValues.is() )
921 		{
922 			m_pImpl->m_bWasNull = sal_False;
923 			m_pImpl->m_xDataSupplier->validate();
924 			return xValues->getInt( columnIndex );
925 		}
926 	}
927 
928 	m_pImpl->m_bWasNull = sal_True;
929 	m_pImpl->m_xDataSupplier->validate();
930 	return 0;
931 }
932 
933 //=========================================================================
934 // virtual
935 sal_Int64 SAL_CALL ResultSet::getLong( sal_Int32 columnIndex )
936 	throw( sdbc::SQLException, uno::RuntimeException )
937 {
938 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
939 	{
940 		uno::Reference< sdbc::XRow > xValues
941 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
942 														m_pImpl->m_nPos - 1 );
943 		if ( xValues.is() )
944 		{
945 			m_pImpl->m_bWasNull = sal_False;
946 			m_pImpl->m_xDataSupplier->validate();
947 			return xValues->getLong( columnIndex );
948 		}
949 	}
950 
951 	m_pImpl->m_bWasNull = sal_True;
952 	m_pImpl->m_xDataSupplier->validate();
953 	return 0;
954 }
955 
956 //=========================================================================
957 // virtual
958 float SAL_CALL ResultSet::getFloat( sal_Int32 columnIndex )
959 	throw( sdbc::SQLException, uno::RuntimeException )
960 {
961 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
962 	{
963 		uno::Reference< sdbc::XRow > xValues
964 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
965 														m_pImpl->m_nPos - 1 );
966 		if ( xValues.is() )
967 		{
968 			m_pImpl->m_bWasNull = sal_False;
969 			m_pImpl->m_xDataSupplier->validate();
970 			return xValues->getFloat( columnIndex );
971 		}
972 	}
973 
974 	m_pImpl->m_bWasNull = sal_True;
975 	m_pImpl->m_xDataSupplier->validate();
976 	return 0;
977 }
978 
979 //=========================================================================
980 // virtual
981 double SAL_CALL ResultSet::getDouble( sal_Int32 columnIndex )
982 	throw( sdbc::SQLException, uno::RuntimeException )
983 {
984 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
985 	{
986 		uno::Reference< sdbc::XRow > xValues
987 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
988 														m_pImpl->m_nPos - 1 );
989 		if ( xValues.is() )
990 		{
991 			m_pImpl->m_bWasNull = sal_False;
992 			m_pImpl->m_xDataSupplier->validate();
993 			return xValues->getDouble( columnIndex );
994 		}
995 	}
996 
997 	m_pImpl->m_bWasNull = sal_True;
998 	m_pImpl->m_xDataSupplier->validate();
999 	return 0;
1000 }
1001 
1002 //=========================================================================
1003 // virtual
1004 uno::Sequence< sal_Int8 > SAL_CALL
1005 ResultSet::getBytes( sal_Int32 columnIndex )
1006 	throw( sdbc::SQLException, uno::RuntimeException )
1007 {
1008 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1009 	{
1010 		uno::Reference< sdbc::XRow > xValues
1011 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1012 														m_pImpl->m_nPos - 1 );
1013 		if ( xValues.is() )
1014 		{
1015 			m_pImpl->m_bWasNull = sal_False;
1016 			m_pImpl->m_xDataSupplier->validate();
1017 			return xValues->getBytes( columnIndex );
1018 		}
1019 	}
1020 
1021 	m_pImpl->m_bWasNull = sal_True;
1022 	m_pImpl->m_xDataSupplier->validate();
1023 	return uno::Sequence< sal_Int8 >();
1024 }
1025 
1026 //=========================================================================
1027 // virtual
1028 util::Date SAL_CALL ResultSet::getDate( sal_Int32 columnIndex )
1029 	throw( sdbc::SQLException, uno::RuntimeException )
1030 {
1031 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1032 	{
1033 		uno::Reference< sdbc::XRow > xValues
1034 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1035 														m_pImpl->m_nPos - 1 );
1036 		if ( xValues.is() )
1037 		{
1038 			m_pImpl->m_bWasNull = sal_False;
1039 			m_pImpl->m_xDataSupplier->validate();
1040 			return xValues->getDate( columnIndex );
1041 		}
1042 	}
1043 
1044 	m_pImpl->m_bWasNull = sal_True;
1045 	m_pImpl->m_xDataSupplier->validate();
1046 	return util::Date();
1047 }
1048 
1049 //=========================================================================
1050 // virtual
1051 util::Time SAL_CALL ResultSet::getTime( sal_Int32 columnIndex )
1052 	throw( sdbc::SQLException, uno::RuntimeException )
1053 {
1054 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1055 	{
1056 		uno::Reference< sdbc::XRow > xValues
1057 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1058 														m_pImpl->m_nPos - 1 );
1059 		if ( xValues.is() )
1060 		{
1061 			m_pImpl->m_bWasNull = sal_False;
1062 			m_pImpl->m_xDataSupplier->validate();
1063 			return xValues->getTime( columnIndex );
1064 		}
1065 	}
1066 
1067 	m_pImpl->m_bWasNull = sal_True;
1068 	m_pImpl->m_xDataSupplier->validate();
1069 	return util::Time();
1070 }
1071 
1072 //=========================================================================
1073 // virtual
1074 util::DateTime SAL_CALL
1075 ResultSet::getTimestamp( sal_Int32 columnIndex )
1076 	throw( sdbc::SQLException, uno::RuntimeException )
1077 {
1078 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1079 	{
1080 		uno::Reference< sdbc::XRow > xValues
1081 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1082 														m_pImpl->m_nPos - 1 );
1083 		if ( xValues.is() )
1084 		{
1085 			m_pImpl->m_bWasNull = sal_False;
1086 			m_pImpl->m_xDataSupplier->validate();
1087 			return xValues->getTimestamp( columnIndex );
1088 		}
1089 	}
1090 
1091 	m_pImpl->m_bWasNull = sal_True;
1092 	m_pImpl->m_xDataSupplier->validate();
1093 	return util::DateTime();
1094 }
1095 
1096 //=========================================================================
1097 // virtual
1098 uno::Reference< io::XInputStream > SAL_CALL
1099 ResultSet::getBinaryStream( sal_Int32 columnIndex )
1100 	throw( sdbc::SQLException, uno::RuntimeException )
1101 {
1102 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1103 	{
1104 		uno::Reference< sdbc::XRow > xValues
1105 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1106 														m_pImpl->m_nPos - 1 );
1107 		if ( xValues.is() )
1108 		{
1109 			m_pImpl->m_bWasNull = sal_False;
1110 			m_pImpl->m_xDataSupplier->validate();
1111 			return xValues->getBinaryStream( columnIndex );
1112 		}
1113 	}
1114 
1115 	m_pImpl->m_bWasNull = sal_True;
1116 	m_pImpl->m_xDataSupplier->validate();
1117 	return uno::Reference< io::XInputStream >();
1118 }
1119 
1120 //=========================================================================
1121 // virtual
1122 uno::Reference< io::XInputStream > SAL_CALL
1123 ResultSet::getCharacterStream( sal_Int32 columnIndex )
1124 	throw( sdbc::SQLException, uno::RuntimeException )
1125 {
1126 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1127 	{
1128 		uno::Reference< sdbc::XRow > xValues
1129 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1130 														m_pImpl->m_nPos - 1 );
1131 		if ( xValues.is() )
1132 		{
1133 			m_pImpl->m_bWasNull = sal_False;
1134 			m_pImpl->m_xDataSupplier->validate();
1135 			return xValues->getCharacterStream( columnIndex );
1136 		}
1137 	}
1138 
1139 	m_pImpl->m_bWasNull = sal_True;
1140 	m_pImpl->m_xDataSupplier->validate();
1141 	return uno::Reference< io::XInputStream >();
1142 }
1143 
1144 //=========================================================================
1145 // virtual
1146 uno::Any SAL_CALL ResultSet::getObject(
1147         sal_Int32 columnIndex,
1148         const uno::Reference< container::XNameAccess >& typeMap )
1149 	throw( sdbc::SQLException, uno::RuntimeException )
1150 {
1151 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1152 	{
1153 		uno::Reference< sdbc::XRow > xValues
1154 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1155 														m_pImpl->m_nPos - 1 );
1156 		if ( xValues.is() )
1157 		{
1158 			m_pImpl->m_bWasNull = sal_False;
1159 			m_pImpl->m_xDataSupplier->validate();
1160 			return xValues->getObject( columnIndex, typeMap );
1161 		}
1162 	}
1163 
1164 	m_pImpl->m_bWasNull = sal_True;
1165 	m_pImpl->m_xDataSupplier->validate();
1166 	return uno::Any();
1167 }
1168 
1169 //=========================================================================
1170 // virtual
1171 uno::Reference< sdbc::XRef > SAL_CALL
1172 ResultSet::getRef( sal_Int32 columnIndex )
1173 	throw( sdbc::SQLException, uno::RuntimeException )
1174 {
1175 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1176 	{
1177 		uno::Reference< sdbc::XRow > xValues
1178 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1179 														m_pImpl->m_nPos - 1 );
1180 		if ( xValues.is() )
1181 		{
1182 			m_pImpl->m_bWasNull = sal_False;
1183 			m_pImpl->m_xDataSupplier->validate();
1184 			return xValues->getRef( columnIndex );
1185 		}
1186 	}
1187 
1188 	m_pImpl->m_bWasNull = sal_True;
1189 	m_pImpl->m_xDataSupplier->validate();
1190 	return uno::Reference< sdbc::XRef >();
1191 }
1192 
1193 //=========================================================================
1194 // virtual
1195 uno::Reference< sdbc::XBlob > SAL_CALL
1196 ResultSet::getBlob( sal_Int32 columnIndex )
1197 	throw( sdbc::SQLException, uno::RuntimeException )
1198 {
1199 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1200 	{
1201 		uno::Reference< sdbc::XRow > xValues
1202 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1203 														m_pImpl->m_nPos - 1 );
1204 		if ( xValues.is() )
1205 		{
1206 			m_pImpl->m_bWasNull = sal_False;
1207 			m_pImpl->m_xDataSupplier->validate();
1208 			return xValues->getBlob( columnIndex );
1209 		}
1210 	}
1211 
1212 	m_pImpl->m_bWasNull = sal_True;
1213 	m_pImpl->m_xDataSupplier->validate();
1214 	return uno::Reference< sdbc::XBlob >();
1215 }
1216 
1217 //=========================================================================
1218 // virtual
1219 uno::Reference< sdbc::XClob > SAL_CALL
1220 ResultSet::getClob( sal_Int32 columnIndex )
1221 	throw( sdbc::SQLException, uno::RuntimeException )
1222 {
1223 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1224 	{
1225 		uno::Reference< sdbc::XRow > xValues
1226 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1227 														m_pImpl->m_nPos - 1 );
1228 		if ( xValues.is() )
1229 		{
1230 			m_pImpl->m_bWasNull = sal_False;
1231 			m_pImpl->m_xDataSupplier->validate();
1232 			return xValues->getClob( columnIndex );
1233 		}
1234 	}
1235 
1236 	m_pImpl->m_bWasNull = sal_True;
1237 	m_pImpl->m_xDataSupplier->validate();
1238 	return uno::Reference< sdbc::XClob >();
1239 }
1240 
1241 //=========================================================================
1242 // virtual
1243 uno::Reference< sdbc::XArray > SAL_CALL
1244 ResultSet::getArray( sal_Int32 columnIndex )
1245 	throw( sdbc::SQLException, uno::RuntimeException )
1246 {
1247 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1248 	{
1249 		uno::Reference< sdbc::XRow > xValues
1250 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1251 														m_pImpl->m_nPos - 1 );
1252 		if ( xValues.is() )
1253 		{
1254 			m_pImpl->m_bWasNull = sal_False;
1255 			m_pImpl->m_xDataSupplier->validate();
1256 			return xValues->getArray( columnIndex );
1257 		}
1258 	}
1259 
1260 	m_pImpl->m_bWasNull = sal_True;
1261 	m_pImpl->m_xDataSupplier->validate();
1262 	return uno::Reference< sdbc::XArray >();
1263 }
1264 
1265 //=========================================================================
1266 //
1267 // XCloseable methods.
1268 //
1269 //=========================================================================
1270 
1271 // virtual
1272 void SAL_CALL ResultSet::close()
1273 	throw( sdbc::SQLException, uno::RuntimeException )
1274 {
1275 	m_pImpl->m_xDataSupplier->close();
1276 	m_pImpl->m_xDataSupplier->validate();
1277 }
1278 
1279 //=========================================================================
1280 //
1281 // XContentAccess methods.
1282 //
1283 //=========================================================================
1284 
1285 // virtual
1286 rtl::OUString SAL_CALL ResultSet::queryContentIdentifierString()
1287 	throw( uno::RuntimeException )
1288 {
1289 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1290 		return m_pImpl->m_xDataSupplier->queryContentIdentifierString(
1291 														m_pImpl->m_nPos - 1 );
1292 
1293 	return rtl::OUString();
1294 }
1295 
1296 //=========================================================================
1297 // virtual
1298 uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL
1299 ResultSet::queryContentIdentifier()
1300 	throw( uno::RuntimeException )
1301 {
1302 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1303 		return m_pImpl->m_xDataSupplier->queryContentIdentifier(
1304 														m_pImpl->m_nPos - 1 );
1305 
1306 	return uno::Reference< com::sun::star::ucb::XContentIdentifier >();
1307 }
1308 
1309 //=========================================================================
1310 // virtual
1311 uno::Reference< com::sun::star::ucb::XContent > SAL_CALL
1312 ResultSet::queryContent()
1313 	throw( uno::RuntimeException )
1314 {
1315 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1316 		return m_pImpl->m_xDataSupplier->queryContent( m_pImpl->m_nPos - 1 );
1317 
1318 	return uno::Reference< com::sun::star::ucb::XContent >();
1319 }
1320 
1321 //=========================================================================
1322 //
1323 // XPropertySet methods.
1324 //
1325 //=========================================================================
1326 
1327 // virtual
1328 uno::Reference< beans::XPropertySetInfo > SAL_CALL
1329 ResultSet::getPropertySetInfo()
1330 	throw( uno::RuntimeException )
1331 {
1332 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1333 
1334 	if ( !m_pImpl->m_xPropSetInfo.is() )
1335 		m_pImpl->m_xPropSetInfo
1336 			= new PropertySetInfo( m_pImpl->m_xSMgr,
1337 								   aPropertyTable,
1338 								   RESULTSET_PROPERTY_COUNT );
1339 	return m_pImpl->m_xPropSetInfo;
1340 }
1341 
1342 //=========================================================================
1343 // virtual
1344 void SAL_CALL ResultSet::setPropertyValue( const rtl::OUString& aPropertyName,
1345 										   const uno::Any& )
1346 	throw( beans::UnknownPropertyException,
1347 		   beans::PropertyVetoException,
1348 		   lang::IllegalArgumentException,
1349 		   lang::WrappedTargetException,
1350 		   uno::RuntimeException )
1351 {
1352 	if ( !aPropertyName.getLength() )
1353 		throw beans::UnknownPropertyException();
1354 
1355 	if ( aPropertyName.equals(
1356 				rtl::OUString::createFromAscii( "RowCount" ) ) )
1357 	{
1358 		// property is read-only.
1359 		throw lang::IllegalArgumentException();
1360 	}
1361 	else if ( aPropertyName.equals(
1362 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1363 	{
1364 		// property is read-only.
1365 		throw lang::IllegalArgumentException();
1366 	}
1367 	else
1368 	{
1369 		throw beans::UnknownPropertyException();
1370 	}
1371 }
1372 
1373 //=========================================================================
1374 // virtual
1375 uno::Any SAL_CALL ResultSet::getPropertyValue(
1376         const rtl::OUString& PropertyName )
1377 	throw( beans::UnknownPropertyException,
1378 		   lang::WrappedTargetException,
1379 		   uno::RuntimeException )
1380 {
1381 	if ( !PropertyName.getLength() )
1382 		throw beans::UnknownPropertyException();
1383 
1384 	uno::Any aValue;
1385 
1386 	if ( PropertyName.equals(
1387 				rtl::OUString::createFromAscii( "RowCount" ) ) )
1388 	{
1389 		aValue <<= m_pImpl->m_xDataSupplier->currentCount();
1390 	}
1391 	else if ( PropertyName.equals(
1392 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1393 	{
1394 		aValue <<= m_pImpl->m_xDataSupplier->isCountFinal();
1395 	}
1396 	else
1397 	{
1398 		throw beans::UnknownPropertyException();
1399 	}
1400 
1401 	return aValue;
1402 }
1403 
1404 //=========================================================================
1405 // virtual
1406 void SAL_CALL ResultSet::addPropertyChangeListener(
1407         const rtl::OUString& aPropertyName,
1408         const uno::Reference< beans::XPropertyChangeListener >& xListener )
1409 	throw( beans::UnknownPropertyException,
1410 		   lang::WrappedTargetException,
1411 		   uno::RuntimeException )
1412 {
1413 	// Note: An empty property name means a listener for "all" properties.
1414 
1415 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1416 
1417 	if ( aPropertyName.getLength() &&
1418 	     !aPropertyName.equals(
1419 				rtl::OUString::createFromAscii( "RowCount" ) ) &&
1420 		 !aPropertyName.equals(
1421 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1422 		throw beans::UnknownPropertyException();
1423 
1424 	if ( !m_pImpl->m_pPropertyChangeListeners )
1425 		m_pImpl->m_pPropertyChangeListeners
1426 			= new PropertyChangeListeners( m_pImpl->m_aMutex );
1427 
1428 	m_pImpl->m_pPropertyChangeListeners->addInterface(
1429 												aPropertyName, xListener );
1430 }
1431 
1432 //=========================================================================
1433 // virtual
1434 void SAL_CALL ResultSet::removePropertyChangeListener(
1435         const rtl::OUString& aPropertyName,
1436 		const uno::Reference< beans::XPropertyChangeListener >& xListener )
1437 	throw( beans::UnknownPropertyException,
1438 		   lang::WrappedTargetException,
1439 		   uno::RuntimeException )
1440 {
1441 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1442 
1443 	if ( aPropertyName.getLength() &&
1444 	     !aPropertyName.equals(
1445 				rtl::OUString::createFromAscii( "RowCount" ) ) &&
1446 		 !aPropertyName.equals(
1447 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1448 		throw beans::UnknownPropertyException();
1449 
1450 	if ( m_pImpl->m_pPropertyChangeListeners )
1451 		m_pImpl->m_pPropertyChangeListeners->removeInterface(
1452 													aPropertyName, xListener );
1453 
1454 }
1455 
1456 //=========================================================================
1457 // virtual
1458 void SAL_CALL ResultSet::addVetoableChangeListener(
1459         const rtl::OUString&,
1460         const uno::Reference< beans::XVetoableChangeListener >& )
1461 	throw( beans::UnknownPropertyException,
1462 		   lang::WrappedTargetException,
1463 		   uno::RuntimeException )
1464 {
1465 	//	No constrained props, at the moment.
1466 }
1467 
1468 //=========================================================================
1469 // virtual
1470 void SAL_CALL ResultSet::removeVetoableChangeListener(
1471         const rtl::OUString&,
1472         const uno::Reference< beans::XVetoableChangeListener >& )
1473 	throw( beans::UnknownPropertyException,
1474 		   lang::WrappedTargetException,
1475 		   uno::RuntimeException )
1476 {
1477 	//	No constrained props, at the moment.
1478 }
1479 
1480 //=========================================================================
1481 //
1482 // Non-interface methods.
1483 //
1484 //=========================================================================
1485 
1486 void ResultSet::propertyChanged( const beans::PropertyChangeEvent& rEvt )
1487 {
1488 	if ( !m_pImpl->m_pPropertyChangeListeners )
1489 		return;
1490 
1491 	// Notify listeners interested especially in the changed property.
1492 	cppu::OInterfaceContainerHelper* pPropsContainer
1493 		= m_pImpl->m_pPropertyChangeListeners->getContainer(
1494 														rEvt.PropertyName );
1495 	if ( pPropsContainer )
1496 	{
1497 		cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
1498 		while ( aIter.hasMoreElements() )
1499 		{
1500 			uno::Reference< beans::XPropertyChangeListener > xListener(
1501                 aIter.next(), uno::UNO_QUERY );
1502 			if ( xListener.is() )
1503 				xListener->propertyChange( rEvt );
1504 		}
1505 	}
1506 
1507 	// Notify listeners interested in all properties.
1508 	pPropsContainer
1509 		= m_pImpl->m_pPropertyChangeListeners->getContainer( rtl::OUString() );
1510 	if ( pPropsContainer )
1511 	{
1512 		cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
1513 		while ( aIter.hasMoreElements() )
1514 		{
1515 			uno::Reference< beans::XPropertyChangeListener > xListener(
1516                 aIter.next(), uno::UNO_QUERY );
1517 			if ( xListener.is() )
1518 				xListener->propertyChange( rEvt );
1519 		}
1520 	}
1521 }
1522 
1523 //=========================================================================
1524 void ResultSet::rowCountChanged( sal_uInt32 nOld, sal_uInt32 nNew )
1525 {
1526 	OSL_ENSURE( nOld < nNew, "ResultSet::rowCountChanged - nOld >= nNew!" );
1527 
1528 	if ( !m_pImpl->m_pPropertyChangeListeners )
1529 		return;
1530 
1531 	propertyChanged(
1532 		beans::PropertyChangeEvent(
1533             static_cast< cppu::OWeakObject * >( this ),
1534             rtl::OUString::createFromAscii( "RowCount" ),
1535             sal_False,
1536             1001,
1537             uno::makeAny( nOld ),	  // old value
1538             uno::makeAny( nNew ) ) ); // new value
1539 }
1540 
1541 //=========================================================================
1542 void ResultSet::rowCountFinal()
1543 {
1544 	if ( !m_pImpl->m_pPropertyChangeListeners )
1545 		return;
1546 
1547 	propertyChanged(
1548 		beans::PropertyChangeEvent(
1549             static_cast< cppu::OWeakObject * >( this ),
1550             rtl::OUString::createFromAscii( "IsRowCountFinal" ),
1551             sal_False,
1552             1000,
1553 			uno:: makeAny( sal_False ),	  // old value
1554             uno::makeAny( sal_True ) ) ); // new value
1555 }
1556 
1557 //=========================================================================
1558 const uno::Sequence< beans::Property >&	ResultSet::getProperties()
1559 {
1560 	return m_pImpl->m_aProperties;
1561 }
1562 
1563 //=========================================================================
1564 const uno::Reference< com::sun::star::ucb::XCommandEnvironment >&
1565 ResultSet::getEnvironment()
1566 {
1567 	return m_pImpl->m_xEnv;
1568 }
1569 
1570 } // namespace ucbhelper
1571 
1572 namespace ucbhelper_impl {
1573 
1574 //=========================================================================
1575 //=========================================================================
1576 //
1577 // PropertySetInfo Implementation.
1578 //
1579 //=========================================================================
1580 //=========================================================================
1581 
1582 PropertySetInfo::PropertySetInfo(
1583     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
1584     const PropertyInfo* pProps,
1585     sal_Int32 nProps )
1586 : m_xSMgr( rxSMgr )
1587 {
1588 	m_pProps = new uno::Sequence< beans::Property >( nProps );
1589 
1590 	if ( nProps )
1591 	{
1592 		const PropertyInfo* pEntry = pProps;
1593 		beans::Property* pProperties = m_pProps->getArray();
1594 
1595 		for ( sal_Int32 n = 0; n < nProps; ++n )
1596 		{
1597 			beans::Property& rProp = pProperties[ n ];
1598 
1599 			rProp.Name		 = rtl::OUString::createFromAscii( pEntry->pName );
1600     		rProp.Handle	 = pEntry->nHandle;
1601     		rProp.Type		 = pEntry->pGetCppuType();
1602     		rProp.Attributes = pEntry->nAttributes;
1603 
1604 			pEntry++;
1605 		}
1606 	}
1607 }
1608 
1609 //=========================================================================
1610 // virtual
1611 PropertySetInfo::~PropertySetInfo()
1612 {
1613 	delete m_pProps;
1614 }
1615 
1616 //=========================================================================
1617 //
1618 // XInterface methods.
1619 //
1620 //=========================================================================
1621 
1622 XINTERFACE_IMPL_2( PropertySetInfo,
1623 				   lang::XTypeProvider,
1624 				   beans::XPropertySetInfo );
1625 
1626 //=========================================================================
1627 //
1628 // XTypeProvider methods.
1629 //
1630 //=========================================================================
1631 
1632 XTYPEPROVIDER_IMPL_2( PropertySetInfo,
1633 				   	  lang::XTypeProvider,
1634 				   	  beans::XPropertySetInfo );
1635 
1636 //=========================================================================
1637 //
1638 // XPropertySetInfo methods.
1639 //
1640 //=========================================================================
1641 
1642 // virtual
1643 uno::Sequence< beans::Property > SAL_CALL PropertySetInfo::getProperties()
1644 	throw( uno::RuntimeException )
1645 {
1646 	return uno::Sequence< beans::Property >( *m_pProps );
1647 }
1648 
1649 //=========================================================================
1650 // virtual
1651 beans::Property SAL_CALL PropertySetInfo::getPropertyByName(
1652         const rtl::OUString& aName )
1653 	throw( beans::UnknownPropertyException, uno::RuntimeException )
1654 {
1655 	beans::Property aProp;
1656 	if ( queryProperty( aName, aProp ) )
1657 		return aProp;
1658 
1659 	throw beans::UnknownPropertyException();
1660 }
1661 
1662 //=========================================================================
1663 // virtual
1664 sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName(
1665         const rtl::OUString& Name )
1666 	throw( uno::RuntimeException )
1667 {
1668 	beans::Property aProp;
1669 	return queryProperty( Name, aProp );
1670 }
1671 
1672 //=========================================================================
1673 sal_Bool PropertySetInfo::queryProperty(
1674     const rtl::OUString& aName, beans::Property& rProp )
1675 {
1676 	sal_Int32 nCount = m_pProps->getLength();
1677 	const beans::Property* pProps = m_pProps->getConstArray();
1678 	for ( sal_Int32 n = 0; n < nCount; ++n )
1679 	{
1680 		const beans::Property& rCurr = pProps[ n ];
1681 		if ( rCurr.Name == aName )
1682 		{
1683 			rProp = rCurr;
1684 			return sal_True;
1685 		}
1686 	}
1687 
1688 	return sal_False;
1689 }
1690 
1691 } // namespace ucbhelper_impl
1692