1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "OPropertySet.hxx"
31 #include "ImplOPropertySet.hxx"
32 #include "ContainerHelper.hxx"
33 #include <rtl/uuid.h>
34 #include <cppuhelper/queryinterface.hxx>
35 
36 #include <vector>
37 #include <algorithm>
38 
39 using namespace ::com::sun::star;
40 
41 using ::com::sun::star::style::XStyleSupplier;
42 // using ::com::sun::star::beans::XFastPropertyState;
43 
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::Sequence;
46 using ::com::sun::star::uno::Any;
47 using ::rtl::OUString;
48 using ::osl::MutexGuard;
49 
50 // needed for MS compiler
51 using ::cppu::OBroadcastHelper;
52 using ::cppu::OPropertySetHelper;
53 using ::cppu::OWeakObject;
54 
55 namespace property
56 {
57 
58 OPropertySet::OPropertySet( ::osl::Mutex & par_rMutex ) :
59         OBroadcastHelper( par_rMutex ),
60         // the following causes a warning; there seems to be no way to avoid it
61         OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )),
62         m_rMutex( par_rMutex ),
63         m_pImplProperties( new impl::ImplOPropertySet() ),
64         m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false)
65 {
66 }
67 
68 OPropertySet::OPropertySet( const OPropertySet & rOther, ::osl::Mutex & par_rMutex ) :
69         OBroadcastHelper( par_rMutex ),
70         // the following causes a warning; there seems to be no way to avoid it
71         OPropertySetHelper( static_cast< OBroadcastHelper & >( *this )),
72         m_rMutex( par_rMutex ),
73         m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault(false)
74 {
75     // /--
76     MutexGuard aGuard( m_rMutex );
77     if( rOther.m_pImplProperties.get())
78         m_pImplProperties.reset( new impl::ImplOPropertySet( * rOther.m_pImplProperties.get()));
79     // \--
80 }
81 
82 void OPropertySet::SetNewValuesExplicitlyEvenIfTheyEqualDefault()
83 {
84     m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault = true;
85 }
86 
87 OPropertySet::~OPropertySet()
88 {}
89 
90 void OPropertySet::disposePropertySet()
91 {
92     m_pImplProperties.reset( 0 );
93 }
94 
95 Any SAL_CALL OPropertySet::queryInterface( const uno::Type& aType )
96     throw (uno::RuntimeException)
97 {
98     return ::cppu::queryInterface(
99         aType,
100 //         static_cast< uno::XInterface * >(
101 //             static_cast< uno::XWeak * >( this )),
102 //         static_cast< uno::XWeak * >( this ),
103 //         static_cast< lang::XServiceInfo * >( this ),
104         static_cast< lang::XTypeProvider * >( this ),
105         static_cast< beans::XPropertySet * >( this ),
106         static_cast< beans::XMultiPropertySet * >( this ),
107         static_cast< beans::XFastPropertySet * >( this ),
108         static_cast< beans::XPropertyState * >( this ),
109         static_cast< beans::XMultiPropertyStates * >( this ),
110         static_cast< XStyleSupplier * >( this ) );
111 //         static_cast< XFastPropertyState * >( this ) );
112 }
113 
114 // void SAL_CALL OPropertySet::acquire() throw ()
115 // {
116 //     OWeakObject::acquire();
117 // }
118 
119 // void SAL_CALL OPropertySet::release() throw ()
120 // {
121 //     OWeakObject::release();
122 // }
123 
124 
125 // ____ XServiceInfo ____
126 // OUString SAL_CALL
127 //     OPropertySet::getImplementationName()
128 //     throw (uno::RuntimeException)
129 // {
130 //     return OUString( RTL_CONSTASCII_USTRINGPARAM( "property::OPropertySet" ));
131 // }
132 
133 // sal_Bool SAL_CALL
134 //     OPropertySet::supportsService( const OUString& ServiceName )
135 //     throw (uno::RuntimeException)
136 // {
137 //     return ( 0 == ServiceName.reverseCompareToAsciiL(
138 //                  RTL_CONSTASCII_STRINGPARAM( "com.sun.star.beans.PropertySet" )));
139 // }
140 
141 // Sequence< OUString > SAL_CALL
142 //     OPropertySet::getSupportedServiceNames()
143 //     throw (uno::RuntimeException)
144 // {
145 //     Sequence< OUString > aServiceNames( 1 );
146 //     aServiceNames[ 0 ] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertySet" ));
147 //     return aServiceNames;
148 // }
149 
150 #define LCL_PROP_CPPUTYPE(t) (::getCppuType( reinterpret_cast< const Reference<t> *>(0)))
151 
152 // // ____ XTypeProvider ____
153 Sequence< uno::Type > SAL_CALL
154     OPropertySet::getTypes()
155     throw (uno::RuntimeException)
156 {
157     static Sequence< uno::Type > aTypeList;
158 
159     // /--
160     MutexGuard aGuard( m_rMutex );
161 
162     if( aTypeList.getLength() == 0 )
163     {
164         ::std::vector< uno::Type > aTypes;
165 
166 //         aTypes.push_back( LCL_PROP_CPPUTYPE( uno::XWeak ));
167 //         aTypes.push_back( LCL_PROP_CPPUTYPE( lang::XServiceInfo ));
168         aTypes.push_back( LCL_PROP_CPPUTYPE( lang::XTypeProvider ));
169         aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XPropertySet ));
170         aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XMultiPropertySet ));
171         aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XFastPropertySet ));
172         aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XPropertyState ));
173         aTypes.push_back( LCL_PROP_CPPUTYPE( beans::XMultiPropertyStates ));
174         aTypes.push_back( LCL_PROP_CPPUTYPE( XStyleSupplier ));
175 //         aTypes.push_back( LCL_PROP_CPPUTYPE( XFastPropertyState ));
176 
177         aTypeList = ::chart::ContainerHelper::ContainerToSequence( aTypes );
178     }
179 
180     return aTypeList;
181     // \--
182 }
183 
184 Sequence< sal_Int8 > SAL_CALL
185     OPropertySet::getImplementationId()
186     throw (uno::RuntimeException)
187 {
188 	static uno::Sequence< sal_Int8 > aId;
189 	if( aId.getLength() == 0 )
190 	{
191 		aId.realloc( 16 );
192 		rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True );
193 	}
194 	return aId;
195 }
196 
197 
198 // ____ XPropertyState ____
199 beans::PropertyState SAL_CALL
200     OPropertySet::getPropertyState( const OUString& PropertyName )
201     throw (beans::UnknownPropertyException,
202            uno::RuntimeException)
203 {
204 	cppu::IPropertyArrayHelper & rPH = getInfoHelper();
205 
206     return m_pImplProperties->GetPropertyStateByHandle(
207         rPH.getHandleByName( PropertyName ));
208 }
209 
210 Sequence< beans::PropertyState > SAL_CALL
211     OPropertySet::getPropertyStates( const Sequence< OUString >& aPropertyName )
212     throw (beans::UnknownPropertyException,
213            uno::RuntimeException)
214 {
215 	cppu::IPropertyArrayHelper & rPH = getInfoHelper();
216 
217     sal_Int32 * pHandles = new sal_Int32[ aPropertyName.getLength() ];
218     rPH.fillHandles( pHandles, aPropertyName );
219 
220     ::std::vector< sal_Int32 > aHandles( pHandles, pHandles + aPropertyName.getLength());
221     delete[] pHandles;
222 
223     return m_pImplProperties->GetPropertyStatesByHandle( aHandles );
224 }
225 
226 void SAL_CALL
227     OPropertySet::setPropertyToDefault( const OUString& PropertyName )
228     throw (beans::UnknownPropertyException,
229            uno::RuntimeException)
230 {
231 	cppu::IPropertyArrayHelper & rPH = getInfoHelper();
232 
233     m_pImplProperties->SetPropertyToDefault( rPH.getHandleByName( PropertyName ));
234     firePropertyChangeEvent();
235 }
236 
237 Any SAL_CALL
238     OPropertySet::getPropertyDefault( const OUString& aPropertyName )
239     throw (beans::UnknownPropertyException,
240            lang::WrappedTargetException,
241            uno::RuntimeException)
242 {
243 	cppu::IPropertyArrayHelper & rPH = getInfoHelper();
244 
245     return GetDefaultValue( rPH.getHandleByName( aPropertyName ) );
246 }
247 
248 
249 // ____ XMultiPropertyStates ____
250 
251 // Note: getPropertyStates() is already implemented in XPropertyState with the
252 // same signature
253 
254 void SAL_CALL
255     OPropertySet::setAllPropertiesToDefault()
256     throw (uno::RuntimeException)
257 {
258     m_pImplProperties->SetAllPropertiesToDefault();
259     firePropertyChangeEvent();
260 }
261 
262 void SAL_CALL
263     OPropertySet::setPropertiesToDefault( const Sequence< OUString >& aPropertyNames )
264     throw (beans::UnknownPropertyException,
265            uno::RuntimeException)
266 {
267 	cppu::IPropertyArrayHelper & rPH = getInfoHelper();
268 
269     sal_Int32 * pHandles = new sal_Int32[ aPropertyNames.getLength() ];
270     rPH.fillHandles( pHandles, aPropertyNames );
271 
272     ::std::vector< sal_Int32 > aHandles( pHandles, pHandles + aPropertyNames.getLength());
273     delete[] pHandles;
274 
275     m_pImplProperties->SetPropertiesToDefault( aHandles );
276 }
277 
278 Sequence< Any > SAL_CALL
279     OPropertySet::getPropertyDefaults( const Sequence< OUString >& aPropertyNames )
280     throw (beans::UnknownPropertyException,
281            lang::WrappedTargetException,
282            uno::RuntimeException)
283 {
284 	::cppu::IPropertyArrayHelper & rPH = getInfoHelper();
285     const sal_Int32 nElements = aPropertyNames.getLength();
286 
287     Sequence< Any > aResult( nElements );
288     Any * pResultArray = aResult.getArray();
289     sal_Int32 nI = 0;
290 
291     for( ; nI < nElements; ++nI )
292     {
293         pResultArray[ nI ] = GetDefaultValue(
294             rPH.getHandleByName( aPropertyNames[ nI ] ));
295     }
296 
297     return aResult;
298 }
299 
300 sal_Bool SAL_CALL OPropertySet::convertFastPropertyValue
301     ( Any & rConvertedValue,
302       Any & rOldValue,
303       sal_Int32 nHandle,
304       const Any& rValue )
305     throw (lang::IllegalArgumentException)
306 {
307     getFastPropertyValue( rOldValue, nHandle );
308     //accept longs also for short values
309     {
310         sal_Int16 nValue;
311         if( (rOldValue>>=nValue) && !(rValue>>=nValue) )
312         {
313             sal_Int32 n32Value = 0;
314             if( rValue>>=n32Value )
315             {
316                 rConvertedValue = uno::makeAny( static_cast<sal_Int16>(n32Value) );
317                 return sal_True;
318             }
319 
320             sal_Int64 n64Value = 0;
321             if( rValue>>=n64Value )
322             {
323                 rConvertedValue = uno::makeAny( static_cast<sal_Int16>(n64Value) );
324                 return sal_True;
325             }
326         }
327     }
328     rConvertedValue = rValue;
329     if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && rOldValue == rConvertedValue )
330         return sal_False;//no change necessary
331     return sal_True;
332 }
333 
334 void SAL_CALL OPropertySet::setFastPropertyValue_NoBroadcast
335     ( sal_Int32 nHandle,
336       const Any& rValue )
337     throw (uno::Exception)
338 {
339 #if OSL_DEBUG_LEVEL > 0
340     if( rValue.hasValue())
341     {
342         cppu::IPropertyArrayHelper & rPH = getInfoHelper();
343         OUString aName;
344         rPH.fillPropertyMembersByHandle( &aName, 0, nHandle );
345         OSL_ENSURE( rValue.isExtractableTo( rPH.getPropertyByName( aName ).Type ),
346                     "Property type is wrong" );
347     }
348 #endif
349 
350     Any aDefault;
351     try
352     {
353         aDefault = GetDefaultValue( nHandle );
354     }
355     catch( beans::UnknownPropertyException ex )
356     {
357         aDefault.clear();
358     }
359     m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue );
360     if( !m_bSetNewValuesExplicitlyEvenIfTheyEqualDefault && aDefault.hasValue() && aDefault == rValue ) //#i98893# don't export defaults to file
361         m_pImplProperties->SetPropertyToDefault( nHandle );
362     else
363         m_pImplProperties->SetPropertyValueByHandle( nHandle, rValue );
364 }
365 
366 void SAL_CALL OPropertySet::getFastPropertyValue
367     ( Any& rValue,
368       sal_Int32 nHandle ) const
369 {
370     if( ! m_pImplProperties->GetPropertyValueByHandle( rValue, nHandle ))
371     {
372 //         OSL_TRACE( "OPropertySet: asking style for property" );
373         // property was not set -> try style
374         uno::Reference< beans::XFastPropertySet > xStylePropSet( m_pImplProperties->GetStyle(), uno::UNO_QUERY );
375         if( xStylePropSet.is() )
376         {
377 #ifdef DBG_UTIL
378             {
379                 // check if the handle of the style points to the same property
380                 // name as the handle in this property set
381                 uno::Reference< beans::XPropertySet > xPropSet( xStylePropSet, uno::UNO_QUERY );
382                 if( xPropSet.is())
383                 {
384                     uno::Reference< beans::XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo(),
385                                                                      uno::UNO_QUERY );
386                     if( xInfo.is() )
387                     {
388                         // for some reason the virtual method getInfoHelper() is
389                         // not const
390                         ::cppu::IPropertyArrayHelper & rPH =
391                               const_cast< OPropertySet * >( this )->getInfoHelper();
392 
393                         // find the Property with Handle nHandle in Style
394                         Sequence< beans::Property > aProps( xInfo->getProperties() );
395                         sal_Int32 nI = aProps.getLength() - 1;
396                         while( ( nI >= 0 ) && nHandle != aProps[ nI ].Handle )
397                             --nI;
398 
399                         if( nI >= 0 ) // => nHandle == aProps[nI].Handle
400                         {
401                             // check whether the handle in this property set is
402                             // the same as the one in the style
403                             beans::Property aProp( rPH.getPropertyByName( aProps[ nI ].Name ) );
404                             OSL_ENSURE( nHandle == aProp.Handle,
405                                         "HandleCheck: Handles for same property differ!" );
406 
407                             if( nHandle == aProp.Handle )
408                             {
409                                 OSL_ENSURE( aProp.Type == aProps[nI].Type,
410                                             "HandleCheck: Types differ!" );
411                                 OSL_ENSURE( aProp.Attributes == aProps[nI].Attributes,
412                                             "HandleCheck: Attributes differ!" );
413                             }
414                         }
415                         else
416                         {
417                             OSL_ENSURE( false,  "HandleCheck: Handle not found in Style" );
418                         }
419                     }
420                     else
421                         OSL_ENSURE( false, "HandleCheck: Invalid XPropertySetInfo returned" );
422                 }
423                 else
424                     OSL_ENSURE( false, "HandleCheck: XPropertySet not supported" );
425             }
426 #endif
427             rValue = xStylePropSet->getFastPropertyValue( nHandle );
428         }
429         else
430         {
431 //             OSL_TRACE( "OPropertySet: no style => getting default for property" );
432             // there is no style (or the style does not support XFastPropertySet)
433             // => take the default value
434             try
435             {
436                 rValue = GetDefaultValue( nHandle );
437             }
438             catch( beans::UnknownPropertyException ex )
439             {
440                 rValue.clear();
441             }
442         }
443     }
444 }
445 
446 void OPropertySet::firePropertyChangeEvent()
447 {
448     // nothing in base class
449 }
450 
451 // ____ XStyleSupplier ____
452 Reference< style::XStyle > SAL_CALL OPropertySet::getStyle()
453     throw (uno::RuntimeException)
454 {
455     return m_pImplProperties->GetStyle();
456 }
457 
458 void SAL_CALL OPropertySet::setStyle( const Reference< style::XStyle >& xStyle )
459     throw (lang::IllegalArgumentException,
460            uno::RuntimeException)
461 {
462     if( ! m_pImplProperties->SetStyle( xStyle ))
463         throw lang::IllegalArgumentException(
464             OUString( RTL_CONSTASCII_USTRINGPARAM( "Empty Style" )),
465             static_cast< beans::XPropertySet * >( this ),
466             0 );
467 }
468 
469 // ____ XFastPropertyState ____
470 // beans::PropertyState OPropertySet::SAL_CALL getFastPropertyState( sal_Int32 nHandle )
471 //     throw (beans::UnknownPropertyException,
472 //            uno::RuntimeException)
473 // {
474 //     return m_pImplProperties->GetPropertyStateByHandle( nHandle );
475 // }
476 
477 // uno::Sequence< beans::PropertyState > OPropertySet::SAL_CALL getFastPropertyStates(
478 //     const uno::Sequence< sal_Int32 >& aHandles )
479 //     throw (beans::UnknownPropertyException,
480 //            uno::RuntimeException)
481 // {
482 //     ::std::vector< sal_Int32 > aHandleVec(
483 //         aHandles.getConstArray(),
484 //         aHandles.getConstArray() + aHandles.getLength() );
485 
486 //     return m_pImplProperties->GetPropertyStatesByHandle( aHandleVec );
487 // }
488 
489 // void OPropertySet::SAL_CALL setFastPropertyToDefault( sal_Int32 nHandle )
490 //     throw (beans::UnknownPropertyException,
491 //            uno::RuntimeException)
492 // {
493 //     m_pImplProperties->SetPropertyToDefault( nHandle );
494 // }
495 
496 // uno::Any OPropertySet::SAL_CALL getFastPropertyDefault( sal_Int32 nHandle )
497 //     throw (beans::UnknownPropertyException,
498 //            lang::WrappedTargetException,
499 //            uno::RuntimeException)
500 // {
501 //     return GetDefaultValue( nHandle );
502 // }
503 
504 // ____ XMultiPropertySet ____
505 void SAL_CALL OPropertySet::setPropertyValues(
506     const Sequence< OUString >& PropertyNames, const Sequence< Any >& Values )
507     throw(beans::PropertyVetoException,
508           lang::IllegalArgumentException,
509           lang::WrappedTargetException,
510           uno::RuntimeException)
511 {
512     ::cppu::OPropertySetHelper::setPropertyValues( PropertyNames, Values );
513 
514     firePropertyChangeEvent();
515 }
516 
517 // ____ XFastPropertySet ____
518 void SAL_CALL OPropertySet::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
519     throw(beans::UnknownPropertyException,
520           beans::PropertyVetoException,
521           lang::IllegalArgumentException,
522           lang::WrappedTargetException, uno::RuntimeException)
523 {
524     ::cppu::OPropertySetHelper::setFastPropertyValue( nHandle, rValue );
525 
526     firePropertyChangeEvent();
527 }
528 
529 
530 } //  namespace property
531