1*dde7d3faSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*dde7d3faSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*dde7d3faSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*dde7d3faSAndrew Rist  * distributed with this work for additional information
6*dde7d3faSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*dde7d3faSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*dde7d3faSAndrew Rist  * "License"); you may not use this file except in compliance
9*dde7d3faSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*dde7d3faSAndrew Rist  *
11*dde7d3faSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*dde7d3faSAndrew Rist  *
13*dde7d3faSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*dde7d3faSAndrew Rist  * software distributed under the License is distributed on an
15*dde7d3faSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*dde7d3faSAndrew Rist  * KIND, either express or implied.  See the License for the
17*dde7d3faSAndrew Rist  * specific language governing permissions and limitations
18*dde7d3faSAndrew Rist  * under the License.
19*dde7d3faSAndrew Rist  *
20*dde7d3faSAndrew Rist  *************************************************************/
21*dde7d3faSAndrew Rist 
22*dde7d3faSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_comphelper.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "opropertybag.hxx"
28cdf0e10cSrcweir #include "comphelper_module.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp>
31cdf0e10cSrcweir #include <com/sun/star/beans/NamedValue.hpp>
32cdf0e10cSrcweir #include <com/sun/star/beans/Property.hpp>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <comphelper/namedvaluecollection.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
37cdf0e10cSrcweir #include <osl/thread.h>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <algorithm>
40cdf0e10cSrcweir #include <functional>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir 
43cdf0e10cSrcweir //--------------------------------------------------------------------------
44cdf0e10cSrcweir using namespace ::com::sun::star;
45cdf0e10cSrcweir 
createRegistryInfo_OPropertyBag()46cdf0e10cSrcweir void createRegistryInfo_OPropertyBag()
47cdf0e10cSrcweir {
48cdf0e10cSrcweir     static ::comphelper::module::OAutoRegistration< ::comphelper::OPropertyBag > aAutoRegistration;
49cdf0e10cSrcweir }
50cdf0e10cSrcweir 
51cdf0e10cSrcweir //........................................................................
52cdf0e10cSrcweir namespace comphelper
53cdf0e10cSrcweir {
54cdf0e10cSrcweir //........................................................................
55cdf0e10cSrcweir 
56cdf0e10cSrcweir     using namespace ::com::sun::star::uno;
57cdf0e10cSrcweir     using namespace ::com::sun::star::lang;
58cdf0e10cSrcweir     using namespace ::com::sun::star::beans;
59cdf0e10cSrcweir     using namespace ::com::sun::star::util;
60cdf0e10cSrcweir     using namespace ::com::sun::star::container;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir 	//====================================================================
63cdf0e10cSrcweir 	//= OPropertyBag
64cdf0e10cSrcweir 	//====================================================================
65cdf0e10cSrcweir     //--------------------------------------------------------------------
OPropertyBag(const Reference<XComponentContext> & _rxContext)66cdf0e10cSrcweir     OPropertyBag::OPropertyBag( const Reference< XComponentContext >& _rxContext )
67cdf0e10cSrcweir         :OPropertyBag_PBase( GetBroadcastHelper(), this )
68cdf0e10cSrcweir         ,::cppu::IEventNotificationHook()
69cdf0e10cSrcweir         ,m_aContext( _rxContext )
70cdf0e10cSrcweir         ,m_bAutoAddProperties( false )
71cdf0e10cSrcweir         ,m_NotifyListeners(m_aMutex)
72cdf0e10cSrcweir         ,m_isModified(false)
73cdf0e10cSrcweir 
74cdf0e10cSrcweir     {
75cdf0e10cSrcweir     }
76cdf0e10cSrcweir 
77cdf0e10cSrcweir     //--------------------------------------------------------------------
~OPropertyBag()78cdf0e10cSrcweir     OPropertyBag::~OPropertyBag()
79cdf0e10cSrcweir     {
80cdf0e10cSrcweir     }
81cdf0e10cSrcweir 
82cdf0e10cSrcweir     //--------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2(OPropertyBag,OPropertyBag_Base,OPropertyBag_PBase)83cdf0e10cSrcweir     IMPLEMENT_FORWARD_XINTERFACE2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase )
84cdf0e10cSrcweir     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase )
85cdf0e10cSrcweir 
86cdf0e10cSrcweir     //--------------------------------------------------------------------
87cdf0e10cSrcweir 	Sequence< ::rtl::OUString > OPropertyBag::getSupportedServiceNames_static() throw( RuntimeException )
88cdf0e10cSrcweir     {
89cdf0e10cSrcweir         Sequence< ::rtl::OUString > aServices(1);
90cdf0e10cSrcweir         aServices[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) );
91cdf0e10cSrcweir         return aServices;
92cdf0e10cSrcweir     }
93cdf0e10cSrcweir 
94cdf0e10cSrcweir     //--------------------------------------------------------------------
initialize(const Sequence<Any> & _rArguments)95cdf0e10cSrcweir     void SAL_CALL OPropertyBag::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
96cdf0e10cSrcweir     {
97cdf0e10cSrcweir         ::comphelper::NamedValueCollection aArguments( _rArguments );
98cdf0e10cSrcweir 
99cdf0e10cSrcweir         Sequence< Type > aTypes;
100cdf0e10cSrcweir         if ( aArguments.get_ensureType( "AllowedTypes", aTypes ) )
101cdf0e10cSrcweir             ::std::copy(
102cdf0e10cSrcweir                 aTypes.getConstArray(),
103cdf0e10cSrcweir                 aTypes.getConstArray() + aTypes.getLength(),
104cdf0e10cSrcweir                 ::std::insert_iterator< TypeBag >( m_aAllowedTypes, m_aAllowedTypes.begin() )
105cdf0e10cSrcweir             );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir         aArguments.get_ensureType( "AutomaticAddition", m_bAutoAddProperties );
108cdf0e10cSrcweir         bool AllowEmptyPropertyName(false);
109cdf0e10cSrcweir         aArguments.get_ensureType( "AllowEmptyPropertyName",
110cdf0e10cSrcweir             AllowEmptyPropertyName );
111cdf0e10cSrcweir         if (AllowEmptyPropertyName) {
112cdf0e10cSrcweir             m_aDynamicProperties.setAllowEmptyPropertyName(
113cdf0e10cSrcweir                 AllowEmptyPropertyName);
114cdf0e10cSrcweir         }
115cdf0e10cSrcweir     }
116cdf0e10cSrcweir 
117cdf0e10cSrcweir     //--------------------------------------------------------------------
getImplementationName_static()118cdf0e10cSrcweir 	::rtl::OUString OPropertyBag::getImplementationName_static() throw( RuntimeException )
119cdf0e10cSrcweir     {
120cdf0e10cSrcweir         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.comphelper.OPropertyBag" ) );
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     //--------------------------------------------------------------------
Create(const Reference<XComponentContext> & _rxContext)124cdf0e10cSrcweir 	Reference< XInterface > SAL_CALL OPropertyBag::Create( const Reference< XComponentContext >& _rxContext )
125cdf0e10cSrcweir     {
126cdf0e10cSrcweir         return *new OPropertyBag( _rxContext );
127cdf0e10cSrcweir     }
128cdf0e10cSrcweir 
129cdf0e10cSrcweir     //--------------------------------------------------------------------
getImplementationName()130cdf0e10cSrcweir     ::rtl::OUString SAL_CALL OPropertyBag::getImplementationName() throw (RuntimeException)
131cdf0e10cSrcweir     {
132cdf0e10cSrcweir         return getImplementationName_static();
133cdf0e10cSrcweir     }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     //--------------------------------------------------------------------
supportsService(const::rtl::OUString & rServiceName)136cdf0e10cSrcweir     ::sal_Bool SAL_CALL OPropertyBag::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
137cdf0e10cSrcweir     {
138cdf0e10cSrcweir         Sequence< ::rtl::OUString > aServices( getSupportedServiceNames_static() );
139cdf0e10cSrcweir         const ::rtl::OUString* pStart = aServices.getConstArray();
140cdf0e10cSrcweir         const ::rtl::OUString* pEnd = aServices.getConstArray() + aServices.getLength();
141cdf0e10cSrcweir         return ::std::find( pStart, pEnd, rServiceName ) != pEnd;
142cdf0e10cSrcweir     }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     //--------------------------------------------------------------------
getSupportedServiceNames()145cdf0e10cSrcweir     Sequence< ::rtl::OUString > SAL_CALL OPropertyBag::getSupportedServiceNames(  ) throw (RuntimeException)
146cdf0e10cSrcweir     {
147cdf0e10cSrcweir         return getSupportedServiceNames_static();
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     //--------------------------------------------------------------------
fireEvents(sal_Int32 *,sal_Int32 nCount,sal_Bool bVetoable,bool bIgnoreRuntimeExceptionsWhileFiring)151cdf0e10cSrcweir     void OPropertyBag::fireEvents(
152cdf0e10cSrcweir             sal_Int32 * /*pnHandles*/,
153cdf0e10cSrcweir             sal_Int32 nCount,
154cdf0e10cSrcweir             sal_Bool bVetoable,
155cdf0e10cSrcweir             bool bIgnoreRuntimeExceptionsWhileFiring)
156cdf0e10cSrcweir     {
157cdf0e10cSrcweir         if (nCount && !bVetoable) {
158cdf0e10cSrcweir             setModifiedImpl(sal_True, bIgnoreRuntimeExceptionsWhileFiring);
159cdf0e10cSrcweir         }
160cdf0e10cSrcweir     }
161cdf0e10cSrcweir 
setModifiedImpl(::sal_Bool bModified,bool bIgnoreRuntimeExceptionsWhileFiring)162cdf0e10cSrcweir     void OPropertyBag::setModifiedImpl(::sal_Bool bModified,
163cdf0e10cSrcweir             bool bIgnoreRuntimeExceptionsWhileFiring)
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir         { // do not lock mutex while notifying (#i93514#) to prevent deadlock
166cdf0e10cSrcweir             ::osl::MutexGuard aGuard( m_aMutex );
167cdf0e10cSrcweir             m_isModified = bModified;
168cdf0e10cSrcweir         }
169cdf0e10cSrcweir         if (bModified) {
170cdf0e10cSrcweir             try {
171cdf0e10cSrcweir                 Reference<XInterface> xThis(*this);
172cdf0e10cSrcweir                 EventObject event(xThis);
173cdf0e10cSrcweir                 m_NotifyListeners.notifyEach(
174cdf0e10cSrcweir                     &XModifyListener::modified, event);
175cdf0e10cSrcweir             } catch (RuntimeException &) {
176cdf0e10cSrcweir                 if (!bIgnoreRuntimeExceptionsWhileFiring) {
177cdf0e10cSrcweir                     throw;
178cdf0e10cSrcweir                 }
179cdf0e10cSrcweir             } catch (Exception &) {
180cdf0e10cSrcweir                 // ignore
181cdf0e10cSrcweir             }
182cdf0e10cSrcweir         }
183cdf0e10cSrcweir     }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir     //--------------------------------------------------------------------
isModified()186cdf0e10cSrcweir     ::sal_Bool SAL_CALL OPropertyBag::isModified()
187cdf0e10cSrcweir         throw (RuntimeException)
188cdf0e10cSrcweir     {
189cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_aMutex );
190cdf0e10cSrcweir         return m_isModified;
191cdf0e10cSrcweir     }
192cdf0e10cSrcweir 
setModified(::sal_Bool bModified)193cdf0e10cSrcweir     void SAL_CALL OPropertyBag::setModified( ::sal_Bool bModified )
194cdf0e10cSrcweir         throw (PropertyVetoException, RuntimeException)
195cdf0e10cSrcweir     {
196cdf0e10cSrcweir         setModifiedImpl(bModified, false);
197cdf0e10cSrcweir     }
198cdf0e10cSrcweir 
addModifyListener(const Reference<XModifyListener> & xListener)199cdf0e10cSrcweir     void SAL_CALL OPropertyBag::addModifyListener(
200cdf0e10cSrcweir         const Reference< XModifyListener > & xListener)
201cdf0e10cSrcweir         throw (RuntimeException)
202cdf0e10cSrcweir     {
203cdf0e10cSrcweir         m_NotifyListeners.addInterface(xListener);
204cdf0e10cSrcweir     }
205cdf0e10cSrcweir 
removeModifyListener(const Reference<XModifyListener> & xListener)206cdf0e10cSrcweir     void SAL_CALL OPropertyBag::removeModifyListener(
207cdf0e10cSrcweir         const Reference< XModifyListener > & xListener)
208cdf0e10cSrcweir         throw (RuntimeException)
209cdf0e10cSrcweir     {
210cdf0e10cSrcweir         m_NotifyListeners.removeInterface(xListener);
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertySetInfo()214cdf0e10cSrcweir     Reference< XPropertySetInfo > SAL_CALL OPropertyBag::getPropertySetInfo(  ) throw(RuntimeException)
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         return createPropertySetInfo( getInfoHelper() );
217cdf0e10cSrcweir     }
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     //--------------------------------------------------------------------
has(const Any &)220cdf0e10cSrcweir     ::sal_Bool SAL_CALL OPropertyBag::has( const Any& /*aElement*/ ) throw (RuntimeException)
221cdf0e10cSrcweir     {
222cdf0e10cSrcweir         // XSet is only a workaround for addProperty not being able to add default-void properties.
223cdf0e10cSrcweir         // So, everything of XSet except insert is implemented empty
224cdf0e10cSrcweir         return sal_False;
225cdf0e10cSrcweir     }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     //--------------------------------------------------------------------
insert(const Any & _element)228cdf0e10cSrcweir     void SAL_CALL OPropertyBag::insert( const Any& _element ) throw (IllegalArgumentException, ElementExistException, RuntimeException)
229cdf0e10cSrcweir     {
230cdf0e10cSrcweir         // This is a workaround for addProperty not being able to add default-void properties.
231cdf0e10cSrcweir         // If we ever have a smarter XPropertyContainer::addProperty interface, we can remove this, ehm, well, hack.
232cdf0e10cSrcweir         Property aProperty;
233cdf0e10cSrcweir         if ( !( _element >>= aProperty ) )
234cdf0e10cSrcweir             throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
235cdf0e10cSrcweir 
236cdf0e10cSrcweir         ::osl::ClearableMutexGuard g( m_aMutex );
237cdf0e10cSrcweir 
238cdf0e10cSrcweir         // check whether the type is allowed, everything else will be checked
239cdf0e10cSrcweir         // by m_aDynamicProperties
240cdf0e10cSrcweir         if  (   !m_aAllowedTypes.empty()
241cdf0e10cSrcweir             &&  m_aAllowedTypes.find( aProperty.Type ) == m_aAllowedTypes.end()
242cdf0e10cSrcweir             )
243cdf0e10cSrcweir             throw IllegalTypeException( ::rtl::OUString(), *this );
244cdf0e10cSrcweir 
245cdf0e10cSrcweir         m_aDynamicProperties.addVoidProperty( aProperty.Name, aProperty.Type, findFreeHandle(), aProperty.Attributes );
246cdf0e10cSrcweir 
247cdf0e10cSrcweir         // our property info is dirty
248cdf0e10cSrcweir         m_pArrayHelper.reset();
249cdf0e10cSrcweir 
250cdf0e10cSrcweir         g.clear();
251cdf0e10cSrcweir         setModified(sal_True);
252cdf0e10cSrcweir     }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir     //--------------------------------------------------------------------
remove(const Any &)255cdf0e10cSrcweir     void SAL_CALL OPropertyBag::remove( const Any& /*aElement*/ ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
256cdf0e10cSrcweir     {
257cdf0e10cSrcweir         // XSet is only a workaround for addProperty not being able to add default-void properties.
258cdf0e10cSrcweir         // So, everything of XSet except insert is implemented empty
259cdf0e10cSrcweir         throw NoSuchElementException( ::rtl::OUString(), *this );
260cdf0e10cSrcweir     }
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 
263cdf0e10cSrcweir     //--------------------------------------------------------------------
createEnumeration()264cdf0e10cSrcweir     Reference< XEnumeration > SAL_CALL OPropertyBag::createEnumeration(  ) throw (RuntimeException)
265cdf0e10cSrcweir     {
266cdf0e10cSrcweir         // XSet is only a workaround for addProperty not being able to add default-void properties.
267cdf0e10cSrcweir         // So, everything of XSet except insert is implemented empty
268cdf0e10cSrcweir         return NULL;
269cdf0e10cSrcweir     }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     //--------------------------------------------------------------------
getElementType()272cdf0e10cSrcweir     Type SAL_CALL OPropertyBag::getElementType(  ) throw (RuntimeException)
273cdf0e10cSrcweir     {
274cdf0e10cSrcweir         // XSet is only a workaround for addProperty not being able to add default-void properties.
275cdf0e10cSrcweir         // So, everything of XSet except insert is implemented empty
276cdf0e10cSrcweir         return Type();
277cdf0e10cSrcweir     }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     //--------------------------------------------------------------------
hasElements()280cdf0e10cSrcweir     ::sal_Bool SAL_CALL OPropertyBag::hasElements(  ) throw (RuntimeException)
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         // XSet is only a workaround for addProperty not being able to add default-void properties.
283cdf0e10cSrcweir         // So, everything of XSet except insert is implemented empty
284cdf0e10cSrcweir         return sal_False;
285cdf0e10cSrcweir     }
286cdf0e10cSrcweir 
287cdf0e10cSrcweir     //--------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const288cdf0e10cSrcweir     void SAL_CALL OPropertyBag::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         m_aDynamicProperties.getFastPropertyValue( _nHandle, _rValue );
291cdf0e10cSrcweir     }
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     //--------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)294cdf0e10cSrcweir 	sal_Bool SAL_CALL OPropertyBag::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException)
295cdf0e10cSrcweir     {
296cdf0e10cSrcweir         return m_aDynamicProperties.convertFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
297cdf0e10cSrcweir     }
298cdf0e10cSrcweir 
299cdf0e10cSrcweir     //--------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)300cdf0e10cSrcweir     void SAL_CALL OPropertyBag::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
301cdf0e10cSrcweir     {
302cdf0e10cSrcweir         m_aDynamicProperties.setFastPropertyValue( nHandle, rValue );
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     //--------------------------------------------------------------------
getInfoHelper()306cdf0e10cSrcweir     ::cppu::IPropertyArrayHelper& SAL_CALL OPropertyBag::getInfoHelper()
307cdf0e10cSrcweir     {
308cdf0e10cSrcweir         if ( !m_pArrayHelper.get() )
309cdf0e10cSrcweir         {
310cdf0e10cSrcweir             Sequence< Property > aProperties;
311cdf0e10cSrcweir             m_aDynamicProperties.describeProperties( aProperties );
312cdf0e10cSrcweir             m_pArrayHelper.reset( new ::cppu::OPropertyArrayHelper( aProperties ) );
313cdf0e10cSrcweir         }
314cdf0e10cSrcweir         return *m_pArrayHelper;
315cdf0e10cSrcweir 
316cdf0e10cSrcweir     }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     //--------------------------------------------------------------------
findFreeHandle() const319cdf0e10cSrcweir     sal_Int32 OPropertyBag::findFreeHandle() const
320cdf0e10cSrcweir     {
321cdf0e10cSrcweir         const sal_Int32 nPrime = 1009;
322cdf0e10cSrcweir         const sal_Int32 nSeed = 11;
323cdf0e10cSrcweir 
324cdf0e10cSrcweir         sal_Int32 nCheck = nSeed;
325cdf0e10cSrcweir         while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) && ( nCheck != 1 ) )
326cdf0e10cSrcweir         {
327cdf0e10cSrcweir             nCheck = ( nCheck * nSeed ) % nPrime;
328cdf0e10cSrcweir         }
329cdf0e10cSrcweir 
330cdf0e10cSrcweir         if ( nCheck == 1 )
331cdf0e10cSrcweir         {   // uh ... we already have 1008 handles used up
332cdf0e10cSrcweir             // -> simply count upwards
333cdf0e10cSrcweir             while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) )
334cdf0e10cSrcweir                 ++nCheck;
335cdf0e10cSrcweir         }
336cdf0e10cSrcweir 
337cdf0e10cSrcweir         return nCheck;
338cdf0e10cSrcweir     }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir     //--------------------------------------------------------------------
addProperty(const::rtl::OUString & _rName,::sal_Int16 _nAttributes,const Any & _rInitialValue)341cdf0e10cSrcweir     void SAL_CALL OPropertyBag::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
342cdf0e10cSrcweir     {
343cdf0e10cSrcweir         ::osl::ClearableMutexGuard g( m_aMutex );
344cdf0e10cSrcweir 
345cdf0e10cSrcweir         // check whether the type is allowed, everything else will be checked
346cdf0e10cSrcweir         // by m_aDynamicProperties
347cdf0e10cSrcweir         Type aPropertyType = _rInitialValue.getValueType();
348cdf0e10cSrcweir         if  (   _rInitialValue.hasValue()
349cdf0e10cSrcweir             &&  !m_aAllowedTypes.empty()
350cdf0e10cSrcweir             &&  m_aAllowedTypes.find( aPropertyType ) == m_aAllowedTypes.end()
351cdf0e10cSrcweir             )
352cdf0e10cSrcweir             throw IllegalTypeException( ::rtl::OUString(), *this );
353cdf0e10cSrcweir 
354cdf0e10cSrcweir         m_aDynamicProperties.addProperty( _rName, findFreeHandle(), _nAttributes, _rInitialValue );
355cdf0e10cSrcweir 
356cdf0e10cSrcweir         // our property info is dirty
357cdf0e10cSrcweir         m_pArrayHelper.reset();
358cdf0e10cSrcweir 
359cdf0e10cSrcweir         g.clear();
360cdf0e10cSrcweir         setModified(sal_True);
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     //--------------------------------------------------------------------
removeProperty(const::rtl::OUString & _rName)364cdf0e10cSrcweir     void SAL_CALL OPropertyBag::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
365cdf0e10cSrcweir     {
366cdf0e10cSrcweir         ::osl::ClearableMutexGuard g( m_aMutex );
367cdf0e10cSrcweir 
368cdf0e10cSrcweir         m_aDynamicProperties.removeProperty( _rName );
369cdf0e10cSrcweir 
370cdf0e10cSrcweir         // our property info is dirty
371cdf0e10cSrcweir         m_pArrayHelper.reset();
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         g.clear();
374cdf0e10cSrcweir         setModified(sal_True);
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     //--------------------------------------------------------------------
378cdf0e10cSrcweir     namespace
379cdf0e10cSrcweir     {
380cdf0e10cSrcweir         struct ComparePropertyValueByName : public ::std::binary_function< PropertyValue, PropertyValue, bool >
381cdf0e10cSrcweir         {
operator ()comphelper::__anon0d2da3e80111::ComparePropertyValueByName382cdf0e10cSrcweir             bool operator()( const PropertyValue& _rLHS, const PropertyValue& _rRHS )
383cdf0e10cSrcweir             {
384cdf0e10cSrcweir                 return _rLHS.Name < _rRHS.Name;
385cdf0e10cSrcweir             }
386cdf0e10cSrcweir         };
387cdf0e10cSrcweir 
388cdf0e10cSrcweir         template< typename CLASS >
389cdf0e10cSrcweir         struct TransformPropertyToName : public ::std::unary_function< CLASS, ::rtl::OUString >
390cdf0e10cSrcweir         {
operator ()comphelper::__anon0d2da3e80111::TransformPropertyToName391cdf0e10cSrcweir             const ::rtl::OUString& operator()( const CLASS& _rProp )
392cdf0e10cSrcweir             {
393cdf0e10cSrcweir                 return _rProp.Name;
394cdf0e10cSrcweir             }
395cdf0e10cSrcweir         };
396cdf0e10cSrcweir 
397cdf0e10cSrcweir         struct ExtractPropertyValue : public ::std::unary_function< PropertyValue, Any >
398cdf0e10cSrcweir         {
operator ()comphelper::__anon0d2da3e80111::ExtractPropertyValue399cdf0e10cSrcweir             const Any& operator()( const PropertyValue& _rProp )
400cdf0e10cSrcweir             {
401cdf0e10cSrcweir                 return _rProp.Value;
402cdf0e10cSrcweir             }
403cdf0e10cSrcweir         };
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir 
406cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertyValues()407cdf0e10cSrcweir     Sequence< PropertyValue > SAL_CALL OPropertyBag::getPropertyValues(  ) throw (RuntimeException)
408cdf0e10cSrcweir     {
409cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_aMutex );
410cdf0e10cSrcweir 
411cdf0e10cSrcweir         // all registered properties
412cdf0e10cSrcweir         Sequence< Property > aProperties;
413cdf0e10cSrcweir         m_aDynamicProperties.describeProperties( aProperties );
414cdf0e10cSrcweir 
415cdf0e10cSrcweir         // their names
416cdf0e10cSrcweir         Sequence< ::rtl::OUString > aNames( aProperties.getLength() );
417cdf0e10cSrcweir         ::std::transform(
418cdf0e10cSrcweir             aProperties.getConstArray(),
419cdf0e10cSrcweir             aProperties.getConstArray() + aProperties.getLength(),
420cdf0e10cSrcweir             aNames.getArray(),
421cdf0e10cSrcweir             TransformPropertyToName< Property >()
422cdf0e10cSrcweir         );
423cdf0e10cSrcweir 
424cdf0e10cSrcweir         // their values
425cdf0e10cSrcweir         Sequence< Any > aValues;
426cdf0e10cSrcweir         try
427cdf0e10cSrcweir         {
428cdf0e10cSrcweir             aValues = OPropertyBag_PBase::getPropertyValues( aNames );
429cdf0e10cSrcweir             if ( aValues.getLength() != aNames.getLength() )
430cdf0e10cSrcweir                 throw RuntimeException();
431cdf0e10cSrcweir         }
432cdf0e10cSrcweir         catch( const RuntimeException& )
433cdf0e10cSrcweir         {
434cdf0e10cSrcweir             throw;
435cdf0e10cSrcweir         }
436cdf0e10cSrcweir         catch( const Exception& )
437cdf0e10cSrcweir         {
438cdf0e10cSrcweir             // ignore
439cdf0e10cSrcweir         }
440cdf0e10cSrcweir 
441cdf0e10cSrcweir         // merge names and values, and retrieve the state/handle
442cdf0e10cSrcweir         ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
443cdf0e10cSrcweir 
444cdf0e10cSrcweir         Sequence< PropertyValue > aPropertyValues( aNames.getLength() );
445cdf0e10cSrcweir         const ::rtl::OUString* pName = aNames.getConstArray();
446cdf0e10cSrcweir         const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength();
447cdf0e10cSrcweir         const Any* pValue = aValues.getArray();
448cdf0e10cSrcweir         PropertyValue* pPropertyValue = aPropertyValues.getArray();
449cdf0e10cSrcweir 
450cdf0e10cSrcweir         for ( ; pName != pNamesEnd; ++pName, ++pValue, ++pPropertyValue )
451cdf0e10cSrcweir         {
452cdf0e10cSrcweir             pPropertyValue->Name = *pName;
453cdf0e10cSrcweir             pPropertyValue->Handle = rPropInfo.getHandleByName( *pName );
454cdf0e10cSrcweir             pPropertyValue->Value = *pValue;
455cdf0e10cSrcweir             pPropertyValue->State = getPropertyStateByHandle( pPropertyValue->Handle );
456cdf0e10cSrcweir         }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir         return aPropertyValues;
459cdf0e10cSrcweir     }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_setPropertyValues_throw(const Sequence<PropertyValue> & _rProps)462cdf0e10cSrcweir     void OPropertyBag::impl_setPropertyValues_throw( const Sequence< PropertyValue >& _rProps )
463cdf0e10cSrcweir     {
464cdf0e10cSrcweir         // sort (the XMultiPropertySet interface requires this)
465cdf0e10cSrcweir         Sequence< PropertyValue > aProperties( _rProps );
466cdf0e10cSrcweir         ::std::sort(
467cdf0e10cSrcweir             aProperties.getArray(),
468cdf0e10cSrcweir             aProperties.getArray() + aProperties.getLength(),
469cdf0e10cSrcweir             ComparePropertyValueByName()
470cdf0e10cSrcweir         );
471cdf0e10cSrcweir 
472cdf0e10cSrcweir         // a sequence of names
473cdf0e10cSrcweir         Sequence< ::rtl::OUString > aNames( aProperties.getLength() );
474cdf0e10cSrcweir         ::std::transform(
475cdf0e10cSrcweir             aProperties.getConstArray(),
476cdf0e10cSrcweir             aProperties.getConstArray() + aProperties.getLength(),
477cdf0e10cSrcweir             aNames.getArray(),
478cdf0e10cSrcweir             TransformPropertyToName< PropertyValue >()
479cdf0e10cSrcweir         );
480cdf0e10cSrcweir 
481cdf0e10cSrcweir         try
482cdf0e10cSrcweir         {
483cdf0e10cSrcweir             ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
484cdf0e10cSrcweir 
485cdf0e10cSrcweir             // check for unknown properties
486cdf0e10cSrcweir             // we cannot simply rely on the XMultiPropertySet::setPropertyValues
487cdf0e10cSrcweir             // implementation of our base class, since it does not throw
488cdf0e10cSrcweir             // an UnknownPropertyException. More precise, XMultiPropertySet::setPropertyValues
489cdf0e10cSrcweir             // does not allow to throw this exception, while XPropertyAccess::setPropertyValues
490cdf0e10cSrcweir             // requires it
491cdf0e10cSrcweir             sal_Int32 nCount = aNames.getLength();
492cdf0e10cSrcweir 
493cdf0e10cSrcweir             Sequence< sal_Int32 > aHandles( nCount );
494cdf0e10cSrcweir             sal_Int32* pHandle = aHandles.getArray();
495cdf0e10cSrcweir             const PropertyValue* pProperty = aProperties.getConstArray();
496cdf0e10cSrcweir             for (   const ::rtl::OUString* pName = aNames.getConstArray();
497cdf0e10cSrcweir                     pName != aNames.getConstArray() + aNames.getLength();
498cdf0e10cSrcweir                     ++pName, ++pHandle, ++pProperty
499cdf0e10cSrcweir                 )
500cdf0e10cSrcweir             {
501cdf0e10cSrcweir                 *pHandle = rPropInfo.getHandleByName( *pName );
502cdf0e10cSrcweir                 if ( *pHandle != -1 )
503cdf0e10cSrcweir                     continue;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir                 // there's a property requested which we do not know
506cdf0e10cSrcweir                 if ( m_bAutoAddProperties )
507cdf0e10cSrcweir                 {
508cdf0e10cSrcweir                     // add the property
509cdf0e10cSrcweir                     sal_Int16 nAttributes = PropertyAttribute::BOUND | PropertyAttribute::REMOVEABLE | PropertyAttribute::MAYBEDEFAULT;
510cdf0e10cSrcweir                     addProperty( *pName, nAttributes, pProperty->Value );
511cdf0e10cSrcweir                     // rPropInfo is invalid, refetch
512cdf0e10cSrcweir                     rPropInfo = getInfoHelper();
513cdf0e10cSrcweir                     *pHandle = rPropInfo.getHandleByName( *pName );
514cdf0e10cSrcweir                     continue;
515cdf0e10cSrcweir                 }
516cdf0e10cSrcweir 
517cdf0e10cSrcweir                 // no way out
518cdf0e10cSrcweir                 throw UnknownPropertyException( *pName, *this );
519cdf0e10cSrcweir             }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir             // a sequence of values
522cdf0e10cSrcweir             Sequence< Any > aValues( aProperties.getLength() );
523cdf0e10cSrcweir             ::std::transform(
524cdf0e10cSrcweir                 aProperties.getConstArray(),
525cdf0e10cSrcweir                 aProperties.getConstArray() + aProperties.getLength(),
526cdf0e10cSrcweir                 aValues.getArray(),
527cdf0e10cSrcweir                 ExtractPropertyValue()
528cdf0e10cSrcweir             );
529cdf0e10cSrcweir 
530cdf0e10cSrcweir             setFastPropertyValues( nCount, aHandles.getArray(), aValues.getConstArray(), nCount );
531cdf0e10cSrcweir         }
532cdf0e10cSrcweir         catch( const PropertyVetoException& )       { throw; }
533cdf0e10cSrcweir         catch( const IllegalArgumentException& )    { throw; }
534cdf0e10cSrcweir         catch( const WrappedTargetException& )      { throw; }
535cdf0e10cSrcweir         catch( const RuntimeException& )            { throw; }
536cdf0e10cSrcweir         catch( const UnknownPropertyException& )    { throw; }
537cdf0e10cSrcweir         catch( const Exception& )
538cdf0e10cSrcweir         {
539cdf0e10cSrcweir             throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
540cdf0e10cSrcweir         }
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir 
543cdf0e10cSrcweir     //--------------------------------------------------------------------
setPropertyValues(const Sequence<PropertyValue> & _rProps)544cdf0e10cSrcweir     void SAL_CALL OPropertyBag::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
545cdf0e10cSrcweir     {
546cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_aMutex );
547cdf0e10cSrcweir         impl_setPropertyValues_throw( _rProps );
548cdf0e10cSrcweir     }
549cdf0e10cSrcweir 
550cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertyStateByHandle(sal_Int32 _nHandle)551cdf0e10cSrcweir 	PropertyState OPropertyBag::getPropertyStateByHandle( sal_Int32 _nHandle )
552cdf0e10cSrcweir     {
553cdf0e10cSrcweir         // for properties which do not support the MAYBEDEFAULT attribute, don't rely on the base class, but
554cdf0e10cSrcweir         // assume they're always in DIRECT state.
555cdf0e10cSrcweir         // (Note that this probably would belong into the base class. However, this would mean we would need
556cdf0e10cSrcweir         // to check all existent usages of the base class, where MAYBEDEFAULT is *not* set, but
557cdf0e10cSrcweir         // a default is nonetheless supplied/used. This is hard to accomplish reliably, in the
558cdf0e10cSrcweir         // current phase.
559cdf0e10cSrcweir         // #i78593# / 2007-07-07 / frank.schoenheit@sun.com
560cdf0e10cSrcweir 
561cdf0e10cSrcweir         ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
562cdf0e10cSrcweir         sal_Int16 nAttributes(0);
563cdf0e10cSrcweir         OSL_VERIFY( rPropInfo.fillPropertyMembersByHandle( NULL, &nAttributes, _nHandle ) );
564cdf0e10cSrcweir         if ( ( nAttributes & PropertyAttribute::MAYBEDEFAULT ) == 0 )
565cdf0e10cSrcweir             return PropertyState_DIRECT_VALUE;
566cdf0e10cSrcweir 
567cdf0e10cSrcweir         return OPropertyBag_PBase::getPropertyStateByHandle( _nHandle );
568cdf0e10cSrcweir     }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir     //--------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 _nHandle) const571cdf0e10cSrcweir     Any OPropertyBag::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
572cdf0e10cSrcweir     {
573cdf0e10cSrcweir         Any aDefault;
574cdf0e10cSrcweir         m_aDynamicProperties.getPropertyDefaultByHandle( _nHandle, aDefault );
575cdf0e10cSrcweir         return aDefault;
576cdf0e10cSrcweir     }
577cdf0e10cSrcweir 
578cdf0e10cSrcweir //........................................................................
579cdf0e10cSrcweir }   // namespace comphelper
580cdf0e10cSrcweir //........................................................................
581cdf0e10cSrcweir 
582