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_forms.hxx" 26 27 #include "propertysetbase.hxx" 28 29 #include <cppuhelper/typeprovider.hxx> // for getImplementationId() 30 31 #include <com/sun/star/beans/XPropertySet.hpp> 32 #include <com/sun/star/beans/XMultiPropertySet.hpp> 33 #include <com/sun/star/beans/XPropertyState.hpp> 34 #include <com/sun/star/uno/Reference.hxx> 35 #include <tools/debug.hxx> 36 37 #include <vector> 38 39 using com::sun::star::uno::Any; 40 using com::sun::star::uno::Type; 41 using com::sun::star::uno::Sequence; 42 using com::sun::star::uno::Reference; 43 using com::sun::star::uno::Exception; 44 using com::sun::star::uno::RuntimeException; 45 using com::sun::star::lang::IllegalArgumentException; 46 using com::sun::star::beans::Property; 47 using com::sun::star::beans::XPropertySetInfo; 48 49 oslInterlockedCount SAL_CALL PropertyAccessorBase::acquire() 50 { 51 return ++m_refCount; 52 } 53 54 oslInterlockedCount SAL_CALL PropertyAccessorBase::release() 55 { 56 if ( --m_refCount == 0 ) 57 { 58 delete this; 59 return 0; 60 } 61 return m_refCount; 62 } 63 64 PropertySetBase::PropertySetBase( ) 65 :m_pProperties( NULL ) 66 { 67 } 68 69 PropertySetBase::~PropertySetBase( ) 70 { 71 DELETEZ( m_pProperties ); 72 } 73 74 cppu::IPropertyArrayHelper& SAL_CALL PropertySetBase::getInfoHelper() 75 { 76 if ( !m_pProperties ) 77 { 78 DBG_ASSERT( !m_aProperties.empty(), "PropertySetBase::getInfoHelper: no registered properties!" ); 79 m_pProperties = new cppu::OPropertyArrayHelper( &m_aProperties[0], m_aProperties.size(), sal_False ); 80 } 81 return *m_pProperties; 82 } 83 84 Reference< XPropertySetInfo > SAL_CALL PropertySetBase::getPropertySetInfo( ) throw(RuntimeException) 85 { 86 return cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); 87 } 88 89 void PropertySetBase::registerProperty( const Property& rProperty, 90 const ::rtl::Reference< PropertyAccessorBase >& rAccessor ) 91 { 92 DBG_ASSERT( rAccessor.get(), "PropertySetBase::registerProperty: invalid property accessor, this will crash!" ); 93 m_aAccessors.insert( PropertyAccessors::value_type( rProperty.Handle, rAccessor ) ); 94 95 DBG_ASSERT( ( rAccessor->isWriteable() == true ) 96 == ( ( rProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY ) == 0 ), 97 "PropertySetBase::registerProperty: inconsistence!" ); 98 99 m_aProperties.push_back( rProperty ); 100 } 101 102 void PropertySetBase::notifyAndCachePropertyValue( sal_Int32 nHandle ) 103 { 104 ::osl::ClearableMutexGuard aGuard( GetMutex() ); 105 106 PropertyValueCache::iterator aPos = m_aCache.find( nHandle ); 107 if ( aPos == m_aCache.end() ) 108 { // method has never before been invoked for this property 109 try 110 { 111 // determine the type of this property 112 ::cppu::IPropertyArrayHelper& rPropertyMetaData = getInfoHelper(); 113 ::rtl::OUString sPropName; 114 OSL_VERIFY( rPropertyMetaData.fillPropertyMembersByHandle( &sPropName, NULL, nHandle ) ); 115 Property aProperty = rPropertyMetaData.getPropertyByName( sPropName ); 116 // default construct a value of this type 117 Any aEmptyValue( NULL, aProperty.Type ); 118 // insert into the cache 119 aPos = m_aCache.insert( PropertyValueCache::value_type( nHandle, aEmptyValue ) ).first; 120 } 121 catch( Exception& ) 122 { 123 DBG_ERROR( "PropertySetBase::notifyAndCachePropertyValue: this is not expected to fail!" ); 124 } 125 } 126 Any aOldValue = aPos->second; 127 // determine the current value 128 Any aNewValue; 129 getFastPropertyValue( aNewValue, nHandle ); 130 // remember the old value 131 aPos->second = aNewValue; 132 133 aGuard.clear(); 134 if ( aNewValue != aOldValue ) 135 firePropertyChange( nHandle, aNewValue, aOldValue ); 136 } 137 138 void PropertySetBase::initializePropertyValueCache( sal_Int32 nHandle ) 139 { 140 Any aCurrentValue; 141 getFastPropertyValue( aCurrentValue, nHandle ); 142 143 #if OSL_DEBUG_LEVEL > 0 144 ::std::pair< PropertyValueCache::iterator, bool > aInsertResult = 145 #endif 146 m_aCache.insert( PropertyValueCache::value_type( nHandle, aCurrentValue ) ); 147 DBG_ASSERT( aInsertResult.second, "PropertySetBase::initializePropertyValueCache: already cached a value for this property!" ); 148 } 149 150 PropertyAccessorBase& PropertySetBase::locatePropertyHandler( sal_Int32 nHandle ) const 151 { 152 PropertyAccessors::const_iterator aPropertyPos = m_aAccessors.find( nHandle ); 153 DBG_ASSERT( aPropertyPos != m_aAccessors.end() && aPropertyPos->second.get(), 154 "PropertySetBase::locatePropertyHandler: accessor map is corrupted!" ); 155 // neither should this be called for handles where there is no accessor, nor should a 156 // NULL accssor be in the map 157 return *aPropertyPos->second; 158 } 159 160 sal_Bool SAL_CALL PropertySetBase::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, 161 const Any& rValue ) 162 throw (IllegalArgumentException) 163 { 164 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 165 if ( !rAccessor.approveValue( rValue ) ) 166 throw IllegalArgumentException( ::rtl::OUString(), *this, 0 ); 167 168 rAccessor.getValue( rOldValue ); 169 if ( rOldValue != rValue ) 170 { 171 rConvertedValue = rValue; // no conversion at all 172 return sal_True; 173 } 174 return sal_False; 175 } 176 177 void SAL_CALL PropertySetBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) 178 throw (Exception) 179 { 180 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 181 rAccessor.setValue( rValue ); 182 } 183 184 void SAL_CALL PropertySetBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const 185 { 186 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle ); 187 rAccessor.getValue( rValue ); 188 } 189