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>
26 #include <com/sun/star/beans/Property.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
29 #include <com/sun/star/beans/UnknownPropertyException.hpp>
30 #include <com/sun/star/beans/XExactName.hpp>
31 #include <com/sun/star/beans/XHierarchicalPropertySet.hpp>
32 #include <com/sun/star/beans/XHierarchicalPropertySetInfo.hpp>
33 #include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
34 #include <com/sun/star/beans/XMultiPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
36 #include <com/sun/star/beans/XProperty.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/ContainerEvent.hpp>
42 #include <com/sun/star/container/NoSuchElementException.hpp>
43 #include <com/sun/star/container/XContainer.hpp>
44 #include <com/sun/star/container/XContainerListener.hpp>
45 #include <com/sun/star/container/XElementAccess.hpp>
46 #include <com/sun/star/container/XHierarchicalName.hpp>
47 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
48 #include <com/sun/star/container/XHierarchicalNameReplace.hpp>
49 #include <com/sun/star/container/XNameAccess.hpp>
50 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <com/sun/star/container/XNamed.hpp>
52 #include <com/sun/star/lang/DisposedException.hpp>
53 #include <com/sun/star/lang/EventObject.hpp>
54 #include <com/sun/star/lang/IllegalArgumentException.hpp>
55 #include <com/sun/star/lang/XComponent.hpp>
56 #include <com/sun/star/lang/XEventListener.hpp>
57 #include <com/sun/star/lang/XServiceInfo.hpp>
58 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
59 #include <com/sun/star/lang/XTypeProvider.hpp>
60 #include <com/sun/star/lang/XUnoTunnel.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/lok.hxx>
71 #include <i18nlangtag/languagetag.hxx>
72 #include <cppu/unotype.hxx>
73 #include <cppuhelper/queryinterface.hxx>
74 #include <cppuhelper/supportsservice.hxx>
75 #include <cppuhelper/weak.hxx>
76 #include <osl/interlck.h>
77 #include <osl/mutex.hxx>
78 #include <rtl/character.hxx>
79 #include <rtl/ref.hxx>
80 #include <rtl/ustrbuf.hxx>
81 #include <rtl/ustring.hxx>
82 #include <sal/log.hxx>
83 #include <sal/types.h>
86 #include "broadcaster.hxx"
87 #include "childaccess.hxx"
88 #include "components.hxx"
90 #include "groupnode.hxx"
91 #include "localizedpropertynode.hxx"
92 #include "localizedvaluenode.hxx"
94 #include "modifications.hxx"
96 #include "nodemap.hxx"
97 #include "propertynode.hxx"
98 #include "rootaccess.hxx"
99 #include "setnode.hxx"
102 namespace configmgr
{
106 // Conservatively forbid what is either not an XML Char (including lone
107 // surrogates, even though they should not appear in well-formed UNO OUString
108 // instances anyway), or is a slash (as it causes problems in path syntax):
109 bool isValidName(OUString
const & name
, bool setMember
) {
110 for (sal_Int32 i
= 0; i
!= name
.getLength();) {
111 sal_uInt32 c
= name
.iterateCodePoints(&i
);
112 if ((c
< 0x20 && !(c
== 0x09 || c
== 0x0A || c
== 0x0D))
113 || rtl::isSurrogate(c
) || c
== 0xFFFE || c
== 0xFFFF
114 || (!setMember
&& c
== '/'))
119 return !name
.isEmpty();
124 oslInterlockedCount
Access::acquireCounting() {
125 return osl_atomic_increment(&m_refCount
);
128 void Access::releaseNondeleting() {
129 osl_atomic_decrement(&m_refCount
);
132 bool Access::isValue() {
133 rtl::Reference
< Node
> p(getNode());
135 case Node::KIND_PROPERTY
:
136 case Node::KIND_LOCALIZED_VALUE
:
138 case Node::KIND_LOCALIZED_PROPERTY
:
139 return !Components::allLocales(getRootAccess()->getLocale());
145 void Access::markChildAsModified(rtl::Reference
< ChildAccess
> const & child
) {
146 assert(child
.is() && child
->getParentAccess() == this);
147 modifiedChildren_
[child
->getNameInternal()] = ModifiedChild(child
, true);
148 for (rtl::Reference
< Access
> p(this);;) {
149 rtl::Reference
< Access
> parent(p
->getParentAccess());
153 assert(dynamic_cast< ChildAccess
* >(p
.get()) != nullptr);
154 parent
->modifiedChildren_
.emplace(
155 p
->getNameInternal(),
156 ModifiedChild(static_cast< ChildAccess
* >(p
.get()), false));
161 void Access::releaseChild(OUString
const & name
) {
162 cachedChildren_
.erase(name
);
165 void Access::initBroadcaster(
166 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
)
168 initBroadcasterAndChanges(modifications
, broadcaster
, nullptr);
171 css::uno::Sequence
< css::uno::Type
> Access::getTypes()
173 assert(thisIs(IS_ANY
));
174 osl::MutexGuard
g(*lock_
);
175 checkLocalizedPropertyAccess();
176 std::vector
< css::uno::Type
> types
;
177 types
.push_back(cppu::UnoType
< css::uno::XInterface
>::get());
178 types
.push_back(cppu::UnoType
< css::uno::XWeak
>::get());
179 types
.push_back(cppu::UnoType
< css::lang::XTypeProvider
>::get());
180 types
.push_back(cppu::UnoType
< css::lang::XServiceInfo
>::get());
181 types
.push_back(cppu::UnoType
< css::lang::XComponent
>::get());
182 types
.push_back(cppu::UnoType
< css::container::XContainer
>::get());
183 types
.push_back(cppu::UnoType
< css::beans::XExactName
>::get());
184 types
.push_back(cppu::UnoType
< css::container::XHierarchicalName
>::get());
185 types
.push_back(cppu::UnoType
< css::container::XNamed
>::get());
186 types
.push_back(cppu::UnoType
< css::beans::XProperty
>::get());
187 types
.push_back(cppu::UnoType
< css::container::XElementAccess
>::get());
188 types
.push_back(cppu::UnoType
< css::container::XNameAccess
>::get());
189 if (getNode()->kind() == Node::KIND_GROUP
) {
190 types
.push_back(cppu::UnoType
< css::beans::XPropertySetInfo
>::get());
191 types
.push_back(cppu::UnoType
< css::beans::XPropertySet
>::get());
192 types
.push_back(cppu::UnoType
< css::beans::XMultiPropertySet
>::get());
194 cppu::UnoType
< css::beans::XHierarchicalPropertySet
>::get());
196 cppu::UnoType
< css::beans::XMultiHierarchicalPropertySet
>::get());
198 cppu::UnoType
< css::beans::XHierarchicalPropertySetInfo
>::get());
200 if (getRootAccess()->isUpdate()) {
201 types
.push_back(cppu::UnoType
< css::container::XNameReplace
>::get());
203 cppu::UnoType
< css::container::XHierarchicalNameReplace
>::get());
204 if (getNode()->kind() != Node::KIND_GROUP
||
205 static_cast< GroupNode
* >(getNode().get())->isExtensible())
208 cppu::UnoType
< css::container::XNameContainer
>::get());
210 if (getNode()->kind() == Node::KIND_SET
) {
212 cppu::UnoType
< css::lang::XSingleServiceFactory
>::get());
216 cppu::UnoType
< css::container::XHierarchicalNameAccess
>::get());
219 return comphelper::containerToSequence(types
);
222 css::uno::Sequence
< sal_Int8
> Access::getImplementationId()
224 assert(thisIs(IS_ANY
));
225 osl::MutexGuard
g(*lock_
);
226 checkLocalizedPropertyAccess();
227 return css::uno::Sequence
< sal_Int8
>();
230 OUString
Access::getImplementationName()
232 assert(thisIs(IS_ANY
));
233 osl::MutexGuard
g(*lock_
);
234 checkLocalizedPropertyAccess();
235 return "org.openoffice-configmgr::Access";
238 sal_Bool
Access::supportsService(OUString
const & ServiceName
)
240 return cppu::supportsService(this, ServiceName
);
243 css::uno::Sequence
< OUString
> Access::getSupportedServiceNames()
245 assert(thisIs(IS_ANY
));
246 osl::MutexGuard
g(*lock_
);
247 checkLocalizedPropertyAccess();
248 std::vector
<OUString
> services
;
249 services
.emplace_back("com.sun.star.configuration.ConfigurationAccess");
250 if (getRootAccess()->isUpdate()) {
251 services
.emplace_back("com.sun.star.configuration.ConfigurationUpdateAccess");
253 services
.emplace_back("com.sun.star.configuration.HierarchyAccess");
254 services
.emplace_back("com.sun.star.configuration.HierarchyElement");
255 if (getNode()->kind() == Node::KIND_GROUP
) {
256 services
.emplace_back("com.sun.star.configuration.GroupAccess");
257 services
.emplace_back("com.sun.star.configuration.PropertyHierarchy");
258 if (getRootAccess()->isUpdate()) {
259 services
.emplace_back("com.sun.star.configuration.GroupUpdate");
262 services
.emplace_back("com.sun.star.configuration.SetAccess");
263 services
.emplace_back("com.sun.star.configuration.SimpleSetAccess");
264 if (getRootAccess()->isUpdate()) {
265 services
.emplace_back("com.sun.star.configuration.SetUpdate");
266 services
.emplace_back("com.sun.star.configuration.SimpleSetUpdate");
269 addSupportedServiceNames(&services
);
270 return comphelper::containerToSequence(services
);
273 void Access::dispose() {
274 assert(thisIs(IS_ANY
));
277 osl::MutexGuard
g(*lock_
);
278 checkLocalizedPropertyAccess();
279 if (getParentAccess().is()) {
280 throw css::uno::RuntimeException(
281 "configmgr dispose inappropriate Access",
282 static_cast< cppu::OWeakObject
* >(this));
287 initDisposeBroadcaster(&bc
);
294 void Access::addEventListener(
295 css::uno::Reference
< css::lang::XEventListener
> const & xListener
)
297 assert(thisIs(IS_ANY
));
299 osl::MutexGuard
g(*lock_
);
300 checkLocalizedPropertyAccess();
301 if (!xListener
.is()) {
302 throw css::uno::RuntimeException(
303 "null listener", static_cast< cppu::OWeakObject
* >(this));
306 disposeListeners_
.insert(xListener
);
311 xListener
->disposing(
312 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
313 } catch (css::lang::DisposedException
&) {}
316 void Access::removeEventListener(
317 css::uno::Reference
< css::lang::XEventListener
> const & aListener
)
319 assert(thisIs(IS_ANY
));
320 osl::MutexGuard
g(*lock_
);
321 checkLocalizedPropertyAccess();
322 DisposeListeners::iterator
i(disposeListeners_
.find(aListener
));
323 if (i
!= disposeListeners_
.end()) {
324 disposeListeners_
.erase(i
);
328 css::uno::Type
Access::getElementType() {
329 assert(thisIs(IS_ANY
));
330 osl::MutexGuard
g(*lock_
);
331 checkLocalizedPropertyAccess();
332 rtl::Reference
< Node
> p(getNode());
334 case Node::KIND_LOCALIZED_PROPERTY
:
336 static_cast< LocalizedPropertyNode
* >(p
.get())->getStaticType());
337 case Node::KIND_GROUP
:
338 //TODO: Should a specific type be returned for a non-extensible group
339 // with homogeneous members or for an extensible group that currently
340 // has only homogeneous members?
341 return cppu::UnoType
<void>::get();
343 return cppu::UnoType
<void>::get(); //TODO: correct?
346 throw css::uno::RuntimeException(
347 "this cannot happen", static_cast< cppu::OWeakObject
* >(this));
351 sal_Bool
Access::hasElements() {
352 assert(thisIs(IS_ANY
));
353 osl::MutexGuard
g(*lock_
);
354 checkLocalizedPropertyAccess();
355 return !getAllChildren().empty(); //TODO: optimize
358 bool Access::getByNameFast(const OUString
& name
, css::uno::Any
& value
)
360 bool bGotValue
= false;
361 rtl::Reference
< ChildAccess
> child
;
363 if (getNode()->kind() != Node::KIND_LOCALIZED_PROPERTY
)
364 { // try to get it directly
365 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
366 if (i
!= modifiedChildren_
.end())
368 child
= getModifiedChild(i
);
371 value
= child
->asValue();
377 rtl::Reference
< Node
> node(getNode()->getMember(name
));
380 bGotValue
= ChildAccess::asSimpleValue(node
, value
, components_
);
386 child
= getChild(name
);
389 value
= child
->asValue();
394 css::uno::Any
Access::getByName(OUString
const & aName
)
396 assert(thisIs(IS_ANY
));
397 osl::MutexGuard
g(*lock_
);
398 checkLocalizedPropertyAccess();
400 if (!getByNameFast(aName
, value
))
401 throw css::container::NoSuchElementException(
402 aName
, static_cast< cppu::OWeakObject
* >(this));
406 css::uno::Sequence
< OUString
> Access::getElementNames()
408 assert(thisIs(IS_ANY
));
409 osl::MutexGuard
g(*lock_
);
410 checkLocalizedPropertyAccess();
411 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
412 std::vector
<OUString
> names
;
413 names
.reserve(children
.size());
414 for (auto const& child
: children
)
416 names
.push_back(child
->getNameInternal());
418 return comphelper::containerToSequence(names
);
421 sal_Bool
Access::hasByName(OUString
const & aName
)
423 assert(thisIs(IS_ANY
));
424 osl::MutexGuard
g(*lock_
);
425 checkLocalizedPropertyAccess();
426 return getChild(aName
).is();
429 css::uno::Any
Access::getByHierarchicalName(OUString
const & aName
)
431 assert(thisIs(IS_ANY
));
432 osl::MutexGuard
g(*lock_
);
433 checkLocalizedPropertyAccess();
434 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
436 throw css::container::NoSuchElementException(
437 aName
, static_cast< cppu::OWeakObject
* >(this));
439 return child
->asValue();
442 sal_Bool
Access::hasByHierarchicalName(OUString
const & aName
)
444 assert(thisIs(IS_ANY
));
445 osl::MutexGuard
g(*lock_
);
446 checkLocalizedPropertyAccess();
447 return getSubChild(aName
).is();
450 void Access::replaceByHierarchicalName(
451 OUString
const & aName
, css::uno::Any
const & aElement
)
453 //TODO: Actually support sets and combine with replaceByName:
454 assert(thisIs(IS_UPDATE
));
457 osl::MutexGuard
g(*lock_
);
458 checkLocalizedPropertyAccess();
459 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
461 throw css::container::NoSuchElementException(
462 aName
, static_cast< cppu::OWeakObject
* >(this));
464 child
->checkFinalized();
465 rtl::Reference
< Node
> parent(child
->getParentNode());
467 Modifications localMods
;
468 switch (parent
->kind()) {
469 case Node::KIND_LOCALIZED_PROPERTY
:
470 case Node::KIND_GROUP
:
471 child
->setProperty(aElement
, &localMods
);
474 throw css::lang::IllegalArgumentException(
475 ("configmgr::Access::replaceByHierarchicalName does not"
476 " currently support set members"),
477 static_cast< cppu::OWeakObject
* >(this), 0);
478 case Node::KIND_ROOT
:
479 throw css::lang::IllegalArgumentException(
480 ("configmgr::Access::replaceByHierarchicalName does not allow"
481 " changing component " + aName
),
482 static_cast< cppu::OWeakObject
* >(this), 0);
484 assert(false); // this cannot happen
487 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
492 void Access::addContainerListener(
493 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
495 assert(thisIs(IS_ANY
));
497 osl::MutexGuard
g(*lock_
);
498 checkLocalizedPropertyAccess();
499 if (!xListener
.is()) {
500 throw css::uno::RuntimeException(
501 "null listener", static_cast< cppu::OWeakObject
* >(this));
504 containerListeners_
.insert(xListener
);
509 xListener
->disposing(
510 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
511 } catch (css::lang::DisposedException
&) {}
514 void Access::removeContainerListener(
515 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
517 assert(thisIs(IS_ANY
));
518 osl::MutexGuard
g(*lock_
);
519 checkLocalizedPropertyAccess();
520 ContainerListeners::iterator
i(containerListeners_
.find(xListener
));
521 if (i
!= containerListeners_
.end()) {
522 containerListeners_
.erase(i
);
526 OUString
Access::getExactName(OUString
const & aApproximateName
)
528 assert(thisIs(IS_ANY
));
529 osl::MutexGuard
g(*lock_
);
530 checkLocalizedPropertyAccess();
531 return aApproximateName
;
534 css::uno::Sequence
< css::beans::Property
> Access::getProperties()
536 assert(thisIs(IS_GROUP
));
537 osl::MutexGuard
g(*lock_
);
538 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
539 std::vector
< css::beans::Property
> properties
;
540 properties
.reserve(children
.size());
541 for (auto const& child
: children
)
543 properties
.push_back(child
->asProperty());
545 return comphelper::containerToSequence(properties
);
548 css::beans::Property
Access::getPropertyByName(OUString
const & aName
)
550 assert(thisIs(IS_GROUP
));
551 osl::MutexGuard
g(*lock_
);
552 rtl::Reference
< ChildAccess
> child(getChild(aName
));
554 throw css::beans::UnknownPropertyException(
555 aName
, static_cast< cppu::OWeakObject
* >(this));
557 return child
->asProperty();
560 sal_Bool
Access::hasPropertyByName(OUString
const & Name
)
562 assert(thisIs(IS_GROUP
));
563 osl::MutexGuard
g(*lock_
);
564 return getChild(Name
).is();
567 OUString
Access::getHierarchicalName() {
568 assert(thisIs(IS_ANY
));
569 osl::MutexGuard
g(*lock_
);
570 checkLocalizedPropertyAccess();
571 // For backwards compatibility, return an absolute path representation where
574 rtl::Reference
< RootAccess
> root(getRootAccess());
576 rootPath
= root
->getAbsolutePathRepresentation();
578 OUString
rel(getRelativePathRepresentation());
579 OUStringBuffer
path(rootPath
);
580 if (!rootPath
.isEmpty() && rootPath
!= "/" && !rel
.isEmpty()) {
584 return path
.makeStringAndClear();
587 OUString
Access::composeHierarchicalName(
588 OUString
const & aRelativeName
)
590 assert(thisIs(IS_ANY
));
591 osl::MutexGuard
g(*lock_
);
592 checkLocalizedPropertyAccess();
593 if (aRelativeName
.isEmpty() || aRelativeName
[0] == '/') {
594 throw css::lang::IllegalArgumentException(
595 "configmgr composeHierarchicalName inappropriate relative name",
596 static_cast< cppu::OWeakObject
* >(this), -1);
598 OUStringBuffer
path(getRelativePathRepresentation());
599 if (!path
.isEmpty()) {
602 path
.append(aRelativeName
);
603 return path
.makeStringAndClear();
606 OUString
Access::getName() {
607 assert(thisIs(IS_ANY
));
608 osl::MutexGuard
g(*lock_
);
609 checkLocalizedPropertyAccess();
610 return getNameInternal();
613 void Access::setName(OUString
const & aName
)
615 assert(thisIs(IS_ANY
));
618 osl::MutexGuard
g(*lock_
);
619 checkLocalizedPropertyAccess();
621 Modifications localMods
;
622 switch (getNode()->kind()) {
623 case Node::KIND_GROUP
:
626 rtl::Reference
< Access
> parent(getParentAccess());
628 rtl::Reference
< Node
> node(getNode());
629 if (! node
->getTemplateName().isEmpty()) {
630 rtl::Reference
< ChildAccess
> other(
631 parent
->getChild(aName
));
632 if (other
.get() == this) {
635 if (node
->getMandatory() == Data::NO_LAYER
&&
636 !(other
.is() && other
->isFinalized()))
638 if (!isValidName(aName
, true)) {
639 throw css::uno::RuntimeException(
640 "invalid element name " + aName
);
642 rtl::Reference
< RootAccess
> root(getRootAccess());
643 rtl::Reference
< ChildAccess
> childAccess(
644 static_cast< ChildAccess
* >(this));
645 localMods
.add(getRelativePath());
646 // unbind() modifies the parent chain that
647 // markChildAsModified() walks, so order is
649 parent
->markChildAsModified(childAccess
);
650 //TODO: must not throw
651 childAccess
->unbind(); // must not throw
653 other
->unbind(); // must not throw
655 childAccess
->bind(root
, parent
, aName
);
657 parent
->markChildAsModified(childAccess
);
658 //TODO: must not throw
659 localMods
.add(getRelativePath());
666 case Node::KIND_LOCALIZED_PROPERTY
:
667 // renaming a property could only work for an extension property,
668 // but a localized property is never an extension property
669 throw css::uno::RuntimeException(
670 "configmgr setName inappropriate node",
671 static_cast< cppu::OWeakObject
* >(this));
673 assert(false); // this cannot happen
676 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
681 css::beans::Property
Access::getAsProperty()
683 assert(thisIs(IS_ANY
));
684 osl::MutexGuard
g(*lock_
);
685 checkLocalizedPropertyAccess();
689 css::uno::Reference
< css::beans::XPropertySetInfo
> Access::getPropertySetInfo()
691 assert(thisIs(IS_GROUP
));
695 void Access::setPropertyValue(
696 OUString
const & aPropertyName
, css::uno::Any
const & aValue
)
698 assert(thisIs(IS_GROUP
));
701 osl::MutexGuard
g(*lock_
);
702 if (!getRootAccess()->isUpdate()) {
703 throw css::uno::RuntimeException(
704 "configmgr setPropertyValue on non-update access",
705 static_cast< cppu::OWeakObject
* >(this));
707 Modifications localMods
;
708 if (!setChildProperty(aPropertyName
, aValue
, &localMods
)) {
709 throw css::beans::UnknownPropertyException(
710 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
712 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
717 css::uno::Any
Access::getPropertyValue(OUString
const & PropertyName
)
719 assert(thisIs(IS_GROUP
));
720 osl::MutexGuard
g(*lock_
);
723 if (!getByNameFast(PropertyName
, value
))
724 throw css::beans::UnknownPropertyException(
725 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
729 void Access::addPropertyChangeListener(
730 OUString
const & aPropertyName
,
731 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
734 assert(thisIs(IS_GROUP
));
736 osl::MutexGuard
g(*lock_
);
737 if (!xListener
.is()) {
738 throw css::uno::RuntimeException(
739 "null listener", static_cast< cppu::OWeakObject
* >(this));
741 checkKnownProperty(aPropertyName
);
743 propertyChangeListeners_
[aPropertyName
].insert(xListener
);
748 xListener
->disposing(
749 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
750 } catch (css::lang::DisposedException
&) {}
753 void Access::removePropertyChangeListener(
754 OUString
const & aPropertyName
,
755 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
758 assert(thisIs(IS_GROUP
));
759 osl::MutexGuard
g(*lock_
);
760 checkKnownProperty(aPropertyName
);
761 PropertyChangeListeners::iterator
i(
762 propertyChangeListeners_
.find(aPropertyName
));
763 if (i
!= propertyChangeListeners_
.end()) {
764 PropertyChangeListenersElement::iterator
j(i
->second
.find(aListener
));
765 if (j
!= i
->second
.end()) {
767 if (i
->second
.empty()) {
768 propertyChangeListeners_
.erase(i
);
774 void Access::addVetoableChangeListener(
775 OUString
const & PropertyName
,
776 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
779 assert(thisIs(IS_GROUP
));
781 osl::MutexGuard
g(*lock_
);
782 if (!aListener
.is()) {
783 throw css::uno::RuntimeException(
784 "null listener", static_cast< cppu::OWeakObject
* >(this));
786 checkKnownProperty(PropertyName
);
788 vetoableChangeListeners_
[PropertyName
].insert(aListener
);
789 //TODO: actually call vetoableChangeListeners_
794 aListener
->disposing(
795 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
796 } catch (css::lang::DisposedException
&) {}
799 void Access::removeVetoableChangeListener(
800 OUString
const & PropertyName
,
801 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
804 assert(thisIs(IS_GROUP
));
805 osl::MutexGuard
g(*lock_
);
806 checkKnownProperty(PropertyName
);
807 VetoableChangeListeners::iterator
i(
808 vetoableChangeListeners_
.find(PropertyName
));
809 if (i
!= vetoableChangeListeners_
.end()) {
810 VetoableChangeListenersElement::iterator
j(i
->second
.find(aListener
));
811 if (j
!= i
->second
.end()) {
813 if (i
->second
.empty()) {
814 vetoableChangeListeners_
.erase(i
);
820 void Access::setPropertyValues(
821 css::uno::Sequence
< OUString
> const & aPropertyNames
,
822 css::uno::Sequence
< css::uno::Any
> const & aValues
)
824 assert(thisIs(IS_GROUP
));
827 osl::MutexGuard
g(*lock_
);
828 if (!getRootAccess()->isUpdate()) {
829 throw css::uno::RuntimeException(
830 "configmgr setPropertyValues on non-update access",
831 static_cast< cppu::OWeakObject
* >(this));
833 if (aPropertyNames
.getLength() != aValues
.getLength()) {
834 throw css::lang::IllegalArgumentException(
835 ("configmgr setPropertyValues: aPropertyNames/aValues of"
836 " different length"),
837 static_cast< cppu::OWeakObject
* >(this), -1);
839 Modifications localMods
;
840 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
) {
841 if (!setChildProperty(aPropertyNames
[i
], aValues
[i
], &localMods
)) {
842 throw css::lang::IllegalArgumentException(
843 "configmgr setPropertyValues inappropriate property name",
844 static_cast< cppu::OWeakObject
* >(this), -1);
847 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
852 css::uno::Sequence
< css::uno::Any
> Access::getPropertyValues(
853 css::uno::Sequence
< OUString
> const & aPropertyNames
)
855 assert(thisIs(IS_GROUP
));
856 osl::MutexGuard
g(*lock_
);
857 css::uno::Sequence
< css::uno::Any
> vals(aPropertyNames
.getLength());
859 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
)
861 if (!getByNameFast(aPropertyNames
[i
], vals
[i
]))
862 throw css::uno::RuntimeException(
863 "configmgr getPropertyValues inappropriate property name",
864 static_cast< cppu::OWeakObject
* >(this));
870 void Access::addPropertiesChangeListener(
871 css::uno::Sequence
< OUString
> const &,
872 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
875 assert(thisIs(IS_GROUP
));
877 osl::MutexGuard
g(*lock_
);
878 if (!xListener
.is()) {
879 throw css::uno::RuntimeException(
880 "null listener", static_cast< cppu::OWeakObject
* >(this));
883 propertiesChangeListeners_
.insert(xListener
);
888 xListener
->disposing(
889 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
890 } catch (css::lang::DisposedException
&) {}
893 void Access::removePropertiesChangeListener(
894 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
897 assert(thisIs(IS_GROUP
));
898 osl::MutexGuard
g(*lock_
);
899 PropertiesChangeListeners::iterator
i(
900 propertiesChangeListeners_
.find(xListener
));
901 if (i
!= propertiesChangeListeners_
.end()) {
902 propertiesChangeListeners_
.erase(i
);
906 void Access::firePropertiesChangeEvent(
907 css::uno::Sequence
< OUString
> const & aPropertyNames
,
908 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
911 assert(thisIs(IS_GROUP
));
912 css::uno::Sequence
< css::beans::PropertyChangeEvent
> events(
913 aPropertyNames
.getLength());
914 for (sal_Int32 i
= 0; i
< events
.getLength(); ++i
) {
915 events
[i
].Source
= static_cast< cppu::OWeakObject
* >(this);
916 events
[i
].PropertyName
= aPropertyNames
[i
];
917 events
[i
].Further
= false;
918 events
[i
].PropertyHandle
= -1;
920 xListener
->propertiesChange(events
);
923 css::uno::Reference
< css::beans::XHierarchicalPropertySetInfo
>
924 Access::getHierarchicalPropertySetInfo() {
925 assert(thisIs(IS_GROUP
));
929 void Access::setHierarchicalPropertyValue(
930 OUString
const & aHierarchicalPropertyName
,
931 css::uno::Any
const & aValue
)
933 assert(thisIs(IS_GROUP
));
936 osl::MutexGuard
g(*lock_
);
937 if (!getRootAccess()->isUpdate()) {
938 throw css::uno::RuntimeException(
939 "configmgr setHierarchicalPropertyName on non-update access",
940 static_cast< cppu::OWeakObject
* >(this));
942 rtl::Reference
< ChildAccess
> child(
943 getSubChild(aHierarchicalPropertyName
));
945 throw css::beans::UnknownPropertyException(
946 aHierarchicalPropertyName
,
947 static_cast< cppu::OWeakObject
* >(this));
949 child
->checkFinalized();
950 Modifications localMods
;
951 child
->setProperty(aValue
, &localMods
);
952 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
957 css::uno::Any
Access::getHierarchicalPropertyValue(
958 OUString
const & aHierarchicalPropertyName
)
960 assert(thisIs(IS_GROUP
));
961 osl::MutexGuard
g(*lock_
);
962 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalPropertyName
));
964 throw css::beans::UnknownPropertyException(
965 aHierarchicalPropertyName
,
966 static_cast< cppu::OWeakObject
* >(this));
968 return child
->asValue();
971 void Access::setHierarchicalPropertyValues(
972 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
,
973 css::uno::Sequence
< css::uno::Any
> const & Values
)
975 assert(thisIs(IS_GROUP
));
978 osl::MutexGuard
g(*lock_
);
979 if (!getRootAccess()->isUpdate()) {
980 throw css::uno::RuntimeException(
981 "configmgr setPropertyValues on non-update access",
982 static_cast< cppu::OWeakObject
* >(this));
984 if (aHierarchicalPropertyNames
.getLength() != Values
.getLength()) {
985 throw css::lang::IllegalArgumentException(
986 ("configmgr setHierarchicalPropertyValues:"
987 " aHierarchicalPropertyNames/Values of different length"),
988 static_cast< cppu::OWeakObject
* >(this), -1);
990 Modifications localMods
;
991 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
992 rtl::Reference
< ChildAccess
> child(
993 getSubChild(aHierarchicalPropertyNames
[i
]));
995 throw css::lang::IllegalArgumentException(
996 ("configmgr setHierarchicalPropertyValues inappropriate"
998 static_cast< cppu::OWeakObject
* >(this), -1);
1000 child
->checkFinalized();
1001 child
->setProperty(Values
[i
], &localMods
);
1003 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1008 css::uno::Sequence
< css::uno::Any
> Access::getHierarchicalPropertyValues(
1009 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
)
1011 assert(thisIs(IS_GROUP
));
1012 osl::MutexGuard
g(*lock_
);
1013 css::uno::Sequence
< css::uno::Any
> vals(
1014 aHierarchicalPropertyNames
.getLength());
1015 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1016 rtl::Reference
< ChildAccess
> child(
1017 getSubChild(aHierarchicalPropertyNames
[i
]));
1019 throw css::lang::IllegalArgumentException(
1020 ("configmgr getHierarchicalPropertyValues inappropriate"
1021 " hierarchical property name"),
1022 static_cast< cppu::OWeakObject
* >(this), -1);
1024 vals
[i
] = child
->asValue();
1029 css::beans::Property
Access::getPropertyByHierarchicalName(
1030 OUString
const & aHierarchicalName
)
1032 assert(thisIs(IS_GROUP
));
1033 osl::MutexGuard
g(*lock_
);
1034 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalName
));
1036 throw css::beans::UnknownPropertyException(
1037 aHierarchicalName
, static_cast< cppu::OWeakObject
* >(this));
1039 return child
->asProperty();
1042 sal_Bool
Access::hasPropertyByHierarchicalName(
1043 OUString
const & aHierarchicalName
)
1045 assert(thisIs(IS_GROUP
));
1046 osl::MutexGuard
g(*lock_
);
1047 return getSubChild(aHierarchicalName
).is();
1050 void Access::replaceByName(
1051 OUString
const & aName
, css::uno::Any
const & aElement
)
1053 assert(thisIs(IS_UPDATE
));
1056 osl::MutexGuard
g(*lock_
);
1057 checkLocalizedPropertyAccess();
1058 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1060 throw css::container::NoSuchElementException(
1061 aName
, static_cast< cppu::OWeakObject
* >(this));
1063 child
->checkFinalized();
1064 Modifications localMods
;
1065 switch (getNode()->kind()) {
1066 case Node::KIND_LOCALIZED_PROPERTY
:
1067 case Node::KIND_GROUP
:
1068 child
->setProperty(aElement
, &localMods
);
1070 case Node::KIND_SET
:
1072 rtl::Reference
< ChildAccess
> freeAcc(
1073 getFreeSetMember(aElement
));
1074 rtl::Reference
< RootAccess
> root(getRootAccess());
1075 localMods
.add(child
->getRelativePath());
1076 child
->unbind(); // must not throw
1077 freeAcc
->bind(root
, this, aName
); // must not throw
1078 markChildAsModified(freeAcc
); //TODO: must not throw
1082 assert(false); // this cannot happen
1085 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1090 void Access::insertByName(
1091 OUString
const & aName
, css::uno::Any
const & aElement
)
1093 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1096 osl::MutexGuard
g(*lock_
);
1097 checkLocalizedPropertyAccess();
1099 if (getChild(aName
).is()) {
1100 throw css::container::ElementExistException(
1101 aName
, static_cast< cppu::OWeakObject
* >(this));
1103 Modifications localMods
;
1104 switch (getNode()->kind()) {
1105 case Node::KIND_LOCALIZED_PROPERTY
:
1106 if (!isValidName(aName
, false)) {
1107 throw css::lang::IllegalArgumentException(
1108 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1110 insertLocalizedValueChild(aName
, aElement
, &localMods
);
1112 case Node::KIND_GROUP
:
1114 if (!isValidName(aName
, false)) {
1115 throw css::lang::IllegalArgumentException(
1116 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1118 checkValue(aElement
, TYPE_ANY
, true);
1119 rtl::Reference
child(
1121 components_
, getRootAccess(), this, aName
,
1123 Data::NO_LAYER
, TYPE_ANY
, true, aElement
, true)));
1124 markChildAsModified(child
);
1125 localMods
.add(child
->getRelativePath());
1128 case Node::KIND_SET
:
1130 if (!isValidName(aName
, true)) {
1131 throw css::lang::IllegalArgumentException(
1132 aName
, static_cast<cppu::OWeakObject
*>(this), 0);
1134 rtl::Reference
< ChildAccess
> freeAcc(
1135 getFreeSetMember(aElement
));
1136 freeAcc
->bind(getRootAccess(), this, aName
); // must not throw
1137 markChildAsModified(freeAcc
); //TODO: must not throw
1138 localMods
.add(freeAcc
->getRelativePath());
1142 assert(false); // this cannot happen
1145 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1150 void Access::removeByName(OUString
const & aName
)
1152 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1155 osl::MutexGuard
g(*lock_
);
1156 checkLocalizedPropertyAccess();
1157 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1158 if (!child
.is() || child
->isFinalized() ||
1159 child
->getNode()->getMandatory() != Data::NO_LAYER
)
1161 throw css::container::NoSuchElementException(
1162 aName
, static_cast< cppu::OWeakObject
* >(this));
1164 if (getNode()->kind() == Node::KIND_GROUP
) {
1165 rtl::Reference
< Node
> p(child
->getNode());
1166 if (p
->kind() != Node::KIND_PROPERTY
||
1167 !static_cast< PropertyNode
* >(p
.get())->isExtension())
1169 throw css::container::NoSuchElementException(
1170 aName
, static_cast< cppu::OWeakObject
* >(this));
1173 Modifications localMods
;
1174 localMods
.add(child
->getRelativePath());
1175 // unbind() modifies the parent chain that markChildAsModified() walks,
1176 // so order is important:
1177 markChildAsModified(child
); //TODO: must not throw
1179 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1184 css::uno::Reference
< css::uno::XInterface
> Access::createInstance()
1186 assert(thisIs(IS_SET
|IS_UPDATE
));
1188 static_cast< SetNode
* >(getNode().get())->getDefaultTemplateName());
1189 rtl::Reference
< Node
> tmpl(
1190 components_
.getTemplate(tmplName
));
1192 throw css::uno::Exception(
1193 "unknown template " + tmplName
,
1194 static_cast< cppu::OWeakObject
* >(this));
1196 rtl::Reference
< Node
> node(tmpl
->clone(true));
1197 node
->setLayer(Data::NO_LAYER
);
1198 return static_cast< cppu::OWeakObject
* >(
1199 new ChildAccess(components_
, getRootAccess(), node
));
1202 css::uno::Reference
< css::uno::XInterface
> Access::createInstanceWithArguments(
1203 css::uno::Sequence
< css::uno::Any
> const & aArguments
)
1205 assert(thisIs(IS_SET
|IS_UPDATE
));
1206 if (aArguments
.hasElements()) {
1207 throw css::uno::Exception(
1208 ("configuration SimpleSetUpdate createInstanceWithArguments"
1209 " must not specify any arguments"),
1210 static_cast< cppu::OWeakObject
* >(this));
1212 return createInstance();
1215 Access::Access(Components
& components
):
1216 components_(components
), disposed_(false), lock_( lock() )
1220 Access::~Access() {}
1222 void Access::initDisposeBroadcaster(Broadcaster
* broadcaster
) {
1223 assert(broadcaster
!= nullptr);
1224 for (auto const& disposeListener
: disposeListeners_
)
1226 broadcaster
->addDisposeNotification(
1228 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1230 for (auto const& containerListener
: containerListeners_
)
1232 broadcaster
->addDisposeNotification(
1233 containerListener
.get(),
1234 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1236 for (auto const& propertyChangeListener
: propertyChangeListeners_
)
1238 for (auto const& propertyChangeListenerElement
: propertyChangeListener
.second
)
1240 broadcaster
->addDisposeNotification(
1241 propertyChangeListenerElement
.get(),
1242 css::lang::EventObject(
1243 static_cast< cppu::OWeakObject
* >(this)));
1246 for (auto const& vetoableChangeListener
: vetoableChangeListeners_
)
1248 for (auto const& vetoableChangeListenerElement
: vetoableChangeListener
.second
)
1250 broadcaster
->addDisposeNotification(
1251 vetoableChangeListenerElement
.get(),
1252 css::lang::EventObject(
1253 static_cast< cppu::OWeakObject
* >(this)));
1256 for (auto const& propertiesChangeListener
: propertiesChangeListeners_
)
1258 broadcaster
->addDisposeNotification(
1259 propertiesChangeListener
.get(),
1260 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1262 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1263 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1264 i
!= modifiedChildren_
.end(); ++i
)
1266 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1268 child
->initDisposeBroadcaster(broadcaster
);
1273 void Access::clearListeners() throw() {
1274 disposeListeners_
.clear();
1275 containerListeners_
.clear();
1276 propertyChangeListeners_
.clear();
1277 vetoableChangeListeners_
.clear();
1278 propertiesChangeListeners_
.clear();
1279 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1280 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1281 i
!= modifiedChildren_
.end(); ++i
)
1283 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1285 child
->clearListeners();
1290 css::uno::Any
Access::queryInterface(css::uno::Type
const & aType
)
1292 css::uno::Any
res(OWeakObject::queryInterface(aType
));
1293 if (res
.hasValue()) {
1296 res
= cppu::queryInterface(
1297 aType
, static_cast< css::lang::XTypeProvider
* >(this),
1298 static_cast< css::lang::XServiceInfo
* >(this),
1299 static_cast< css::lang::XComponent
* >(this),
1300 static_cast< css::container::XHierarchicalNameAccess
* >(this),
1301 static_cast< css::container::XContainer
* >(this),
1302 static_cast< css::beans::XExactName
* >(this),
1303 static_cast< css::container::XHierarchicalName
* >(this),
1304 static_cast< css::container::XNamed
* >(this),
1305 static_cast< css::beans::XProperty
* >(this),
1306 static_cast< css::container::XElementAccess
* >(this),
1307 static_cast< css::container::XNameAccess
* >(this));
1308 if (res
.hasValue()) {
1311 if (getNode()->kind() == Node::KIND_GROUP
) {
1312 res
= cppu::queryInterface(
1313 aType
, static_cast< css::beans::XPropertySetInfo
* >(this),
1314 static_cast< css::beans::XPropertySet
* >(this),
1315 static_cast< css::beans::XMultiPropertySet
* >(this),
1316 static_cast< css::beans::XHierarchicalPropertySet
* >(this),
1317 static_cast< css::beans::XMultiHierarchicalPropertySet
* >(this),
1318 static_cast< css::beans::XHierarchicalPropertySetInfo
* >(this));
1319 if (res
.hasValue()) {
1323 if (getRootAccess()->isUpdate()) {
1324 res
= cppu::queryInterface(
1325 aType
, static_cast< css::container::XNameReplace
* >(this),
1326 static_cast< css::container::XHierarchicalNameReplace
* >(this));
1327 if (res
.hasValue()) {
1330 if (getNode()->kind() != Node::KIND_GROUP
||
1331 static_cast< GroupNode
* >(getNode().get())->isExtensible())
1333 res
= cppu::queryInterface(
1334 aType
, static_cast< css::container::XNameContainer
* >(this));
1335 if (res
.hasValue()) {
1339 if (getNode()->kind() == Node::KIND_SET
) {
1340 res
= cppu::queryInterface(
1341 aType
, static_cast< css::lang::XSingleServiceFactory
* >(this));
1348 void Access::checkLocalizedPropertyAccess() {
1349 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
&&
1350 !Components::allLocales(getRootAccess()->getLocale()))
1352 throw css::uno::RuntimeException(
1353 "configmgr Access to specialized LocalizedPropertyNode",
1354 static_cast< cppu::OWeakObject
* >(this));
1358 rtl::Reference
< Node
> Access::getParentNode() {
1359 rtl::Reference
< Access
> parent(getParentAccess());
1360 return parent
.is() ? parent
->getNode() : rtl::Reference
< Node
>();
1363 rtl::Reference
< ChildAccess
> Access::getChild(OUString
const & name
) {
1365 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
1366 && name
.startsWith("*", &locale
))
1368 if (locale
.startsWith("*")) {
1371 ("access best-matching localized property value via"
1372 " \"*<locale>\" with <locale> \"")
1373 << locale
<< "\" recursively starting with \"*\"");
1374 return getChild(locale
);
1377 locale
.isEmpty(), "configmgr",
1378 ("access best-matching localized property value via \"*<locale>\""
1379 " with empty <locale>; falling back to defaults"));
1381 // Since the locale given to us is the one used at initialization,
1382 // here we override it with the actual current-user's language to
1383 // support per-view localization in LOK.
1384 if (comphelper::LibreOfficeKit::isActive())
1385 locale
= comphelper::LibreOfficeKit::getLanguageTag().getLanguage();
1387 if (!locale
.isEmpty()) {
1388 // Find best match using an adaptation of RFC 4647 lookup matching
1389 // rules, removing "-" or "_" delimited segments from the end:
1391 rtl::Reference
< ChildAccess
> child(getChild(locale
));
1395 sal_Int32 i
= locale
.getLength() - 1;
1396 while (i
> 0 && locale
[i
] != '-' && locale
[i
] != '_') {
1402 locale
= locale
.copy(0, i
);
1404 // As a workaround for broken xcu data that does not use shortest
1405 // xml:lang attributes, look for the first entry with the same first
1406 // segment as the requested language tag before falling back to
1407 // defaults (see fdo#33638):
1409 !locale
.isEmpty() && locale
.indexOf('-') == -1 &&
1410 locale
.indexOf('_') == -1);
1411 std::vector
< rtl::Reference
< ChildAccess
> > children(
1413 for (auto const& child
: children
)
1415 OUString
name2(child
->getNameInternal());
1416 if (name2
.startsWith(locale
) &&
1417 (name2
.getLength() == locale
.getLength() ||
1418 name2
[locale
.getLength()] == '-' ||
1419 name2
[locale
.getLength()] == '_'))
1425 // Defaults are the "en-US" locale, the "en" locale, the empty string locale, the first child (if
1426 // any, and if the property is non-nillable), or a null ChildAccess, in that order:
1427 rtl::Reference
< ChildAccess
> child(getChild("en-US"));
1431 child
= getChild("en");
1435 child
= getChild("");
1439 if (!static_cast<LocalizedPropertyNode
*>(getNode().get())->isNillable()) {
1440 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
1441 if (!children
.empty()) {
1442 return children
.front();
1445 return rtl::Reference
< ChildAccess
>();
1447 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
1448 return i
== modifiedChildren_
.end()
1449 ? getUnmodifiedChild(name
) : getModifiedChild(i
);
1452 std::vector
< rtl::Reference
< ChildAccess
> > Access::getAllChildren() {
1453 std::vector
< rtl::Reference
< ChildAccess
> > vec
;
1454 NodeMap
const & members
= getNode()->getMembers();
1455 for (auto const& member
: members
)
1457 if (modifiedChildren_
.find(member
.first
) == modifiedChildren_
.end()) {
1458 vec
.push_back(getUnmodifiedChild(member
.first
));
1459 assert(vec
.back().is());
1462 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1463 i
!= modifiedChildren_
.end(); ++i
)
1465 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1467 vec
.push_back(child
);
1473 void Access::checkValue(css::uno::Any
const & value
, Type type
, bool nillable
) {
1480 switch (getDynamicType(value
)) {
1491 for (;;) std::abort(); // cannot happen
1495 ok
= value
.hasValue() ? value
.isExtractableTo(mapType(type
)) : nillable
;
1498 for (;;) std::abort(); // cannot happen
1501 throw css::lang::IllegalArgumentException(
1502 "configmgr inappropriate property value",
1503 static_cast< cppu::OWeakObject
* >(this), -1);
1507 void Access::insertLocalizedValueChild(
1508 OUString
const & name
, css::uno::Any
const & value
,
1509 Modifications
* localModifications
)
1511 assert(localModifications
!= nullptr);
1512 LocalizedPropertyNode
* locprop
= static_cast< LocalizedPropertyNode
* >(
1514 checkValue(value
, locprop
->getStaticType(), locprop
->isNillable());
1515 rtl::Reference
child(
1517 components_
, getRootAccess(), this, name
,
1518 new LocalizedValueNode(Data::NO_LAYER
, value
)));
1519 markChildAsModified(child
);
1520 localModifications
->add(child
->getRelativePath());
1523 void Access::reportChildChanges(
1524 std::vector
< css::util::ElementChange
> * changes
)
1526 assert(changes
!= nullptr);
1527 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1528 i
!= modifiedChildren_
.end(); ++i
)
1530 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1532 child
->reportChildChanges(changes
);
1533 changes
->push_back(css::util::ElementChange());
1534 //TODO: changed value and/or inserted node
1536 changes
->push_back(css::util::ElementChange()); //TODO: removed node
1541 void Access::commitChildChanges(
1542 bool valid
, Modifications
* globalModifications
)
1544 assert(globalModifications
!= nullptr);
1545 while (!modifiedChildren_
.empty()) {
1546 bool childValid
= valid
;
1547 ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1548 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1550 childValid
= childValid
&& !child
->isFinalized();
1551 child
->commitChanges(childValid
, globalModifications
);
1552 //TODO: currently, this is called here for directly inserted
1553 // children as well as for children whose sub-children were
1554 // modified (and should never be called for directly removed
1555 // children); clarify what exactly should happen here for
1556 // directly inserted children
1558 NodeMap
& members
= getNode()->getMembers();
1559 NodeMap::iterator
j(members
.find(i
->first
));
1562 if (j
!= members
.end()) {
1563 childValid
= childValid
&&
1564 j
->second
->getFinalized() == Data::NO_LAYER
;
1566 child
->getNode()->setMandatory(j
->second
->getMandatory());
1570 members
[i
->first
] = child
->getNode();
1574 childValid
= childValid
&& j
!= members
.end() &&
1575 j
->second
->getFinalized() == Data::NO_LAYER
&&
1576 j
->second
->getMandatory() == Data::NO_LAYER
;
1581 if (childValid
&& i
->second
.directlyModified
) {
1582 std::vector
<OUString
> path(getAbsolutePath());
1583 path
.push_back(i
->first
);
1584 components_
.addModification(path
);
1585 globalModifications
->add(path
);
1587 i
->second
.child
->committed();
1588 modifiedChildren_
.erase(i
);
1592 void Access::initBroadcasterAndChanges(
1593 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
,
1594 std::vector
< css::util::ElementChange
> * allChanges
)
1596 assert(broadcaster
!= nullptr);
1597 std::vector
< css::beans::PropertyChangeEvent
> propChanges
;
1598 bool collectPropChanges
= !propertiesChangeListeners_
.empty();
1599 for (const auto & i
: modifications
.children
)
1601 rtl::Reference
< ChildAccess
> child(getChild(i
.first
));
1603 switch (child
->getNode()->kind()) {
1604 case Node::KIND_LOCALIZED_PROPERTY
:
1605 if (!i
.second
.children
.empty()) {
1606 if (Components::allLocales(getRootAccess()->getLocale())) {
1607 child
->initBroadcasterAndChanges(
1608 i
.second
, broadcaster
, allChanges
);
1609 //TODO: if allChanges==0, recurse only into children
1612 //TODO: filter child mods that are irrelevant for
1614 for (auto const& containerListener
: containerListeners_
)
1617 addContainerElementReplacedNotification(
1619 css::container::ContainerEvent(
1620 static_cast< cppu::OWeakObject
* >(
1622 css::uno::Any(i
.first
),
1623 css::uno::Any(), css::uno::Any()));
1624 //TODO: non-void Element, ReplacedElement
1626 PropertyChangeListeners::iterator
j(
1627 propertyChangeListeners_
.find(i
.first
));
1628 if (j
!= propertyChangeListeners_
.end()) {
1629 for (auto const& propertyChangeListenerElement
: j
->second
)
1631 broadcaster
->addPropertyChangeNotification(
1632 propertyChangeListenerElement
,
1633 css::beans::PropertyChangeEvent(
1634 static_cast< cppu::OWeakObject
* >(
1636 i
.first
, false, -1, css::uno::Any(),
1640 j
= propertyChangeListeners_
.find("");
1641 if (j
!= propertyChangeListeners_
.end()) {
1642 for (auto const& propertyChangeListenerElement
: j
->second
)
1644 broadcaster
->addPropertyChangeNotification(
1645 propertyChangeListenerElement
,
1646 css::beans::PropertyChangeEvent(
1647 static_cast< cppu::OWeakObject
* >(
1649 i
.first
, false, -1, css::uno::Any(),
1653 if (allChanges
!= nullptr) {
1654 allChanges
->push_back(
1655 css::util::ElementChange(
1657 child
->getRelativePathRepresentation()),
1658 css::uno::Any(), css::uno::Any()));
1659 //TODO: non-void Element, ReplacedElement
1661 if (collectPropChanges
) {
1662 propChanges
.emplace_back(
1663 static_cast< cppu::OWeakObject
* >(this),
1664 i
.first
, false, -1, css::uno::Any(),
1669 // else: spurious Modifications::Node not representing a change
1671 case Node::KIND_LOCALIZED_VALUE
:
1672 assert(Components::allLocales(getRootAccess()->getLocale()));
1673 for (auto const& containerListener
: containerListeners_
)
1675 broadcaster
->addContainerElementReplacedNotification(
1677 css::container::ContainerEvent(
1678 static_cast< cppu::OWeakObject
* >(this),
1679 css::uno::Any(i
.first
), child
->asValue(),
1681 //TODO: distinguish add/modify; non-void ReplacedElement
1683 if (allChanges
!= nullptr) {
1684 allChanges
->push_back(
1685 css::util::ElementChange(
1687 child
->getRelativePathRepresentation()),
1688 child
->asValue(), css::uno::Any()));
1689 //TODO: non-void ReplacedElement
1691 assert(!collectPropChanges
);
1693 case Node::KIND_PROPERTY
:
1695 for (auto const& containerListener
: containerListeners_
)
1697 broadcaster
->addContainerElementReplacedNotification(
1699 css::container::ContainerEvent(
1700 static_cast< cppu::OWeakObject
* >(this),
1701 css::uno::Any(i
.first
), child
->asValue(),
1703 //TODO: distinguish add/remove/modify; non-void
1706 PropertyChangeListeners::iterator
j(
1707 propertyChangeListeners_
.find(i
.first
));
1708 if (j
!= propertyChangeListeners_
.end()) {
1709 for (auto const& propertyChangeListenerElement
: j
->second
)
1711 broadcaster
->addPropertyChangeNotification(
1712 propertyChangeListenerElement
,
1713 css::beans::PropertyChangeEvent(
1714 static_cast< cppu::OWeakObject
* >(this),
1715 i
.first
, false, -1, css::uno::Any(),
1719 j
= propertyChangeListeners_
.find("");
1720 if (j
!= propertyChangeListeners_
.end()) {
1721 for (auto const& propertyChangeListenerElement
: j
->second
)
1723 broadcaster
->addPropertyChangeNotification(
1724 propertyChangeListenerElement
,
1725 css::beans::PropertyChangeEvent(
1726 static_cast< cppu::OWeakObject
* >(this),
1727 i
.first
, false, -1, css::uno::Any(),
1731 if (allChanges
!= nullptr) {
1732 allChanges
->push_back(
1733 css::util::ElementChange(
1735 child
->getRelativePathRepresentation()),
1736 child
->asValue(), css::uno::Any()));
1737 //TODO: non-void ReplacedElement
1739 if (collectPropChanges
) {
1740 propChanges
.emplace_back(
1741 static_cast< cppu::OWeakObject
* >(this),
1742 i
.first
, false, -1, css::uno::Any(),
1747 case Node::KIND_GROUP
:
1748 case Node::KIND_SET
:
1749 if (i
.second
.children
.empty()) {
1750 if (!child
->getNode()->getTemplateName().isEmpty()) {
1751 for (auto const& containerListener
: containerListeners_
)
1754 addContainerElementInsertedNotification(
1756 css::container::ContainerEvent(
1757 static_cast< cppu::OWeakObject
* >(
1759 css::uno::Any(i
.first
),
1760 child
->asValue(), css::uno::Any()));
1762 if (allChanges
!= nullptr) {
1763 allChanges
->push_back(
1764 css::util::ElementChange(
1766 child
->getRelativePathRepresentation()),
1767 css::uno::Any(), css::uno::Any()));
1768 //TODO: non-void Element, ReplacedElement
1771 // else: spurious Modifications::Node not representing a
1774 child
->initBroadcasterAndChanges(
1775 i
.second
, broadcaster
, allChanges
);
1776 //TODO: if allChanges==0, recurse only into children w/
1780 case Node::KIND_ROOT
:
1781 assert(false); // this cannot happen
1785 switch (getNode()->kind()) {
1786 case Node::KIND_LOCALIZED_PROPERTY
:
1787 // Removed localized property value:
1788 assert(Components::allLocales(getRootAccess()->getLocale()));
1789 for (auto const& containerListener
: containerListeners_
)
1791 broadcaster
->addContainerElementRemovedNotification(
1793 css::container::ContainerEvent(
1794 static_cast< cppu::OWeakObject
* >(this),
1795 css::uno::Any(i
.first
), css::uno::Any(),
1797 //TODO: non-void ReplacedElement
1799 if (allChanges
!= nullptr) {
1800 OUStringBuffer
path(getRelativePathRepresentation());
1801 if (!path
.isEmpty()) {
1804 path
.append(Data::createSegment("*", i
.first
));
1805 allChanges
->push_back(
1806 css::util::ElementChange(
1807 css::uno::Any(path
.makeStringAndClear()),
1808 css::uno::Any(), css::uno::Any()));
1809 //TODO: non-void ReplacedElement
1811 assert(!collectPropChanges
);
1813 case Node::KIND_GROUP
:
1815 // Removed (non-localized) extension property:
1816 for (auto const& containerListener
: containerListeners_
)
1818 broadcaster
->addContainerElementRemovedNotification(
1820 css::container::ContainerEvent(
1821 static_cast< cppu::OWeakObject
* >(this),
1822 css::uno::Any(i
.first
), css::uno::Any(),
1824 //TODO: non-void ReplacedElement
1826 PropertyChangeListeners::iterator
j(
1827 propertyChangeListeners_
.find(i
.first
));
1828 if (j
!= propertyChangeListeners_
.end()) {
1829 for (auto const& propertyChangeListenerElement
: j
->second
)
1831 broadcaster
->addPropertyChangeNotification(
1832 propertyChangeListenerElement
,
1833 css::beans::PropertyChangeEvent(
1834 static_cast< cppu::OWeakObject
* >(this),
1835 i
.first
, false, -1, css::uno::Any(),
1839 j
= propertyChangeListeners_
.find("");
1840 if (j
!= propertyChangeListeners_
.end()) {
1841 for (auto const& propertyChangeListenerElement
: j
->second
)
1843 broadcaster
->addPropertyChangeNotification(
1844 propertyChangeListenerElement
,
1845 css::beans::PropertyChangeEvent(
1846 static_cast< cppu::OWeakObject
* >(this),
1847 i
.first
, false, -1, css::uno::Any(),
1851 if (allChanges
!= nullptr) {
1852 OUStringBuffer
path(
1853 getRelativePathRepresentation());
1854 if (!path
.isEmpty()) {
1857 path
.append(i
.first
);
1858 allChanges
->push_back(
1859 css::util::ElementChange(
1860 css::uno::Any(path
.makeStringAndClear()),
1861 css::uno::Any(), css::uno::Any()));
1862 //TODO: non-void ReplacedElement
1864 if (collectPropChanges
) {
1865 propChanges
.emplace_back(
1866 static_cast< cppu::OWeakObject
* >(this),
1867 i
.first
, false, -1, css::uno::Any(),
1872 case Node::KIND_SET
:
1873 // Removed set member:
1874 if (i
.second
.children
.empty()) {
1875 for (auto const& containerListener
: containerListeners_
)
1877 broadcaster
->addContainerElementRemovedNotification(
1879 css::container::ContainerEvent(
1880 static_cast< cppu::OWeakObject
* >(this),
1881 css::uno::Any(i
.first
),
1882 css::uno::Any(), css::uno::Any()));
1883 //TODO: non-void ReplacedElement
1885 if (allChanges
!= nullptr) {
1886 OUStringBuffer
path(
1887 getRelativePathRepresentation());
1888 if (!path
.isEmpty()) {
1891 path
.append(Data::createSegment("*", i
.first
));
1892 allChanges
->push_back(
1893 css::util::ElementChange(
1894 css::uno::Any(path
.makeStringAndClear()),
1895 css::uno::Any(), css::uno::Any()));
1896 //TODO: non-void ReplacedElement
1899 // else: spurious Modifications::Node not representing a change
1902 assert(false); // this cannot happen
1907 if (!propChanges
.empty()) {
1908 css::uno::Sequence
< css::beans::PropertyChangeEvent
> seq(
1909 comphelper::containerToSequence(propChanges
));
1910 for (auto const& propertyChangeListener
: propertiesChangeListeners_
)
1912 broadcaster
->addPropertiesChangeNotification(propertyChangeListener
, seq
);
1918 Access::ModifiedChild::ModifiedChild():
1919 directlyModified(false)
1922 Access::ModifiedChild::ModifiedChild(
1923 rtl::Reference
< ChildAccess
> const & theChild
, bool theDirectlyModified
):
1924 child(theChild
), directlyModified(theDirectlyModified
)
1927 rtl::Reference
< ChildAccess
> Access::getModifiedChild(
1928 ModifiedChildren::iterator
const & childIterator
)
1930 return (childIterator
->second
.child
->getParentAccess() == this &&
1931 (childIterator
->second
.child
->getNameInternal() ==
1932 childIterator
->first
))
1933 ? childIterator
->second
.child
: rtl::Reference
< ChildAccess
>();
1936 rtl::Reference
< ChildAccess
> Access::createUnmodifiedChild(
1937 const OUString
&name
, const rtl::Reference
< Node
> &node
)
1939 rtl::Reference
child(
1940 new ChildAccess(components_
, getRootAccess(), this, name
, node
));
1941 cachedChildren_
[name
] = child
.get();
1945 rtl::Reference
< ChildAccess
> Access::getUnmodifiedChild(
1946 OUString
const & name
)
1948 assert(modifiedChildren_
.find(name
) == modifiedChildren_
.end());
1949 rtl::Reference
< Node
> node(getNode()->getMember(name
));
1951 return rtl::Reference
< ChildAccess
>();
1953 WeakChildMap::iterator
i(cachedChildren_
.find(name
));
1954 if (i
!= cachedChildren_
.end()) {
1955 rtl::Reference
< ChildAccess
> child
;
1956 if (i
->second
->acquireCounting() > 1) {
1957 child
.set(i
->second
); // must not throw
1959 i
->second
->releaseNondeleting();
1961 child
->setNode(node
);
1965 return createUnmodifiedChild(name
,node
);
1968 rtl::Reference
< ChildAccess
> Access::getSubChild(OUString
const & path
) {
1970 // For backwards compatibility, allow absolute paths where meaningful:
1971 if( path
.startsWith("/") ) {
1973 if (!getRootAccess().is()) {
1974 return rtl::Reference
< ChildAccess
>();
1976 std::vector
<OUString
> abs(getAbsolutePath());
1977 for (auto const& elem
: abs
)
1981 OUString templateName1
;
1982 i
= Data::parseSegment(
1983 path
, i
, &name1
, &setElement1
, &templateName1
);
1984 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
1985 return rtl::Reference
< ChildAccess
>();
1989 OUString templateName2
;
1990 Data::parseSegment(elem
, 0, &name2
, &setElement2
, &templateName2
);
1991 if (name1
!= name2
|| setElement1
!= setElement2
||
1993 !Data::equalTemplateNames(templateName1
, templateName2
)))
1995 return rtl::Reference
< ChildAccess
>();
1997 if (i
!= path
.getLength()) {
2002 for (rtl::Reference
< Access
> parent(this);;) {
2005 OUString templateName
;
2006 i
= Data::parseSegment(path
, i
, &name
, &setElement
, &templateName
);
2007 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2008 return rtl::Reference
< ChildAccess
>();
2010 rtl::Reference
< ChildAccess
> child(parent
->getChild(name
));
2012 return rtl::Reference
< ChildAccess
>();
2015 rtl::Reference
< Node
> p(parent
->getNode());
2016 switch (p
->kind()) {
2017 case Node::KIND_LOCALIZED_PROPERTY
:
2018 if (!Components::allLocales(getRootAccess()->getLocale()) ||
2019 !templateName
.isEmpty())
2021 return rtl::Reference
< ChildAccess
>();
2024 case Node::KIND_SET
:
2025 if (!templateName
.isEmpty() &&
2026 !static_cast< SetNode
* >(p
.get())->isValidTemplate(
2029 return rtl::Reference
< ChildAccess
>();
2033 return rtl::Reference
< ChildAccess
>();
2036 // For backwards compatibility, ignore a final slash after non-value
2038 if (child
->isValue()) {
2039 return i
== path
.getLength()
2040 ? child
: rtl::Reference
< ChildAccess
>();
2041 } else if (i
>= path
.getLength() - 1) {
2045 parent
= child
.get();
2049 bool Access::setChildProperty(
2050 OUString
const & name
, css::uno::Any
const & value
,
2051 Modifications
* localModifications
)
2053 assert(localModifications
!= nullptr);
2054 rtl::Reference
< ChildAccess
> child(getChild(name
));
2058 child
->checkFinalized();
2059 child
->setProperty(value
, localModifications
);
2063 css::beans::Property
Access::asProperty() {
2064 css::uno::Type type
;
2067 rtl::Reference
< Node
> p(getNode());
2068 switch (p
->kind()) {
2069 case Node::KIND_PROPERTY
:
2071 PropertyNode
* prop
= static_cast< PropertyNode
* >(p
.get());
2072 type
= mapType(prop
->getStaticType());
2073 nillable
= prop
->isNillable();
2074 removable
= prop
->isExtension();
2077 case Node::KIND_LOCALIZED_PROPERTY
:
2079 LocalizedPropertyNode
* locprop
=
2080 static_cast< LocalizedPropertyNode
*>(p
.get());
2081 if (Components::allLocales(getRootAccess()->getLocale())) {
2082 type
= cppu::UnoType
< css::uno::XInterface
>::get();
2086 type
= mapType(locprop
->getStaticType());
2087 removable
= false; //TODO ???
2089 nillable
= locprop
->isNillable();
2092 case Node::KIND_LOCALIZED_VALUE
:
2094 LocalizedPropertyNode
* locprop
=
2095 static_cast< LocalizedPropertyNode
* >(getParentNode().get());
2096 type
= mapType(locprop
->getStaticType());
2097 nillable
= locprop
->isNillable();
2098 removable
= false; //TODO ???
2102 type
= cppu::UnoType
< css::uno::XInterface
>::get(); //TODO: correct?
2104 rtl::Reference
< Node
> parent(getParentNode());
2105 removable
= parent
.is() && parent
->kind() == Node::KIND_SET
;
2108 return css::beans::Property(
2109 getNameInternal(), -1, type
,
2110 (css::beans::PropertyAttribute::BOUND
| //TODO: correct for group/set?
2111 css::beans::PropertyAttribute::CONSTRAINED
|
2112 (nillable
? css::beans::PropertyAttribute::MAYBEVOID
: 0) |
2113 (getRootAccess()->isUpdate() && removable
2114 ? css::beans::PropertyAttribute::REMOVABLE
: 0) |
2115 (!getRootAccess()->isUpdate() || p
->getFinalized() != Data::NO_LAYER
2116 ? css::beans::PropertyAttribute::READONLY
: 0))); //TODO: MAYBEDEFAULT
2119 void Access::checkFinalized() {
2120 if (isFinalized()) {
2121 throw css::lang::IllegalArgumentException(
2122 "configmgr modification of finalized item",
2123 static_cast< cppu::OWeakObject
* >(this), -1);
2127 void Access::checkKnownProperty(OUString
const & descriptor
) {
2128 if (descriptor
.isEmpty()) {
2131 rtl::Reference
< ChildAccess
> child(getChild(descriptor
));
2133 switch (child
->getNode()->kind()) {
2134 case Node::KIND_PROPERTY
:
2136 case Node::KIND_LOCALIZED_PROPERTY
:
2137 if (!Components::allLocales(getRootAccess()->getLocale())) {
2141 case Node::KIND_LOCALIZED_VALUE
:
2142 if (Components::allLocales(getRootAccess()->getLocale())) {
2150 throw css::beans::UnknownPropertyException(
2151 descriptor
, static_cast< cppu::OWeakObject
* >(this));
2154 rtl::Reference
< ChildAccess
> Access::getFreeSetMember(
2155 css::uno::Any
const & value
)
2157 rtl::Reference
< ChildAccess
> freeAcc
;
2158 css::uno::Reference
< css::lang::XUnoTunnel
> tunnel
;
2162 reinterpret_cast< ChildAccess
* >(
2163 tunnel
->getSomething(ChildAccess::getTunnelId())));
2165 if (!freeAcc
.is() || freeAcc
->getParentAccess().is() ||
2166 (freeAcc
->isInTransaction() &&
2167 freeAcc
->getRootAccess() != getRootAccess()))
2169 throw css::lang::IllegalArgumentException(
2170 "configmgr inappropriate set element",
2171 static_cast< cppu::OWeakObject
* >(this), 1);
2173 assert(dynamic_cast< SetNode
* >(getNode().get()) != nullptr);
2174 if (!static_cast< SetNode
* >(getNode().get())->isValidTemplate(
2175 freeAcc
->getNode()->getTemplateName()))
2177 throw css::lang::IllegalArgumentException(
2178 "configmgr inappropriate set element",
2179 static_cast< cppu::OWeakObject
* >(this), 1);
2184 rtl::Reference
< Access
> Access::getNotificationRoot() {
2185 for (rtl::Reference
< Access
> p(this);;) {
2186 rtl::Reference
< Access
> parent(p
->getParentAccess());
2195 bool Access::thisIs(int what
) {
2196 osl::MutexGuard
g(*lock_
);
2197 rtl::Reference
< Node
> p(getNode());
2198 Node::Kind
k(p
->kind());
2199 return (k
!= Node::KIND_PROPERTY
&& k
!= Node::KIND_LOCALIZED_VALUE
&&
2200 ((what
& IS_GROUP
) == 0 || k
== Node::KIND_GROUP
) &&
2201 ((what
& IS_SET
) == 0 || k
== Node::KIND_SET
) &&
2202 ((what
& IS_EXTENSIBLE
) == 0 || k
!= Node::KIND_GROUP
||
2203 static_cast< GroupNode
* >(p
.get())->isExtensible()) &&
2204 ((what
& IS_GROUP_MEMBER
) == 0 ||
2205 getParentNode()->kind() == Node::KIND_GROUP
)) ||
2206 ((what
& IS_SET_MEMBER
) == 0 ||
2207 getParentNode()->kind() == Node::KIND_SET
) ||
2208 ((what
& IS_UPDATE
) == 0 || getRootAccess()->isUpdate());
2214 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */