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