Branch libreoffice-5-0-4
[LibreOffice.git] / ucbhelper / source / provider / propertyvalueset.cxx
blob1732e70855642648cddfe039868143ae07302b9a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 /**************************************************************************
22 TODO
23 **************************************************************************
25 *************************************************************************/
27 #include <vector>
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
52 // PropertyValue.
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;
77 struct PropertyValue
79 OUString
80 sPropertyName;
82 sal_uInt32 nPropsSet;
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 ),
108 bBoolean(false),
109 nByte(0),
110 nShort(0),
111 nInt(0),
112 nLong(0),
113 nFloat(0.0),
114 nDouble(0.0)
117 } // namespace ucbhelper_impl
119 using namespace ucbhelper_impl;
121 namespace ucbhelper
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 */ \
148 m_bWasNull = true; \
150 if ( ( columnIndex < 1 ) \
151 || ( columnIndex > sal_Int32( m_pValues->size() ) ) ) \
153 OSL_FAIL( "PropertyValueSet - index out of range!" ); \
155 else \
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; \
168 else \
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; \
189 else \
191 /* Last chance. Try type converter service... */ \
193 Reference< XTypeConverter > xConverter \
194 = getTypeConverter(); \
195 if ( xConverter.is() ) \
197 try \
199 Any aConvAny = xConverter->convertTo( \
200 rValue.aObject, \
201 _cppu_type_ ); \
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&) \
223 return aValue;
225 #define GETVALUE_IMPL( _type_, _type_name_, _member_name_ ) \
226 GETVALUE_IMPL_TYPE( _type_, \
227 _type_name_, \
228 _member_name_, \
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 ),
258 m_bWasNull( false ),
259 m_bTriedToGetTypeConverter( false )
265 // virtual
266 PropertyValueSet::~PropertyValueSet()
268 delete m_pValues;
273 // XInterface methods.
274 void SAL_CALL PropertyValueSet::acquire()
275 throw()
277 OWeakObject::acquire();
280 void SAL_CALL PropertyValueSet::release()
281 throw()
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,
302 XTypeProvider,
303 XRow,
304 XColumnLocate );
308 // XRow methods.
312 // virtual
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...
319 return m_bWasNull;
323 // virtual
324 OUString SAL_CALL PropertyValueSet::getString( sal_Int32 columnIndex )
325 throw( SQLException, RuntimeException, std::exception )
327 GETVALUE_IMPL( OUString, STRING_VALUE_SET, aString );
331 // virtual
332 sal_Bool SAL_CALL PropertyValueSet::getBoolean( sal_Int32 columnIndex )
333 throw( SQLException, RuntimeException, std::exception )
335 GETVALUE_IMPL_TYPE(
336 bool, BOOLEAN_VALUE_SET, bBoolean, cppu::UnoType<bool>::get() );
340 // virtual
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 );
348 // virtual
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 );
356 // virtual
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 );
364 // virtual
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 );
372 // virtual
373 float SAL_CALL PropertyValueSet::getFloat( sal_Int32 columnIndex )
374 throw( SQLException, RuntimeException, std::exception )
376 GETVALUE_IMPL( float, FLOAT_VALUE_SET, nFloat );
380 // virtual
381 double SAL_CALL PropertyValueSet::getDouble( sal_Int32 columnIndex )
382 throw( SQLException, RuntimeException, std::exception )
384 GETVALUE_IMPL( double, DOUBLE_VALUE_SET, nDouble );
388 // virtual
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 );
397 // virtual
398 Date SAL_CALL PropertyValueSet::getDate( sal_Int32 columnIndex )
399 throw( SQLException, RuntimeException, std::exception )
401 GETVALUE_IMPL( Date, DATE_VALUE_SET, aDate );
405 // virtual
406 Time SAL_CALL PropertyValueSet::getTime( sal_Int32 columnIndex )
407 throw( SQLException, RuntimeException, std::exception )
409 GETVALUE_IMPL( Time, TIME_VALUE_SET, aTime );
413 // virtual
414 DateTime SAL_CALL PropertyValueSet::getTimestamp( sal_Int32 columnIndex )
415 throw( SQLException, RuntimeException, std::exception )
417 GETVALUE_IMPL( DateTime, TIMESTAMP_VALUE_SET, aTimestamp );
421 // virtual
422 Reference< XInputStream > SAL_CALL
423 PropertyValueSet::getBinaryStream( sal_Int32 columnIndex )
424 throw( SQLException, RuntimeException, std::exception )
426 GETVALUE_IMPL(
427 Reference< XInputStream >, BINARYSTREAM_VALUE_SET, xBinaryStream );
431 // virtual
432 Reference< XInputStream > SAL_CALL
433 PropertyValueSet::getCharacterStream( sal_Int32 columnIndex )
434 throw( SQLException, RuntimeException, std::exception )
436 GETVALUE_IMPL(
437 Reference< XInputStream >, CHARACTERSTREAM_VALUE_SET, xCharacterStream );
441 // virtual
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 );
449 Any aValue;
451 m_bWasNull = true;
453 if ( ( columnIndex < 1 )
454 || ( columnIndex > sal_Int32( m_pValues->size() ) ) )
456 OSL_FAIL( "PropertyValueSet - index out of range!" );
458 else
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;
467 m_bWasNull = false;
469 else
471 // Make Any from original value.
473 switch ( rValue.nOrigValue )
475 case NO_VALUE_SET:
476 break;
478 case STRING_VALUE_SET:
479 aValue <<= rValue.aString;
480 break;
482 case BOOLEAN_VALUE_SET:
483 aValue <<= rValue.bBoolean;
484 break;
486 case BYTE_VALUE_SET:
487 aValue <<= rValue.nByte;
488 break;
490 case SHORT_VALUE_SET:
491 aValue <<= rValue.nShort;
492 break;
494 case INT_VALUE_SET:
495 aValue <<= rValue.nInt;
496 break;
498 case LONG_VALUE_SET:
499 aValue <<= rValue.nLong;
500 break;
502 case FLOAT_VALUE_SET:
503 aValue <<= rValue.nFloat;
504 break;
506 case DOUBLE_VALUE_SET:
507 aValue <<= rValue.nDouble;
508 break;
510 case BYTES_VALUE_SET:
511 aValue <<= rValue.aBytes;
512 break;
514 case DATE_VALUE_SET:
515 aValue <<= rValue.aDate;
516 break;
518 case TIME_VALUE_SET:
519 aValue <<= rValue.aTime;
520 break;
522 case TIMESTAMP_VALUE_SET:
523 aValue <<= rValue.aTimestamp;
524 break;
526 case BINARYSTREAM_VALUE_SET:
527 aValue <<= rValue.xBinaryStream;
528 break;
530 case CHARACTERSTREAM_VALUE_SET:
531 aValue <<= rValue.xCharacterStream;
532 break;
534 case REF_VALUE_SET:
535 aValue <<= rValue.xRef;
536 break;
538 case BLOB_VALUE_SET:
539 aValue <<= rValue.xBlob;
540 break;
542 case CLOB_VALUE_SET:
543 aValue <<= rValue.xClob;
544 break;
546 case ARRAY_VALUE_SET:
547 aValue <<= rValue.xArray;
548 break;
550 case OBJECT_VALUE_SET:
551 // Fall-through is intended!
552 default:
553 OSL_FAIL( "PropertyValueSet::getObject - "
554 "Wrong original type" );
555 break;
558 if ( aValue.hasValue() )
560 rValue.aObject = aValue;
561 rValue.nPropsSet |= OBJECT_VALUE_SET;
562 m_bWasNull = false;
567 return aValue;
571 // virtual
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 );
579 // virtual
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 );
587 // virtual
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 );
595 // virtual
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.
608 // virtual
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.
623 return 0;
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,
657 bool bValue )
659 SETVALUE_IMPL( rPropName, BOOLEAN_VALUE_SET, bBoolean, bValue );
663 void PropertyValueSet::appendLong( const OUString& rPropName,
664 sal_Int64 nValue )
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,
678 const Any& rValue )
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 )
693 if ( rxSet.is() )
695 Reference< XPropertySetInfo > xInfo = rxSet->getPropertySetInfo();
696 if ( xInfo.is() )
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
717 = pPropValues[ n ];
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 )
725 // Found!
726 appendObject( rProp, rPropValue.Value );
727 break;
732 else
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 )
764 if ( rxSet.is() )
768 Any aValue = rxSet->getPropertyValue( rProperty.Name );
769 if ( aValue.hasValue() )
771 appendObject( rProperty, aValue );
772 return true;
775 catch (const UnknownPropertyException&)
778 catch (const WrappedTargetException&)
783 // Error.
784 return false;
787 } // namespace ucbhelper
789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */