xref: /AOO41X/main/comphelper/source/property/propertystatecontainer.cxx (revision dde7d3faf6dcd9cbeb7b48ba6d0cea5ffcc883d0)
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     {
lcl_getUnknownPropertyErrorMessage(const::rtl::OUString & _rPropertyName)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     //---------------------------------------------------------------------
OPropertyStateContainer(::cppu::OBroadcastHelper & _rBHelper)58     OPropertyStateContainer::OPropertyStateContainer( ::cppu::OBroadcastHelper& _rBHelper )
59         :OPropertyContainer( _rBHelper )
60     {
61     }
62 
63     //--------------------------------------------------------------------
queryInterface(const Type & _rType)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     //--------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2(OPropertyStateContainer,OPropertyContainer,OPropertyStateContainer_TBase)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     //--------------------------------------------------------------------
getPropertyState(const::rtl::OUString & _rPropertyName)89     PropertyState SAL_CALL OPropertyStateContainer::getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
90     {
91         return getPropertyStateByHandle( getHandleForName( _rPropertyName ) );
92     }
93 
94     //--------------------------------------------------------------------
getPropertyStates(const Sequence<::rtl::OUString> & _rPropertyNames)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     //--------------------------------------------------------------------
setPropertyToDefault(const::rtl::OUString & _rPropertyName)148     void SAL_CALL OPropertyStateContainer::setPropertyToDefault( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
149     {
150         setPropertyToDefaultByHandle( getHandleForName( _rPropertyName ) );
151     }
152 
153     //--------------------------------------------------------------------
getPropertyDefault(const::rtl::OUString & _rPropertyName)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     //--------------------------------------------------------------------
getPropertyStateByHandle(sal_Int32 _nHandle)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     //--------------------------------------------------------------------
setPropertyToDefaultByHandle(sal_Int32 _nHandle)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     //---------------------------------------------------------------------
Test()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     //---------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(Test,Test_RefCountBase,OPropertyStateContainer)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     //---------------------------------------------------------------------
getPropertySetInfo()304     Reference< XPropertySetInfo > SAL_CALL Test::getPropertySetInfo(  ) throw(RuntimeException)
305     {
306         return createPropertySetInfo( getInfoHelper() );
307     }
308 
309     //---------------------------------------------------------------------
getInfoHelper()310     ::cppu::IPropertyArrayHelper& SAL_CALL Test::getInfoHelper()
311     {
312         return *getArrayHelper();
313     }
314 
315     //---------------------------------------------------------------------
createArrayHelper() const316     ::cppu::IPropertyArrayHelper* Test::createArrayHelper( ) const
317     {
318         Sequence< Property > aProps;
319         describeProperties( aProps );
320         return new ::cppu::OPropertyArrayHelper( aProps );
321     }
322 
323     //---------------------------------------------------------------------
Create()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