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