1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "sal/config.h"
23 #include "cppuhelper/propertysetmixin.hxx"
25 #include "com/sun/star/beans/Property.hpp"
26 #include "com/sun/star/beans/PropertyChangeEvent.hpp"
27 #include "com/sun/star/beans/PropertyAttribute.hpp"
28 #include "com/sun/star/beans/PropertyValue.hpp"
29 #include "com/sun/star/beans/PropertyVetoException.hpp"
30 #include "com/sun/star/beans/UnknownPropertyException.hpp"
31 #include "com/sun/star/beans/XFastPropertySet.hpp"
32 #include "com/sun/star/beans/XPropertyAccess.hpp"
33 #include "com/sun/star/beans/XPropertyChangeListener.hpp"
34 #include "com/sun/star/beans/XPropertySet.hpp"
35 #include "com/sun/star/beans/XPropertySetInfo.hpp"
36 #include "com/sun/star/beans/XVetoableChangeListener.hpp"
37 #include "com/sun/star/container/NoSuchElementException.hpp"
38 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
39 #include "com/sun/star/lang/DisposedException.hpp"
40 #include "com/sun/star/lang/EventObject.hpp"
41 #include "com/sun/star/lang/IllegalAccessException.hpp"
42 #include "com/sun/star/lang/IllegalArgumentException.hpp"
43 #include "com/sun/star/lang/WrappedTargetException.hpp"
44 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
45 #include "com/sun/star/lang/XComponent.hpp"
46 #include "com/sun/star/lang/XMultiComponentFactory.hpp"
47 #include "com/sun/star/reflection/XCompoundTypeDescription.hpp"
48 #include "com/sun/star/reflection/XIdlClass.hpp"
49 #include "com/sun/star/reflection/XIdlField2.hpp"
50 #include "com/sun/star/reflection/XIdlReflection.hpp"
51 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
52 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
53 #include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp"
54 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
55 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
56 #include "com/sun/star/reflection/XTypeDescription.hpp"
57 #include "com/sun/star/uno/Any.hxx"
58 #include "com/sun/star/uno/DeploymentException.hpp"
59 #include "com/sun/star/uno/Exception.hpp"
60 #include "com/sun/star/uno/Reference.hxx"
61 #include "com/sun/star/uno/RuntimeException.hpp"
62 #include "com/sun/star/uno/Sequence.hxx"
63 #include "com/sun/star/uno/Type.hxx"
64 #include "com/sun/star/uno/TypeClass.hpp"
65 #include "com/sun/star/uno/XComponentContext.hpp"
66 #include "com/sun/star/uno/XInterface.hpp"
67 #include "cppuhelper/implbase1.hxx"
68 #include "cppuhelper/weak.hxx"
69 #include "osl/diagnose.h"
70 #include "osl/mutex.hxx"
71 #include "rtl/ref.hxx"
72 #include "rtl/string.h"
73 #include "rtl/ustring.h"
74 #include "rtl/ustring.hxx"
75 #include "sal/types.h"
76 #include "salhelper/simplereferenceobject.hxx"
84 using cppu::PropertySetMixinImpl
;
88 template< typename T
> struct AutoDispose
{
98 css::uno::Reference
< css::lang::XComponent
> comp(
99 ifc
, css::uno::UNO_QUERY
);
106 css::uno::Reference
< T
> ifc
;
109 AutoDispose(AutoDispose
&); // not defined
110 void operator =(AutoDispose
); // not defined
113 struct PropertyData
{
114 explicit PropertyData(
115 css::beans::Property
const & theProperty
, bool thePresent
):
116 property(theProperty
), present(thePresent
) {}
118 css::beans::Property property
;
122 struct Data
: public salhelper::SimpleReferenceObject
{
123 typedef std::map
< rtl::OUString
, PropertyData
> PropertyMap
;
125 PropertyMap properties
;
127 PropertyMap::const_iterator
get(
128 css::uno::Reference
< css::uno::XInterface
> const & object
,
129 rtl::OUString
const & name
) const;
133 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
134 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
135 std::vector
< rtl::OUString
> * handleNames
)
138 initProperties(type
, absentOptional
, handleNames
, &seen
);
142 typedef std::set
< rtl::OUString
> TypeSet
;
145 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
146 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
147 std::vector
< rtl::OUString
> * handleNames
, TypeSet
* seen
);
149 static css::uno::Reference
< css::reflection::XTypeDescription
>
151 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
);
154 Data::PropertyMap::const_iterator
Data::get(
155 css::uno::Reference
< css::uno::XInterface
> const & object
,
156 rtl::OUString
const & name
) const
158 PropertyMap::const_iterator
i(properties
.find(name
));
159 if (i
== properties
.end() || !i
->second
.present
) {
160 throw css::beans::UnknownPropertyException(name
, object
);
165 void Data::initProperties(
166 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
167 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
168 std::vector
< rtl::OUString
> * handleNames
, TypeSet
* seen
)
170 css::uno::Reference
< css::reflection::XInterfaceTypeDescription2
> ifc(
171 resolveTypedefs(type
), css::uno::UNO_QUERY_THROW
);
172 if (seen
->insert(ifc
->getName()).second
) {
174 css::uno::Reference
< css::reflection::XTypeDescription
> > bases(
175 ifc
->getBaseTypes());
176 for (sal_Int32 i
= 0; i
< bases
.getLength(); ++i
) {
177 initProperties(bases
[i
], absentOptional
, handleNames
, seen
);
181 css::reflection::XInterfaceMemberTypeDescription
> > members(
183 rtl::OUString
const * absentBegin
= absentOptional
.getConstArray();
184 rtl::OUString
const * absentEnd
=
185 absentBegin
+ absentOptional
.getLength();
186 for (sal_Int32 i
= 0; i
< members
.getLength(); ++i
) {
187 if (members
[i
]->getTypeClass()
188 == css::uno::TypeClass_INTERFACE_ATTRIBUTE
)
191 css::reflection::XInterfaceAttributeTypeDescription2
> attr(
192 members
[i
], css::uno::UNO_QUERY_THROW
);
193 sal_Int16 attrAttribs
= 0;
194 if (attr
->isBound()) {
195 attrAttribs
|= css::beans::PropertyAttribute::BOUND
;
197 bool setUnknown
= false;
198 if (attr
->isReadOnly()) {
199 attrAttribs
|= css::beans::PropertyAttribute::READONLY
;
204 css::reflection::XCompoundTypeDescription
> > excs(
205 attr
->getGetExceptions());
206 bool getUnknown
= false;
207 //XXX Special interpretation of getter/setter exceptions only
208 // works if the specified exceptions are of the exact type, not
210 for (sal_Int32 j
= 0; j
< excs
.getLength(); ++j
) {
211 if ( excs
[j
]->getName() == "com.sun.star.beans.UnknownPropertyException" )
217 excs
= attr
->getSetExceptions();
218 for (sal_Int32 j
= 0; j
< excs
.getLength(); ++j
) {
219 if ( excs
[j
]->getName() == "com.sun.star.beans.UnknownPropertyException" )
222 } else if ( excs
[j
]->getName() == "com.sun.star.beans.PropertyVetoException" )
225 |= css::beans::PropertyAttribute::CONSTRAINED
;
228 if (getUnknown
&& setUnknown
) {
229 attrAttribs
|= css::beans::PropertyAttribute::OPTIONAL
;
231 css::uno::Reference
< css::reflection::XTypeDescription
> t(
235 t
= resolveTypedefs(t
);
237 if (t
->getName().matchAsciiL(
238 RTL_CONSTASCII_STRINGPARAM(
239 "com.sun.star.beans.Ambiguous<")))
241 n
= css::beans::PropertyAttribute::MAYBEAMBIGUOUS
;
242 } else if (t
->getName().matchAsciiL(
243 RTL_CONSTASCII_STRINGPARAM(
244 "com.sun.star.beans.Defaulted<")))
246 n
= css::beans::PropertyAttribute::MAYBEDEFAULT
;
247 } else if (t
->getName().matchAsciiL(
248 RTL_CONSTASCII_STRINGPARAM(
249 "com.sun.star.beans.Optional<")))
251 n
= css::beans::PropertyAttribute::MAYBEVOID
;
255 if ((attrAttribs
& n
) != 0) {
260 css::uno::Reference
< css::reflection::XTypeDescription
> >
263 css::reflection::XStructTypeDescription
>(
265 css::uno::UNO_QUERY_THROW
)->getTypeArguments());
266 if (args
.getLength() != 1) {
267 throw css::uno::RuntimeException(
269 "inconsistent UNO type registry"),
270 css::uno::Reference
< css::uno::XInterface
>());
274 std::vector
< rtl::OUString
>::size_type handles
275 = handleNames
->size();
276 if (handles
> SAL_MAX_INT32
) {
277 throw css::uno::RuntimeException(
279 "interface type has too many attributes"),
280 css::uno::Reference
< css::uno::XInterface
>());
282 rtl::OUString
name(members
[i
]->getMemberName());
283 if (!properties
.insert(
284 PropertyMap::value_type(
287 css::beans::Property(
288 name
, static_cast< sal_Int32
>(handles
),
290 t
->getTypeClass(), t
->getName()),
292 (std::find(absentBegin
, absentEnd
, name
)
296 throw css::uno::RuntimeException(
298 "inconsistent UNO type registry"),
299 css::uno::Reference
< css::uno::XInterface
>());
301 handleNames
->push_back(name
);
307 css::uno::Reference
< css::reflection::XTypeDescription
> Data::resolveTypedefs(
308 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
)
310 css::uno::Reference
< css::reflection::XTypeDescription
> t(type
);
311 while (t
->getTypeClass() == css::uno::TypeClass_TYPEDEF
) {
312 t
= css::uno::Reference
< css::reflection::XIndirectTypeDescription
>(
313 t
, css::uno::UNO_QUERY_THROW
)->getReferencedType();
318 class Info
: public cppu::WeakImplHelper1
< css::beans::XPropertySetInfo
> {
320 explicit Info(Data
* data
): m_data(data
) {}
322 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties()
323 throw (css::uno::RuntimeException
);
325 virtual css::beans::Property SAL_CALL
getPropertyByName(
326 rtl::OUString
const & name
)
328 css::beans::UnknownPropertyException
, css::uno::RuntimeException
);
330 virtual sal_Bool SAL_CALL
hasPropertyByName(rtl::OUString
const & name
)
331 throw (css::uno::RuntimeException
);
334 rtl::Reference
< Data
> m_data
;
337 css::uno::Sequence
< css::beans::Property
> Info::getProperties()
338 throw (css::uno::RuntimeException
)
341 OSL_ASSERT(m_data
->properties
.size() <= SAL_MAX_INT32
);
342 css::uno::Sequence
< css::beans::Property
> s(
343 static_cast< sal_Int32
>(m_data
->properties
.size()));
345 for (Data::PropertyMap::iterator
i(m_data
->properties
.begin());
346 i
!= m_data
->properties
.end(); ++i
)
348 if (i
->second
.present
) {
349 s
[n
++] = i
->second
.property
;
354 } catch (std::bad_alloc
&) {
355 //TODO OutOfMemoryException:
356 throw css::uno::RuntimeException(
357 rtl::OUString(), static_cast< cppu::OWeakObject
* >(this));
361 css::beans::Property
Info::getPropertyByName(rtl::OUString
const & name
)
362 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
)
364 return m_data
->get(static_cast< cppu::OWeakObject
* >(this), name
)->
368 sal_Bool
Info::hasPropertyByName(rtl::OUString
const & name
)
369 throw (css::uno::RuntimeException
)
371 Data::PropertyMap::iterator
i(m_data
->properties
.find(name
));
372 return i
!= m_data
->properties
.end() && i
->second
.present
;
376 std::multiset
< css::uno::Reference
< css::beans::XPropertyChangeListener
> >
381 class PropertySetMixinImpl::BoundListeners::Impl
{
383 BoundListenerBag specificListeners
;
384 BoundListenerBag unspecificListeners
;
385 css::beans::PropertyChangeEvent event
;
388 PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl
) {}
390 PropertySetMixinImpl::BoundListeners::~BoundListeners() {
394 void PropertySetMixinImpl::BoundListeners::notify() const {
395 for (BoundListenerBag::const_iterator
i(m_impl
->specificListeners
.begin());
396 i
!= m_impl
->specificListeners
.end(); ++i
)
399 (*i
)->propertyChange(m_impl
->event
);
400 } catch (css::lang::DisposedException
&) {}
402 for (BoundListenerBag::const_iterator
i(
403 m_impl
->unspecificListeners
.begin());
404 i
!= m_impl
->unspecificListeners
.end(); ++i
)
407 (*i
)->propertyChange(m_impl
->event
);
408 } catch (css::lang::DisposedException
&) {}
412 class PropertySetMixinImpl::Impl
: public Data
{
415 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
416 Implements theImplements
,
417 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
418 css::uno::Type
const & type
);
420 rtl::OUString
translateHandle(
421 css::uno::Reference
< css::uno::XInterface
> const & object
,
422 sal_Int32 handle
) const;
425 css::uno::Reference
< css::uno::XInterface
> const & object
,
426 rtl::OUString
const & name
, css::uno::Any
const & value
,
427 bool isAmbiguous
, bool isDefaulted
, sal_Int16 illegalArgumentPosition
)
430 css::uno::Any
getProperty(
431 css::uno::Reference
< css::uno::XInterface
> const & object
,
432 rtl::OUString
const & name
, css::beans::PropertyState
* state
) const;
434 PropertySetMixinImpl::Implements implements
;
435 css::uno::Sequence
< rtl::OUString
> handleMap
;
437 typedef std::map
< rtl::OUString
, BoundListenerBag
> BoundListenerMap
;
440 std::multiset
< css::uno::Reference
< css::beans::XVetoableChangeListener
> >
443 typedef std::map
< rtl::OUString
, VetoListenerBag
> VetoListenerMap
;
445 mutable osl::Mutex mutex
;
446 BoundListenerMap boundListeners
;
447 VetoListenerMap vetoListeners
;
451 css::uno::Reference
< css::reflection::XIdlClass
> getReflection(
452 rtl::OUString
const & typeName
) const;
454 static css::uno::Any
wrapValue(
455 css::uno::Reference
< css::uno::XInterface
> const & object
,
456 css::uno::Any
const & value
,
457 css::uno::Reference
< css::reflection::XIdlClass
> const & type
,
458 bool wrapAmbiguous
, bool isAmbiguous
, bool wrapDefaulted
,
459 bool isDefaulted
, bool wrapOptional
);
461 css::uno::Reference
< css::uno::XComponentContext
> const & m_context
;
462 css::uno::Sequence
< rtl::OUString
> m_absentOptional
;
463 css::uno::Type m_type
;
464 css::uno::Reference
< css::reflection::XIdlClass
> m_idlClass
;
467 PropertySetMixinImpl::Impl::Impl(
468 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
469 Implements theImplements
,
470 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
471 css::uno::Type
const & type
):
472 implements(theImplements
), disposed(false), m_context(context
),
473 m_absentOptional(absentOptional
), m_type(type
)
478 & ~(IMPLEMENTS_PROPERTY_SET
| IMPLEMENTS_FAST_PROPERTY_SET
479 | IMPLEMENTS_PROPERTY_ACCESS
))
481 m_idlClass
= getReflection(m_type
.getTypeName());
482 css::uno::Reference
< css::reflection::XTypeDescription
> ifc
;
484 ifc
= css::uno::Reference
< css::reflection::XTypeDescription
>(
485 css::uno::Reference
< css::container::XHierarchicalNameAccess
>(
486 m_context
->getValueByName(
488 "/singletons/com.sun.star.reflection."
489 "theTypeDescriptionManager")),
490 css::uno::UNO_QUERY_THROW
)->getByHierarchicalName(
491 m_type
.getTypeName()),
492 css::uno::UNO_QUERY_THROW
);
493 } catch (css::container::NoSuchElementException
& e
) {
494 throw css::uno::RuntimeException(
497 " com.sun.star.container.NoSuchElementException: ")
499 css::uno::Reference
< css::uno::XInterface
>());
501 std::vector
< rtl::OUString
> handleNames
;
502 initProperties(ifc
, m_absentOptional
, &handleNames
);
503 std::vector
< rtl::OUString
>::size_type size
= handleNames
.size();
504 OSL_ASSERT(size
<= SAL_MAX_INT32
);
505 handleMap
.realloc(static_cast< sal_Int32
>(size
));
506 std::copy(handleNames
.begin(), handleNames
.end(), handleMap
.getArray());
509 rtl::OUString
PropertySetMixinImpl::Impl::translateHandle(
510 css::uno::Reference
< css::uno::XInterface
> const & object
,
511 sal_Int32 handle
) const
513 if (handle
< 0 || handle
>= handleMap
.getLength()) {
514 throw css::beans::UnknownPropertyException(
515 (rtl::OUString("bad handle ")
516 + rtl::OUString::valueOf(handle
)),
519 return handleMap
[handle
];
522 void PropertySetMixinImpl::Impl::setProperty(
523 css::uno::Reference
< css::uno::XInterface
> const & object
,
524 rtl::OUString
const & name
, css::uno::Any
const & value
, bool isAmbiguous
,
525 bool isDefaulted
, sal_Int16 illegalArgumentPosition
) const
527 PropertyMap::const_iterator
i(properties
.find(name
));
528 if (i
== properties
.end()) {
529 throw css::beans::UnknownPropertyException(name
, object
);
532 && ((i
->second
.property
.Attributes
533 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
536 && ((i
->second
.property
.Attributes
537 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
540 throw css::lang::IllegalArgumentException(
542 "flagging as ambiguous/defaulted non-ambiguous/defaulted"
545 object
, illegalArgumentPosition
);
547 css::uno::Reference
< css::reflection::XIdlField2
> f(
548 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
);
549 css::uno::Any
o(object
->queryInterface(m_type
));
553 (css::uno::Reference
< css::reflection::XIdlField2
>(
554 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
)->
556 ((i
->second
.property
.Attributes
557 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
560 ((i
->second
.property
.Attributes
561 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
564 ((i
->second
.property
.Attributes
565 & css::beans::PropertyAttribute::MAYBEVOID
)
569 } catch (css::lang::IllegalArgumentException
& e
) {
570 if (e
.ArgumentPosition
== 1) {
571 throw css::lang::IllegalArgumentException(
572 e
.Message
, object
, illegalArgumentPosition
);
574 throw css::uno::RuntimeException(
577 " com.sun.star.lang.IllegalArgumentException: ")
581 } catch (css::lang::IllegalAccessException
&) {
582 //TODO Clarify whether PropertyVetoException is the correct exception
583 // to throw when trying to set a read-only property:
584 throw css::beans::PropertyVetoException(
585 (rtl::OUString("cannot set read-only property ")
588 } catch (css::lang::WrappedTargetRuntimeException
& e
) {
589 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
590 // guaranteed to originate directly within XIdlField2.get (and thus have
591 // the expected semantics); it might also be passed through from lower
593 if (e
.TargetException
.isExtractableTo(
595 static_cast< css::beans::UnknownPropertyException
* >(0)))
596 && ((i
->second
.property
.Attributes
597 & css::beans::PropertyAttribute::OPTIONAL
)
600 throw css::beans::UnknownPropertyException(name
, object
);
601 } else if (e
.TargetException
.isExtractableTo(
603 static_cast< css::beans::PropertyVetoException
* >(
605 && ((i
->second
.property
.Attributes
606 & css::beans::PropertyAttribute::CONSTRAINED
)
609 css::beans::PropertyVetoException exc
;
610 e
.TargetException
>>= exc
;
611 if (exc
.Message
.isEmpty() )
612 throw css::beans::PropertyVetoException("Invalid " + name
, object
);
616 throw css::lang::WrappedTargetException(
617 e
.Message
, object
, e
.TargetException
);
622 css::uno::Any
PropertySetMixinImpl::Impl::getProperty(
623 css::uno::Reference
< css::uno::XInterface
> const & object
,
624 rtl::OUString
const & name
, css::beans::PropertyState
* state
) const
626 PropertyMap::const_iterator
i(properties
.find(name
));
627 if (i
== properties
.end()) {
628 throw css::beans::UnknownPropertyException(name
, object
);
630 css::uno::Reference
< css::reflection::XIdlField2
> field(
631 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
);
634 value
= field
->get(object
->queryInterface(m_type
));
635 } catch (css::lang::IllegalArgumentException
& e
) {
636 throw css::uno::RuntimeException(
638 "unexpected com.sun.star.lang.IllegalArgumentException: ")
641 } catch (css::lang::WrappedTargetRuntimeException
& e
) {
642 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
643 // guaranteed to originate directly within XIdlField2.get (and thus have
644 // the expected semantics); it might also be passed through from lower
646 if (e
.TargetException
.isExtractableTo(
648 static_cast< css::beans::UnknownPropertyException
* >(0)))
649 && ((i
->second
.property
.Attributes
650 & css::beans::PropertyAttribute::OPTIONAL
)
653 throw css::beans::UnknownPropertyException(name
, object
);
655 throw css::lang::WrappedTargetException(
656 e
.Message
, object
, e
.TargetException
);
660 = ((i
->second
.property
.Attributes
661 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
664 = ((i
->second
.property
.Attributes
665 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
668 = ((i
->second
.property
.Attributes
669 & css::beans::PropertyAttribute::MAYBEVOID
)
671 bool isAmbiguous
= false;
672 bool isDefaulted
= false;
673 while (undoAmbiguous
|| undoDefaulted
|| undoOptional
) {
675 && value
.getValueTypeName().matchAsciiL(
676 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<")))
678 css::uno::Reference
< css::reflection::XIdlClass
> ambiguous(
679 getReflection(value
.getValueTypeName()));
681 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
683 rtl::OUString("IsAmbiguous")),
684 css::uno::UNO_QUERY_THROW
)->get(value
)
687 throw css::uno::RuntimeException(
690 " com.sun.star.beans.Ambiguous IsAmbiguous"
694 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
696 rtl::OUString("Value")),
697 css::uno::UNO_QUERY_THROW
)->get(value
);
698 } catch (css::lang::IllegalArgumentException
& e
) {
699 throw css::uno::RuntimeException(
701 "unexpected com.sun.star.lang."
702 "IllegalArgumentException: ")
706 undoAmbiguous
= false;
707 } else if (undoDefaulted
708 && value
.getValueTypeName().matchAsciiL(
709 RTL_CONSTASCII_STRINGPARAM(
710 "com.sun.star.beans.Defaulted<")))
712 css::uno::Reference
< css::reflection::XIdlClass
> defaulted(
713 getReflection(value
.getValueTypeName()));
716 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
718 rtl::OUString("IsDefaulted")),
719 css::uno::UNO_QUERY_THROW
)->get(value
)
722 throw css::uno::RuntimeException(
725 " com.sun.star.beans.Defaulted IsDefaulted"
729 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
731 rtl::OUString("Value")),
732 css::uno::UNO_QUERY_THROW
)->get(value
);
733 } catch (css::lang::IllegalArgumentException
& e
) {
734 throw css::uno::RuntimeException(
736 "unexpected com.sun.star.lang."
737 "IllegalArgumentException: ")
741 undoDefaulted
= false;
742 } else if (undoOptional
743 && value
.getValueTypeName().matchAsciiL(
744 RTL_CONSTASCII_STRINGPARAM(
745 "com.sun.star.beans.Optional<")))
747 css::uno::Reference
< css::reflection::XIdlClass
> optional(
748 getReflection(value
.getValueTypeName()));
750 bool present
= false;
751 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
753 rtl::OUString("IsPresent")),
754 css::uno::UNO_QUERY_THROW
)->get(value
)
757 throw css::uno::RuntimeException(
759 "unexpected type of com.sun.star.beans.Optional"
760 " IsPresent member"),
767 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
769 rtl::OUString("Value")),
770 css::uno::UNO_QUERY_THROW
)->get(value
);
771 } catch (css::lang::IllegalArgumentException
& e
) {
772 throw css::uno::RuntimeException(
774 "unexpected com.sun.star.lang."
775 "IllegalArgumentException: ")
779 undoOptional
= false;
781 throw css::uno::RuntimeException(
783 "unexpected type of attribute ")
789 //XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE
790 // over DEFAULT_VALUE:
792 ? css::beans::PropertyState_AMBIGUOUS_VALUE
794 ? css::beans::PropertyState_DEFAULT_VALUE
795 : css::beans::PropertyState_DIRECT_VALUE
;
800 css::uno::Reference
< css::reflection::XIdlClass
>
801 PropertySetMixinImpl::Impl::getReflection(rtl::OUString
const & typeName
) const
803 css::uno::Reference
< css::lang::XMultiComponentFactory
> factory(
804 m_context
->getServiceManager(), css::uno::UNO_QUERY_THROW
);
805 AutoDispose
< css::reflection::XIdlReflection
> refl
;
807 refl
.ifc
= css::uno::Reference
< css::reflection::XIdlReflection
>(
808 factory
->createInstanceWithContext(
810 "com.sun.star.reflection.CoreReflection"),
812 css::uno::UNO_QUERY_THROW
);
813 } catch (css::uno::RuntimeException
&) {
815 } catch (css::uno::Exception
& e
) {
816 throw css::uno::DeploymentException(
818 "component context fails to supply service"
819 " com.sun.star.reflection.CoreReflection: ")
823 css::uno::Reference
< css::reflection::XIdlClass
> idlClass(
824 refl
.ifc
->forName(typeName
), css::uno::UNO_QUERY_THROW
);
829 css::uno::Any
PropertySetMixinImpl::Impl::wrapValue(
830 css::uno::Reference
< css::uno::XInterface
> const & object
,
831 css::uno::Any
const & value
,
832 css::uno::Reference
< css::reflection::XIdlClass
> const & type
,
833 bool wrapAmbiguous
, bool isAmbiguous
, bool wrapDefaulted
, bool isDefaulted
,
837 (wrapAmbiguous
|| !isAmbiguous
) && (wrapDefaulted
|| !isDefaulted
));
839 && type
->getName().matchAsciiL(
840 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Ambiguous<")))
843 type
->createObject(strct
);
845 css::uno::Reference
< css::reflection::XIdlField2
> field(
847 rtl::OUString("Value")),
848 css::uno::UNO_QUERY_THROW
);
852 object
, value
, field
->getType(), false, false,
853 wrapDefaulted
, isDefaulted
, wrapOptional
));
854 css::uno::Reference
< css::reflection::XIdlField2
>(
856 rtl::OUString("IsAmbiguous")),
857 css::uno::UNO_QUERY_THROW
)->set(
858 strct
, css::uno::makeAny(isAmbiguous
));
859 } catch (css::lang::IllegalArgumentException
& e
) {
860 throw css::uno::RuntimeException(
863 " com.sun.star.lang.IllegalArgumentException: ")
866 } catch (css::lang::IllegalAccessException
& e
) {
867 throw css::uno::RuntimeException(
870 " com.sun.star.lang.IllegalAccessException: ")
875 } else if (wrapDefaulted
876 && type
->getName().matchAsciiL(
877 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Defaulted<")))
880 type
->createObject(strct
);
882 css::uno::Reference
< css::reflection::XIdlField2
> field(
884 rtl::OUString("Value")),
885 css::uno::UNO_QUERY_THROW
);
889 object
, value
, field
->getType(), wrapAmbiguous
, isAmbiguous
,
890 false, false, wrapOptional
));
891 css::uno::Reference
< css::reflection::XIdlField2
>(
893 rtl::OUString("IsDefaulted")),
894 css::uno::UNO_QUERY_THROW
)->set(
895 strct
, css::uno::makeAny(isDefaulted
));
896 } catch (css::lang::IllegalArgumentException
& e
) {
897 throw css::uno::RuntimeException(
900 " com.sun.star.lang.IllegalArgumentException: ")
903 } catch (css::lang::IllegalAccessException
& e
) {
904 throw css::uno::RuntimeException(
907 " com.sun.star.lang.IllegalAccessException: ")
912 } else if (wrapOptional
913 && type
->getName().matchAsciiL(
914 RTL_CONSTASCII_STRINGPARAM("com.sun.star.beans.Optional<")))
917 type
->createObject(strct
);
918 bool present
= value
.hasValue();
920 css::uno::Reference
< css::reflection::XIdlField2
>(
922 rtl::OUString("IsPresent")),
923 css::uno::UNO_QUERY_THROW
)->set(
924 strct
, css::uno::makeAny(present
));
926 css::uno::Reference
< css::reflection::XIdlField2
> field(
928 rtl::OUString("Value")),
929 css::uno::UNO_QUERY_THROW
);
933 object
, value
, field
->getType(), wrapAmbiguous
,
934 isAmbiguous
, wrapDefaulted
, isDefaulted
, false));
936 } catch (css::lang::IllegalArgumentException
& e
) {
937 throw css::uno::RuntimeException(
940 " com.sun.star.lang.IllegalArgumentException: ")
943 } catch (css::lang::IllegalAccessException
& e
) {
944 throw css::uno::RuntimeException(
947 " com.sun.star.lang.IllegalAccessException: ")
953 if (wrapAmbiguous
|| wrapDefaulted
|| wrapOptional
) {
954 throw css::uno::RuntimeException(
956 "unexpected type of attribute"),
963 PropertySetMixinImpl::PropertySetMixinImpl(
964 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
965 Implements implements
,
966 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
967 css::uno::Type
const & type
)
969 m_impl
= new Impl(context
, implements
, absentOptional
, type
);
973 PropertySetMixinImpl::~PropertySetMixinImpl() {
977 void PropertySetMixinImpl::checkUnknown(rtl::OUString
const & propertyName
) {
978 if (!propertyName
.isEmpty()) {
980 static_cast< css::beans::XPropertySet
* >(this), propertyName
);
984 void PropertySetMixinImpl::prepareSet(
985 rtl::OUString
const & propertyName
, css::uno::Any
const & oldValue
,
986 css::uno::Any
const & newValue
, BoundListeners
* boundListeners
)
988 Impl::PropertyMap::const_iterator
it(m_impl
->properties
.find(propertyName
));
989 OSL_ASSERT(it
!= m_impl
->properties
.end());
990 Impl::VetoListenerBag specificVeto
;
991 Impl::VetoListenerBag unspecificVeto
;
993 osl::MutexGuard
g(m_impl
->mutex
);
994 if (m_impl
->disposed
) {
995 throw css::lang::DisposedException(
996 rtl::OUString("disposed"),
997 static_cast< css::beans::XPropertySet
* >(this));
999 if ((it
->second
.property
.Attributes
1000 & css::beans::PropertyAttribute::CONSTRAINED
)
1003 Impl::VetoListenerMap::const_iterator
i(
1004 m_impl
->vetoListeners
.find(propertyName
));
1005 if (i
!= m_impl
->vetoListeners
.end()) {
1006 specificVeto
= i
->second
;
1008 i
= m_impl
->vetoListeners
.find(rtl::OUString());
1009 if (i
!= m_impl
->vetoListeners
.end()) {
1010 unspecificVeto
= i
->second
;
1013 if ((it
->second
.property
.Attributes
1014 & css::beans::PropertyAttribute::BOUND
)
1017 OSL_ASSERT(boundListeners
!= 0);
1018 Impl::BoundListenerMap::const_iterator
i(
1019 m_impl
->boundListeners
.find(propertyName
));
1020 if (i
!= m_impl
->boundListeners
.end()) {
1021 boundListeners
->m_impl
->specificListeners
= i
->second
;
1023 i
= m_impl
->boundListeners
.find(rtl::OUString());
1024 if (i
!= m_impl
->boundListeners
.end()) {
1025 boundListeners
->m_impl
->unspecificListeners
= i
->second
;
1029 if ((it
->second
.property
.Attributes
1030 & css::beans::PropertyAttribute::CONSTRAINED
)
1033 css::beans::PropertyChangeEvent
event(
1034 static_cast< css::beans::XPropertySet
* >(this), propertyName
,
1035 false, it
->second
.property
.Handle
, oldValue
, newValue
);
1036 for (Impl::VetoListenerBag::iterator
i(specificVeto
.begin());
1037 i
!= specificVeto
.end(); ++i
)
1040 (*i
)->vetoableChange(event
);
1041 } catch (css::lang::DisposedException
&) {}
1043 for (Impl::VetoListenerBag::iterator
i(unspecificVeto
.begin());
1044 i
!= unspecificVeto
.end(); ++i
)
1047 (*i
)->vetoableChange(event
);
1048 } catch (css::lang::DisposedException
&) {}
1051 if ((it
->second
.property
.Attributes
& css::beans::PropertyAttribute::BOUND
)
1054 OSL_ASSERT(boundListeners
!= 0);
1055 boundListeners
->m_impl
->event
= css::beans::PropertyChangeEvent(
1056 static_cast< css::beans::XPropertySet
* >(this), propertyName
,
1057 false, it
->second
.property
.Handle
, oldValue
, newValue
);
1061 void PropertySetMixinImpl::dispose() {
1062 Impl::BoundListenerMap boundListeners
;
1063 Impl::VetoListenerMap vetoListeners
;
1065 osl::MutexGuard
g(m_impl
->mutex
);
1066 boundListeners
.swap(m_impl
->boundListeners
);
1067 vetoListeners
.swap(m_impl
->vetoListeners
);
1068 m_impl
->disposed
= true;
1070 css::lang::EventObject
event(
1071 static_cast< css::beans::XPropertySet
* >(this));
1072 for (Impl::BoundListenerMap::iterator
i(boundListeners
.begin());
1073 i
!= boundListeners
.end(); ++i
)
1075 for (BoundListenerBag::iterator
j(i
->second
.begin());
1076 j
!= i
->second
.end(); ++j
)
1078 (*j
)->disposing(event
);
1081 for (Impl::VetoListenerMap::iterator
i(vetoListeners
.begin());
1082 i
!= vetoListeners
.end(); ++i
)
1084 for (Impl::VetoListenerBag::iterator
j(i
->second
.begin());
1085 j
!= i
->second
.end(); ++j
)
1087 (*j
)->disposing(event
);
1092 css::uno::Any
PropertySetMixinImpl::queryInterface(css::uno::Type
const & type
)
1093 throw (css::uno::RuntimeException
)
1095 if (((m_impl
->implements
& IMPLEMENTS_PROPERTY_SET
) != 0
1096 && type
== css::beans::XPropertySet::static_type()))
1098 css::uno::Reference
< css::uno::XInterface
> ifc(
1099 static_cast< css::beans::XPropertySet
* >(this));
1100 return css::uno::Any(&ifc
, type
);
1101 } else if ((m_impl
->implements
& IMPLEMENTS_FAST_PROPERTY_SET
) != 0
1102 && type
== css::beans::XFastPropertySet::static_type())
1104 css::uno::Reference
< css::uno::XInterface
> ifc(
1105 static_cast< css::beans::XFastPropertySet
* >(this));
1106 return css::uno::Any(&ifc
, type
);
1107 } else if ((m_impl
->implements
& IMPLEMENTS_PROPERTY_ACCESS
) != 0
1108 && type
== css::beans::XPropertyAccess::static_type())
1110 css::uno::Reference
< css::uno::XInterface
> ifc(
1111 static_cast< css::beans::XPropertyAccess
* >(this));
1112 return css::uno::Any(&ifc
, type
);
1114 return css::uno::Any();
1118 css::uno::Reference
< css::beans::XPropertySetInfo
>
1119 PropertySetMixinImpl::getPropertySetInfo() throw (css::uno::RuntimeException
) {
1121 return new Info(m_impl
);
1122 } catch (std::bad_alloc
&) {
1123 //TODO OutOfMemoryException:
1124 throw css::uno::RuntimeException(
1125 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1129 void PropertySetMixinImpl::setPropertyValue(
1130 rtl::OUString
const & propertyName
, css::uno::Any
const & value
)
1132 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1133 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1134 css::uno::RuntimeException
)
1137 m_impl
->setProperty(
1138 static_cast< css::beans::XPropertySet
* >(this), propertyName
,
1139 value
, false, false, 1);
1140 } catch (std::bad_alloc
&) {
1141 //TODO OutOfMemoryException:
1142 throw css::uno::RuntimeException(
1143 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1147 css::uno::Any
PropertySetMixinImpl::getPropertyValue(
1148 rtl::OUString
const & propertyName
)
1150 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1151 css::uno::RuntimeException
)
1154 return m_impl
->getProperty(
1155 static_cast< css::beans::XPropertySet
* >(this), propertyName
, 0);
1156 } catch (std::bad_alloc
&) {
1157 //TODO OutOfMemoryException:
1158 throw css::uno::RuntimeException(
1159 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1163 void PropertySetMixinImpl::addPropertyChangeListener(
1164 rtl::OUString
const & propertyName
,
1165 css::uno::Reference
< css::beans::XPropertyChangeListener
> const & listener
)
1167 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1168 css::uno::RuntimeException
)
1170 css::uno::Reference
< css::beans::XPropertyChangeListener
>(
1171 listener
, css::uno::UNO_QUERY_THROW
); // reject NULL listener
1172 checkUnknown(propertyName
);
1176 osl::MutexGuard
g(m_impl
->mutex
);
1177 disposed
= m_impl
->disposed
;
1179 m_impl
->boundListeners
[propertyName
].insert(listener
);
1183 listener
->disposing(
1184 css::lang::EventObject(
1185 static_cast< css::beans::XPropertySet
* >(this)));
1187 } catch (std::bad_alloc
&) {
1188 //TODO OutOfMemoryException:
1189 throw css::uno::RuntimeException(
1190 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1194 void PropertySetMixinImpl::removePropertyChangeListener(
1195 rtl::OUString
const & propertyName
,
1196 css::uno::Reference
< css::beans::XPropertyChangeListener
> const & listener
)
1198 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1199 css::uno::RuntimeException
)
1201 OSL_ASSERT(listener
.is());
1202 checkUnknown(propertyName
);
1204 osl::MutexGuard
g(m_impl
->mutex
);
1205 Impl::BoundListenerMap::iterator
i(
1206 m_impl
->boundListeners
.find(propertyName
));
1207 if (i
!= m_impl
->boundListeners
.end()) {
1208 BoundListenerBag::iterator
j(i
->second
.find(listener
));
1209 if (j
!= i
->second
.end()) {
1213 } catch (std::bad_alloc
&) {
1214 //TODO OutOfMemoryException:
1215 throw css::uno::RuntimeException(
1216 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1220 void PropertySetMixinImpl::addVetoableChangeListener(
1221 rtl::OUString
const & propertyName
,
1222 css::uno::Reference
< css::beans::XVetoableChangeListener
> const & listener
)
1224 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1225 css::uno::RuntimeException
)
1227 css::uno::Reference
< css::beans::XVetoableChangeListener
>(
1228 listener
, css::uno::UNO_QUERY_THROW
); // reject NULL listener
1229 checkUnknown(propertyName
);
1233 osl::MutexGuard
g(m_impl
->mutex
);
1234 disposed
= m_impl
->disposed
;
1236 m_impl
->vetoListeners
[propertyName
].insert(listener
);
1240 listener
->disposing(
1241 css::lang::EventObject(
1242 static_cast< css::beans::XPropertySet
* >(this)));
1244 } catch (std::bad_alloc
&) {
1245 //TODO OutOfMemoryException:
1246 throw css::uno::RuntimeException(
1247 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1251 void PropertySetMixinImpl::removeVetoableChangeListener(
1252 rtl::OUString
const & propertyName
,
1253 css::uno::Reference
< css::beans::XVetoableChangeListener
> const & listener
)
1255 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1256 css::uno::RuntimeException
)
1258 OSL_ASSERT(listener
.is());
1259 checkUnknown(propertyName
);
1261 osl::MutexGuard
g(m_impl
->mutex
);
1262 Impl::VetoListenerMap::iterator
i(
1263 m_impl
->vetoListeners
.find(propertyName
));
1264 if (i
!= m_impl
->vetoListeners
.end()) {
1265 Impl::VetoListenerBag::iterator
j(i
->second
.find(listener
));
1266 if (j
!= i
->second
.end()) {
1270 } catch (std::bad_alloc
&) {
1271 //TODO OutOfMemoryException:
1272 throw css::uno::RuntimeException(
1273 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1277 void PropertySetMixinImpl::setFastPropertyValue(
1278 sal_Int32 handle
, css::uno::Any
const & value
)
1280 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1281 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1282 css::uno::RuntimeException
)
1285 m_impl
->setProperty(
1286 static_cast< css::beans::XPropertySet
* >(this),
1287 m_impl
->translateHandle(
1288 static_cast< css::beans::XPropertySet
* >(this), handle
),
1289 value
, false, false, 1);
1290 } catch (std::bad_alloc
&) {
1291 //TODO OutOfMemoryException:
1292 throw css::uno::RuntimeException(
1293 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1297 css::uno::Any
PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle
)
1299 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1300 css::uno::RuntimeException
)
1303 return m_impl
->getProperty(
1304 static_cast< css::beans::XPropertySet
* >(this),
1305 m_impl
->translateHandle(
1306 static_cast< css::beans::XPropertySet
* >(this), handle
),
1308 } catch (std::bad_alloc
&) {
1309 //TODO OutOfMemoryException:
1310 throw css::uno::RuntimeException(
1311 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1315 css::uno::Sequence
< css::beans::PropertyValue
>
1316 PropertySetMixinImpl::getPropertyValues() throw (css::uno::RuntimeException
) {
1318 css::uno::Sequence
< css::beans::PropertyValue
> s(
1319 m_impl
->handleMap
.getLength());
1321 for (sal_Int32 i
= 0; i
< m_impl
->handleMap
.getLength(); ++i
) {
1323 s
[n
].Value
= m_impl
->getProperty(
1324 static_cast< css::beans::XPropertySet
* >(this),
1325 m_impl
->handleMap
[i
], &s
[n
].State
);
1326 } catch (css::beans::UnknownPropertyException
&) {
1328 } catch (css::lang::WrappedTargetException
& e
) {
1329 throw css::lang::WrappedTargetRuntimeException(
1330 e
.Message
, static_cast< css::beans::XPropertySet
* >(this),
1333 s
[n
].Name
= m_impl
->handleMap
[i
];
1339 } catch (std::bad_alloc
&) {
1340 //TODO OutOfMemoryException:
1341 throw css::uno::RuntimeException(
1342 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1346 void PropertySetMixinImpl::setPropertyValues(
1347 css::uno::Sequence
< css::beans::PropertyValue
> const & props
)
1349 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1350 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1351 css::uno::RuntimeException
)
1354 for (sal_Int32 i
= 0; i
< props
.getLength(); ++i
) {
1355 if (props
[i
].Handle
!= -1
1357 != m_impl
->translateHandle(
1358 static_cast< css::beans::XPropertySet
* >(this),
1361 throw css::beans::UnknownPropertyException(
1362 (rtl::OUString("name ")
1364 + rtl::OUString(" does not match handle ")
1365 + rtl::OUString::valueOf(props
[i
].Handle
)),
1366 static_cast< css::beans::XPropertySet
* >(this));
1368 m_impl
->setProperty(
1369 static_cast< css::beans::XPropertySet
* >(this), props
[i
].Name
,
1371 props
[i
].State
== css::beans::PropertyState_AMBIGUOUS_VALUE
,
1372 props
[i
].State
== css::beans::PropertyState_DEFAULT_VALUE
, 0);
1374 } catch (std::bad_alloc
&) {
1375 //TODO OutOfMemoryException:
1376 throw css::uno::RuntimeException(
1377 rtl::OUString(), static_cast< css::beans::XPropertySet
* >(this));
1381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */