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
acquire()49 oslInterlockedCount SAL_CALL PropertyAccessorBase::acquire()
50 {
51 return ++m_refCount;
52 }
53
release()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
PropertySetBase()64 PropertySetBase::PropertySetBase( )
65 :m_pProperties( NULL )
66 {
67 }
68
~PropertySetBase()69 PropertySetBase::~PropertySetBase( )
70 {
71 DELETEZ( m_pProperties );
72 }
73
getInfoHelper()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
getPropertySetInfo()84 Reference< XPropertySetInfo > SAL_CALL PropertySetBase::getPropertySetInfo( ) throw(RuntimeException)
85 {
86 return cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
87 }
88
registerProperty(const Property & rProperty,const::rtl::Reference<PropertyAccessorBase> & rAccessor)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
notifyAndCachePropertyValue(sal_Int32 nHandle)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
initializePropertyValueCache(sal_Int32 nHandle)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
locatePropertyHandler(sal_Int32 nHandle) const150 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
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)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
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)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
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const184 void SAL_CALL PropertySetBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
185 {
186 PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle );
187 rAccessor.getValue( rValue );
188 }
189