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 .
20 #include "sal/config.h"
29 #include "com/sun/star/beans/Property.hpp"
30 #include "com/sun/star/beans/PropertyChangeEvent.hpp"
31 #include "com/sun/star/beans/PropertyAttribute.hpp"
32 #include "com/sun/star/beans/PropertyValue.hpp"
33 #include "com/sun/star/beans/PropertyVetoException.hpp"
34 #include "com/sun/star/beans/UnknownPropertyException.hpp"
35 #include "com/sun/star/beans/XFastPropertySet.hpp"
36 #include "com/sun/star/beans/XPropertyAccess.hpp"
37 #include "com/sun/star/beans/XPropertyChangeListener.hpp"
38 #include "com/sun/star/beans/XPropertySet.hpp"
39 #include "com/sun/star/beans/XPropertySetInfo.hpp"
40 #include "com/sun/star/beans/XVetoableChangeListener.hpp"
41 #include "com/sun/star/container/NoSuchElementException.hpp"
42 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
43 #include "com/sun/star/lang/DisposedException.hpp"
44 #include "com/sun/star/lang/EventObject.hpp"
45 #include "com/sun/star/lang/IllegalAccessException.hpp"
46 #include "com/sun/star/lang/IllegalArgumentException.hpp"
47 #include "com/sun/star/lang/WrappedTargetException.hpp"
48 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
49 #include "com/sun/star/reflection/XCompoundTypeDescription.hpp"
50 #include "com/sun/star/reflection/XIdlClass.hpp"
51 #include "com/sun/star/reflection/XIdlField2.hpp"
52 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
53 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
54 #include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp"
55 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
56 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
57 #include "com/sun/star/reflection/XTypeDescription.hpp"
58 #include "com/sun/star/reflection/theCoreReflection.hpp"
59 #include "com/sun/star/uno/Any.hxx"
60 #include "com/sun/star/uno/DeploymentException.hpp"
61 #include "com/sun/star/uno/Exception.hpp"
62 #include "com/sun/star/uno/Reference.hxx"
63 #include "com/sun/star/uno/RuntimeException.hpp"
64 #include "com/sun/star/uno/Sequence.hxx"
65 #include "com/sun/star/uno/Type.hxx"
66 #include "com/sun/star/uno/TypeClass.hpp"
67 #include "com/sun/star/uno/XComponentContext.hpp"
68 #include "com/sun/star/uno/XInterface.hpp"
69 #include "cppuhelper/implbase1.hxx"
70 #include "cppuhelper/propertysetmixin.hxx"
71 #include "cppuhelper/weak.hxx"
72 #include "osl/mutex.hxx"
73 #include "rtl/ref.hxx"
74 #include "rtl/ustring.hxx"
75 #include "sal/types.h"
76 #include "salhelper/simplereferenceobject.hxx"
78 using cppu::PropertySetMixinImpl
;
83 explicit PropertyData(
84 css::beans::Property
const & theProperty
, bool thePresent
):
85 property(theProperty
), present(thePresent
) {}
87 css::beans::Property property
;
91 struct Data
: public salhelper::SimpleReferenceObject
{
92 typedef std::map
< rtl::OUString
, PropertyData
> PropertyMap
;
94 PropertyMap properties
;
96 PropertyMap::const_iterator
get(
97 css::uno::Reference
< css::uno::XInterface
> const & object
,
98 rtl::OUString
const & name
) const;
102 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
103 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
104 std::vector
< rtl::OUString
> * handleNames
)
107 initProperties(type
, absentOptional
, handleNames
, &seen
);
111 typedef std::set
< rtl::OUString
> TypeSet
;
114 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
115 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
116 std::vector
< rtl::OUString
> * handleNames
, TypeSet
* seen
);
118 static css::uno::Reference
< css::reflection::XTypeDescription
>
120 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
);
123 Data::PropertyMap::const_iterator
Data::get(
124 css::uno::Reference
< css::uno::XInterface
> const & object
,
125 rtl::OUString
const & name
) const
127 PropertyMap::const_iterator
i(properties
.find(name
));
128 if (i
== properties
.end() || !i
->second
.present
) {
129 throw css::beans::UnknownPropertyException(name
, object
);
134 void Data::initProperties(
135 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
,
136 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
137 std::vector
< rtl::OUString
> * handleNames
, TypeSet
* seen
)
139 css::uno::Reference
< css::reflection::XInterfaceTypeDescription2
> ifc(
140 resolveTypedefs(type
), css::uno::UNO_QUERY_THROW
);
141 if (seen
->insert(ifc
->getName()).second
) {
143 css::uno::Reference
< css::reflection::XTypeDescription
> > bases(
144 ifc
->getBaseTypes());
145 for (sal_Int32 i
= 0; i
< bases
.getLength(); ++i
) {
146 initProperties(bases
[i
], absentOptional
, handleNames
, seen
);
150 css::reflection::XInterfaceMemberTypeDescription
> > members(
152 rtl::OUString
const * absentBegin
= absentOptional
.getConstArray();
153 rtl::OUString
const * absentEnd
=
154 absentBegin
+ absentOptional
.getLength();
155 for (sal_Int32 i
= 0; i
< members
.getLength(); ++i
) {
156 if (members
[i
]->getTypeClass()
157 == css::uno::TypeClass_INTERFACE_ATTRIBUTE
)
160 css::reflection::XInterfaceAttributeTypeDescription2
> attr(
161 members
[i
], css::uno::UNO_QUERY_THROW
);
162 sal_Int16 attrAttribs
= 0;
163 if (attr
->isBound()) {
164 attrAttribs
|= css::beans::PropertyAttribute::BOUND
;
166 bool setUnknown
= false;
167 if (attr
->isReadOnly()) {
168 attrAttribs
|= css::beans::PropertyAttribute::READONLY
;
173 css::reflection::XCompoundTypeDescription
> > excs(
174 attr
->getGetExceptions());
175 bool getUnknown
= false;
176 //XXX Special interpretation of getter/setter exceptions only
177 // works if the specified exceptions are of the exact type, not
179 for (sal_Int32 j
= 0; j
< excs
.getLength(); ++j
) {
180 if ( excs
[j
]->getName() == "com.sun.star.beans.UnknownPropertyException" )
186 excs
= attr
->getSetExceptions();
187 for (sal_Int32 j
= 0; j
< excs
.getLength(); ++j
) {
188 if ( excs
[j
]->getName() == "com.sun.star.beans.UnknownPropertyException" )
191 } else if ( excs
[j
]->getName() == "com.sun.star.beans.PropertyVetoException" )
194 |= css::beans::PropertyAttribute::CONSTRAINED
;
197 if (getUnknown
&& setUnknown
) {
198 attrAttribs
|= css::beans::PropertyAttribute::OPTIONAL
;
200 css::uno::Reference
< css::reflection::XTypeDescription
> t(
204 t
= resolveTypedefs(t
);
206 if (t
->getName().startsWith(
207 "com.sun.star.beans.Ambiguous<"))
209 n
= css::beans::PropertyAttribute::MAYBEAMBIGUOUS
;
210 } else if (t
->getName().startsWith(
211 "com.sun.star.beans.Defaulted<"))
213 n
= css::beans::PropertyAttribute::MAYBEDEFAULT
;
214 } else if (t
->getName().startsWith(
215 "com.sun.star.beans.Optional<"))
217 n
= css::beans::PropertyAttribute::MAYBEVOID
;
221 if ((attrAttribs
& n
) != 0) {
226 css::uno::Reference
< css::reflection::XTypeDescription
> >
229 css::reflection::XStructTypeDescription
>(
230 t
, css::uno::UNO_QUERY_THROW
)->
232 if (args
.getLength() != 1) {
233 throw css::uno::RuntimeException(
234 "inconsistent UNO type registry",
235 css::uno::Reference
< css::uno::XInterface
>());
239 std::vector
< rtl::OUString
>::size_type handles
240 = handleNames
->size();
241 if (handles
> SAL_MAX_INT32
) {
242 throw css::uno::RuntimeException(
243 "interface type has too many attributes",
244 css::uno::Reference
< css::uno::XInterface
>());
246 rtl::OUString
name(members
[i
]->getMemberName());
247 if (!properties
.insert(
248 PropertyMap::value_type(
251 css::beans::Property(
252 name
, static_cast< sal_Int32
>(handles
),
254 t
->getTypeClass(), t
->getName()),
256 (std::find(absentBegin
, absentEnd
, name
)
260 throw css::uno::RuntimeException(
261 "inconsistent UNO type registry",
262 css::uno::Reference
< css::uno::XInterface
>());
264 handleNames
->push_back(name
);
270 css::uno::Reference
< css::reflection::XTypeDescription
> Data::resolveTypedefs(
271 css::uno::Reference
< css::reflection::XTypeDescription
> const & type
)
273 css::uno::Reference
< css::reflection::XTypeDescription
> t(type
);
274 while (t
->getTypeClass() == css::uno::TypeClass_TYPEDEF
) {
275 t
= css::uno::Reference
< css::reflection::XIndirectTypeDescription
>(
276 t
, css::uno::UNO_QUERY_THROW
)->getReferencedType();
281 class Info
: public cppu::WeakImplHelper1
< css::beans::XPropertySetInfo
> {
283 explicit Info(Data
* data
): m_data(data
) {}
285 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties()
286 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
288 virtual css::beans::Property SAL_CALL
getPropertyByName(
289 rtl::OUString
const & name
)
291 css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
293 virtual sal_Bool SAL_CALL
hasPropertyByName(rtl::OUString
const & name
)
294 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
297 rtl::Reference
< Data
> m_data
;
300 css::uno::Sequence
< css::beans::Property
> Info::getProperties()
301 throw (css::uno::RuntimeException
, std::exception
)
303 assert(m_data
->properties
.size() <= SAL_MAX_INT32
);
304 css::uno::Sequence
< css::beans::Property
> s(
305 static_cast< sal_Int32
>(m_data
->properties
.size()));
307 for (Data::PropertyMap::iterator
i(m_data
->properties
.begin());
308 i
!= m_data
->properties
.end(); ++i
)
310 if (i
->second
.present
) {
311 s
[n
++] = i
->second
.property
;
318 css::beans::Property
Info::getPropertyByName(rtl::OUString
const & name
)
319 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
)
321 return m_data
->get(static_cast< cppu::OWeakObject
* >(this), name
)->
325 sal_Bool
Info::hasPropertyByName(rtl::OUString
const & name
)
326 throw (css::uno::RuntimeException
, std::exception
)
328 Data::PropertyMap::iterator
i(m_data
->properties
.find(name
));
329 return i
!= m_data
->properties
.end() && i
->second
.present
;
333 std::multiset
< css::uno::Reference
< css::beans::XPropertyChangeListener
> >
338 class PropertySetMixinImpl::BoundListeners::Impl
{
340 BoundListenerBag specificListeners
;
341 BoundListenerBag unspecificListeners
;
342 css::beans::PropertyChangeEvent event
;
345 PropertySetMixinImpl::BoundListeners::BoundListeners(): m_impl(new Impl
) {}
347 PropertySetMixinImpl::BoundListeners::~BoundListeners() {
351 void PropertySetMixinImpl::BoundListeners::notify() const {
352 for (BoundListenerBag::const_iterator
i(m_impl
->specificListeners
.begin());
353 i
!= m_impl
->specificListeners
.end(); ++i
)
356 (*i
)->propertyChange(m_impl
->event
);
357 } catch (css::lang::DisposedException
&) {}
359 for (BoundListenerBag::const_iterator
i(
360 m_impl
->unspecificListeners
.begin());
361 i
!= m_impl
->unspecificListeners
.end(); ++i
)
364 (*i
)->propertyChange(m_impl
->event
);
365 } catch (css::lang::DisposedException
&) {}
369 class PropertySetMixinImpl::Impl
: public Data
{
372 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
373 Implements theImplements
,
374 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
375 css::uno::Type
const & type
);
377 rtl::OUString
translateHandle(
378 css::uno::Reference
< css::uno::XInterface
> const & object
,
379 sal_Int32 handle
) const;
382 css::uno::Reference
< css::uno::XInterface
> const & object
,
383 rtl::OUString
const & name
, css::uno::Any
const & value
,
384 bool isAmbiguous
, bool isDefaulted
, sal_Int16 illegalArgumentPosition
)
387 css::uno::Any
getProperty(
388 css::uno::Reference
< css::uno::XInterface
> const & object
,
389 rtl::OUString
const & name
, css::beans::PropertyState
* state
) const;
391 PropertySetMixinImpl::Implements implements
;
392 css::uno::Sequence
< rtl::OUString
> handleMap
;
394 typedef std::map
< rtl::OUString
, BoundListenerBag
> BoundListenerMap
;
397 std::multiset
< css::uno::Reference
< css::beans::XVetoableChangeListener
> >
400 typedef std::map
< rtl::OUString
, VetoListenerBag
> VetoListenerMap
;
402 mutable osl::Mutex mutex
;
403 BoundListenerMap boundListeners
;
404 VetoListenerMap vetoListeners
;
408 css::uno::Reference
< css::reflection::XIdlClass
> getReflection(
409 rtl::OUString
const & typeName
) const;
411 static css::uno::Any
wrapValue(
412 css::uno::Reference
< css::uno::XInterface
> const & object
,
413 css::uno::Any
const & value
,
414 css::uno::Reference
< css::reflection::XIdlClass
> const & type
,
415 bool wrapAmbiguous
, bool isAmbiguous
, bool wrapDefaulted
,
416 bool isDefaulted
, bool wrapOptional
);
418 css::uno::Reference
< css::uno::XComponentContext
> const & m_context
;
419 css::uno::Sequence
< rtl::OUString
> m_absentOptional
;
420 css::uno::Type m_type
;
421 css::uno::Reference
< css::reflection::XIdlClass
> m_idlClass
;
424 PropertySetMixinImpl::Impl::Impl(
425 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
426 Implements theImplements
,
427 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
428 css::uno::Type
const & type
):
429 implements(theImplements
), disposed(false), m_context(context
),
430 m_absentOptional(absentOptional
), m_type(type
)
432 assert(context
.is());
435 & ~(IMPLEMENTS_PROPERTY_SET
| IMPLEMENTS_FAST_PROPERTY_SET
436 | IMPLEMENTS_PROPERTY_ACCESS
))
438 m_idlClass
= getReflection(m_type
.getTypeName());
439 css::uno::Reference
< css::reflection::XTypeDescription
> ifc
;
441 ifc
= css::uno::Reference
< css::reflection::XTypeDescription
>(
442 css::uno::Reference
< css::container::XHierarchicalNameAccess
>(
443 m_context
->getValueByName(
444 "/singletons/com.sun.star.reflection."
445 "theTypeDescriptionManager"),
446 css::uno::UNO_QUERY_THROW
)->getByHierarchicalName(
447 m_type
.getTypeName()),
448 css::uno::UNO_QUERY_THROW
);
449 } catch (css::container::NoSuchElementException
& e
) {
450 throw css::uno::RuntimeException(
451 ("unexpected com.sun.star.container.NoSuchElementException: "
453 css::uno::Reference
< css::uno::XInterface
>());
455 std::vector
< rtl::OUString
> handleNames
;
456 initProperties(ifc
, m_absentOptional
, &handleNames
);
457 std::vector
< rtl::OUString
>::size_type size
= handleNames
.size();
458 assert(size
<= SAL_MAX_INT32
);
459 handleMap
.realloc(static_cast< sal_Int32
>(size
));
460 std::copy(handleNames
.begin(), handleNames
.end(), handleMap
.getArray());
463 rtl::OUString
PropertySetMixinImpl::Impl::translateHandle(
464 css::uno::Reference
< css::uno::XInterface
> const & object
,
465 sal_Int32 handle
) const
467 if (handle
< 0 || handle
>= handleMap
.getLength()) {
468 throw css::beans::UnknownPropertyException(
469 "bad handle " + rtl::OUString::number(handle
), object
);
471 return handleMap
[handle
];
474 void PropertySetMixinImpl::Impl::setProperty(
475 css::uno::Reference
< css::uno::XInterface
> const & object
,
476 rtl::OUString
const & name
, css::uno::Any
const & value
, bool isAmbiguous
,
477 bool isDefaulted
, sal_Int16 illegalArgumentPosition
) const
479 PropertyMap::const_iterator
i(properties
.find(name
));
480 if (i
== properties
.end()) {
481 throw css::beans::UnknownPropertyException(name
, object
);
484 && ((i
->second
.property
.Attributes
485 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
488 && ((i
->second
.property
.Attributes
489 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
492 throw css::lang::IllegalArgumentException(
493 ("flagging as ambiguous/defaulted non-ambiguous/defaulted property "
495 object
, illegalArgumentPosition
);
497 css::uno::Reference
< css::reflection::XIdlField2
> f(
498 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
);
499 css::uno::Any
o(object
->queryInterface(m_type
));
503 (css::uno::Reference
< css::reflection::XIdlField2
>(
504 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
)->
506 ((i
->second
.property
.Attributes
507 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
510 ((i
->second
.property
.Attributes
511 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
514 ((i
->second
.property
.Attributes
515 & css::beans::PropertyAttribute::MAYBEVOID
)
519 } catch (css::lang::IllegalArgumentException
& e
) {
520 if (e
.ArgumentPosition
== 1) {
521 throw css::lang::IllegalArgumentException(
522 e
.Message
, object
, illegalArgumentPosition
);
524 throw css::uno::RuntimeException(
525 ("unexpected com.sun.star.lang.IllegalArgumentException: "
529 } catch (css::lang::IllegalAccessException
&) {
530 //TODO Clarify whether PropertyVetoException is the correct exception
531 // to throw when trying to set a read-only property:
532 throw css::beans::PropertyVetoException(
533 "cannot set read-only property " + name
, object
);
534 } catch (css::lang::WrappedTargetRuntimeException
& e
) {
535 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
536 // guaranteed to originate directly within XIdlField2.get (and thus have
537 // the expected semantics); it might also be passed through from lower
539 if (e
.TargetException
.isExtractableTo(
540 cppu::UnoType
<css::beans::UnknownPropertyException
>::get())
541 && ((i
->second
.property
.Attributes
542 & css::beans::PropertyAttribute::OPTIONAL
)
545 throw css::beans::UnknownPropertyException(name
, object
);
546 } else if (e
.TargetException
.isExtractableTo(
547 cppu::UnoType
<css::beans::PropertyVetoException
>::get())
548 && ((i
->second
.property
.Attributes
549 & css::beans::PropertyAttribute::CONSTRAINED
)
552 css::beans::PropertyVetoException exc
;
553 e
.TargetException
>>= exc
;
554 if (exc
.Message
.isEmpty() )
555 throw css::beans::PropertyVetoException("Invalid " + name
, object
);
559 throw css::lang::WrappedTargetException(
560 e
.Message
, object
, e
.TargetException
);
565 css::uno::Any
PropertySetMixinImpl::Impl::getProperty(
566 css::uno::Reference
< css::uno::XInterface
> const & object
,
567 rtl::OUString
const & name
, css::beans::PropertyState
* state
) const
569 PropertyMap::const_iterator
i(properties
.find(name
));
570 if (i
== properties
.end()) {
571 throw css::beans::UnknownPropertyException(name
, object
);
573 css::uno::Reference
< css::reflection::XIdlField2
> field(
574 m_idlClass
->getField(name
), css::uno::UNO_QUERY_THROW
);
577 value
= field
->get(object
->queryInterface(m_type
));
578 } catch (css::lang::IllegalArgumentException
& e
) {
579 throw css::uno::RuntimeException(
580 ("unexpected com.sun.star.lang.IllegalArgumentException: "
583 } catch (css::lang::WrappedTargetRuntimeException
& e
) {
584 //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not
585 // guaranteed to originate directly within XIdlField2.get (and thus have
586 // the expected semantics); it might also be passed through from lower
588 if (e
.TargetException
.isExtractableTo(
589 cppu::UnoType
<css::beans::UnknownPropertyException
>::get())
590 && ((i
->second
.property
.Attributes
591 & css::beans::PropertyAttribute::OPTIONAL
)
594 throw css::beans::UnknownPropertyException(name
, object
);
596 throw css::lang::WrappedTargetException(
597 e
.Message
, object
, e
.TargetException
);
601 = ((i
->second
.property
.Attributes
602 & css::beans::PropertyAttribute::MAYBEAMBIGUOUS
)
605 = ((i
->second
.property
.Attributes
606 & css::beans::PropertyAttribute::MAYBEDEFAULT
)
609 = ((i
->second
.property
.Attributes
610 & css::beans::PropertyAttribute::MAYBEVOID
)
612 bool isAmbiguous
= false;
613 bool isDefaulted
= false;
614 while (undoAmbiguous
|| undoDefaulted
|| undoOptional
) {
616 && value
.getValueTypeName().startsWith(
617 "com.sun.star.beans.Ambiguous<"))
619 css::uno::Reference
< css::reflection::XIdlClass
> ambiguous(
620 getReflection(value
.getValueTypeName()));
622 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
623 ambiguous
->getField("IsAmbiguous"),
624 css::uno::UNO_QUERY_THROW
)->get(value
)
627 throw css::uno::RuntimeException(
628 ("unexpected type of com.sun.star.beans.Ambiguous"
629 " IsAmbiguous member"),
632 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
633 ambiguous
->getField("Value"), css::uno::UNO_QUERY_THROW
)->
635 } catch (css::lang::IllegalArgumentException
& e
) {
636 throw css::uno::RuntimeException(
637 ("unexpected com.sun.star.lang.IllegalArgumentException: "
641 undoAmbiguous
= false;
642 } else if (undoDefaulted
643 && value
.getValueTypeName().startsWith(
644 "com.sun.star.beans.Defaulted<"))
646 css::uno::Reference
< css::reflection::XIdlClass
> defaulted(
647 getReflection(value
.getValueTypeName()));
650 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
651 defaulted
->getField("IsDefaulted"),
652 css::uno::UNO_QUERY_THROW
)->get(value
)
655 throw css::uno::RuntimeException(
656 ("unexpected type of com.sun.star.beans.Defaulted"
657 " IsDefaulted member"),
660 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
661 defaulted
->getField("Value"), css::uno::UNO_QUERY_THROW
)->
663 } catch (css::lang::IllegalArgumentException
& e
) {
664 throw css::uno::RuntimeException(
665 ("unexpected com.sun.star.lang.IllegalArgumentException: "
669 undoDefaulted
= false;
670 } else if (undoOptional
671 && value
.getValueTypeName().startsWith(
672 "com.sun.star.beans.Optional<"))
674 css::uno::Reference
< css::reflection::XIdlClass
> optional(
675 getReflection(value
.getValueTypeName()));
677 bool present
= false;
678 if (!(css::uno::Reference
< css::reflection::XIdlField2
>(
679 optional
->getField("IsPresent"),
680 css::uno::UNO_QUERY_THROW
)->get(value
)
683 throw css::uno::RuntimeException(
684 ("unexpected type of com.sun.star.beans.Optional"
685 " IsPresent member"),
692 value
= css::uno::Reference
< css::reflection::XIdlField2
>(
693 optional
->getField("Value"), css::uno::UNO_QUERY_THROW
)->
695 } catch (css::lang::IllegalArgumentException
& e
) {
696 throw css::uno::RuntimeException(
697 ("unexpected com.sun.star.lang.IllegalArgumentException: "
701 undoOptional
= false;
703 throw css::uno::RuntimeException(
704 "unexpected type of attribute " + name
, object
);
708 //XXX If isAmbiguous && isDefaulted, arbitrarily choose AMBIGUOUS_VALUE
709 // over DEFAULT_VALUE:
711 ? css::beans::PropertyState_AMBIGUOUS_VALUE
713 ? css::beans::PropertyState_DEFAULT_VALUE
714 : css::beans::PropertyState_DIRECT_VALUE
;
719 css::uno::Reference
< css::reflection::XIdlClass
>
720 PropertySetMixinImpl::Impl::getReflection(rtl::OUString
const & typeName
) const
722 return css::uno::Reference
< css::reflection::XIdlClass
>(
723 css::reflection::theCoreReflection::get(m_context
)->forName(typeName
),
724 css::uno::UNO_SET_THROW
);
727 css::uno::Any
PropertySetMixinImpl::Impl::wrapValue(
728 css::uno::Reference
< css::uno::XInterface
> const & object
,
729 css::uno::Any
const & value
,
730 css::uno::Reference
< css::reflection::XIdlClass
> const & type
,
731 bool wrapAmbiguous
, bool isAmbiguous
, bool wrapDefaulted
, bool isDefaulted
,
734 assert(wrapAmbiguous
|| !isAmbiguous
);
735 assert(wrapDefaulted
|| !isDefaulted
);
737 && type
->getName().startsWith("com.sun.star.beans.Ambiguous<"))
740 type
->createObject(strct
);
742 css::uno::Reference
< css::reflection::XIdlField2
> field(
743 type
->getField("Value"), css::uno::UNO_QUERY_THROW
);
747 object
, value
, field
->getType(), false, false,
748 wrapDefaulted
, isDefaulted
, wrapOptional
));
749 css::uno::Reference
< css::reflection::XIdlField2
>(
750 type
->getField("IsAmbiguous"), css::uno::UNO_QUERY_THROW
)->set(
751 strct
, css::uno::makeAny(isAmbiguous
));
752 } catch (css::lang::IllegalArgumentException
& e
) {
753 throw css::uno::RuntimeException(
754 ("unexpected com.sun.star.lang.IllegalArgumentException: "
757 } catch (css::lang::IllegalAccessException
& e
) {
758 throw css::uno::RuntimeException(
759 ("unexpected com.sun.star.lang.IllegalAccessException: "
764 } else if (wrapDefaulted
765 && type
->getName().startsWith("com.sun.star.beans.Defaulted<"))
768 type
->createObject(strct
);
770 css::uno::Reference
< css::reflection::XIdlField2
> field(
771 type
->getField("Value"), css::uno::UNO_QUERY_THROW
);
775 object
, value
, field
->getType(), wrapAmbiguous
, isAmbiguous
,
776 false, false, wrapOptional
));
777 css::uno::Reference
< css::reflection::XIdlField2
>(
778 type
->getField("IsDefaulted"), css::uno::UNO_QUERY_THROW
)->set(
779 strct
, css::uno::makeAny(isDefaulted
));
780 } catch (css::lang::IllegalArgumentException
& e
) {
781 throw css::uno::RuntimeException(
782 ("unexpected com.sun.star.lang.IllegalArgumentException: "
785 } catch (css::lang::IllegalAccessException
& e
) {
786 throw css::uno::RuntimeException(
787 ("unexpected com.sun.star.lang.IllegalAccessException: "
792 } else if (wrapOptional
793 && type
->getName().startsWith("com.sun.star.beans.Optional<"))
796 type
->createObject(strct
);
797 bool present
= value
.hasValue();
799 css::uno::Reference
< css::reflection::XIdlField2
>(
800 type
->getField("IsPresent"), css::uno::UNO_QUERY_THROW
)->set(
801 strct
, css::uno::makeAny(present
));
803 css::uno::Reference
< css::reflection::XIdlField2
> field(
804 type
->getField("Value"), css::uno::UNO_QUERY_THROW
);
808 object
, value
, field
->getType(), wrapAmbiguous
,
809 isAmbiguous
, wrapDefaulted
, isDefaulted
, false));
811 } catch (css::lang::IllegalArgumentException
& e
) {
812 throw css::uno::RuntimeException(
813 ("unexpected com.sun.star.lang.IllegalArgumentException: "
816 } catch (css::lang::IllegalAccessException
& e
) {
817 throw css::uno::RuntimeException(
818 ("unexpected com.sun.star.lang.IllegalAccessException: "
824 if (wrapAmbiguous
|| wrapDefaulted
|| wrapOptional
) {
825 throw css::uno::RuntimeException(
826 "unexpected type of attribute", object
);
832 PropertySetMixinImpl::PropertySetMixinImpl(
833 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
834 Implements implements
,
835 css::uno::Sequence
< rtl::OUString
> const & absentOptional
,
836 css::uno::Type
const & type
)
838 m_impl
= new Impl(context
, implements
, absentOptional
, type
);
842 PropertySetMixinImpl::~PropertySetMixinImpl() {
846 void PropertySetMixinImpl::checkUnknown(rtl::OUString
const & propertyName
) {
847 if (!propertyName
.isEmpty()) {
849 static_cast< css::beans::XPropertySet
* >(this), propertyName
);
853 void PropertySetMixinImpl::prepareSet(
854 rtl::OUString
const & propertyName
, css::uno::Any
const & oldValue
,
855 css::uno::Any
const & newValue
, BoundListeners
* boundListeners
)
857 Impl::PropertyMap::const_iterator
it(m_impl
->properties
.find(propertyName
));
858 assert(it
!= m_impl
->properties
.end());
859 Impl::VetoListenerBag specificVeto
;
860 Impl::VetoListenerBag unspecificVeto
;
862 osl::MutexGuard
g(m_impl
->mutex
);
863 if (m_impl
->disposed
) {
864 throw css::lang::DisposedException(
865 "disposed", static_cast< css::beans::XPropertySet
* >(this));
867 if ((it
->second
.property
.Attributes
868 & css::beans::PropertyAttribute::CONSTRAINED
)
871 Impl::VetoListenerMap::const_iterator
i(
872 m_impl
->vetoListeners
.find(propertyName
));
873 if (i
!= m_impl
->vetoListeners
.end()) {
874 specificVeto
= i
->second
;
876 i
= m_impl
->vetoListeners
.find("");
877 if (i
!= m_impl
->vetoListeners
.end()) {
878 unspecificVeto
= i
->second
;
881 if ((it
->second
.property
.Attributes
882 & css::beans::PropertyAttribute::BOUND
)
885 assert(boundListeners
!= 0);
886 Impl::BoundListenerMap::const_iterator
i(
887 m_impl
->boundListeners
.find(propertyName
));
888 if (i
!= m_impl
->boundListeners
.end()) {
889 boundListeners
->m_impl
->specificListeners
= i
->second
;
891 i
= m_impl
->boundListeners
.find("");
892 if (i
!= m_impl
->boundListeners
.end()) {
893 boundListeners
->m_impl
->unspecificListeners
= i
->second
;
897 if ((it
->second
.property
.Attributes
898 & css::beans::PropertyAttribute::CONSTRAINED
)
901 css::beans::PropertyChangeEvent
event(
902 static_cast< css::beans::XPropertySet
* >(this), propertyName
,
903 false, it
->second
.property
.Handle
, oldValue
, newValue
);
904 for (Impl::VetoListenerBag::iterator
i(specificVeto
.begin());
905 i
!= specificVeto
.end(); ++i
)
908 (*i
)->vetoableChange(event
);
909 } catch (css::lang::DisposedException
&) {}
911 for (Impl::VetoListenerBag::iterator
i(unspecificVeto
.begin());
912 i
!= unspecificVeto
.end(); ++i
)
915 (*i
)->vetoableChange(event
);
916 } catch (css::lang::DisposedException
&) {}
919 if ((it
->second
.property
.Attributes
& css::beans::PropertyAttribute::BOUND
)
922 assert(boundListeners
!= 0);
923 boundListeners
->m_impl
->event
= css::beans::PropertyChangeEvent(
924 static_cast< css::beans::XPropertySet
* >(this), propertyName
,
925 false, it
->second
.property
.Handle
, oldValue
, newValue
);
929 void PropertySetMixinImpl::dispose() {
930 Impl::BoundListenerMap boundListeners
;
931 Impl::VetoListenerMap vetoListeners
;
933 osl::MutexGuard
g(m_impl
->mutex
);
934 boundListeners
.swap(m_impl
->boundListeners
);
935 vetoListeners
.swap(m_impl
->vetoListeners
);
936 m_impl
->disposed
= true;
938 css::lang::EventObject
event(
939 static_cast< css::beans::XPropertySet
* >(this));
940 for (Impl::BoundListenerMap::iterator
i(boundListeners
.begin());
941 i
!= boundListeners
.end(); ++i
)
943 for (BoundListenerBag::iterator
j(i
->second
.begin());
944 j
!= i
->second
.end(); ++j
)
946 (*j
)->disposing(event
);
949 for (Impl::VetoListenerMap::iterator
i(vetoListeners
.begin());
950 i
!= vetoListeners
.end(); ++i
)
952 for (Impl::VetoListenerBag::iterator
j(i
->second
.begin());
953 j
!= i
->second
.end(); ++j
)
955 (*j
)->disposing(event
);
960 css::uno::Any
PropertySetMixinImpl::queryInterface(css::uno::Type
const & type
)
961 throw (css::uno::RuntimeException
, std::exception
)
963 if (((m_impl
->implements
& IMPLEMENTS_PROPERTY_SET
) != 0
964 && type
== css::beans::XPropertySet::static_type()))
966 css::uno::Reference
< css::uno::XInterface
> ifc(
967 static_cast< css::beans::XPropertySet
* >(this));
968 return css::uno::Any(&ifc
, type
);
969 } else if ((m_impl
->implements
& IMPLEMENTS_FAST_PROPERTY_SET
) != 0
970 && type
== css::beans::XFastPropertySet::static_type())
972 css::uno::Reference
< css::uno::XInterface
> ifc(
973 static_cast< css::beans::XFastPropertySet
* >(this));
974 return css::uno::Any(&ifc
, type
);
975 } else if ((m_impl
->implements
& IMPLEMENTS_PROPERTY_ACCESS
) != 0
976 && type
== css::beans::XPropertyAccess::static_type())
978 css::uno::Reference
< css::uno::XInterface
> ifc(
979 static_cast< css::beans::XPropertyAccess
* >(this));
980 return css::uno::Any(&ifc
, type
);
982 return css::uno::Any();
986 css::uno::Reference
< css::beans::XPropertySetInfo
>
987 PropertySetMixinImpl::getPropertySetInfo()
988 throw (css::uno::RuntimeException
, std::exception
)
990 return new Info(m_impl
);
993 void PropertySetMixinImpl::setPropertyValue(
994 rtl::OUString
const & propertyName
, css::uno::Any
const & value
)
996 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
997 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
998 css::uno::RuntimeException
, std::exception
)
1000 m_impl
->setProperty(
1001 static_cast< css::beans::XPropertySet
* >(this), propertyName
, value
,
1005 css::uno::Any
PropertySetMixinImpl::getPropertyValue(
1006 rtl::OUString
const & propertyName
)
1008 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1009 css::uno::RuntimeException
, std::exception
)
1011 return m_impl
->getProperty(
1012 static_cast< css::beans::XPropertySet
* >(this), propertyName
, 0);
1015 void PropertySetMixinImpl::addPropertyChangeListener(
1016 rtl::OUString
const & propertyName
,
1017 css::uno::Reference
< css::beans::XPropertyChangeListener
> const & listener
)
1019 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1020 css::uno::RuntimeException
, std::exception
)
1022 css::uno::Reference
< css::beans::XPropertyChangeListener
>(
1023 listener
, css::uno::UNO_SET_THROW
); // reject NULL listener
1024 checkUnknown(propertyName
);
1027 osl::MutexGuard
g(m_impl
->mutex
);
1028 disposed
= m_impl
->disposed
;
1030 m_impl
->boundListeners
[propertyName
].insert(listener
);
1034 listener
->disposing(
1035 css::lang::EventObject(
1036 static_cast< css::beans::XPropertySet
* >(this)));
1040 void PropertySetMixinImpl::removePropertyChangeListener(
1041 rtl::OUString
const & propertyName
,
1042 css::uno::Reference
< css::beans::XPropertyChangeListener
> const & listener
)
1044 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1045 css::uno::RuntimeException
, std::exception
)
1047 assert(listener
.is());
1048 checkUnknown(propertyName
);
1049 osl::MutexGuard
g(m_impl
->mutex
);
1050 Impl::BoundListenerMap::iterator
i(
1051 m_impl
->boundListeners
.find(propertyName
));
1052 if (i
!= m_impl
->boundListeners
.end()) {
1053 BoundListenerBag::iterator
j(i
->second
.find(listener
));
1054 if (j
!= i
->second
.end()) {
1060 void PropertySetMixinImpl::addVetoableChangeListener(
1061 rtl::OUString
const & propertyName
,
1062 css::uno::Reference
< css::beans::XVetoableChangeListener
> const & listener
)
1064 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1065 css::uno::RuntimeException
, std::exception
)
1067 css::uno::Reference
< css::beans::XVetoableChangeListener
>(
1068 listener
, css::uno::UNO_SET_THROW
); // reject NULL listener
1069 checkUnknown(propertyName
);
1072 osl::MutexGuard
g(m_impl
->mutex
);
1073 disposed
= m_impl
->disposed
;
1075 m_impl
->vetoListeners
[propertyName
].insert(listener
);
1079 listener
->disposing(
1080 css::lang::EventObject(
1081 static_cast< css::beans::XPropertySet
* >(this)));
1085 void PropertySetMixinImpl::removeVetoableChangeListener(
1086 rtl::OUString
const & propertyName
,
1087 css::uno::Reference
< css::beans::XVetoableChangeListener
> const & listener
)
1089 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1090 css::uno::RuntimeException
, std::exception
)
1092 assert(listener
.is());
1093 checkUnknown(propertyName
);
1094 osl::MutexGuard
g(m_impl
->mutex
);
1095 Impl::VetoListenerMap::iterator
i(m_impl
->vetoListeners
.find(propertyName
));
1096 if (i
!= m_impl
->vetoListeners
.end()) {
1097 Impl::VetoListenerBag::iterator
j(i
->second
.find(listener
));
1098 if (j
!= i
->second
.end()) {
1104 void PropertySetMixinImpl::setFastPropertyValue(
1105 sal_Int32 handle
, css::uno::Any
const & value
)
1107 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1108 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1109 css::uno::RuntimeException
, std::exception
)
1111 m_impl
->setProperty(
1112 static_cast< css::beans::XPropertySet
* >(this),
1113 m_impl
->translateHandle(
1114 static_cast< css::beans::XPropertySet
* >(this), handle
),
1115 value
, false, false, 1);
1118 css::uno::Any
PropertySetMixinImpl::getFastPropertyValue(sal_Int32 handle
)
1120 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
1121 css::uno::RuntimeException
, std::exception
)
1123 return m_impl
->getProperty(
1124 static_cast< css::beans::XPropertySet
* >(this),
1125 m_impl
->translateHandle(
1126 static_cast< css::beans::XPropertySet
* >(this), handle
),
1130 css::uno::Sequence
< css::beans::PropertyValue
>
1131 PropertySetMixinImpl::getPropertyValues()
1132 throw (css::uno::RuntimeException
, std::exception
)
1134 css::uno::Sequence
< css::beans::PropertyValue
> s(
1135 m_impl
->handleMap
.getLength());
1137 for (sal_Int32 i
= 0; i
< m_impl
->handleMap
.getLength(); ++i
) {
1139 s
[n
].Value
= m_impl
->getProperty(
1140 static_cast< css::beans::XPropertySet
* >(this),
1141 m_impl
->handleMap
[i
], &s
[n
].State
);
1142 } catch (css::beans::UnknownPropertyException
&) {
1144 } catch (css::lang::WrappedTargetException
& e
) {
1145 throw css::lang::WrappedTargetRuntimeException(
1146 e
.Message
, static_cast< css::beans::XPropertySet
* >(this),
1149 s
[n
].Name
= m_impl
->handleMap
[i
];
1157 void PropertySetMixinImpl::setPropertyValues(
1158 css::uno::Sequence
< css::beans::PropertyValue
> const & props
)
1160 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1161 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1162 css::uno::RuntimeException
, std::exception
)
1164 for (sal_Int32 i
= 0; i
< props
.getLength(); ++i
) {
1165 if (props
[i
].Handle
!= -1
1167 != m_impl
->translateHandle(
1168 static_cast< css::beans::XPropertySet
* >(this),
1171 throw css::beans::UnknownPropertyException(
1172 ("name " + props
[i
].Name
+ " does not match handle "
1173 + rtl::OUString::number(props
[i
].Handle
)),
1174 static_cast< css::beans::XPropertySet
* >(this));
1176 m_impl
->setProperty(
1177 static_cast< css::beans::XPropertySet
* >(this), props
[i
].Name
,
1179 props
[i
].State
== css::beans::PropertyState_AMBIGUOUS_VALUE
,
1180 props
[i
].State
== css::beans::PropertyState_DEFAULT_VALUE
, 0);
1184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */