1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_forms.hxx" 30 31 #include "propertysetbase.hxx" 32 33 #include <cppuhelper/typeprovider.hxx> // for getImplementationId() 34 35 #include <com/sun/star/beans/XPropertySet.hpp> 36 #include <com/sun/star/beans/XMultiPropertySet.hpp> 37 #include <com/sun/star/beans/XPropertyState.hpp> 38 #include <com/sun/star/uno/Reference.hxx> 39 #include <tools/debug.hxx> 40 41 #include <vector> 42 43 using com::sun::star::uno::Any; 44 using com::sun::star::uno::Type; 45 using com::sun::star::uno::Sequence; 46 using com::sun::star::uno::Reference; 47 using com::sun::star::uno::Exception; 48 using com::sun::star::uno::RuntimeException; 49 using com::sun::star::lang::IllegalArgumentException; 50 using com::sun::star::beans::Property; 51 using com::sun::star::beans::XPropertySetInfo; 52 53 oslInterlockedCount SAL_CALL PropertyAccessorBase::acquire() 54 { 55 return ++m_refCount; 56 } 57 58 oslInterlockedCount SAL_CALL PropertyAccessorBase::release() 59 { 60 if ( --m_refCount == 0 ) 61 { 62 delete this; 63 return 0; 64 } 65 return m_refCount; 66 } 67 68 PropertySetBase::PropertySetBase( ) 69 :m_pProperties( NULL ) 70 { 71 } 72 73 PropertySetBase::~PropertySetBase( ) 74 { 75 DELETEZ( m_pProperties ); 76 } 77 78 cppu::IPropertyArrayHelper& SAL_CALL PropertySetBase::getInfoHelper() 79 { 80 if ( !m_pProperties ) 81 { 82 DBG_ASSERT( !m_aProperties.empty(), "PropertySetBase::getInfoHelper: no registered properties!" ); 83 m_pProperties = new cppu::OPropertyArrayHelper( &m_aProperties[0], m_aProperties.size(), sal_False ); 84 } 85 return *m_pProperties; 86 } 87 88 Reference< XPropertySetInfo > SAL_CALL PropertySetBase::getPropertySetInfo( ) throw(RuntimeException) 89 { 90 return cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); 91 } 92 93 void PropertySetBase::registerProperty( const Property& rProperty, 94 const ::rtl::Reference< PropertyAccessorBase >& rAccessor ) 95 { 96 DBG_ASSERT( rAccessor.get(), "PropertySetBase::registerProperty: invalid property accessor, this will crash!" ); 97 m_aAccessors.insert( PropertyAccessors::value_type( rProperty.Handle, rAccessor ) ); 98 99 DBG_ASSERT( ( rAccessor->isWriteable() == true ) 100 == ( ( rProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY ) == 0 ), 101 "PropertySetBase::registerProperty: inconsistence!" ); 102 103 m_aProperties.push_back( rProperty ); 104 } 105 106 void PropertySetBase::notifyAndCachePropertyValue( sal_Int32 nHandle ) 107 { 108 ::osl::ClearableMutexGuard aGuard( GetMutex() ); 109 110 PropertyValueCache::iterator aPos = m_aCache.find( nHandle ); 111 if ( aPos == m_aCache.end() ) 112 { // method has never before been invoked for this property 113 try 114 { 115 // determine the type of this property 116 ::cppu::IPropertyArrayHelper& rPropertyMetaData = getInfoHelper(); 117 ::rtl::OUString sPropName; 118 OSL_VERIFY( rPropertyMetaData.fillPropertyMembersByHandle( &sPropName, NULL, nHandle ) ); 119 Property aProperty = rPropertyMetaData.getPropertyByName( sPropName ); 120 // default construct a value of this type 121 Any aEmptyValue( NULL, aProperty.Type ); 122 // insert into the cache 123 aPos = m_aCache.insert( PropertyValueCache::value_type( nHandle, aEmptyValue ) ).first; 124 } 125 catch( Exception& ) 126 { 127 DBG_ERROR( "PropertySetBase::notifyAndCachePropertyValue: this is not expected to fail!" ); 128 } 129 } 130 Any aOldValue = aPos->second; 131 // determine the current value 132 Any aNewValue; 133 getFastPropertyValue( aNewValue, nHandle ); 134 // remember the old value 135 aPos->second = aNewValue; 136 137 aGuard.clear(); 138 if ( aNewValue != aOldValue ) 139 firePropertyChange( nHandle, aNewValue, aOldValue ); 140 } 141 142 void PropertySetBase::initializePropertyValueCache( sal_Int32 nHandle ) 143 { 144 Any aCurrentValue; 145 getFastPropertyValue( aCurrentValue, nHandle ); 146 147 #if OSL_DEBUG_LEVEL > 0 148 ::std::pair< PropertyValueCache::iterator, bool > aInsertResult = 149 #endif 150 m_aCache.insert( PropertyValueCache::value_type( nHandle, aCurrentValue ) ); 151 DBG_ASSERT( aInsertResult.second, "PropertySetBase::initializePropertyValueCache: already cached a value for this property!" ); 152 } 153 154 PropertyAccessorBase& PropertySetBase::locatePropertyHandler( sal_Int32 nHandle ) const 155 { 156 PropertyAccessors::const_iterator aPropertyPos = m_aAccessors.find( nHandle ); 157 DBG_ASSERT( aPropertyPos != m_aAccessors.end() && aPropertyPos->second.get(), 158 "PropertySetBase::locatePropertyHandler: accessor map is corrupted!" ); 159 // neither should this be called for handles where there is no accessor, nor should a 160 // NULL accssor be in the map 161 return *aPropertyPos->second; 162 } 163 164 sal_Bool SAL_CALL PropertySetBase::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, 165 const Any& rValue ) 166 throw (IllegalArgumentException) 167 { 168 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 169 if ( !rAccessor.approveValue( rValue ) ) 170 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 171 172 rAccessor.getValue( rOldValue ); 173 if ( rOldValue != rValue ) 174 { 175 rConvertedValue = rValue; // no conversion at all 176 return sal_True; 177 } 178 return sal_False; 179 } 180 181 void SAL_CALL PropertySetBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) 182 throw (Exception) 183 { 184 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 185 rAccessor.setValue( rValue ); 186 } 187 188 void SAL_CALL PropertySetBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const 189 { 190 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 191 rAccessor.getValue( rValue ); 192 } 193