1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
28 #include <com/sun/star/beans/Property.hpp>
29 #include <com/sun/star/beans/XPropertyAccess.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/beans/XPropertySetInfo.hpp>
32 #include <com/sun/star/script/Converter.hpp>
34 #include "osl/diagnose.h"
35 #include "osl/mutex.hxx"
36 #include <ucbhelper/propertyvalueset.hxx>
38 using namespace com::sun::star::beans
;
39 using namespace com::sun::star::container
;
40 using namespace com::sun::star::io
;
41 using namespace com::sun::star::lang
;
42 using namespace com::sun::star::script
;
43 using namespace com::sun::star::sdbc
;
44 using namespace com::sun::star::uno
;
45 using namespace com::sun::star::util
;
47 namespace ucbhelper_impl
56 const sal_uInt32 NO_VALUE_SET
= 0x00000000;
57 const sal_uInt32 STRING_VALUE_SET
= 0x00000001;
58 const sal_uInt32 BOOLEAN_VALUE_SET
= 0x00000002;
59 const sal_uInt32 BYTE_VALUE_SET
= 0x00000004;
60 const sal_uInt32 SHORT_VALUE_SET
= 0x00000008;
61 const sal_uInt32 INT_VALUE_SET
= 0x00000010;
62 const sal_uInt32 LONG_VALUE_SET
= 0x00000020;
63 const sal_uInt32 FLOAT_VALUE_SET
= 0x00000040;
64 const sal_uInt32 DOUBLE_VALUE_SET
= 0x00000080;
65 const sal_uInt32 BYTES_VALUE_SET
= 0x00000100;
66 const sal_uInt32 DATE_VALUE_SET
= 0x00000200;
67 const sal_uInt32 TIME_VALUE_SET
= 0x00000400;
68 const sal_uInt32 TIMESTAMP_VALUE_SET
= 0x00000800;
69 const sal_uInt32 BINARYSTREAM_VALUE_SET
= 0x00001000;
70 const sal_uInt32 CHARACTERSTREAM_VALUE_SET
= 0x00002000;
71 const sal_uInt32 REF_VALUE_SET
= 0x00004000;
72 const sal_uInt32 BLOB_VALUE_SET
= 0x00008000;
73 const sal_uInt32 CLOB_VALUE_SET
= 0x00010000;
74 const sal_uInt32 ARRAY_VALUE_SET
= 0x00020000;
75 const sal_uInt32 OBJECT_VALUE_SET
= 0x00040000;
83 sal_uInt32 nOrigValue
;
85 OUString aString
; // getString
86 bool bBoolean
; // getBoolean
87 sal_Int8 nByte
; // getByte
88 sal_Int16 nShort
; // getShort
89 sal_Int32 nInt
; // getInt
90 sal_Int64 nLong
; // getLong
91 float nFloat
; // getFloat
92 double nDouble
; // getDouble
94 Sequence
< sal_Int8
> aBytes
; // getBytes
95 Date aDate
; // getDate
96 Time aTime
; // getTime
97 DateTime aTimestamp
; // getTimestamp
98 Reference
< XInputStream
> xBinaryStream
; // getBinaryStream
99 Reference
< XInputStream
> xCharacterStream
; // getCharacterStream
100 Reference
< XRef
> xRef
; // getRef
101 Reference
< XBlob
> xBlob
; // getBlob
102 Reference
< XClob
> xClob
; // getClob
103 Reference
< XArray
> xArray
; // getArray
104 Any aObject
; // getObject
106 inline PropertyValue()
107 : nPropsSet( NO_VALUE_SET
), nOrigValue( NO_VALUE_SET
),
117 } // namespace ucbhelper_impl
119 using namespace ucbhelper_impl
;
126 // class PropertyValues.
130 typedef std::vector
< ucbhelper_impl::PropertyValue
> PropertyValuesVector
;
132 class PropertyValues
: public PropertyValuesVector
{};
134 } // namespace ucbhelper
138 // Welcome to the macro hell...
142 #define GETVALUE_IMPL_TYPE( _type_, _type_name_, _member_name_, _cppu_type_ ) \
144 osl::MutexGuard aGuard( m_aMutex ); \
146 _type_ aValue = _type_(); /* default ctor */ \
150 if ( ( columnIndex < 1 ) \
151 || ( columnIndex > sal_Int32( m_pValues->size() ) ) ) \
153 OSL_FAIL( "PropertyValueSet - index out of range!" ); \
157 ucbhelper_impl::PropertyValue& rValue \
158 = (*m_pValues)[ columnIndex - 1 ]; \
160 if ( rValue.nOrigValue != NO_VALUE_SET ) \
162 if ( rValue.nPropsSet & _type_name_ ) \
164 /* Values is present natively... */ \
165 aValue = rValue._member_name_; \
166 m_bWasNull = false; \
170 if ( !(rValue.nPropsSet & OBJECT_VALUE_SET) ) \
172 /* Value is not (yet) available as Any. Create it. */ \
173 getObject( columnIndex, Reference< XNameAccess >() ); \
176 if ( rValue.nPropsSet & OBJECT_VALUE_SET ) \
178 /* Value is available as Any. */ \
180 if ( rValue.aObject.hasValue() ) \
182 /* Try to convert into native value. */ \
183 if ( rValue.aObject >>= aValue ) \
185 rValue._member_name_ = aValue; \
186 rValue.nPropsSet |= _type_name_; \
187 m_bWasNull = false; \
191 /* Last chance. Try type converter service... */ \
193 Reference< XTypeConverter > xConverter \
194 = getTypeConverter(); \
195 if ( xConverter.is() ) \
199 Any aConvAny = xConverter->convertTo( \
203 if ( aConvAny >>= aValue ) \
205 rValue._member_name_ = aValue; \
206 rValue.nPropsSet |= _type_name_; \
207 m_bWasNull = false; \
210 catch (const IllegalArgumentException&) \
213 catch (const CannotConvertException&) \
225 #define GETVALUE_IMPL( _type_, _type_name_, _member_name_ ) \
226 GETVALUE_IMPL_TYPE( _type_, \
229 cppu::UnoType<_type_>::get() )
231 #define SETVALUE_IMPL( _prop_name_, _type_name_, _member_name_, _value_ ) \
233 osl::MutexGuard aGuard( m_aMutex ); \
235 ucbhelper_impl::PropertyValue aNewValue; \
236 aNewValue.sPropertyName = _prop_name_; \
237 aNewValue.nPropsSet = _type_name_; \
238 aNewValue.nOrigValue = _type_name_; \
239 aNewValue._member_name_ = _value_; \
241 m_pValues->push_back( aNewValue );
243 namespace ucbhelper
{
248 // PropertyValueSet Implementation.
254 PropertyValueSet::PropertyValueSet(
255 const Reference
< XComponentContext
>& rxContext
)
256 : m_xContext( rxContext
),
257 m_pValues( new PropertyValues
),
259 m_bTriedToGetTypeConverter( false )
266 PropertyValueSet::~PropertyValueSet()
273 // XInterface methods.
274 void SAL_CALL
PropertyValueSet::acquire()
277 OWeakObject::acquire();
280 void SAL_CALL
PropertyValueSet::release()
283 OWeakObject::release();
286 css::uno::Any SAL_CALL
PropertyValueSet::queryInterface( const css::uno::Type
& rType
)
287 throw( css::uno::RuntimeException
, std::exception
)
289 css::uno::Any aRet
= cppu::queryInterface( rType
,
290 (static_cast< XTypeProvider
* >(this)),
291 (static_cast< XRow
* >(this)),
292 (static_cast< XColumnLocate
* >(this))
294 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
297 // XTypeProvider methods.
301 XTYPEPROVIDER_IMPL_3( PropertyValueSet
,
313 sal_Bool SAL_CALL
PropertyValueSet::wasNull()
314 throw( SQLException
, RuntimeException
, std::exception
)
316 // This method can not be implemented correctly!!! Imagine different
317 // threads doing a getXYZ - wasNull calling sequence on the same
318 // implementation object...
324 OUString SAL_CALL
PropertyValueSet::getString( sal_Int32 columnIndex
)
325 throw( SQLException
, RuntimeException
, std::exception
)
327 GETVALUE_IMPL( OUString
, STRING_VALUE_SET
, aString
);
332 sal_Bool SAL_CALL
PropertyValueSet::getBoolean( sal_Int32 columnIndex
)
333 throw( SQLException
, RuntimeException
, std::exception
)
336 bool, BOOLEAN_VALUE_SET
, bBoolean
, cppu::UnoType
<bool>::get() );
341 sal_Int8 SAL_CALL
PropertyValueSet::getByte( sal_Int32 columnIndex
)
342 throw( SQLException
, RuntimeException
, std::exception
)
344 GETVALUE_IMPL( sal_Int8
, BYTE_VALUE_SET
, nByte
);
349 sal_Int16 SAL_CALL
PropertyValueSet::getShort( sal_Int32 columnIndex
)
350 throw( SQLException
, RuntimeException
, std::exception
)
352 GETVALUE_IMPL( sal_Int16
, SHORT_VALUE_SET
, nShort
);
357 sal_Int32 SAL_CALL
PropertyValueSet::getInt( sal_Int32 columnIndex
)
358 throw( SQLException
, RuntimeException
, std::exception
)
360 GETVALUE_IMPL( sal_Int32
, INT_VALUE_SET
, nInt
);
365 sal_Int64 SAL_CALL
PropertyValueSet::getLong( sal_Int32 columnIndex
)
366 throw( SQLException
, RuntimeException
, std::exception
)
368 GETVALUE_IMPL( sal_Int64
, LONG_VALUE_SET
, nLong
);
373 float SAL_CALL
PropertyValueSet::getFloat( sal_Int32 columnIndex
)
374 throw( SQLException
, RuntimeException
, std::exception
)
376 GETVALUE_IMPL( float, FLOAT_VALUE_SET
, nFloat
);
381 double SAL_CALL
PropertyValueSet::getDouble( sal_Int32 columnIndex
)
382 throw( SQLException
, RuntimeException
, std::exception
)
384 GETVALUE_IMPL( double, DOUBLE_VALUE_SET
, nDouble
);
389 Sequence
< sal_Int8
> SAL_CALL
390 PropertyValueSet::getBytes( sal_Int32 columnIndex
)
391 throw( SQLException
, RuntimeException
, std::exception
)
393 GETVALUE_IMPL( Sequence
< sal_Int8
>, BYTES_VALUE_SET
, aBytes
);
398 Date SAL_CALL
PropertyValueSet::getDate( sal_Int32 columnIndex
)
399 throw( SQLException
, RuntimeException
, std::exception
)
401 GETVALUE_IMPL( Date
, DATE_VALUE_SET
, aDate
);
406 Time SAL_CALL
PropertyValueSet::getTime( sal_Int32 columnIndex
)
407 throw( SQLException
, RuntimeException
, std::exception
)
409 GETVALUE_IMPL( Time
, TIME_VALUE_SET
, aTime
);
414 DateTime SAL_CALL
PropertyValueSet::getTimestamp( sal_Int32 columnIndex
)
415 throw( SQLException
, RuntimeException
, std::exception
)
417 GETVALUE_IMPL( DateTime
, TIMESTAMP_VALUE_SET
, aTimestamp
);
422 Reference
< XInputStream
> SAL_CALL
423 PropertyValueSet::getBinaryStream( sal_Int32 columnIndex
)
424 throw( SQLException
, RuntimeException
, std::exception
)
427 Reference
< XInputStream
>, BINARYSTREAM_VALUE_SET
, xBinaryStream
);
432 Reference
< XInputStream
> SAL_CALL
433 PropertyValueSet::getCharacterStream( sal_Int32 columnIndex
)
434 throw( SQLException
, RuntimeException
, std::exception
)
437 Reference
< XInputStream
>, CHARACTERSTREAM_VALUE_SET
, xCharacterStream
);
442 Any SAL_CALL
PropertyValueSet::getObject(
443 sal_Int32 columnIndex
,
444 const Reference
< XNameAccess
>& )
445 throw( SQLException
, RuntimeException
, std::exception
)
447 osl::MutexGuard
aGuard( m_aMutex
);
453 if ( ( columnIndex
< 1 )
454 || ( columnIndex
> sal_Int32( m_pValues
->size() ) ) )
456 OSL_FAIL( "PropertyValueSet - index out of range!" );
460 ucbhelper_impl::PropertyValue
& rValue
461 = (*m_pValues
)[ columnIndex
- 1 ];
463 if ( rValue
.nPropsSet
& OBJECT_VALUE_SET
)
465 // Values is present natively...
466 aValue
= rValue
.aObject
;
471 // Make Any from original value.
473 switch ( rValue
.nOrigValue
)
478 case STRING_VALUE_SET
:
479 aValue
<<= rValue
.aString
;
482 case BOOLEAN_VALUE_SET
:
483 aValue
<<= rValue
.bBoolean
;
487 aValue
<<= rValue
.nByte
;
490 case SHORT_VALUE_SET
:
491 aValue
<<= rValue
.nShort
;
495 aValue
<<= rValue
.nInt
;
499 aValue
<<= rValue
.nLong
;
502 case FLOAT_VALUE_SET
:
503 aValue
<<= rValue
.nFloat
;
506 case DOUBLE_VALUE_SET
:
507 aValue
<<= rValue
.nDouble
;
510 case BYTES_VALUE_SET
:
511 aValue
<<= rValue
.aBytes
;
515 aValue
<<= rValue
.aDate
;
519 aValue
<<= rValue
.aTime
;
522 case TIMESTAMP_VALUE_SET
:
523 aValue
<<= rValue
.aTimestamp
;
526 case BINARYSTREAM_VALUE_SET
:
527 aValue
<<= rValue
.xBinaryStream
;
530 case CHARACTERSTREAM_VALUE_SET
:
531 aValue
<<= rValue
.xCharacterStream
;
535 aValue
<<= rValue
.xRef
;
539 aValue
<<= rValue
.xBlob
;
543 aValue
<<= rValue
.xClob
;
546 case ARRAY_VALUE_SET
:
547 aValue
<<= rValue
.xArray
;
550 case OBJECT_VALUE_SET
:
551 // Fall-through is intended!
553 OSL_FAIL( "PropertyValueSet::getObject - "
554 "Wrong original type" );
558 if ( aValue
.hasValue() )
560 rValue
.aObject
= aValue
;
561 rValue
.nPropsSet
|= OBJECT_VALUE_SET
;
572 Reference
< XRef
> SAL_CALL
PropertyValueSet::getRef( sal_Int32 columnIndex
)
573 throw( SQLException
, RuntimeException
, std::exception
)
575 GETVALUE_IMPL( Reference
< XRef
>, REF_VALUE_SET
, xRef
);
580 Reference
< XBlob
> SAL_CALL
PropertyValueSet::getBlob( sal_Int32 columnIndex
)
581 throw( SQLException
, RuntimeException
, std::exception
)
583 GETVALUE_IMPL( Reference
< XBlob
>, BLOB_VALUE_SET
, xBlob
);
588 Reference
< XClob
> SAL_CALL
PropertyValueSet::getClob( sal_Int32 columnIndex
)
589 throw( SQLException
, RuntimeException
, std::exception
)
591 GETVALUE_IMPL( Reference
< XClob
>, CLOB_VALUE_SET
, xClob
);
596 Reference
< XArray
> SAL_CALL
PropertyValueSet::getArray( sal_Int32 columnIndex
)
597 throw( SQLException
, RuntimeException
, std::exception
)
599 GETVALUE_IMPL( Reference
< XArray
>, ARRAY_VALUE_SET
, xArray
);
604 // XColumnLocate methods.
609 sal_Int32 SAL_CALL
PropertyValueSet::findColumn( const OUString
& columnName
)
610 throw( SQLException
, RuntimeException
, std::exception
)
612 osl::MutexGuard
aGuard( m_aMutex
);
614 if ( !columnName
.isEmpty() )
616 sal_Int32 nCount
= m_pValues
->size();
617 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
619 if ( (*m_pValues
)[ n
].sPropertyName
.equals( columnName
) )
620 return sal_Int32( n
+ 1 ); // Index is 1-based.
628 // Non-interface methods.
632 const Reference
< XTypeConverter
>& PropertyValueSet::getTypeConverter()
634 osl::MutexGuard
aGuard( m_aMutex
);
636 if ( !m_bTriedToGetTypeConverter
&& !m_xTypeConverter
.is() )
638 m_bTriedToGetTypeConverter
= true;
639 m_xTypeConverter
= Converter::create(m_xContext
);
641 OSL_ENSURE( m_xTypeConverter
.is(),
642 "PropertyValueSet::getTypeConverter() - "
643 "Service 'com.sun.star.script.Converter' n/a!" );
645 return m_xTypeConverter
;
649 void PropertyValueSet::appendString( const OUString
& rPropName
,
650 const OUString
& rValue
)
652 SETVALUE_IMPL( rPropName
, STRING_VALUE_SET
, aString
, rValue
);
656 void PropertyValueSet::appendBoolean( const OUString
& rPropName
,
659 SETVALUE_IMPL( rPropName
, BOOLEAN_VALUE_SET
, bBoolean
, bValue
);
663 void PropertyValueSet::appendLong( const OUString
& rPropName
,
666 SETVALUE_IMPL( rPropName
, LONG_VALUE_SET
, nLong
, nValue
);
670 void PropertyValueSet::appendTimestamp( const OUString
& rPropName
,
671 const DateTime
& rValue
)
673 SETVALUE_IMPL( rPropName
, TIMESTAMP_VALUE_SET
, aTimestamp
, rValue
);
677 void PropertyValueSet::appendObject( const OUString
& rPropName
,
680 SETVALUE_IMPL( rPropName
, OBJECT_VALUE_SET
, aObject
, rValue
);
684 void PropertyValueSet::appendVoid( const OUString
& rPropName
)
686 SETVALUE_IMPL( rPropName
, NO_VALUE_SET
, aObject
, Any() );
690 void PropertyValueSet::appendPropertySet(
691 const Reference
< XPropertySet
>& rxSet
)
695 Reference
< XPropertySetInfo
> xInfo
= rxSet
->getPropertySetInfo();
698 Sequence
< Property
> aProps
= xInfo
->getProperties();
699 const Property
* pProps
= aProps
.getConstArray();
700 sal_Int32 nPropsCount
= aProps
.getLength();
702 Reference
< XPropertyAccess
> xPropertyAccess( rxSet
, UNO_QUERY
);
703 if ( xPropertyAccess
.is() )
705 // Efficient: Get all prop values with one ( remote) call.
707 Sequence
< ::com::sun::star::beans::PropertyValue
> aPropValues
708 = xPropertyAccess
->getPropertyValues();
710 const ::com::sun::star::beans::PropertyValue
* pPropValues
711 = aPropValues
.getConstArray();
713 sal_Int32 nValuesCount
= aPropValues
.getLength();
714 for ( sal_Int32 n
= 0; n
< nValuesCount
; ++n
)
716 const ::com::sun::star::beans::PropertyValue
& rPropValue
719 // Find info for current property value.
720 for ( sal_Int32 m
= 0; m
< nPropsCount
; ++m
)
722 const Property
& rProp
= pProps
[ m
];
723 if ( rProp
.Name
== rPropValue
.Name
)
726 appendObject( rProp
, rPropValue
.Value
);
734 // Get every single prop value with one ( remote) call.
736 for ( sal_Int32 n
= 0; n
< nPropsCount
; ++n
)
738 const Property
& rProp
= pProps
[ n
];
742 Any aValue
= rxSet
->getPropertyValue( rProp
.Name
);
744 if ( aValue
.hasValue() )
745 appendObject( rProp
, aValue
);
747 catch (const UnknownPropertyException
&)
750 catch (const WrappedTargetException
&)
760 bool PropertyValueSet::appendPropertySetValue(
761 const Reference
< XPropertySet
>& rxSet
,
762 const Property
& rProperty
)
768 Any aValue
= rxSet
->getPropertyValue( rProperty
.Name
);
769 if ( aValue
.hasValue() )
771 appendObject( rProperty
, aValue
);
775 catch (const UnknownPropertyException
&)
778 catch (const WrappedTargetException
&)
787 } // namespace ucbhelper
789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */