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>
27 #include <com/sun/star/beans/Property.hpp>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
30 #include <com/sun/star/beans/UnknownPropertyException.hpp>
31 #include <com/sun/star/beans/XExactName.hpp>
32 #include <com/sun/star/beans/XHierarchicalPropertySet.hpp>
33 #include <com/sun/star/beans/XHierarchicalPropertySetInfo.hpp>
34 #include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
35 #include <com/sun/star/beans/XMultiPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
37 #include <com/sun/star/beans/XProperty.hpp>
38 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/beans/XPropertySetInfo.hpp>
41 #include <com/sun/star/beans/XVetoableChangeListener.hpp>
42 #include <com/sun/star/container/ContainerEvent.hpp>
43 #include <com/sun/star/container/NoSuchElementException.hpp>
44 #include <com/sun/star/container/XContainer.hpp>
45 #include <com/sun/star/container/XContainerListener.hpp>
46 #include <com/sun/star/container/XElementAccess.hpp>
47 #include <com/sun/star/container/XHierarchicalName.hpp>
48 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
49 #include <com/sun/star/container/XHierarchicalNameReplace.hpp>
50 #include <com/sun/star/container/XNameAccess.hpp>
51 #include <com/sun/star/container/XNameContainer.hpp>
52 #include <com/sun/star/container/XNamed.hpp>
53 #include <com/sun/star/lang/DisposedException.hpp>
54 #include <com/sun/star/lang/EventObject.hpp>
55 #include <com/sun/star/lang/IllegalArgumentException.hpp>
56 #include <com/sun/star/lang/XComponent.hpp>
57 #include <com/sun/star/lang/XEventListener.hpp>
58 #include <com/sun/star/lang/XServiceInfo.hpp>
59 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
60 #include <com/sun/star/lang/XTypeProvider.hpp>
61 #include <com/sun/star/uno/Any.hxx>
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/XInterface.hpp>
67 #include <com/sun/star/uno/XWeak.hpp>
68 #include <com/sun/star/util/ElementChange.hpp>
69 #include <comphelper/sequence.hxx>
70 #include <comphelper/servicehelper.hxx>
71 #include <comphelper/string.hxx>
72 #include <comphelper/lok.hxx>
73 #include <i18nlangtag/languagetag.hxx>
74 #include <cppu/unotype.hxx>
75 #include <cppuhelper/queryinterface.hxx>
76 #include <cppuhelper/supportsservice.hxx>
77 #include <cppuhelper/weak.hxx>
78 #include <osl/interlck.h>
79 #include <osl/mutex.hxx>
80 #include <rtl/character.hxx>
81 #include <rtl/ref.hxx>
82 #include <rtl/ustrbuf.hxx>
83 #include <rtl/ustring.hxx>
84 #include <sal/log.hxx>
85 #include <sal/types.h>
88 #include "broadcaster.hxx"
89 #include "childaccess.hxx"
90 #include "components.hxx"
92 #include "groupnode.hxx"
93 #include "localizedpropertynode.hxx"
94 #include "localizedvaluenode.hxx"
96 #include "modifications.hxx"
98 #include "nodemap.hxx"
99 #include "propertynode.hxx"
100 #include "rootaccess.hxx"
101 #include "setnode.hxx"
104 namespace configmgr
{
108 // Conservatively forbid what is either not an XML Char (including lone
109 // surrogates, even though they should not appear in well-formed UNO OUString
110 // instances anyway), or is a slash (as it causes problems in path syntax):
111 bool isValidName(OUString
const & name
, bool setMember
) {
112 for (sal_Int32 i
= 0; i
!= name
.getLength();) {
113 sal_uInt32 c
= name
.iterateCodePoints(&i
);
114 if ((c
< 0x20 && !(c
== 0x09 || c
== 0x0A || c
== 0x0D))
115 || rtl::isSurrogate(c
) || c
== 0xFFFE || c
== 0xFFFF
116 || (!setMember
&& c
== '/'))
121 return !name
.isEmpty();
126 oslInterlockedCount
Access::acquireCounting() {
127 return osl_atomic_increment(&m_refCount
);
130 void Access::releaseNondeleting() {
131 osl_atomic_decrement(&m_refCount
);
134 bool Access::isValue() {
135 rtl::Reference
< Node
> p(getNode());
137 case Node::KIND_PROPERTY
:
138 case Node::KIND_LOCALIZED_VALUE
:
140 case Node::KIND_LOCALIZED_PROPERTY
:
141 return !Components::allLocales(getRootAccess()->getLocale());
147 void Access::markChildAsModified(rtl::Reference
< ChildAccess
> const & child
) {
148 assert(child
.is() && child
->getParentAccess() == this);
149 modifiedChildren_
[child
->getNameInternal()] = ModifiedChild(child
, true);
150 for (rtl::Reference
< Access
> p(this);;) {
151 rtl::Reference
< Access
> parent(p
->getParentAccess());
155 assert(dynamic_cast< ChildAccess
* >(p
.get()) != nullptr);
156 parent
->modifiedChildren_
.emplace(
157 p
->getNameInternal(),
158 ModifiedChild(static_cast< ChildAccess
* >(p
.get()), false));
163 void Access::releaseChild(OUString
const & name
) {
164 cachedChildren_
.erase(name
);
167 void Access::initBroadcaster(
168 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
)
170 initBroadcasterAndChanges(modifications
, broadcaster
, nullptr);
173 css::uno::Sequence
< css::uno::Type
> Access::getTypes()
175 assert(thisIs(IS_ANY
));
176 osl::MutexGuard
g(*lock_
);
177 checkLocalizedPropertyAccess();
178 std::vector
< css::uno::Type
> types
{ cppu::UnoType
< css::uno::XInterface
>::get(),
179 cppu::UnoType
< css::uno::XWeak
>::get(),
180 cppu::UnoType
< css::lang::XTypeProvider
>::get(),
181 cppu::UnoType
< css::lang::XServiceInfo
>::get(),
182 cppu::UnoType
< css::lang::XComponent
>::get(),
183 cppu::UnoType
< css::container::XContainer
>::get(),
184 cppu::UnoType
< css::beans::XExactName
>::get(),
185 cppu::UnoType
< css::container::XHierarchicalName
>::get(),
186 cppu::UnoType
< css::container::XNamed
>::get(),
187 cppu::UnoType
< css::beans::XProperty
>::get(),
188 cppu::UnoType
< css::container::XElementAccess
>::get(),
189 cppu::UnoType
< css::container::XNameAccess
>::get()
191 if (getNode()->kind() == Node::KIND_GROUP
) {
192 types
.push_back(cppu::UnoType
< css::beans::XPropertySetInfo
>::get());
193 types
.push_back(cppu::UnoType
< css::beans::XPropertySet
>::get());
194 types
.push_back(cppu::UnoType
< css::beans::XMultiPropertySet
>::get());
196 cppu::UnoType
< css::beans::XHierarchicalPropertySet
>::get());
198 cppu::UnoType
< css::beans::XMultiHierarchicalPropertySet
>::get());
200 cppu::UnoType
< css::beans::XHierarchicalPropertySetInfo
>::get());
202 if (getRootAccess()->isUpdate()) {
203 types
.push_back(cppu::UnoType
< css::container::XNameReplace
>::get());
205 cppu::UnoType
< css::container::XHierarchicalNameReplace
>::get());
206 if (getNode()->kind() != Node::KIND_GROUP
||
207 static_cast< GroupNode
* >(getNode().get())->isExtensible())
210 cppu::UnoType
< css::container::XNameContainer
>::get());
212 if (getNode()->kind() == Node::KIND_SET
) {
214 cppu::UnoType
< css::lang::XSingleServiceFactory
>::get());
218 cppu::UnoType
< css::container::XHierarchicalNameAccess
>::get());
221 return comphelper::containerToSequence(types
);
224 css::uno::Sequence
< sal_Int8
> Access::getImplementationId()
226 assert(thisIs(IS_ANY
));
227 osl::MutexGuard
g(*lock_
);
228 checkLocalizedPropertyAccess();
229 return css::uno::Sequence
< sal_Int8
>();
232 OUString
Access::getImplementationName()
234 assert(thisIs(IS_ANY
));
235 osl::MutexGuard
g(*lock_
);
236 checkLocalizedPropertyAccess();
237 return "org.openoffice-configmgr::Access";
240 sal_Bool
Access::supportsService(OUString
const & ServiceName
)
242 return cppu::supportsService(this, ServiceName
);
245 css::uno::Sequence
< OUString
> Access::getSupportedServiceNames()
247 assert(thisIs(IS_ANY
));
248 osl::MutexGuard
g(*lock_
);
249 checkLocalizedPropertyAccess();
250 std::vector
<OUString
> services
;
251 services
.emplace_back("com.sun.star.configuration.ConfigurationAccess");
252 if (getRootAccess()->isUpdate()) {
253 services
.emplace_back("com.sun.star.configuration.ConfigurationUpdateAccess");
255 services
.emplace_back("com.sun.star.configuration.HierarchyAccess");
256 services
.emplace_back("com.sun.star.configuration.HierarchyElement");
257 if (getNode()->kind() == Node::KIND_GROUP
) {
258 services
.emplace_back("com.sun.star.configuration.GroupAccess");
259 services
.emplace_back("com.sun.star.configuration.PropertyHierarchy");
260 if (getRootAccess()->isUpdate()) {
261 services
.emplace_back("com.sun.star.configuration.GroupUpdate");
264 services
.emplace_back("com.sun.star.configuration.SetAccess");
265 services
.emplace_back("com.sun.star.configuration.SimpleSetAccess");
266 if (getRootAccess()->isUpdate()) {
267 services
.emplace_back("com.sun.star.configuration.SetUpdate");
268 services
.emplace_back("com.sun.star.configuration.SimpleSetUpdate");
271 addSupportedServiceNames(&services
);
272 return comphelper::containerToSequence(services
);
275 void Access::dispose() {
276 assert(thisIs(IS_ANY
));
279 osl::MutexGuard
g(*lock_
);
280 checkLocalizedPropertyAccess();
281 if (getParentAccess().is()) {
282 throw css::uno::RuntimeException(
283 "configmgr dispose inappropriate Access",
284 static_cast< cppu::OWeakObject
* >(this));
289 initDisposeBroadcaster(&bc
);
296 void Access::addEventListener(
297 css::uno::Reference
< css::lang::XEventListener
> const & xListener
)
299 assert(thisIs(IS_ANY
));
301 osl::MutexGuard
g(*lock_
);
302 checkLocalizedPropertyAccess();
303 if (!xListener
.is()) {
304 throw css::uno::RuntimeException(
305 "null listener", static_cast< cppu::OWeakObject
* >(this));
308 disposeListeners_
.insert(xListener
);
313 xListener
->disposing(
314 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
315 } catch (css::lang::DisposedException
&) {}
318 void Access::removeEventListener(
319 css::uno::Reference
< css::lang::XEventListener
> const & aListener
)
321 assert(thisIs(IS_ANY
));
322 osl::MutexGuard
g(*lock_
);
323 checkLocalizedPropertyAccess();
324 DisposeListeners::iterator
i(disposeListeners_
.find(aListener
));
325 if (i
!= disposeListeners_
.end()) {
326 disposeListeners_
.erase(i
);
330 css::uno::Type
Access::getElementType() {
331 assert(thisIs(IS_ANY
));
332 osl::MutexGuard
g(*lock_
);
333 checkLocalizedPropertyAccess();
334 rtl::Reference
< Node
> p(getNode());
336 case Node::KIND_LOCALIZED_PROPERTY
:
338 static_cast< LocalizedPropertyNode
* >(p
.get())->getStaticType());
339 case Node::KIND_GROUP
:
340 //TODO: Should a specific type be returned for a non-extensible group
341 // with homogeneous members or for an extensible group that currently
342 // has only homogeneous members?
343 return cppu::UnoType
<void>::get();
345 return cppu::UnoType
<void>::get(); //TODO: correct?
348 throw css::uno::RuntimeException(
349 "this cannot happen", static_cast< cppu::OWeakObject
* >(this));
353 sal_Bool
Access::hasElements() {
354 assert(thisIs(IS_ANY
));
355 osl::MutexGuard
g(*lock_
);
356 checkLocalizedPropertyAccess();
357 return !getAllChildren().empty(); //TODO: optimize
360 bool Access::getByNameFast(const OUString
& name
, css::uno::Any
& value
)
362 bool bGotValue
= false;
363 rtl::Reference
< ChildAccess
> child
;
365 if (getNode()->kind() != Node::KIND_LOCALIZED_PROPERTY
)
366 { // try to get it directly
367 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
368 if (i
!= modifiedChildren_
.end())
370 child
= getModifiedChild(i
);
373 value
= child
->asValue();
379 rtl::Reference
< Node
> node(getNode()->getMember(name
));
382 bGotValue
= ChildAccess::asSimpleValue(node
, value
, components_
);
388 child
= getChild(name
);
391 value
= child
->asValue();
396 css::uno::Any
Access::getByName(OUString
const & aName
)
398 assert(thisIs(IS_ANY
));
399 osl::MutexGuard
g(*lock_
);
400 checkLocalizedPropertyAccess();
402 if (!getByNameFast(aName
, value
))
403 throw css::container::NoSuchElementException(
404 aName
, static_cast< cppu::OWeakObject
* >(this));
408 css::uno::Sequence
< OUString
> Access::getElementNames()
410 assert(thisIs(IS_ANY
));
411 osl::MutexGuard
g(*lock_
);
412 checkLocalizedPropertyAccess();
413 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
414 css::uno::Sequence
<OUString
> names(children
.size());
415 OUString
* pArray
= names
.getArray();
416 for (auto const& child
: children
)
418 *pArray
++ = child
->getNameInternal();
423 sal_Bool
Access::hasByName(OUString
const & aName
)
425 assert(thisIs(IS_ANY
));
426 osl::MutexGuard
g(*lock_
);
427 checkLocalizedPropertyAccess();
428 return getChild(aName
).is();
431 css::uno::Any
Access::getByHierarchicalName(OUString
const & aName
)
433 assert(thisIs(IS_ANY
));
434 osl::MutexGuard
g(*lock_
);
435 checkLocalizedPropertyAccess();
436 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
438 throw css::container::NoSuchElementException(
439 aName
, static_cast< cppu::OWeakObject
* >(this));
441 return child
->asValue();
444 sal_Bool
Access::hasByHierarchicalName(OUString
const & aName
)
446 assert(thisIs(IS_ANY
));
447 osl::MutexGuard
g(*lock_
);
448 checkLocalizedPropertyAccess();
449 return getSubChild(aName
).is();
452 void Access::replaceByHierarchicalName(
453 OUString
const & aName
, css::uno::Any
const & aElement
)
455 //TODO: Actually support sets and combine with replaceByName:
456 assert(thisIs(IS_UPDATE
));
459 osl::MutexGuard
g(*lock_
);
460 checkLocalizedPropertyAccess();
461 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
463 throw css::container::NoSuchElementException(
464 aName
, static_cast< cppu::OWeakObject
* >(this));
466 child
->checkFinalized();
467 rtl::Reference
< Node
> parent(child
->getParentNode());
469 Modifications localMods
;
470 switch (parent
->kind()) {
471 case Node::KIND_LOCALIZED_PROPERTY
:
472 case Node::KIND_GROUP
:
473 child
->setProperty(aElement
, &localMods
);
476 throw css::lang::IllegalArgumentException(
477 ("configmgr::Access::replaceByHierarchicalName does not"
478 " currently support set members"),
479 static_cast< cppu::OWeakObject
* >(this), 0);
480 case Node::KIND_ROOT
:
481 throw css::lang::IllegalArgumentException(
482 ("configmgr::Access::replaceByHierarchicalName does not allow"
483 " changing component " + aName
),
484 static_cast< cppu::OWeakObject
* >(this), 0);
486 assert(false); // this cannot happen
489 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
494 void Access::addContainerListener(
495 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
497 assert(thisIs(IS_ANY
));
499 osl::MutexGuard
g(*lock_
);
500 checkLocalizedPropertyAccess();
501 if (!xListener
.is()) {
502 throw css::uno::RuntimeException(
503 "null listener", static_cast< cppu::OWeakObject
* >(this));
506 containerListeners_
.insert(xListener
);
511 xListener
->disposing(
512 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
513 } catch (css::lang::DisposedException
&) {}
516 void Access::removeContainerListener(
517 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
519 assert(thisIs(IS_ANY
));
520 osl::MutexGuard
g(*lock_
);
521 checkLocalizedPropertyAccess();
522 ContainerListeners::iterator
i(containerListeners_
.find(xListener
));
523 if (i
!= containerListeners_
.end()) {
524 containerListeners_
.erase(i
);
528 OUString
Access::getExactName(OUString
const & aApproximateName
)
530 assert(thisIs(IS_ANY
));
531 osl::MutexGuard
g(*lock_
);
532 checkLocalizedPropertyAccess();
533 return aApproximateName
;
536 css::uno::Sequence
< css::beans::Property
> Access::getProperties()
538 assert(thisIs(IS_GROUP
));
539 osl::MutexGuard
g(*lock_
);
540 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
541 std::vector
< css::beans::Property
> properties
;
542 properties
.reserve(children
.size());
543 for (auto const& child
: children
)
545 properties
.push_back(child
->asProperty());
547 return comphelper::containerToSequence(properties
);
550 css::beans::Property
Access::getPropertyByName(OUString
const & aName
)
552 assert(thisIs(IS_GROUP
));
553 osl::MutexGuard
g(*lock_
);
554 rtl::Reference
< ChildAccess
> child(getChild(aName
));
556 throw css::beans::UnknownPropertyException(
557 aName
, static_cast< cppu::OWeakObject
* >(this));
559 return child
->asProperty();
562 sal_Bool
Access::hasPropertyByName(OUString
const & Name
)
564 assert(thisIs(IS_GROUP
));
565 osl::MutexGuard
g(*lock_
);
566 return getChild(Name
).is();
569 OUString
Access::getHierarchicalName() {
570 assert(thisIs(IS_ANY
));
571 osl::MutexGuard
g(*lock_
);
572 checkLocalizedPropertyAccess();
573 // For backwards compatibility, return an absolute path representation where
576 rtl::Reference
< RootAccess
> root(getRootAccess());
578 rootPath
= root
->getAbsolutePathRepresentation();
580 OUString
rel(getRelativePathRepresentation());
581 OUStringBuffer
path(rootPath
);
582 if (!rootPath
.isEmpty() && rootPath
!= "/" && !rel
.isEmpty()) {
586 return path
.makeStringAndClear();
589 OUString
Access::composeHierarchicalName(
590 OUString
const & aRelativeName
)
592 assert(thisIs(IS_ANY
));
593 osl::MutexGuard
g(*lock_
);
594 checkLocalizedPropertyAccess();
595 if (aRelativeName
.isEmpty() || aRelativeName
[0] == '/') {
596 throw css::lang::IllegalArgumentException(
597 "configmgr composeHierarchicalName inappropriate relative name",
598 static_cast< cppu::OWeakObject
* >(this), -1);
600 OUStringBuffer
path(getRelativePathRepresentation());
601 if (!path
.isEmpty()) {
604 path
.append(aRelativeName
);
605 return path
.makeStringAndClear();
608 OUString
Access::getName() {
609 assert(thisIs(IS_ANY
));
610 osl::MutexGuard
g(*lock_
);
611 checkLocalizedPropertyAccess();
612 return getNameInternal();
615 void Access::setName(OUString
const & aName
)
617 assert(thisIs(IS_ANY
));
620 osl::MutexGuard
g(*lock_
);
621 checkLocalizedPropertyAccess();
623 Modifications localMods
;
624 switch (getNode()->kind()) {
625 case Node::KIND_GROUP
:
628 rtl::Reference
< Access
> parent(getParentAccess());
630 rtl::Reference
< Node
> node(getNode());
631 if (! node
->getTemplateName().isEmpty()) {
632 rtl::Reference
< ChildAccess
> other(
633 parent
->getChild(aName
));
634 if (other
.get() == this) {
637 if (node
->getMandatory() == Data::NO_LAYER
&&
638 !(other
.is() && other
->isFinalized()))
640 if (!isValidName(aName
, true)) {
641 throw css::uno::RuntimeException(
642 "invalid element name " + aName
);
644 rtl::Reference
< RootAccess
> root(getRootAccess());
645 rtl::Reference
< ChildAccess
> childAccess(
646 static_cast< ChildAccess
* >(this));
647 localMods
.add(getRelativePath());
648 // unbind() modifies the parent chain that
649 // markChildAsModified() walks, so order is
651 parent
->markChildAsModified(childAccess
);
652 //TODO: must not throw
653 childAccess
->unbind(); // must not throw
655 other
->unbind(); // must not throw
657 childAccess
->bind(root
, parent
, aName
);
659 parent
->markChildAsModified(childAccess
);
660 //TODO: must not throw
661 localMods
.add(getRelativePath());
668 case Node::KIND_LOCALIZED_PROPERTY
:
669 // renaming a property could only work for an extension property,
670 // but a localized property is never an extension property
671 throw css::uno::RuntimeException(
672 "configmgr setName inappropriate node",
673 static_cast< cppu::OWeakObject
* >(this));
675 assert(false); // this cannot happen
678 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
683 css::beans::Property
Access::getAsProperty()
685 assert(thisIs(IS_ANY
));
686 osl::MutexGuard
g(*lock_
);
687 checkLocalizedPropertyAccess();
691 css::uno::Reference
< css::beans::XPropertySetInfo
> Access::getPropertySetInfo()
693 assert(thisIs(IS_GROUP
));
697 void Access::setPropertyValue(
698 OUString
const & aPropertyName
, css::uno::Any
const & aValue
)
700 assert(thisIs(IS_GROUP
));
703 osl::MutexGuard
g(*lock_
);
704 if (!getRootAccess()->isUpdate()) {
705 throw css::uno::RuntimeException(
706 "configmgr setPropertyValue on non-update access",
707 static_cast< cppu::OWeakObject
* >(this));
709 Modifications localMods
;
710 if (!setChildProperty(aPropertyName
, aValue
, &localMods
)) {
711 throw css::beans::UnknownPropertyException(
712 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
714 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
719 css::uno::Any
Access::getPropertyValue(OUString
const & PropertyName
)
721 assert(thisIs(IS_GROUP
));
722 osl::MutexGuard
g(*lock_
);
725 if (!getByNameFast(PropertyName
, value
))
726 throw css::beans::UnknownPropertyException(
727 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
731 void Access::addPropertyChangeListener(
732 OUString
const & aPropertyName
,
733 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
736 assert(thisIs(IS_GROUP
));
738 osl::MutexGuard
g(*lock_
);
739 if (!xListener
.is()) {
740 throw css::uno::RuntimeException(
741 "null listener", static_cast< cppu::OWeakObject
* >(this));
743 checkKnownProperty(aPropertyName
);
745 propertyChangeListeners_
[aPropertyName
].insert(xListener
);
750 xListener
->disposing(
751 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
752 } catch (css::lang::DisposedException
&) {}
755 void Access::removePropertyChangeListener(
756 OUString
const & aPropertyName
,
757 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
760 assert(thisIs(IS_GROUP
));
761 osl::MutexGuard
g(*lock_
);
762 checkKnownProperty(aPropertyName
);
763 PropertyChangeListeners::iterator
i(
764 propertyChangeListeners_
.find(aPropertyName
));
765 if (i
!= propertyChangeListeners_
.end()) {
766 PropertyChangeListenersElement::iterator
j(i
->second
.find(aListener
));
767 if (j
!= i
->second
.end()) {
769 if (i
->second
.empty()) {
770 propertyChangeListeners_
.erase(i
);
776 void Access::addVetoableChangeListener(
777 OUString
const & PropertyName
,
778 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
781 assert(thisIs(IS_GROUP
));
783 osl::MutexGuard
g(*lock_
);
784 if (!aListener
.is()) {
785 throw css::uno::RuntimeException(
786 "null listener", static_cast< cppu::OWeakObject
* >(this));
788 checkKnownProperty(PropertyName
);
790 vetoableChangeListeners_
[PropertyName
].insert(aListener
);
791 //TODO: actually call vetoableChangeListeners_
796 aListener
->disposing(
797 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
798 } catch (css::lang::DisposedException
&) {}
801 void Access::removeVetoableChangeListener(
802 OUString
const & PropertyName
,
803 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
806 assert(thisIs(IS_GROUP
));
807 osl::MutexGuard
g(*lock_
);
808 checkKnownProperty(PropertyName
);
809 VetoableChangeListeners::iterator
i(
810 vetoableChangeListeners_
.find(PropertyName
));
811 if (i
!= vetoableChangeListeners_
.end()) {
812 VetoableChangeListenersElement::iterator
j(i
->second
.find(aListener
));
813 if (j
!= i
->second
.end()) {
815 if (i
->second
.empty()) {
816 vetoableChangeListeners_
.erase(i
);
822 void Access::setPropertyValues(
823 css::uno::Sequence
< OUString
> const & aPropertyNames
,
824 css::uno::Sequence
< css::uno::Any
> const & aValues
)
826 assert(thisIs(IS_GROUP
));
829 osl::MutexGuard
g(*lock_
);
830 if (!getRootAccess()->isUpdate()) {
831 throw css::uno::RuntimeException(
832 "configmgr setPropertyValues on non-update access",
833 static_cast< cppu::OWeakObject
* >(this));
835 if (aPropertyNames
.getLength() != aValues
.getLength()) {
836 throw css::lang::IllegalArgumentException(
837 ("configmgr setPropertyValues: aPropertyNames/aValues of"
838 " different length"),
839 static_cast< cppu::OWeakObject
* >(this), -1);
841 Modifications localMods
;
842 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
) {
843 if (!setChildProperty(aPropertyNames
[i
], aValues
[i
], &localMods
)) {
844 throw css::lang::IllegalArgumentException(
845 "configmgr setPropertyValues inappropriate property name",
846 static_cast< cppu::OWeakObject
* >(this), -1);
849 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
854 css::uno::Sequence
< css::uno::Any
> Access::getPropertyValues(
855 css::uno::Sequence
< OUString
> const & aPropertyNames
)
857 assert(thisIs(IS_GROUP
));
858 osl::MutexGuard
g(*lock_
);
859 css::uno::Sequence
< css::uno::Any
> vals(aPropertyNames
.getLength());
860 auto aValsRange
= asNonConstRange(vals
);
861 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
)
863 if (!getByNameFast(aPropertyNames
[i
], aValsRange
[i
]))
864 throw css::uno::RuntimeException(
865 "configmgr getPropertyValues inappropriate property name",
866 static_cast< cppu::OWeakObject
* >(this));
872 void Access::addPropertiesChangeListener(
873 css::uno::Sequence
< OUString
> const &,
874 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
877 assert(thisIs(IS_GROUP
));
879 osl::MutexGuard
g(*lock_
);
880 if (!xListener
.is()) {
881 throw css::uno::RuntimeException(
882 "null listener", static_cast< cppu::OWeakObject
* >(this));
885 propertiesChangeListeners_
.insert(xListener
);
890 xListener
->disposing(
891 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
892 } catch (css::lang::DisposedException
&) {}
895 void Access::removePropertiesChangeListener(
896 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
899 assert(thisIs(IS_GROUP
));
900 osl::MutexGuard
g(*lock_
);
901 PropertiesChangeListeners::iterator
i(
902 propertiesChangeListeners_
.find(xListener
));
903 if (i
!= propertiesChangeListeners_
.end()) {
904 propertiesChangeListeners_
.erase(i
);
908 void Access::firePropertiesChangeEvent(
909 css::uno::Sequence
< OUString
> const & aPropertyNames
,
910 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
913 assert(thisIs(IS_GROUP
));
914 css::uno::Sequence
< css::beans::PropertyChangeEvent
> events(
915 aPropertyNames
.getLength());
916 auto aEventsRange
= asNonConstRange(events
);
917 for (sal_Int32 i
= 0; i
< events
.getLength(); ++i
) {
918 aEventsRange
[i
].Source
= static_cast< cppu::OWeakObject
* >(this);
919 aEventsRange
[i
].PropertyName
= aPropertyNames
[i
];
920 aEventsRange
[i
].Further
= false;
921 aEventsRange
[i
].PropertyHandle
= -1;
923 xListener
->propertiesChange(events
);
926 css::uno::Reference
< css::beans::XHierarchicalPropertySetInfo
>
927 Access::getHierarchicalPropertySetInfo() {
928 assert(thisIs(IS_GROUP
));
932 void Access::setHierarchicalPropertyValue(
933 OUString
const & aHierarchicalPropertyName
,
934 css::uno::Any
const & aValue
)
936 assert(thisIs(IS_GROUP
));
939 osl::MutexGuard
g(*lock_
);
940 if (!getRootAccess()->isUpdate()) {
941 throw css::uno::RuntimeException(
942 "configmgr setHierarchicalPropertyName on non-update access",
943 static_cast< cppu::OWeakObject
* >(this));
945 rtl::Reference
< ChildAccess
> child(
946 getSubChild(aHierarchicalPropertyName
));
948 throw css::beans::UnknownPropertyException(
949 aHierarchicalPropertyName
,
950 static_cast< cppu::OWeakObject
* >(this));
952 child
->checkFinalized();
953 Modifications localMods
;
954 child
->setProperty(aValue
, &localMods
);
955 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
960 css::uno::Any
Access::getHierarchicalPropertyValue(
961 OUString
const & aHierarchicalPropertyName
)
963 assert(thisIs(IS_GROUP
));
964 osl::MutexGuard
g(*lock_
);
965 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalPropertyName
));
967 throw css::beans::UnknownPropertyException(
968 aHierarchicalPropertyName
,
969 static_cast< cppu::OWeakObject
* >(this));
971 return child
->asValue();
974 void Access::setHierarchicalPropertyValues(
975 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
,
976 css::uno::Sequence
< css::uno::Any
> const & Values
)
978 assert(thisIs(IS_GROUP
));
981 osl::MutexGuard
g(*lock_
);
982 if (!getRootAccess()->isUpdate()) {
983 throw css::uno::RuntimeException(
984 "configmgr setPropertyValues on non-update access",
985 static_cast< cppu::OWeakObject
* >(this));
987 if (aHierarchicalPropertyNames
.getLength() != Values
.getLength()) {
988 throw css::lang::IllegalArgumentException(
989 ("configmgr setHierarchicalPropertyValues:"
990 " aHierarchicalPropertyNames/Values of different length"),
991 static_cast< cppu::OWeakObject
* >(this), -1);
993 Modifications localMods
;
994 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
995 rtl::Reference
< ChildAccess
> child(
996 getSubChild(aHierarchicalPropertyNames
[i
]));
998 throw css::lang::IllegalArgumentException(
999 ("configmgr setHierarchicalPropertyValues inappropriate"
1001 static_cast< cppu::OWeakObject
* >(this), -1);
1003 child
->checkFinalized();
1004 child
->setProperty(Values
[i
], &localMods
);
1006 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1011 css::uno::Sequence
< css::uno::Any
> Access::getHierarchicalPropertyValues(
1012 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
)
1014 assert(thisIs(IS_GROUP
));
1015 osl::MutexGuard
g(*lock_
);
1016 css::uno::Sequence
< css::uno::Any
> vals(
1017 aHierarchicalPropertyNames
.getLength());
1018 auto aValsRange
= asNonConstRange(vals
);
1019 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1020 rtl::Reference
< ChildAccess
> child(
1021 getSubChild(aHierarchicalPropertyNames
[i
]));
1023 throw css::lang::IllegalArgumentException(
1024 ("configmgr getHierarchicalPropertyValues inappropriate"
1025 " hierarchical property name"),
1026 static_cast< cppu::OWeakObject
* >(this), -1);
1028 aValsRange
[i
] = child
->asValue();
1033 css::beans::Property
Access::getPropertyByHierarchicalName(
1034 OUString
const & aHierarchicalName
)
1036 assert(thisIs(IS_GROUP
));
1037 osl::MutexGuard
g(*lock_
);
1038 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalName
));
1040 throw css::beans::UnknownPropertyException(
1041 aHierarchicalName
, static_cast< cppu::OWeakObject
* >(this));
1043 return child
->asProperty();
1046 sal_Bool
Access::hasPropertyByHierarchicalName(
1047 OUString
const & aHierarchicalName
)
1049 assert(thisIs(IS_GROUP
));
1050 osl::MutexGuard
g(*lock_
);
1051 return getSubChild(aHierarchicalName
).is();
1054 void Access::replaceByName(
1055 OUString
const & aName
, css::uno::Any
const & aElement
)
1057 assert(thisIs(IS_UPDATE
));
1060 osl::MutexGuard
g(*lock_
);
1061 checkLocalizedPropertyAccess();
1062 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1064 throw css::container::NoSuchElementException(
1065 aName
, static_cast< cppu::OWeakObject
* >(this));
1067 child
->checkFinalized();
1068 Modifications localMods
;
1069 switch (getNode()->kind()) {
1070 case Node::KIND_LOCALIZED_PROPERTY
:
1071 case Node::KIND_GROUP
:
1072 child
->setProperty(aElement
, &localMods
);
1074 case Node::KIND_SET
:
1076 rtl::Reference
< ChildAccess
> freeAcc(
1077 getFreeSetMember(aElement
));
1078 rtl::Reference
< RootAccess
> root(getRootAccess());
1079 localMods
.add(child
->getRelativePath());
1080 child
->unbind(); // must not throw
1081 freeAcc
->bind(root
, this, aName
); // must not throw
1082 markChildAsModified(freeAcc
); //TODO: must not throw
1086 assert(false); // this cannot happen
1089 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1094 void Access::insertByName(
1095 OUString
const & aName
, css::uno::Any
const & aElement
)
1097 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1100 osl::MutexGuard
g(*lock_
);
1101 checkLocalizedPropertyAccess();
1103 if (getChild(aName
).is()) {
1104 throw css::container::ElementExistException(
1105 aName
, static_cast< cppu::OWeakObject
* >(this));
1107 Modifications localMods
;
1108 switch (getNode()->kind()) {
1109 case Node::KIND_LOCALIZED_PROPERTY
:
1110 if (!isValidName(aName
, false)) {
1111 throw css::lang::IllegalArgumentException(
1112 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1114 insertLocalizedValueChild(aName
, aElement
, &localMods
);
1116 case Node::KIND_GROUP
:
1118 if (!isValidName(aName
, false)) {
1119 throw css::lang::IllegalArgumentException(
1120 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1122 checkValue(aElement
, TYPE_ANY
, true);
1123 rtl::Reference
child(
1125 components_
, getRootAccess(), this, aName
,
1127 Data::NO_LAYER
, TYPE_ANY
, true, aElement
, true)));
1128 markChildAsModified(child
);
1129 localMods
.add(child
->getRelativePath());
1132 case Node::KIND_SET
:
1134 if (!isValidName(aName
, true)) {
1135 throw css::lang::IllegalArgumentException(
1136 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1138 rtl::Reference
< ChildAccess
> freeAcc(
1139 getFreeSetMember(aElement
));
1140 freeAcc
->bind(getRootAccess(), this, aName
); // must not throw
1141 markChildAsModified(freeAcc
); //TODO: must not throw
1142 localMods
.add(freeAcc
->getRelativePath());
1146 assert(false); // this cannot happen
1149 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1154 void Access::removeByName(OUString
const & aName
)
1156 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1159 osl::MutexGuard
g(*lock_
);
1160 checkLocalizedPropertyAccess();
1161 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1162 if (!child
.is() || child
->isFinalized() ||
1163 child
->getNode()->getMandatory() != Data::NO_LAYER
)
1165 throw css::container::NoSuchElementException(
1166 aName
, static_cast< cppu::OWeakObject
* >(this));
1168 if (getNode()->kind() == Node::KIND_GROUP
) {
1169 rtl::Reference
< Node
> p(child
->getNode());
1170 if (p
->kind() != Node::KIND_PROPERTY
||
1171 !static_cast< PropertyNode
* >(p
.get())->isExtension())
1173 throw css::container::NoSuchElementException(
1174 aName
, static_cast< cppu::OWeakObject
* >(this));
1177 Modifications localMods
;
1178 localMods
.add(child
->getRelativePath());
1179 // unbind() modifies the parent chain that markChildAsModified() walks,
1180 // so order is important:
1181 markChildAsModified(child
); //TODO: must not throw
1183 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1188 css::uno::Reference
< css::uno::XInterface
> Access::createInstance()
1190 assert(thisIs(IS_SET
|IS_UPDATE
));
1192 static_cast< SetNode
* >(getNode().get())->getDefaultTemplateName());
1193 rtl::Reference
< Node
> tmpl(
1194 components_
.getTemplate(tmplName
));
1196 throw css::uno::Exception(
1197 "unknown template " + tmplName
,
1198 static_cast< cppu::OWeakObject
* >(this));
1200 rtl::Reference
< Node
> node(tmpl
->clone(true));
1201 node
->setLayer(Data::NO_LAYER
);
1202 return static_cast< cppu::OWeakObject
* >(
1203 new ChildAccess(components_
, getRootAccess(), node
));
1206 css::uno::Reference
< css::uno::XInterface
> Access::createInstanceWithArguments(
1207 css::uno::Sequence
< css::uno::Any
> const & aArguments
)
1209 assert(thisIs(IS_SET
|IS_UPDATE
));
1210 if (aArguments
.hasElements()) {
1211 throw css::uno::Exception(
1212 ("configuration SimpleSetUpdate createInstanceWithArguments"
1213 " must not specify any arguments"),
1214 static_cast< cppu::OWeakObject
* >(this));
1216 return createInstance();
1219 Access::Access(Components
& components
):
1220 components_(components
), disposed_(false), lock_( lock() )
1224 Access::~Access() {}
1226 void Access::initDisposeBroadcaster(Broadcaster
* broadcaster
) {
1227 assert(broadcaster
!= nullptr);
1228 for (auto const& disposeListener
: disposeListeners_
)
1230 broadcaster
->addDisposeNotification(
1232 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1234 for (auto const& containerListener
: containerListeners_
)
1236 broadcaster
->addDisposeNotification(
1238 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1240 for (auto const& propertyChangeListener
: propertyChangeListeners_
)
1242 for (auto const& propertyChangeListenerElement
: propertyChangeListener
.second
)
1244 broadcaster
->addDisposeNotification(
1245 propertyChangeListenerElement
,
1246 css::lang::EventObject(
1247 static_cast< cppu::OWeakObject
* >(this)));
1250 for (auto const& vetoableChangeListener
: vetoableChangeListeners_
)
1252 for (auto const& vetoableChangeListenerElement
: vetoableChangeListener
.second
)
1254 broadcaster
->addDisposeNotification(
1255 vetoableChangeListenerElement
,
1256 css::lang::EventObject(
1257 static_cast< cppu::OWeakObject
* >(this)));
1260 for (auto const& propertiesChangeListener
: propertiesChangeListeners_
)
1262 broadcaster
->addDisposeNotification(
1263 propertiesChangeListener
,
1264 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1266 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1267 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1268 i
!= modifiedChildren_
.end(); ++i
)
1270 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1272 child
->initDisposeBroadcaster(broadcaster
);
1277 void Access::clearListeners() noexcept
{
1278 disposeListeners_
.clear();
1279 containerListeners_
.clear();
1280 propertyChangeListeners_
.clear();
1281 vetoableChangeListeners_
.clear();
1282 propertiesChangeListeners_
.clear();
1283 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1284 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1285 i
!= modifiedChildren_
.end(); ++i
)
1287 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1289 child
->clearListeners();
1294 css::uno::Any
Access::queryInterface(css::uno::Type
const & aType
)
1296 css::uno::Any
res(OWeakObject::queryInterface(aType
));
1297 if (res
.hasValue()) {
1300 res
= cppu::queryInterface(
1301 aType
, static_cast< css::lang::XTypeProvider
* >(this),
1302 static_cast< css::lang::XServiceInfo
* >(this),
1303 static_cast< css::lang::XComponent
* >(this),
1304 static_cast< css::container::XHierarchicalNameAccess
* >(this),
1305 static_cast< css::container::XContainer
* >(this),
1306 static_cast< css::beans::XExactName
* >(this),
1307 static_cast< css::container::XHierarchicalName
* >(this),
1308 static_cast< css::container::XNamed
* >(this),
1309 static_cast< css::beans::XProperty
* >(this),
1310 static_cast< css::container::XElementAccess
* >(this),
1311 static_cast< css::container::XNameAccess
* >(this));
1312 if (res
.hasValue()) {
1315 if (getNode()->kind() == Node::KIND_GROUP
) {
1316 res
= cppu::queryInterface(
1317 aType
, static_cast< css::beans::XPropertySetInfo
* >(this),
1318 static_cast< css::beans::XPropertySet
* >(this),
1319 static_cast< css::beans::XMultiPropertySet
* >(this),
1320 static_cast< css::beans::XHierarchicalPropertySet
* >(this),
1321 static_cast< css::beans::XMultiHierarchicalPropertySet
* >(this),
1322 static_cast< css::beans::XHierarchicalPropertySetInfo
* >(this));
1323 if (res
.hasValue()) {
1327 if (getRootAccess()->isUpdate()) {
1328 res
= cppu::queryInterface(
1329 aType
, static_cast< css::container::XNameReplace
* >(this),
1330 static_cast< css::container::XHierarchicalNameReplace
* >(this));
1331 if (res
.hasValue()) {
1334 if (getNode()->kind() != Node::KIND_GROUP
||
1335 static_cast< GroupNode
* >(getNode().get())->isExtensible())
1337 res
= cppu::queryInterface(
1338 aType
, static_cast< css::container::XNameContainer
* >(this));
1339 if (res
.hasValue()) {
1343 if (getNode()->kind() == Node::KIND_SET
) {
1344 res
= cppu::queryInterface(
1345 aType
, static_cast< css::lang::XSingleServiceFactory
* >(this));
1352 void Access::checkLocalizedPropertyAccess() {
1353 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
&&
1354 !Components::allLocales(getRootAccess()->getLocale()))
1356 throw css::uno::RuntimeException(
1357 "configmgr Access to specialized LocalizedPropertyNode",
1358 static_cast< cppu::OWeakObject
* >(this));
1362 rtl::Reference
< Node
> Access::getParentNode() {
1363 rtl::Reference
< Access
> parent(getParentAccess());
1364 return parent
.is() ? parent
->getNode() : rtl::Reference
< Node
>();
1367 rtl::Reference
< ChildAccess
> Access::getChild(OUString
const & name
) {
1369 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
1370 && name
.startsWith("*", &locale
))
1372 if (locale
.startsWith("*")) {
1375 ("access best-matching localized property value via"
1376 " \"*<locale>\" with <locale> \"")
1377 << locale
<< "\" recursively starting with \"*\"");
1378 return getChild(locale
);
1381 locale
.isEmpty(), "configmgr",
1382 ("access best-matching localized property value via \"*<locale>\""
1383 " with empty <locale>; falling back to defaults"));
1385 // Since the locale given to us is the one used at initialization,
1386 // here we override it with the actual current-user's language to
1387 // support per-view localization in LOK.
1388 if (comphelper::LibreOfficeKit::isActive())
1389 locale
= comphelper::LibreOfficeKit::getLanguageTag().getBcp47();
1391 if (!locale
.isEmpty()) {
1392 // Try exact match first, avoiding all fallback overhead.
1393 rtl::Reference
<ChildAccess
> directChild(getChild(locale
));
1394 if (directChild
.is())
1397 LanguageTag
aLanguageTag(locale
, true);
1398 if (aLanguageTag
.getBcp47() != locale
)
1400 // Original may be overridden by a known locale, for example
1401 // "zh-Hant-TW" by "zh-TW".
1402 rtl::Reference
<ChildAccess
> child(getChild(aLanguageTag
.getBcp47()));
1407 // Find the best match using the LanguageTag fallback mechanism,
1408 // excluding the original tag.
1409 std::vector
<OUString
> aFallbacks
= aLanguageTag
.getFallbackStrings(false);
1410 for (const OUString
& rFallback
: aFallbacks
)
1412 rtl::Reference
<ChildAccess
> child(getChild(rFallback
));
1417 // As a workaround for broken xcu data that does not use shortest
1418 // xml:lang attributes, look for the first entry with the same first
1419 // segment as the requested language tag before falling back to
1420 // defaults (see fdo#33638):
1421 auto const i
= comphelper::string::indexOfAny(locale
, u
"-_", 1);
1423 locale
= locale
.copy(0, i
);
1425 assert(!locale
.isEmpty());
1426 std::vector
< rtl::Reference
< ChildAccess
> > children(
1428 for (auto const& child
: children
)
1430 const OUString
& name2(child
->getNameInternal());
1431 if (name2
.startsWith(locale
) &&
1432 (name2
.getLength() == locale
.getLength() ||
1433 name2
[locale
.getLength()] == '-' ||
1434 name2
[locale
.getLength()] == '_'))
1440 // Defaults are the "en-US" locale, the "en" locale, the empty string locale, the first child (if
1441 // any, and if the property is non-nillable), or a null ChildAccess, in that order:
1442 rtl::Reference
< ChildAccess
> child(getChild("en-US"));
1446 child
= getChild("en");
1450 child
= getChild("");
1454 if (!static_cast<LocalizedPropertyNode
*>(getNode().get())->isNillable()) {
1455 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
1456 if (!children
.empty()) {
1457 return children
.front();
1460 return rtl::Reference
< ChildAccess
>();
1462 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
1463 return i
== modifiedChildren_
.end()
1464 ? getUnmodifiedChild(name
) : getModifiedChild(i
);
1467 std::vector
< rtl::Reference
< ChildAccess
> > Access::getAllChildren() {
1468 std::vector
< rtl::Reference
< ChildAccess
> > vec
;
1469 NodeMap
const & members
= getNode()->getMembers();
1470 for (auto const& member
: members
)
1472 if (modifiedChildren_
.find(member
.first
) == modifiedChildren_
.end()) {
1473 vec
.push_back(getUnmodifiedChild(member
.first
));
1474 assert(vec
.back().is());
1477 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1478 i
!= modifiedChildren_
.end(); ++i
)
1480 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1482 vec
.push_back(child
);
1488 void Access::checkValue(css::uno::Any
const & value
, Type type
, bool nillable
) {
1495 switch (getDynamicType(value
)) {
1506 for (;;) std::abort(); // cannot happen
1510 ok
= value
.hasValue() ? value
.isExtractableTo(mapType(type
)) : nillable
;
1513 for (;;) std::abort(); // cannot happen
1516 throw css::lang::IllegalArgumentException(
1517 "configmgr inappropriate property value",
1518 static_cast< cppu::OWeakObject
* >(this), -1);
1522 void Access::insertLocalizedValueChild(
1523 OUString
const & name
, css::uno::Any
const & value
,
1524 Modifications
* localModifications
)
1526 assert(localModifications
!= nullptr);
1527 LocalizedPropertyNode
* locprop
= static_cast< LocalizedPropertyNode
* >(
1529 checkValue(value
, locprop
->getStaticType(), locprop
->isNillable());
1530 rtl::Reference
child(
1532 components_
, getRootAccess(), this, name
,
1533 new LocalizedValueNode(Data::NO_LAYER
, value
)));
1534 markChildAsModified(child
);
1535 localModifications
->add(child
->getRelativePath());
1538 void Access::reportChildChanges(
1539 std::vector
< css::util::ElementChange
> * changes
)
1541 assert(changes
!= nullptr);
1542 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1543 i
!= modifiedChildren_
.end(); ++i
)
1545 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1547 child
->reportChildChanges(changes
);
1548 changes
->push_back(css::util::ElementChange());
1549 //TODO: changed value and/or inserted node
1551 changes
->push_back(css::util::ElementChange()); //TODO: removed node
1556 void Access::commitChildChanges(
1557 bool valid
, Modifications
* globalModifications
)
1559 assert(globalModifications
!= nullptr);
1560 while (!modifiedChildren_
.empty()) {
1561 bool childValid
= valid
;
1562 ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1563 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1565 childValid
= childValid
&& !child
->isFinalized();
1566 child
->commitChanges(childValid
, globalModifications
);
1567 //TODO: currently, this is called here for directly inserted
1568 // children as well as for children whose sub-children were
1569 // modified (and should never be called for directly removed
1570 // children); clarify what exactly should happen here for
1571 // directly inserted children
1573 NodeMap
& members
= getNode()->getMembers();
1574 NodeMap::iterator
j(members
.find(i
->first
));
1577 if (j
!= members
.end()) {
1578 childValid
= childValid
&&
1579 j
->second
->getFinalized() == Data::NO_LAYER
;
1581 child
->getNode()->setMandatory(j
->second
->getMandatory());
1585 members
[i
->first
] = child
->getNode();
1589 childValid
= childValid
&& j
!= members
.end() &&
1590 j
->second
->getFinalized() == Data::NO_LAYER
&&
1591 j
->second
->getMandatory() == Data::NO_LAYER
;
1596 if (childValid
&& i
->second
.directlyModified
) {
1597 std::vector
<OUString
> path(getAbsolutePath());
1598 path
.push_back(i
->first
);
1599 components_
.addModification(path
);
1600 globalModifications
->add(path
);
1602 i
->second
.child
->committed();
1603 modifiedChildren_
.erase(i
);
1607 void Access::initBroadcasterAndChanges(
1608 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
,
1609 std::vector
< css::util::ElementChange
> * allChanges
)
1611 assert(broadcaster
!= nullptr);
1612 std::vector
< css::beans::PropertyChangeEvent
> propChanges
;
1613 bool collectPropChanges
= !propertiesChangeListeners_
.empty();
1614 for (const auto & i
: modifications
.children
)
1616 rtl::Reference
< ChildAccess
> child(getChild(i
.first
));
1618 switch (child
->getNode()->kind()) {
1619 case Node::KIND_LOCALIZED_PROPERTY
:
1620 if (!i
.second
.children
.empty()) {
1621 if (Components::allLocales(getRootAccess()->getLocale())) {
1622 child
->initBroadcasterAndChanges(
1623 i
.second
, broadcaster
, allChanges
);
1624 //TODO: if allChanges==0, recurse only into children
1627 //TODO: filter child mods that are irrelevant for
1629 for (auto const& containerListener
: containerListeners_
)
1632 addContainerElementReplacedNotification(
1634 css::container::ContainerEvent(
1635 static_cast< cppu::OWeakObject
* >(
1637 css::uno::Any(i
.first
),
1638 css::uno::Any(), css::uno::Any()));
1639 //TODO: non-void Element, ReplacedElement
1641 PropertyChangeListeners::iterator
j(
1642 propertyChangeListeners_
.find(i
.first
));
1643 if (j
!= propertyChangeListeners_
.end()) {
1644 for (auto const& propertyChangeListenerElement
: j
->second
)
1646 broadcaster
->addPropertyChangeNotification(
1647 propertyChangeListenerElement
,
1648 css::beans::PropertyChangeEvent(
1649 static_cast< cppu::OWeakObject
* >(
1651 i
.first
, false, -1, css::uno::Any(),
1655 j
= propertyChangeListeners_
.find("");
1656 if (j
!= propertyChangeListeners_
.end()) {
1657 for (auto const& propertyChangeListenerElement
: j
->second
)
1659 broadcaster
->addPropertyChangeNotification(
1660 propertyChangeListenerElement
,
1661 css::beans::PropertyChangeEvent(
1662 static_cast< cppu::OWeakObject
* >(
1664 i
.first
, false, -1, css::uno::Any(),
1668 if (allChanges
!= nullptr) {
1669 allChanges
->push_back(
1670 css::util::ElementChange(
1672 child
->getRelativePathRepresentation()),
1673 css::uno::Any(), css::uno::Any()));
1674 //TODO: non-void Element, ReplacedElement
1676 if (collectPropChanges
) {
1677 propChanges
.emplace_back(
1678 static_cast< cppu::OWeakObject
* >(this),
1679 i
.first
, false, -1, css::uno::Any(),
1684 // else: spurious Modifications::Node not representing a change
1686 case Node::KIND_LOCALIZED_VALUE
:
1687 assert(Components::allLocales(getRootAccess()->getLocale()));
1688 for (auto const& containerListener
: containerListeners_
)
1690 broadcaster
->addContainerElementReplacedNotification(
1692 css::container::ContainerEvent(
1693 static_cast< cppu::OWeakObject
* >(this),
1694 css::uno::Any(i
.first
), child
->asValue(),
1696 //TODO: distinguish add/modify; non-void ReplacedElement
1698 if (allChanges
!= nullptr) {
1699 allChanges
->push_back(
1700 css::util::ElementChange(
1702 child
->getRelativePathRepresentation()),
1703 child
->asValue(), css::uno::Any()));
1704 //TODO: non-void ReplacedElement
1706 assert(!collectPropChanges
);
1708 case Node::KIND_PROPERTY
:
1710 for (auto const& containerListener
: containerListeners_
)
1712 broadcaster
->addContainerElementReplacedNotification(
1714 css::container::ContainerEvent(
1715 static_cast< cppu::OWeakObject
* >(this),
1716 css::uno::Any(i
.first
), child
->asValue(),
1718 //TODO: distinguish add/remove/modify; non-void
1721 PropertyChangeListeners::iterator
j(
1722 propertyChangeListeners_
.find(i
.first
));
1723 if (j
!= propertyChangeListeners_
.end()) {
1724 for (auto const& propertyChangeListenerElement
: j
->second
)
1726 broadcaster
->addPropertyChangeNotification(
1727 propertyChangeListenerElement
,
1728 css::beans::PropertyChangeEvent(
1729 static_cast< cppu::OWeakObject
* >(this),
1730 i
.first
, false, -1, css::uno::Any(),
1734 j
= propertyChangeListeners_
.find("");
1735 if (j
!= propertyChangeListeners_
.end()) {
1736 for (auto const& propertyChangeListenerElement
: j
->second
)
1738 broadcaster
->addPropertyChangeNotification(
1739 propertyChangeListenerElement
,
1740 css::beans::PropertyChangeEvent(
1741 static_cast< cppu::OWeakObject
* >(this),
1742 i
.first
, false, -1, css::uno::Any(),
1746 if (allChanges
!= nullptr) {
1747 allChanges
->push_back(
1748 css::util::ElementChange(
1750 child
->getRelativePathRepresentation()),
1751 child
->asValue(), css::uno::Any()));
1752 //TODO: non-void ReplacedElement
1754 if (collectPropChanges
) {
1755 propChanges
.emplace_back(
1756 static_cast< cppu::OWeakObject
* >(this),
1757 i
.first
, false, -1, css::uno::Any(),
1762 case Node::KIND_GROUP
:
1763 case Node::KIND_SET
:
1764 if (i
.second
.children
.empty()) {
1765 if (!child
->getNode()->getTemplateName().isEmpty()) {
1766 for (auto const& containerListener
: containerListeners_
)
1769 addContainerElementInsertedNotification(
1771 css::container::ContainerEvent(
1772 static_cast< cppu::OWeakObject
* >(
1774 css::uno::Any(i
.first
),
1775 child
->asValue(), css::uno::Any()));
1777 if (allChanges
!= nullptr) {
1778 allChanges
->push_back(
1779 css::util::ElementChange(
1781 child
->getRelativePathRepresentation()),
1782 css::uno::Any(), css::uno::Any()));
1783 //TODO: non-void Element, ReplacedElement
1786 // else: spurious Modifications::Node not representing a
1789 child
->initBroadcasterAndChanges(
1790 i
.second
, broadcaster
, allChanges
);
1791 //TODO: if allChanges==0, recurse only into children w/
1795 case Node::KIND_ROOT
:
1796 assert(false); // this cannot happen
1800 switch (getNode()->kind()) {
1801 case Node::KIND_LOCALIZED_PROPERTY
:
1802 // Removed localized property value:
1803 assert(Components::allLocales(getRootAccess()->getLocale()));
1804 for (auto const& containerListener
: containerListeners_
)
1806 broadcaster
->addContainerElementRemovedNotification(
1808 css::container::ContainerEvent(
1809 static_cast< cppu::OWeakObject
* >(this),
1810 css::uno::Any(i
.first
), css::uno::Any(),
1812 //TODO: non-void ReplacedElement
1814 if (allChanges
!= nullptr) {
1815 OUStringBuffer
path(getRelativePathRepresentation());
1816 if (!path
.isEmpty()) {
1819 path
.append(Data::createSegment(u
"*", i
.first
));
1820 allChanges
->push_back(
1821 css::util::ElementChange(
1822 css::uno::Any(path
.makeStringAndClear()),
1823 css::uno::Any(), css::uno::Any()));
1824 //TODO: non-void ReplacedElement
1826 assert(!collectPropChanges
);
1828 case Node::KIND_GROUP
:
1830 // Removed (non-localized) extension property:
1831 for (auto const& containerListener
: containerListeners_
)
1833 broadcaster
->addContainerElementRemovedNotification(
1835 css::container::ContainerEvent(
1836 static_cast< cppu::OWeakObject
* >(this),
1837 css::uno::Any(i
.first
), css::uno::Any(),
1839 //TODO: non-void ReplacedElement
1841 PropertyChangeListeners::iterator
j(
1842 propertyChangeListeners_
.find(i
.first
));
1843 if (j
!= propertyChangeListeners_
.end()) {
1844 for (auto const& propertyChangeListenerElement
: j
->second
)
1846 broadcaster
->addPropertyChangeNotification(
1847 propertyChangeListenerElement
,
1848 css::beans::PropertyChangeEvent(
1849 static_cast< cppu::OWeakObject
* >(this),
1850 i
.first
, false, -1, css::uno::Any(),
1854 j
= propertyChangeListeners_
.find("");
1855 if (j
!= propertyChangeListeners_
.end()) {
1856 for (auto const& propertyChangeListenerElement
: j
->second
)
1858 broadcaster
->addPropertyChangeNotification(
1859 propertyChangeListenerElement
,
1860 css::beans::PropertyChangeEvent(
1861 static_cast< cppu::OWeakObject
* >(this),
1862 i
.first
, false, -1, css::uno::Any(),
1866 if (allChanges
!= nullptr) {
1867 OUStringBuffer
path(
1868 getRelativePathRepresentation());
1869 if (!path
.isEmpty()) {
1872 path
.append(i
.first
);
1873 allChanges
->push_back(
1874 css::util::ElementChange(
1875 css::uno::Any(path
.makeStringAndClear()),
1876 css::uno::Any(), css::uno::Any()));
1877 //TODO: non-void ReplacedElement
1879 if (collectPropChanges
) {
1880 propChanges
.emplace_back(
1881 static_cast< cppu::OWeakObject
* >(this),
1882 i
.first
, false, -1, css::uno::Any(),
1887 case Node::KIND_SET
:
1888 // Removed set member:
1889 if (i
.second
.children
.empty()) {
1890 for (auto const& containerListener
: containerListeners_
)
1892 broadcaster
->addContainerElementRemovedNotification(
1894 css::container::ContainerEvent(
1895 static_cast< cppu::OWeakObject
* >(this),
1896 css::uno::Any(i
.first
),
1897 css::uno::Any(), css::uno::Any()));
1898 //TODO: non-void ReplacedElement
1900 if (allChanges
!= nullptr) {
1901 OUStringBuffer
path(
1902 getRelativePathRepresentation());
1903 if (!path
.isEmpty()) {
1906 path
.append(Data::createSegment(u
"*", i
.first
));
1907 allChanges
->push_back(
1908 css::util::ElementChange(
1909 css::uno::Any(path
.makeStringAndClear()),
1910 css::uno::Any(), css::uno::Any()));
1911 //TODO: non-void ReplacedElement
1914 // else: spurious Modifications::Node not representing a change
1917 assert(false); // this cannot happen
1922 if (!propChanges
.empty()) {
1923 css::uno::Sequence
< css::beans::PropertyChangeEvent
> seq(
1924 comphelper::containerToSequence(propChanges
));
1925 for (auto const& propertyChangeListener
: propertiesChangeListeners_
)
1927 broadcaster
->addPropertiesChangeNotification(propertyChangeListener
, seq
);
1933 Access::ModifiedChild::ModifiedChild():
1934 directlyModified(false)
1937 Access::ModifiedChild::ModifiedChild(
1938 rtl::Reference
< ChildAccess
> theChild
, bool theDirectlyModified
):
1939 child(std::move(theChild
)), directlyModified(theDirectlyModified
)
1942 rtl::Reference
< ChildAccess
> Access::getModifiedChild(
1943 ModifiedChildren::iterator
const & childIterator
)
1945 return (childIterator
->second
.child
->getParentAccess() == this &&
1946 (childIterator
->second
.child
->getNameInternal() ==
1947 childIterator
->first
))
1948 ? childIterator
->second
.child
: rtl::Reference
< ChildAccess
>();
1951 rtl::Reference
< ChildAccess
> Access::createUnmodifiedChild(
1952 const OUString
&name
, const rtl::Reference
< Node
> &node
)
1954 rtl::Reference
child(
1955 new ChildAccess(components_
, getRootAccess(), this, name
, node
));
1956 cachedChildren_
[name
] = child
.get();
1960 rtl::Reference
< ChildAccess
> Access::getUnmodifiedChild(
1961 OUString
const & name
)
1963 assert(modifiedChildren_
.find(name
) == modifiedChildren_
.end());
1964 rtl::Reference
< Node
> node(getNode()->getMember(name
));
1966 return rtl::Reference
< ChildAccess
>();
1968 WeakChildMap::iterator
i(cachedChildren_
.find(name
));
1969 if (i
!= cachedChildren_
.end()) {
1970 rtl::Reference
< ChildAccess
> child
;
1971 if (i
->second
->acquireCounting() > 1) {
1972 child
.set(i
->second
); // must not throw
1974 i
->second
->releaseNondeleting();
1976 child
->setNode(node
);
1980 return createUnmodifiedChild(name
,node
);
1983 rtl::Reference
< ChildAccess
> Access::getSubChild(OUString
const & path
) {
1985 // For backwards compatibility, allow absolute paths where meaningful:
1986 if( path
.startsWith("/") ) {
1988 if (!getRootAccess().is()) {
1989 return rtl::Reference
< ChildAccess
>();
1991 std::vector
<OUString
> abs(getAbsolutePath());
1992 for (auto const& elem
: abs
)
1996 OUString templateName1
;
1997 i
= Data::parseSegment(
1998 path
, i
, &name1
, &setElement1
, &templateName1
);
1999 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2000 return rtl::Reference
< ChildAccess
>();
2004 OUString templateName2
;
2005 Data::parseSegment(elem
, 0, &name2
, &setElement2
, &templateName2
);
2006 if (name1
!= name2
|| setElement1
!= setElement2
||
2008 !Data::equalTemplateNames(templateName1
, templateName2
)))
2010 return rtl::Reference
< ChildAccess
>();
2012 if (i
!= path
.getLength()) {
2017 for (rtl::Reference
< Access
> parent(this);;) {
2020 OUString templateName
;
2021 i
= Data::parseSegment(path
, i
, &name
, &setElement
, &templateName
);
2022 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2023 return rtl::Reference
< ChildAccess
>();
2025 rtl::Reference
< ChildAccess
> child(parent
->getChild(name
));
2027 return rtl::Reference
< ChildAccess
>();
2030 rtl::Reference
< Node
> p(parent
->getNode());
2031 switch (p
->kind()) {
2032 case Node::KIND_LOCALIZED_PROPERTY
:
2033 if (!Components::allLocales(getRootAccess()->getLocale()) ||
2034 !templateName
.isEmpty())
2036 return rtl::Reference
< ChildAccess
>();
2039 case Node::KIND_SET
:
2040 if (!templateName
.isEmpty() &&
2041 !static_cast< SetNode
* >(p
.get())->isValidTemplate(
2044 return rtl::Reference
< ChildAccess
>();
2048 return rtl::Reference
< ChildAccess
>();
2051 // For backwards compatibility, ignore a final slash after non-value
2053 if (child
->isValue()) {
2054 return i
== path
.getLength()
2055 ? child
: rtl::Reference
< ChildAccess
>();
2056 } else if (i
>= path
.getLength() - 1) {
2060 parent
= child
.get();
2064 bool Access::setChildProperty(
2065 OUString
const & name
, css::uno::Any
const & value
,
2066 Modifications
* localModifications
)
2068 assert(localModifications
!= nullptr);
2069 rtl::Reference
< ChildAccess
> child(getChild(name
));
2073 child
->checkFinalized();
2074 child
->setProperty(value
, localModifications
);
2078 css::beans::Property
Access::asProperty() {
2079 css::uno::Type type
;
2082 rtl::Reference
< Node
> p(getNode());
2083 switch (p
->kind()) {
2084 case Node::KIND_PROPERTY
:
2086 PropertyNode
* prop
= static_cast< PropertyNode
* >(p
.get());
2087 type
= mapType(prop
->getStaticType());
2088 nillable
= prop
->isNillable();
2089 removable
= prop
->isExtension();
2092 case Node::KIND_LOCALIZED_PROPERTY
:
2094 LocalizedPropertyNode
* locprop
=
2095 static_cast< LocalizedPropertyNode
*>(p
.get());
2096 if (Components::allLocales(getRootAccess()->getLocale())) {
2097 type
= cppu::UnoType
< css::uno::XInterface
>::get();
2101 type
= mapType(locprop
->getStaticType());
2102 removable
= false; //TODO ???
2104 nillable
= locprop
->isNillable();
2107 case Node::KIND_LOCALIZED_VALUE
:
2109 LocalizedPropertyNode
* locprop
=
2110 static_cast< LocalizedPropertyNode
* >(getParentNode().get());
2111 type
= mapType(locprop
->getStaticType());
2112 nillable
= locprop
->isNillable();
2113 removable
= false; //TODO ???
2117 type
= cppu::UnoType
< css::uno::XInterface
>::get(); //TODO: correct?
2119 rtl::Reference
< Node
> parent(getParentNode());
2120 removable
= parent
.is() && parent
->kind() == Node::KIND_SET
;
2123 return css::beans::Property(
2124 getNameInternal(), -1, type
,
2125 (css::beans::PropertyAttribute::BOUND
| //TODO: correct for group/set?
2126 css::beans::PropertyAttribute::CONSTRAINED
|
2127 (nillable
? css::beans::PropertyAttribute::MAYBEVOID
: 0) |
2128 (getRootAccess()->isUpdate() && removable
2129 ? css::beans::PropertyAttribute::REMOVABLE
: 0) |
2130 (!getRootAccess()->isUpdate() || p
->getFinalized() != Data::NO_LAYER
2131 ? css::beans::PropertyAttribute::READONLY
: 0))); //TODO: MAYBEDEFAULT
2134 void Access::checkFinalized() {
2135 if (isFinalized()) {
2136 throw css::lang::IllegalArgumentException(
2137 "configmgr modification of finalized item",
2138 static_cast< cppu::OWeakObject
* >(this), -1);
2142 void Access::checkKnownProperty(OUString
const & descriptor
) {
2143 if (descriptor
.isEmpty()) {
2146 rtl::Reference
< ChildAccess
> child(getChild(descriptor
));
2148 switch (child
->getNode()->kind()) {
2149 case Node::KIND_PROPERTY
:
2151 case Node::KIND_LOCALIZED_PROPERTY
:
2152 if (!Components::allLocales(getRootAccess()->getLocale())) {
2156 case Node::KIND_LOCALIZED_VALUE
:
2157 if (Components::allLocales(getRootAccess()->getLocale())) {
2165 throw css::beans::UnknownPropertyException(
2166 descriptor
, static_cast< cppu::OWeakObject
* >(this));
2169 rtl::Reference
< ChildAccess
> Access::getFreeSetMember(
2170 css::uno::Any
const & value
)
2172 css::uno::Reference
<XInterface
> xTmp
;
2174 rtl::Reference
< ChildAccess
> freeAcc
= dynamic_cast<ChildAccess
*>(xTmp
.get());
2175 if (!freeAcc
.is() || freeAcc
->getParentAccess().is() ||
2176 (freeAcc
->isInTransaction() &&
2177 freeAcc
->getRootAccess() != getRootAccess()))
2179 throw css::lang::IllegalArgumentException(
2180 "configmgr inappropriate set element",
2181 static_cast< cppu::OWeakObject
* >(this), 1);
2183 assert(dynamic_cast< SetNode
* >(getNode().get()) != nullptr);
2184 if (!static_cast< SetNode
* >(getNode().get())->isValidTemplate(
2185 freeAcc
->getNode()->getTemplateName()))
2187 throw css::lang::IllegalArgumentException(
2188 "configmgr inappropriate set element",
2189 static_cast< cppu::OWeakObject
* >(this), 1);
2194 rtl::Reference
< Access
> Access::getNotificationRoot() {
2195 for (rtl::Reference
< Access
> p(this);;) {
2196 rtl::Reference
< Access
> parent(p
->getParentAccess());
2205 bool Access::thisIs(int what
) {
2206 osl::MutexGuard
g(*lock_
);
2207 rtl::Reference
< Node
> p(getNode());
2208 Node::Kind
k(p
->kind());
2209 return (k
!= Node::KIND_PROPERTY
&& k
!= Node::KIND_LOCALIZED_VALUE
&&
2210 ((what
& IS_GROUP
) == 0 || k
== Node::KIND_GROUP
) &&
2211 ((what
& IS_SET
) == 0 || k
== Node::KIND_SET
) &&
2212 ((what
& IS_EXTENSIBLE
) == 0 || k
!= Node::KIND_GROUP
||
2213 static_cast< GroupNode
* >(p
.get())->isExtensible()) &&
2214 ((what
& IS_GROUP_MEMBER
) == 0 ||
2215 getParentNode()->kind() == Node::KIND_GROUP
)) ||
2216 ((what
& IS_SET_MEMBER
) == 0 ||
2217 getParentNode()->kind() == Node::KIND_SET
) ||
2218 ((what
& IS_UPDATE
) == 0 || getRootAccess()->isUpdate());
2224 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */