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_comphelper.hxx" 26 #include "comphelper/propertystatecontainer.hxx" 27 #include <rtl/ustrbuf.hxx> 28 29 //......................................................................... 30 namespace comphelper 31 { 32 //......................................................................... 33 34 using namespace ::com::sun::star::uno; 35 using namespace ::com::sun::star::beans; 36 using namespace ::com::sun::star::lang; 37 38 namespace 39 { 40 static ::rtl::OUString lcl_getUnknownPropertyErrorMessage( const ::rtl::OUString& _rPropertyName ) 41 { 42 // TODO: perhaps it's time to think about resources in the comphelper module? 43 // Would be nice to have localized exception strings (a simply resource file containing 44 // strings only would suffice, and could be realized with an UNO service, so we do not 45 // need the dependency to the Tools project) 46 ::rtl::OUStringBuffer sMessage; 47 sMessage.appendAscii( "The property \"" ); 48 sMessage.append( _rPropertyName ); 49 sMessage.appendAscii( "\" is unknown." ); 50 return sMessage.makeStringAndClear(); 51 } 52 } 53 54 //===================================================================== 55 //= OPropertyStateContainer 56 //===================================================================== 57 //--------------------------------------------------------------------- 58 OPropertyStateContainer::OPropertyStateContainer( ::cppu::OBroadcastHelper& _rBHelper ) 59 :OPropertyContainer( _rBHelper ) 60 { 61 } 62 63 //-------------------------------------------------------------------- 64 Any SAL_CALL OPropertyStateContainer::queryInterface( const Type& _rType ) throw (RuntimeException) 65 { 66 Any aReturn = OPropertyContainer::queryInterface( _rType ); 67 if ( !aReturn.hasValue() ) 68 aReturn = OPropertyStateContainer_TBase::queryInterface( _rType ); 69 return aReturn; 70 } 71 72 //-------------------------------------------------------------------- 73 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OPropertyStateContainer, OPropertyContainer, OPropertyStateContainer_TBase ) 74 75 //-------------------------------------------------------------------- 76 sal_Int32 OPropertyStateContainer::getHandleForName( const ::rtl::OUString& _rPropertyName ) SAL_THROW( ( UnknownPropertyException ) ) 77 { 78 // look up the handle for the name 79 ::cppu::IPropertyArrayHelper& rPH = getInfoHelper(); 80 sal_Int32 nHandle = rPH.getHandleByName( _rPropertyName ); 81 82 if ( -1 == nHandle ) 83 throw UnknownPropertyException( lcl_getUnknownPropertyErrorMessage( _rPropertyName ), static_cast< XPropertyState* >( this ) ); 84 85 return nHandle; 86 } 87 88 //-------------------------------------------------------------------- 89 PropertyState SAL_CALL OPropertyStateContainer::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException) 90 { 91 return getPropertyStateByHandle( getHandleForName( _rPropertyName ) ); 92 } 93 94 //-------------------------------------------------------------------- 95 Sequence< PropertyState > SAL_CALL OPropertyStateContainer::getPropertyStates( const Sequence< ::rtl::OUString >& _rPropertyNames ) throw (UnknownPropertyException, RuntimeException) 96 { 97 sal_Int32 nProperties = _rPropertyNames.getLength(); 98 Sequence< PropertyState> aStates( nProperties ); 99 if ( !nProperties ) 100 return aStates; 101 102 #ifdef _DEBUG 103 // precondition: property sequence is sorted (the algorythm below relies on this) 104 { 105 const ::rtl::OUString* pNames = _rPropertyNames.getConstArray(); 106 const ::rtl::OUString* pNamesCompare = pNames + 1; 107 const ::rtl::OUString* pNamesEnd = _rPropertyNames.getConstArray() + _rPropertyNames.getLength(); 108 for ( ; pNamesCompare != pNamesEnd; ++pNames, ++pNamesCompare ) 109 OSL_PRECOND( pNames->compareTo( *pNamesCompare ) < 0, 110 "OPropertyStateContainer::getPropertyStates: property sequence not sorted!" ); 111 } 112 #endif 113 114 const ::rtl::OUString* pLookup = _rPropertyNames.getConstArray(); 115 const ::rtl::OUString* pLookupEnd = pLookup + nProperties; 116 PropertyState* pStates = aStates.getArray(); 117 118 cppu::IPropertyArrayHelper& rHelper = getInfoHelper(); 119 Sequence< Property> aAllProperties = rHelper.getProperties(); 120 sal_Int32 nAllProperties = aAllProperties.getLength(); 121 const Property* pAllProperties = aAllProperties.getConstArray(); 122 const Property* pAllPropertiesEnd = pAllProperties + nAllProperties; 123 124 osl::MutexGuard aGuard( rBHelper.rMutex ); 125 for ( ; ( pAllProperties != pAllPropertiesEnd ) && ( pLookup != pLookupEnd ); ++pAllProperties ) 126 { 127 #ifdef _DEBUG 128 if ( pAllProperties < pAllPropertiesEnd - 1 ) 129 OSL_ENSURE( pAllProperties->Name.compareTo( (pAllProperties + 1)->Name ) < 0, 130 "OPropertyStateContainer::getPropertyStates: all-properties not sorted!" ); 131 #endif 132 if ( pAllProperties->Name.equals( *pLookup ) ) 133 { 134 *pStates++ = getPropertyState( *pLookup ); 135 ++pLookup; 136 } 137 } 138 139 if ( pLookup != pLookupEnd ) 140 // we run out of properties from the IPropertyArrayHelper, but still have properties to lookup 141 // -> we were asked for a nonexistent property 142 throw UnknownPropertyException( lcl_getUnknownPropertyErrorMessage( *pLookup ), static_cast< XPropertyState* >( this ) ); 143 144 return aStates; 145 } 146 147 //-------------------------------------------------------------------- 148 void SAL_CALL OPropertyStateContainer::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException) 149 { 150 setPropertyToDefaultByHandle( getHandleForName( _rPropertyName ) ); 151 } 152 153 //-------------------------------------------------------------------- 154 Any SAL_CALL OPropertyStateContainer::getPropertyDefault( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) 155 { 156 Any aDefault; 157 getPropertyDefaultByHandle( getHandleForName( _rPropertyName ), aDefault ); 158 return aDefault; 159 } 160 161 //-------------------------------------------------------------------- 162 PropertyState OPropertyStateContainer::getPropertyStateByHandle( sal_Int32 _nHandle ) 163 { 164 // simply compare the current and the default value 165 Any aCurrentValue; getFastPropertyValue( aCurrentValue, _nHandle ); 166 Any aDefaultValue; getPropertyDefaultByHandle( _nHandle, aDefaultValue ); 167 168 sal_Bool bEqual = uno_type_equalData( 169 const_cast< void* >( aCurrentValue.getValue() ), aCurrentValue.getValueType().getTypeLibType(), 170 const_cast< void* >( aDefaultValue.getValue() ), aDefaultValue.getValueType().getTypeLibType(), 171 reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), 172 reinterpret_cast< uno_ReleaseFunc >(cpp_release) 173 ); 174 if ( bEqual ) 175 return PropertyState_DEFAULT_VALUE; 176 else 177 return PropertyState_DIRECT_VALUE; 178 } 179 180 //-------------------------------------------------------------------- 181 void OPropertyStateContainer::setPropertyToDefaultByHandle( sal_Int32 _nHandle ) 182 { 183 Any aDefault; 184 getPropertyDefaultByHandle( _nHandle, aDefault ); 185 setFastPropertyValue( _nHandle, aDefault ); 186 } 187 188 //......................................................................... 189 } // namespace comphelper 190 //......................................................................... 191 192 #ifdef FS_PRIV_DEBUG 193 #define STATECONTAINER_TEST 194 #endif 195 196 #ifdef STATECONTAINER_TEST 197 #include <com/sun/star/beans/PropertyAttribute.hpp> 198 #include <comphelper/proparrhlp.hxx> 199 #include <comphelper/broadcasthelper.hxx> 200 201 //......................................................................... 202 namespace comphelper 203 { 204 //......................................................................... 205 206 using namespace ::com::sun::star::uno; 207 using namespace ::com::sun::star::beans; 208 209 //===================================================================== 210 //= Test - compiler test 211 //===================================================================== 212 typedef ::cppu::OWeakAggObject Test_RefCountBase; 213 class Test :public OMutexAndBroadcastHelper 214 ,public OPropertyStateContainer 215 ,public OPropertyArrayUsageHelper< Test > 216 ,public Test_RefCountBase 217 { 218 private: 219 ::rtl::OUString m_sStringProperty; 220 Reference< XInterface > m_xInterfaceProperty; 221 Any m_aMayBeVoidProperty; 222 223 protected: 224 Test( ); 225 226 DECLARE_XINTERFACE( ) 227 228 public: 229 static Test* Create( ); 230 231 protected: 232 virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(RuntimeException); 233 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); 234 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; 235 236 protected: 237 // OPropertyStateContainer overridables 238 virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const; 239 }; 240 241 //--------------------------------------------------------------------- 242 Test::Test( ) 243 :OPropertyStateContainer( GetBroadcastHelper() ) 244 { 245 registerProperty( 246 ::rtl::OUString::createFromAscii( "StringProperty" ), 247 1, 248 PropertyAttribute::BOUND, 249 &m_sStringProperty, 250 ::getCppuType( &m_sStringProperty ) 251 ); 252 253 registerProperty( 254 ::rtl::OUString::createFromAscii( "InterfaceProperty" ), 255 2, 256 PropertyAttribute::BOUND, 257 &m_xInterfaceProperty, 258 ::getCppuType( &m_xInterfaceProperty ) 259 ); 260 261 registerMayBeVoidProperty( 262 ::rtl::OUString::createFromAscii( "IntProperty" ), 263 3, 264 PropertyAttribute::BOUND, 265 &m_aMayBeVoidProperty, 266 ::getCppuType( static_cast< sal_Int32* >( NULL ) ) 267 ); 268 269 registerPropertyNoMember( 270 ::rtl::OUString::createFromAscii( "OtherInterfaceProperty" ), 271 4, 272 PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, 273 ::getCppuType( static_cast< Reference< XInterface >* >( NULL ) ), 274 NULL 275 ); 276 } 277 278 //--------------------------------------------------------------------- 279 IMPLEMENT_FORWARD_XINTERFACE2( Test, Test_RefCountBase, OPropertyStateContainer ) 280 281 //--------------------------------------------------------------------- 282 void Test::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const 283 { 284 switch ( _nHandle ) 285 { 286 case 1: 287 _rDefault = makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StringPropertyDefault" ) ) ); 288 break; 289 case 2: 290 _rDefault = makeAny( Reference< XInterface >( ) ); 291 break; 292 case 3: 293 // void 294 break; 295 case 4: 296 _rDefault = makeAny( Reference< XInterface >( ) ); 297 break; 298 default: 299 OSL_ENSURE( sal_False, "Test::getPropertyDefaultByHandle: invalid handle!" ); 300 } 301 } 302 303 //--------------------------------------------------------------------- 304 Reference< XPropertySetInfo > SAL_CALL Test::getPropertySetInfo( ) throw(RuntimeException) 305 { 306 return createPropertySetInfo( getInfoHelper() ); 307 } 308 309 //--------------------------------------------------------------------- 310 ::cppu::IPropertyArrayHelper& SAL_CALL Test::getInfoHelper() 311 { 312 return *getArrayHelper(); 313 } 314 315 //--------------------------------------------------------------------- 316 ::cppu::IPropertyArrayHelper* Test::createArrayHelper( ) const 317 { 318 Sequence< Property > aProps; 319 describeProperties( aProps ); 320 return new ::cppu::OPropertyArrayHelper( aProps ); 321 } 322 323 //--------------------------------------------------------------------- 324 Test* Test::Create( ) 325 { 326 Test* pInstance = new Test; 327 return pInstance; 328 } 329 330 //......................................................................... 331 } // namespace comphelper 332 //......................................................................... 333 334 #endif 335 336