1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_comphelper.hxx"
30*cdf0e10cSrcweir #include <comphelper/propertycontainerhelper.hxx>
31*cdf0e10cSrcweir #include <comphelper/property.hxx>
32*cdf0e10cSrcweir #include <osl/diagnose.h>
33*cdf0e10cSrcweir #include <uno/data.h>
34*cdf0e10cSrcweir #include <com/sun/star/uno/genfunc.h>
35*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp>
36*cdf0e10cSrcweir #include <com/sun/star/beans/UnknownPropertyException.hpp>
37*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <algorithm>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir //.........................................................................
42*cdf0e10cSrcweir namespace comphelper
43*cdf0e10cSrcweir {
44*cdf0e10cSrcweir //.........................................................................
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
47*cdf0e10cSrcweir using namespace ::com::sun::star::lang;
48*cdf0e10cSrcweir using namespace ::com::sun::star::beans;
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir //--------------------------------------------------------------------------
51*cdf0e10cSrcweir namespace
52*cdf0e10cSrcweir {
53*cdf0e10cSrcweir 	// comparing two property descriptions
54*cdf0e10cSrcweir 	struct PropertyDescriptionCompareByHandle : public ::std::binary_function< PropertyDescription, PropertyDescription, bool >
55*cdf0e10cSrcweir 	{
56*cdf0e10cSrcweir 		bool operator() (const PropertyDescription& x, const PropertyDescription& y) const
57*cdf0e10cSrcweir 		{
58*cdf0e10cSrcweir 			return x.aProperty.Handle < y.aProperty.Handle;
59*cdf0e10cSrcweir 		}
60*cdf0e10cSrcweir 	};
61*cdf0e10cSrcweir 	// comparing two property descriptions
62*cdf0e10cSrcweir 	struct PropertyDescriptionHandleCompare : public ::std::binary_function< PropertyDescription, sal_Int32, bool >
63*cdf0e10cSrcweir 	{
64*cdf0e10cSrcweir 		bool operator() (const PropertyDescription& x, const sal_Int32& y) const
65*cdf0e10cSrcweir 		{
66*cdf0e10cSrcweir 			return x.aProperty.Handle < y;
67*cdf0e10cSrcweir 		}
68*cdf0e10cSrcweir 		bool operator() (const sal_Int32& x, const PropertyDescription& y) const
69*cdf0e10cSrcweir 		{
70*cdf0e10cSrcweir 			return x < y.aProperty.Handle;
71*cdf0e10cSrcweir 		}
72*cdf0e10cSrcweir 	};
73*cdf0e10cSrcweir 	// comparing two property descriptions (by name)
74*cdf0e10cSrcweir     struct PropertyDescriptionNameMatch : public ::std::unary_function< PropertyDescription, bool >
75*cdf0e10cSrcweir 	{
76*cdf0e10cSrcweir         ::rtl::OUString m_rCompare;
77*cdf0e10cSrcweir         PropertyDescriptionNameMatch( const ::rtl::OUString& _rCompare ) : m_rCompare( _rCompare ) { }
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir         bool operator() (const PropertyDescription& x ) const
80*cdf0e10cSrcweir 		{
81*cdf0e10cSrcweir 			return x.aProperty.Name.equals(m_rCompare);
82*cdf0e10cSrcweir 		}
83*cdf0e10cSrcweir 	};
84*cdf0e10cSrcweir }
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir //==========================================================================
87*cdf0e10cSrcweir //= OPropertyContainerHelper
88*cdf0e10cSrcweir //==========================================================================
89*cdf0e10cSrcweir //--------------------------------------------------------------------------
90*cdf0e10cSrcweir OPropertyContainerHelper::OPropertyContainerHelper()
91*cdf0e10cSrcweir     :m_bUnused(sal_False)
92*cdf0e10cSrcweir {
93*cdf0e10cSrcweir }
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir // -------------------------------------------------------------------------
96*cdf0e10cSrcweir OPropertyContainerHelper::~OPropertyContainerHelper()
97*cdf0e10cSrcweir {
98*cdf0e10cSrcweir }
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir //--------------------------------------------------------------------------
101*cdf0e10cSrcweir void OPropertyContainerHelper::registerProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle,
102*cdf0e10cSrcweir 		sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType)
103*cdf0e10cSrcweir {
104*cdf0e10cSrcweir 	OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) == 0,
105*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerProperty: don't use this for properties which may be void ! There is a method called \"registerMayBeVoidProperty\" for this !");
106*cdf0e10cSrcweir 	OSL_ENSURE(!_rMemberType.equals(::getCppuType(static_cast< Any* >(NULL))),
107*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerProperty: don't give my the type of an uno::Any ! Really can't handle this !");
108*cdf0e10cSrcweir 	OSL_ENSURE(_pPointerToMember,
109*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerProperty: you gave me nonsense : the pointer must be non-NULL");
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir 	PropertyDescription aNewProp;
112*cdf0e10cSrcweir 	aNewProp.aProperty = Property( _rName, _nHandle, _rMemberType, (sal_Int16)_nAttributes );
113*cdf0e10cSrcweir 	aNewProp.eLocated = PropertyDescription::ltDerivedClassRealType;
114*cdf0e10cSrcweir 	aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir 	implPushBackProperty(aNewProp);
117*cdf0e10cSrcweir }
118*cdf0e10cSrcweir 
119*cdf0e10cSrcweir //--------------------------------------------------------------------------
120*cdf0e10cSrcweir void OPropertyContainerHelper::revokeProperty( sal_Int32 _nHandle )
121*cdf0e10cSrcweir {
122*cdf0e10cSrcweir     PropertiesIterator aPos = searchHandle( _nHandle );
123*cdf0e10cSrcweir     if ( aPos == m_aProperties.end() )
124*cdf0e10cSrcweir         throw UnknownPropertyException();
125*cdf0e10cSrcweir     m_aProperties.erase( aPos );
126*cdf0e10cSrcweir }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir //--------------------------------------------------------------------------
129*cdf0e10cSrcweir void OPropertyContainerHelper::registerMayBeVoidProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
130*cdf0e10cSrcweir 		Any* _pPointerToMember, const Type& _rExpectedType)
131*cdf0e10cSrcweir {
132*cdf0e10cSrcweir 	OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) != 0,
133*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerMayBeVoidProperty: why calling this when the attributes say nothing about may-be-void ?");
134*cdf0e10cSrcweir 	OSL_ENSURE(!_rExpectedType.equals(::getCppuType(static_cast< Any* >(NULL))),
135*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerMayBeVoidProperty: don't give my the type of an uno::Any ! Really can't handle this !");
136*cdf0e10cSrcweir 	OSL_ENSURE(_pPointerToMember,
137*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerMayBeVoidProperty: you gave me nonsense : the pointer must be non-NULL");
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir 	_nAttributes |= PropertyAttribute::MAYBEVOID;
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir 	PropertyDescription aNewProp;
142*cdf0e10cSrcweir 	aNewProp.aProperty = Property( _rName, _nHandle, _rExpectedType, (sal_Int16)_nAttributes );
143*cdf0e10cSrcweir 	aNewProp.eLocated = PropertyDescription::ltDerivedClassAnyType;
144*cdf0e10cSrcweir 	aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir 	implPushBackProperty(aNewProp);
147*cdf0e10cSrcweir }
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir 
150*cdf0e10cSrcweir //--------------------------------------------------------------------------
151*cdf0e10cSrcweir void OPropertyContainerHelper::registerPropertyNoMember(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
152*cdf0e10cSrcweir 		const Type& _rType, const void* _pInitialValue)
153*cdf0e10cSrcweir {
154*cdf0e10cSrcweir 	OSL_ENSURE(!_rType.equals(::getCppuType(static_cast< Any* >(NULL))),
155*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerPropertyNoMember : don't give my the type of an uno::Any ! Really can't handle this !");
156*cdf0e10cSrcweir 	OSL_ENSURE(_pInitialValue || ((_nAttributes & PropertyAttribute::MAYBEVOID) != 0),
157*cdf0e10cSrcweir 		"OPropertyContainerHelper::registerPropertyNoMember : you should not ommit the initial value if the property can't be void ! This will definitivly crash later !");
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir 	PropertyDescription aNewProp;
160*cdf0e10cSrcweir 	aNewProp.aProperty = Property( _rName, _nHandle, _rType, (sal_Int16)_nAttributes );
161*cdf0e10cSrcweir 	aNewProp.eLocated = PropertyDescription::ltHoldMyself;
162*cdf0e10cSrcweir 	aNewProp.aLocation.nOwnClassVectorIndex = m_aHoldProperties.size();
163*cdf0e10cSrcweir 	if (_pInitialValue)
164*cdf0e10cSrcweir 		m_aHoldProperties.push_back(Any(_pInitialValue, _rType));
165*cdf0e10cSrcweir 	else
166*cdf0e10cSrcweir 		m_aHoldProperties.push_back(Any());
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir 	implPushBackProperty(aNewProp);
169*cdf0e10cSrcweir }
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir //--------------------------------------------------------------------------
172*cdf0e10cSrcweir sal_Bool OPropertyContainerHelper::isRegisteredProperty( sal_Int32 _nHandle ) const
173*cdf0e10cSrcweir {
174*cdf0e10cSrcweir     return const_cast< OPropertyContainerHelper* >( this )->searchHandle( _nHandle ) != m_aProperties.end();
175*cdf0e10cSrcweir }
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir //--------------------------------------------------------------------------
178*cdf0e10cSrcweir sal_Bool OPropertyContainerHelper::isRegisteredProperty( const ::rtl::OUString& _rName ) const
179*cdf0e10cSrcweir {
180*cdf0e10cSrcweir     // TODO: the current structure is from a time where properties were
181*cdf0e10cSrcweir     // static, not dynamic. Since we allow that properties are also dynamic,
182*cdf0e10cSrcweir     // i.e. registered and revoked even though the XPropertySet has already been
183*cdf0e10cSrcweir     // accessed, a vector is not really the best data structure anymore ...
184*cdf0e10cSrcweir 
185*cdf0e10cSrcweir     ConstPropertiesIterator pos = ::std::find_if(
186*cdf0e10cSrcweir         m_aProperties.begin(),
187*cdf0e10cSrcweir         m_aProperties.end(),
188*cdf0e10cSrcweir         PropertyDescriptionNameMatch( _rName )
189*cdf0e10cSrcweir     );
190*cdf0e10cSrcweir     return pos != m_aProperties.end();
191*cdf0e10cSrcweir }
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir //--------------------------------------------------------------------------
194*cdf0e10cSrcweir namespace
195*cdf0e10cSrcweir {
196*cdf0e10cSrcweir     struct ComparePropertyWithHandle
197*cdf0e10cSrcweir     {
198*cdf0e10cSrcweir         bool operator()( const PropertyDescription& _rLHS, sal_Int32 _nRHS ) const
199*cdf0e10cSrcweir         {
200*cdf0e10cSrcweir             return _rLHS.aProperty.Handle < _nRHS;
201*cdf0e10cSrcweir         }
202*cdf0e10cSrcweir         bool operator()( sal_Int32 _nLHS, const PropertyDescription& _rRHS ) const
203*cdf0e10cSrcweir         {
204*cdf0e10cSrcweir             return _nLHS < _rRHS.aProperty.Handle;
205*cdf0e10cSrcweir         }
206*cdf0e10cSrcweir     };
207*cdf0e10cSrcweir }
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir //--------------------------------------------------------------------------
210*cdf0e10cSrcweir void OPropertyContainerHelper::implPushBackProperty(const PropertyDescription& _rProp)
211*cdf0e10cSrcweir {
212*cdf0e10cSrcweir #ifdef DBG_UTIL
213*cdf0e10cSrcweir 	for	(	PropertiesIterator checkConflicts = m_aProperties.begin();
214*cdf0e10cSrcweir 			checkConflicts != m_aProperties.end();
215*cdf0e10cSrcweir 			++checkConflicts
216*cdf0e10cSrcweir 		)
217*cdf0e10cSrcweir 	{
218*cdf0e10cSrcweir 		OSL_ENSURE(checkConflicts->aProperty.Name != _rProp.aProperty.Name, "OPropertyContainerHelper::implPushBackProperty: name already exists!");
219*cdf0e10cSrcweir 		OSL_ENSURE(checkConflicts->aProperty.Handle != _rProp.aProperty.Handle, "OPropertyContainerHelper::implPushBackProperty: handle already exists!");
220*cdf0e10cSrcweir 	}
221*cdf0e10cSrcweir #endif
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir     PropertiesIterator pos = ::std::lower_bound(
224*cdf0e10cSrcweir         m_aProperties.begin(), m_aProperties.end(),
225*cdf0e10cSrcweir         _rProp.aProperty.Handle, ComparePropertyWithHandle() );
226*cdf0e10cSrcweir 
227*cdf0e10cSrcweir     m_aProperties.insert( pos, _rProp );
228*cdf0e10cSrcweir }
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir //--------------------------------------------------------------------------
231*cdf0e10cSrcweir namespace
232*cdf0e10cSrcweir {
233*cdf0e10cSrcweir     void lcl_throwIllegalPropertyValueTypeException( const PropertyDescription& _rProperty, const Any& _rValue )
234*cdf0e10cSrcweir     {
235*cdf0e10cSrcweir         ::rtl::OUStringBuffer aErrorMessage;
236*cdf0e10cSrcweir         aErrorMessage.appendAscii( "The given value cannot be converted to the required property type." );
237*cdf0e10cSrcweir         aErrorMessage.appendAscii( "\n(property name \"" );
238*cdf0e10cSrcweir         aErrorMessage.append( _rProperty.aProperty.Name );
239*cdf0e10cSrcweir         aErrorMessage.appendAscii( "\", found value type \"" );
240*cdf0e10cSrcweir         aErrorMessage.append( _rValue.getValueType().getTypeName() );
241*cdf0e10cSrcweir         aErrorMessage.appendAscii( "\", required property type \"" );
242*cdf0e10cSrcweir         aErrorMessage.append( _rProperty.aProperty.Type.getTypeName() );
243*cdf0e10cSrcweir         aErrorMessage.appendAscii( "\")" );
244*cdf0e10cSrcweir 		throw IllegalArgumentException( aErrorMessage.makeStringAndClear(), NULL, 4 );
245*cdf0e10cSrcweir     }
246*cdf0e10cSrcweir }
247*cdf0e10cSrcweir 
248*cdf0e10cSrcweir //--------------------------------------------------------------------------
249*cdf0e10cSrcweir sal_Bool OPropertyContainerHelper::convertFastPropertyValue(
250*cdf0e10cSrcweir 	Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) SAL_THROW( (IllegalArgumentException) )
251*cdf0e10cSrcweir {
252*cdf0e10cSrcweir 	sal_Bool bModified = sal_False;
253*cdf0e10cSrcweir 
254*cdf0e10cSrcweir 	// get the property somebody is asking for
255*cdf0e10cSrcweir 	PropertiesIterator aPos = searchHandle(_nHandle);
256*cdf0e10cSrcweir 	if (aPos == m_aProperties.end())
257*cdf0e10cSrcweir 	{
258*cdf0e10cSrcweir 		OSL_ENSURE( false, "OPropertyContainerHelper::convertFastPropertyValue: unknown handle!" );
259*cdf0e10cSrcweir 		// should not happen if the derived class has built a correct property set info helper to be used by
260*cdf0e10cSrcweir 		// our base class OPropertySetHelper
261*cdf0e10cSrcweir 		return bModified;
262*cdf0e10cSrcweir 	}
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir 	switch (aPos->eLocated)
265*cdf0e10cSrcweir 	{
266*cdf0e10cSrcweir 		// similar handling for the two cases where the value is stored in an any
267*cdf0e10cSrcweir 		case PropertyDescription::ltHoldMyself:
268*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassAnyType:
269*cdf0e10cSrcweir 		{
270*cdf0e10cSrcweir 			sal_Bool bMayBeVoid = ((aPos->aProperty.Attributes & PropertyAttribute::MAYBEVOID) != 0);
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir 
273*cdf0e10cSrcweir 			// non modifiable version of the value-to-be-set
274*cdf0e10cSrcweir 			Any aNewRequestedValue( _rValue );
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir 			// normalization
277*cdf0e10cSrcweir 			// (#102329# - 2002-08-14 - fs@openoffice.org)
278*cdf0e10cSrcweir 			// (#i29490# - 2004-06-16 - fs@openoffice.org)
279*cdf0e10cSrcweir 			if ( !aNewRequestedValue.getValueType().equals( aPos->aProperty.Type ) )
280*cdf0e10cSrcweir 			{	// the actually given value is not of the same type as the one required
281*cdf0e10cSrcweir 				Any aProperlyTyped( NULL, aPos->aProperty.Type.getTypeLibType() );
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir 				if (	uno_type_assignData(
284*cdf0e10cSrcweir 							const_cast< void* >( aProperlyTyped.getValue() ), aProperlyTyped.getValueType().getTypeLibType(),
285*cdf0e10cSrcweir 							const_cast< void* >( aNewRequestedValue.getValue() ), aNewRequestedValue.getValueType().getTypeLibType(),
286*cdf0e10cSrcweir 							reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
287*cdf0e10cSrcweir                             reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
288*cdf0e10cSrcweir                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
289*cdf0e10cSrcweir 						)
290*cdf0e10cSrcweir 					)
291*cdf0e10cSrcweir 				{
292*cdf0e10cSrcweir 					// we were able to query the given XInterface-derivee for the interface
293*cdf0e10cSrcweir 					// which is required for this property
294*cdf0e10cSrcweir 					aNewRequestedValue = aProperlyTyped;
295*cdf0e10cSrcweir 				}
296*cdf0e10cSrcweir 			}
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir 			// argument check
299*cdf0e10cSrcweir 			if	(	!	(	(bMayBeVoid && !aNewRequestedValue.hasValue())			            // void is allowed if the attribute says so
300*cdf0e10cSrcweir 						||	(aNewRequestedValue.getValueType().equals(aPos->aProperty.Type))	// else the types have to be equal
301*cdf0e10cSrcweir 						)
302*cdf0e10cSrcweir 				)
303*cdf0e10cSrcweir 			{
304*cdf0e10cSrcweir                 lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
305*cdf0e10cSrcweir 			}
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir 			Any* pPropContainer = NULL;
308*cdf0e10cSrcweir 				// the pointer to the any which holds the property value, no matter if located in the derived clas
309*cdf0e10cSrcweir 				// or in out vector
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir 			if (PropertyDescription::ltHoldMyself == aPos->eLocated)
312*cdf0e10cSrcweir 			{
313*cdf0e10cSrcweir 				OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
314*cdf0e10cSrcweir 					"OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
315*cdf0e10cSrcweir 				PropertyContainerIterator aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex;
316*cdf0e10cSrcweir 				pPropContainer = &(*aIter);
317*cdf0e10cSrcweir 			}
318*cdf0e10cSrcweir 			else
319*cdf0e10cSrcweir 				pPropContainer = reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir 			// check if the new value differs from the current one
322*cdf0e10cSrcweir 			if (!pPropContainer->hasValue() || !aNewRequestedValue.hasValue())
323*cdf0e10cSrcweir 				bModified = pPropContainer->hasValue() != aNewRequestedValue.hasValue();
324*cdf0e10cSrcweir 			else
325*cdf0e10cSrcweir 				bModified = !uno_type_equalData(
326*cdf0e10cSrcweir                                 const_cast< void* >( pPropContainer->getValue() ), aPos->aProperty.Type.getTypeLibType(),
327*cdf0e10cSrcweir                                 const_cast< void* >( aNewRequestedValue.getValue() ), aPos->aProperty.Type.getTypeLibType(),
328*cdf0e10cSrcweir                                 reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
329*cdf0e10cSrcweir                                 reinterpret_cast< uno_ReleaseFunc >( cpp_release )
330*cdf0e10cSrcweir 							);
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir 			if (bModified)
333*cdf0e10cSrcweir 			{
334*cdf0e10cSrcweir 				_rOldValue = *pPropContainer;
335*cdf0e10cSrcweir 				_rConvertedValue = aNewRequestedValue;
336*cdf0e10cSrcweir 			}
337*cdf0e10cSrcweir 		}
338*cdf0e10cSrcweir 		break;
339*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassRealType:
340*cdf0e10cSrcweir 			// let the UNO runtime library do any possible conversion
341*cdf0e10cSrcweir 			// this may include a change of the type - for instance, if a LONG is required,
342*cdf0e10cSrcweir 			// but a short is given, then this is valid, as it can be converted without any potential
343*cdf0e10cSrcweir 			// data loss
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 			Any aProperlyTyped;
346*cdf0e10cSrcweir 			const Any* pNewValue = &_rValue;
347*cdf0e10cSrcweir 
348*cdf0e10cSrcweir 			if (!_rValue.getValueType().equals(aPos->aProperty.Type))
349*cdf0e10cSrcweir 			{
350*cdf0e10cSrcweir 				sal_Bool bConverted = sal_False;
351*cdf0e10cSrcweir 
352*cdf0e10cSrcweir 				// a temporary any of the correct (required) type
353*cdf0e10cSrcweir 				aProperlyTyped = Any( NULL, aPos->aProperty.Type.getTypeLibType() );
354*cdf0e10cSrcweir 					// (need this as we do not want to overwrite the derived class member here)
355*cdf0e10cSrcweir 
356*cdf0e10cSrcweir 				if (	uno_type_assignData(
357*cdf0e10cSrcweir 							const_cast<void*>(aProperlyTyped.getValue()), aProperlyTyped.getValueType().getTypeLibType(),
358*cdf0e10cSrcweir 							const_cast<void*>(_rValue.getValue()), _rValue.getValueType().getTypeLibType(),
359*cdf0e10cSrcweir 							reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
360*cdf0e10cSrcweir                             reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
361*cdf0e10cSrcweir                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
362*cdf0e10cSrcweir 						)
363*cdf0e10cSrcweir 					)
364*cdf0e10cSrcweir 				{
365*cdf0e10cSrcweir 					// could query for the requested interface
366*cdf0e10cSrcweir 					bConverted = sal_True;
367*cdf0e10cSrcweir 					pNewValue = &aProperlyTyped;
368*cdf0e10cSrcweir 				}
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir 				if ( !bConverted )
371*cdf0e10cSrcweir                     lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
372*cdf0e10cSrcweir 			}
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir 			// from here on, we should have the proper type
375*cdf0e10cSrcweir 			OSL_ENSURE( pNewValue->getValueType() == aPos->aProperty.Type,
376*cdf0e10cSrcweir 				"OPropertyContainerHelper::convertFastPropertyValue: conversion failed!" );
377*cdf0e10cSrcweir 			bModified = !uno_type_equalData(
378*cdf0e10cSrcweir                             aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(),
379*cdf0e10cSrcweir                             const_cast<void*>(pNewValue->getValue()), aPos->aProperty.Type.getTypeLibType(),
380*cdf0e10cSrcweir                             reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
381*cdf0e10cSrcweir                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
382*cdf0e10cSrcweir 						);
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir 			if (bModified)
385*cdf0e10cSrcweir 			{
386*cdf0e10cSrcweir 				_rOldValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
387*cdf0e10cSrcweir 				_rConvertedValue = *pNewValue;
388*cdf0e10cSrcweir 			}
389*cdf0e10cSrcweir 			break;
390*cdf0e10cSrcweir 	}
391*cdf0e10cSrcweir 
392*cdf0e10cSrcweir 	return bModified;
393*cdf0e10cSrcweir }
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir //--------------------------------------------------------------------------
396*cdf0e10cSrcweir void OPropertyContainerHelper::setFastPropertyValue(sal_Int32 _nHandle, const Any& _rValue) SAL_THROW( (Exception) )
397*cdf0e10cSrcweir {
398*cdf0e10cSrcweir 	// get the property somebody is asking for
399*cdf0e10cSrcweir 	PropertiesIterator aPos = searchHandle(_nHandle);
400*cdf0e10cSrcweir 	if (aPos == m_aProperties.end())
401*cdf0e10cSrcweir 	{
402*cdf0e10cSrcweir 		OSL_ENSURE( false, "OPropertyContainerHelper::setFastPropertyValue: unknown handle!" );
403*cdf0e10cSrcweir 		// should not happen if the derived class has built a correct property set info helper to be used by
404*cdf0e10cSrcweir 		// our base class OPropertySetHelper
405*cdf0e10cSrcweir 		return;
406*cdf0e10cSrcweir 	}
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir 	switch (aPos->eLocated)
409*cdf0e10cSrcweir 	{
410*cdf0e10cSrcweir 		case PropertyDescription::ltHoldMyself:
411*cdf0e10cSrcweir 			m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex] = _rValue;
412*cdf0e10cSrcweir 			break;
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassAnyType:
415*cdf0e10cSrcweir 			*reinterpret_cast< Any* >(aPos->aLocation.pDerivedClassMember) = _rValue;
416*cdf0e10cSrcweir 			break;
417*cdf0e10cSrcweir 
418*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassRealType:
419*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
420*cdf0e10cSrcweir 			sal_Bool bSuccess =
421*cdf0e10cSrcweir #endif
422*cdf0e10cSrcweir 			// copy the data from the to-be-set value
423*cdf0e10cSrcweir 			uno_type_assignData(
424*cdf0e10cSrcweir 				aPos->aLocation.pDerivedClassMember,		aPos->aProperty.Type.getTypeLibType(),
425*cdf0e10cSrcweir 				const_cast< void* >( _rValue.getValue() ),	_rValue.getValueType().getTypeLibType(),
426*cdf0e10cSrcweir 				reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
427*cdf0e10cSrcweir 				reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
428*cdf0e10cSrcweir                 reinterpret_cast< uno_ReleaseFunc >( cpp_release ) );
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir 			OSL_ENSURE( bSuccess,
431*cdf0e10cSrcweir 				"OPropertyContainerHelper::setFastPropertyValue: ooops .... the value could not be assigned!");
432*cdf0e10cSrcweir 
433*cdf0e10cSrcweir 			break;
434*cdf0e10cSrcweir 	}
435*cdf0e10cSrcweir }
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir //--------------------------------------------------------------------------
438*cdf0e10cSrcweir void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
439*cdf0e10cSrcweir {
440*cdf0e10cSrcweir 	// get the property somebody is asking for
441*cdf0e10cSrcweir 	PropertiesIterator aPos = const_cast<OPropertyContainerHelper*>(this)->searchHandle(_nHandle);
442*cdf0e10cSrcweir 	if (aPos == m_aProperties.end())
443*cdf0e10cSrcweir 	{
444*cdf0e10cSrcweir 		OSL_ENSURE( false, "OPropertyContainerHelper::getFastPropertyValue: unknown handle!" );
445*cdf0e10cSrcweir 		// should not happen if the derived class has built a correct property set info helper to be used by
446*cdf0e10cSrcweir 		// our base class OPropertySetHelper
447*cdf0e10cSrcweir 		return;
448*cdf0e10cSrcweir 	}
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir 	switch (aPos->eLocated)
451*cdf0e10cSrcweir 	{
452*cdf0e10cSrcweir 		case PropertyDescription::ltHoldMyself:
453*cdf0e10cSrcweir 			OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
454*cdf0e10cSrcweir 				"OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
455*cdf0e10cSrcweir 			_rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex];
456*cdf0e10cSrcweir 			break;
457*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassAnyType:
458*cdf0e10cSrcweir 			_rValue = *reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
459*cdf0e10cSrcweir 			break;
460*cdf0e10cSrcweir 		case PropertyDescription::ltDerivedClassRealType:
461*cdf0e10cSrcweir 			_rValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
462*cdf0e10cSrcweir 			break;
463*cdf0e10cSrcweir 	}
464*cdf0e10cSrcweir }
465*cdf0e10cSrcweir 
466*cdf0e10cSrcweir //--------------------------------------------------------------------------
467*cdf0e10cSrcweir OPropertyContainerHelper::PropertiesIterator OPropertyContainerHelper::searchHandle(sal_Int32 _nHandle)
468*cdf0e10cSrcweir {
469*cdf0e10cSrcweir 	// search a lower bound
470*cdf0e10cSrcweir 	PropertiesIterator aLowerBound = ::std::lower_bound(
471*cdf0e10cSrcweir 		m_aProperties.begin(),
472*cdf0e10cSrcweir 		m_aProperties.end(),
473*cdf0e10cSrcweir 		_nHandle,
474*cdf0e10cSrcweir 		PropertyDescriptionHandleCompare());
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir 	// check for identity
477*cdf0e10cSrcweir 	if ((aLowerBound != m_aProperties.end()) && aLowerBound->aProperty.Handle != _nHandle)
478*cdf0e10cSrcweir 		aLowerBound = m_aProperties.end();
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir 	return aLowerBound;
481*cdf0e10cSrcweir }
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir //--------------------------------------------------------------------------
484*cdf0e10cSrcweir const Property& OPropertyContainerHelper::getProperty( const ::rtl::OUString& _rName ) const
485*cdf0e10cSrcweir {
486*cdf0e10cSrcweir     ConstPropertiesIterator pos = ::std::find_if(
487*cdf0e10cSrcweir         m_aProperties.begin(),
488*cdf0e10cSrcweir         m_aProperties.end(),
489*cdf0e10cSrcweir         PropertyDescriptionNameMatch( _rName )
490*cdf0e10cSrcweir     );
491*cdf0e10cSrcweir     if ( pos == m_aProperties.end() )
492*cdf0e10cSrcweir         throw UnknownPropertyException( _rName, NULL );
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir     return pos->aProperty;
495*cdf0e10cSrcweir }
496*cdf0e10cSrcweir 
497*cdf0e10cSrcweir //--------------------------------------------------------------------------
498*cdf0e10cSrcweir void OPropertyContainerHelper::modifyAttributes(sal_Int32 _nHandle, sal_Int32 _nAddAttrib, sal_Int32 _nRemoveAttrib)
499*cdf0e10cSrcweir {
500*cdf0e10cSrcweir 	// get the property somebody is asking for
501*cdf0e10cSrcweir 	PropertiesIterator aPos = searchHandle(_nHandle);
502*cdf0e10cSrcweir 	if (aPos == m_aProperties.end())
503*cdf0e10cSrcweir 	{
504*cdf0e10cSrcweir 		OSL_ENSURE( false, "OPropertyContainerHelper::modifyAttributes: unknown handle!" );
505*cdf0e10cSrcweir 		// should not happen if the derived class has built a correct property set info helper to be used by
506*cdf0e10cSrcweir 		// our base class OPropertySetHelper
507*cdf0e10cSrcweir 		return;
508*cdf0e10cSrcweir 	}
509*cdf0e10cSrcweir 	aPos->aProperty.Handle |= _nAddAttrib;
510*cdf0e10cSrcweir 	aPos->aProperty.Handle &= ~_nRemoveAttrib;
511*cdf0e10cSrcweir }
512*cdf0e10cSrcweir 
513*cdf0e10cSrcweir //--------------------------------------------------------------------------
514*cdf0e10cSrcweir void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) const
515*cdf0e10cSrcweir {
516*cdf0e10cSrcweir 	Sequence< Property > aOwnProps(m_aProperties.size());
517*cdf0e10cSrcweir 	Property* pOwnProps = aOwnProps.getArray();
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir 	for	(	ConstPropertiesIterator aLoop = m_aProperties.begin();
520*cdf0e10cSrcweir 			aLoop != m_aProperties.end();
521*cdf0e10cSrcweir 			++aLoop, ++pOwnProps
522*cdf0e10cSrcweir 		)
523*cdf0e10cSrcweir 	{
524*cdf0e10cSrcweir 		pOwnProps->Name = aLoop->aProperty.Name;
525*cdf0e10cSrcweir 		pOwnProps->Handle = aLoop->aProperty.Handle;
526*cdf0e10cSrcweir 		pOwnProps->Attributes = (sal_Int16)aLoop->aProperty.Attributes;
527*cdf0e10cSrcweir 		pOwnProps->Type = aLoop->aProperty.Type;
528*cdf0e10cSrcweir 	}
529*cdf0e10cSrcweir 
530*cdf0e10cSrcweir 	// as our property vector is sorted by handles, not by name, we have to sort aOwnProps
531*cdf0e10cSrcweir 	::std::sort(aOwnProps.getArray(), aOwnProps.getArray() + aOwnProps.getLength(), PropertyCompareByName());
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir 	// unfortunally the STL merge function does not allow the output range to overlap one of the input ranges,
534*cdf0e10cSrcweir 	// so we need an extra sequence
535*cdf0e10cSrcweir 	Sequence< Property > aOutput;
536*cdf0e10cSrcweir 	aOutput.realloc(_rProps.getLength() + aOwnProps.getLength());
537*cdf0e10cSrcweir 	// do the merge
538*cdf0e10cSrcweir 	::std::merge(	_rProps.getConstArray(), _rProps.getConstArray() + _rProps.getLength(),			// input 1
539*cdf0e10cSrcweir 					aOwnProps.getConstArray(), aOwnProps.getConstArray() + aOwnProps.getLength(),	// input 2
540*cdf0e10cSrcweir 					aOutput.getArray(),																// output
541*cdf0e10cSrcweir 					PropertyCompareByName()															// compare operator
542*cdf0e10cSrcweir 				);
543*cdf0e10cSrcweir 
544*cdf0e10cSrcweir 	// copy the output
545*cdf0e10cSrcweir 	_rProps = aOutput;
546*cdf0e10cSrcweir }
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir //.........................................................................
549*cdf0e10cSrcweir }	// namespace comphelper
550*cdf0e10cSrcweir //.........................................................................
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir 
553