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"
25 #include "com/sun/star/beans/Property.hpp"
26 #include "com/sun/star/beans/PropertyAttribute.hpp"
27 #include "com/sun/star/beans/PropertyChangeEvent.hpp"
28 #include "com/sun/star/beans/PropertyVetoException.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/NoSupportException.hpp"
56 #include "com/sun/star/lang/WrappedTargetException.hpp"
57 #include "com/sun/star/lang/XComponent.hpp"
58 #include "com/sun/star/lang/XEventListener.hpp"
59 #include "com/sun/star/lang/XServiceInfo.hpp"
60 #include "com/sun/star/lang/XSingleServiceFactory.hpp"
61 #include "com/sun/star/lang/XTypeProvider.hpp"
62 #include "com/sun/star/lang/XUnoTunnel.hpp"
63 #include "com/sun/star/uno/Any.hxx"
64 #include "com/sun/star/uno/Reference.hxx"
65 #include "com/sun/star/uno/RuntimeException.hpp"
66 #include "com/sun/star/uno/Sequence.hxx"
67 #include "com/sun/star/uno/Type.hxx"
68 #include "com/sun/star/uno/TypeClass.hpp"
69 #include "com/sun/star/uno/XInterface.hpp"
70 #include "com/sun/star/uno/XWeak.hpp"
71 #include "com/sun/star/util/ElementChange.hpp"
72 #include "comphelper/sequenceasvector.hxx"
73 #include "cppu/unotype.hxx"
74 #include "cppuhelper/queryinterface.hxx"
75 #include "cppuhelper/weak.hxx"
76 #include "osl/interlck.h"
77 #include "osl/mutex.hxx"
78 #include "rtl/ref.hxx"
79 #include "rtl/ustrbuf.hxx"
80 #include "rtl/ustring.h"
81 #include "rtl/ustring.hxx"
82 #include "sal/types.h"
85 #include "broadcaster.hxx"
86 #include "childaccess.hxx"
87 #include "components.hxx"
89 #include "groupnode.hxx"
90 #include "localizedpropertynode.hxx"
91 #include "localizedvaluenode.hxx"
93 #include "modifications.hxx"
95 #include "nodemap.hxx"
97 #include "propertynode.hxx"
98 #include "rootaccess.hxx"
99 #include "setnode.hxx"
102 namespace configmgr
{
104 oslInterlockedCount
Access::acquireCounting() {
105 return osl_atomic_increment(&m_refCount
);
108 void Access::releaseNondeleting() {
109 osl_atomic_decrement(&m_refCount
);
112 bool Access::isValue() {
113 rtl::Reference
< Node
> p(getNode());
115 case Node::KIND_PROPERTY
:
116 case Node::KIND_LOCALIZED_VALUE
:
118 case Node::KIND_LOCALIZED_PROPERTY
:
119 return !Components::allLocales(getRootAccess()->getLocale());
125 void Access::markChildAsModified(rtl::Reference
< ChildAccess
> const & child
) {
126 assert(child
.is() && child
->getParentAccess() == this);
127 modifiedChildren_
[child
->getNameInternal()] = ModifiedChild(child
, true);
128 for (rtl::Reference
< Access
> p(this);;) {
129 rtl::Reference
< Access
> parent(p
->getParentAccess());
133 assert(dynamic_cast< ChildAccess
* >(p
.get()) != 0);
134 parent
->modifiedChildren_
.insert(
135 ModifiedChildren::value_type(
136 p
->getNameInternal(),
137 ModifiedChild(dynamic_cast< ChildAccess
* >(p
.get()), false)));
142 void Access::releaseChild(rtl::OUString
const & name
) {
143 cachedChildren_
.erase(name
);
146 void Access::initBroadcaster(
147 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
)
149 initBroadcasterAndChanges(modifications
, broadcaster
, 0);
152 css::uno::Sequence
< css::uno::Type
> Access::getTypes()
153 throw (css::uno::RuntimeException
)
155 assert(thisIs(IS_ANY
));
156 osl::MutexGuard
g(*lock_
);
157 checkLocalizedPropertyAccess();
158 comphelper::SequenceAsVector
< css::uno::Type
> types
;
159 types
.push_back(cppu::UnoType
< css::uno::XInterface
>::get());
160 types
.push_back(cppu::UnoType
< css::uno::XWeak
>::get());
161 types
.push_back(cppu::UnoType
< css::lang::XTypeProvider
>::get());
162 types
.push_back(cppu::UnoType
< css::lang::XServiceInfo
>::get());
163 types
.push_back(cppu::UnoType
< css::lang::XComponent
>::get());
164 types
.push_back(cppu::UnoType
< css::container::XContainer
>::get());
165 types
.push_back(cppu::UnoType
< css::beans::XExactName
>::get());
166 types
.push_back(cppu::UnoType
< css::container::XHierarchicalName
>::get());
167 types
.push_back(cppu::UnoType
< css::container::XNamed
>::get());
168 types
.push_back(cppu::UnoType
< css::beans::XProperty
>::get());
169 types
.push_back(cppu::UnoType
< css::container::XElementAccess
>::get());
170 types
.push_back(cppu::UnoType
< css::container::XNameAccess
>::get());
171 if (getNode()->kind() == Node::KIND_GROUP
) {
172 types
.push_back(cppu::UnoType
< css::beans::XPropertySetInfo
>::get());
173 types
.push_back(cppu::UnoType
< css::beans::XPropertySet
>::get());
174 types
.push_back(cppu::UnoType
< css::beans::XMultiPropertySet
>::get());
176 cppu::UnoType
< css::beans::XHierarchicalPropertySet
>::get());
178 cppu::UnoType
< css::beans::XMultiHierarchicalPropertySet
>::get());
180 cppu::UnoType
< css::beans::XHierarchicalPropertySetInfo
>::get());
182 if (getRootAccess()->isUpdate()) {
183 types
.push_back(cppu::UnoType
< css::container::XNameReplace
>::get());
185 cppu::UnoType
< css::container::XHierarchicalNameReplace
>::get());
186 if (getNode()->kind() != Node::KIND_GROUP
||
187 dynamic_cast< GroupNode
* >(getNode().get())->isExtensible())
190 cppu::UnoType
< css::container::XNameContainer
>::get());
192 if (getNode()->kind() == Node::KIND_SET
) {
194 cppu::UnoType
< css::lang::XSingleServiceFactory
>::get());
198 cppu::UnoType
< css::container::XHierarchicalNameAccess
>::get());
201 return types
.getAsConstList();
204 css::uno::Sequence
< sal_Int8
> Access::getImplementationId()
205 throw (css::uno::RuntimeException
)
207 assert(thisIs(IS_ANY
));
208 osl::MutexGuard
g(*lock_
);
209 checkLocalizedPropertyAccess();
210 return css::uno::Sequence
< sal_Int8
>();
213 rtl::OUString
Access::getImplementationName() throw (css::uno::RuntimeException
)
215 assert(thisIs(IS_ANY
));
216 osl::MutexGuard
g(*lock_
);
217 checkLocalizedPropertyAccess();
218 return rtl::OUString(
219 RTL_CONSTASCII_USTRINGPARAM("org.openoffice-configmgr::Access"));
222 sal_Bool
Access::supportsService(rtl::OUString
const & ServiceName
)
223 throw (css::uno::RuntimeException
)
225 assert(thisIs(IS_ANY
));
226 osl::MutexGuard
g(*lock_
);
227 checkLocalizedPropertyAccess();
228 css::uno::Sequence
< rtl::OUString
> names(getSupportedServiceNames());
229 for (sal_Int32 i
= 0; i
< names
.getLength(); ++i
) {
230 if (names
[i
] == ServiceName
) {
237 css::uno::Sequence
< rtl::OUString
> Access::getSupportedServiceNames()
238 throw (css::uno::RuntimeException
)
240 assert(thisIs(IS_ANY
));
241 osl::MutexGuard
g(*lock_
);
242 checkLocalizedPropertyAccess();
243 comphelper::SequenceAsVector
< rtl::OUString
> services
;
246 RTL_CONSTASCII_USTRINGPARAM(
247 "com.sun.star.configuration.ConfigurationAccess")));
248 if (getRootAccess()->isUpdate()) {
251 RTL_CONSTASCII_USTRINGPARAM(
252 "com.sun.star.configuration.ConfigurationUpdateAccess")));
256 RTL_CONSTASCII_USTRINGPARAM(
257 "com.sun.star.configuration.HierarchyAccess")));
260 RTL_CONSTASCII_USTRINGPARAM(
261 "com.sun.star.configuration.HierarchyElement")));
262 if (getNode()->kind() == Node::KIND_GROUP
) {
265 RTL_CONSTASCII_USTRINGPARAM(
266 "com.sun.star.configuration.GroupAccess")));
269 RTL_CONSTASCII_USTRINGPARAM(
270 "com.sun.star.configuration.PropertyHierarchy")));
271 if (getRootAccess()->isUpdate()) {
274 RTL_CONSTASCII_USTRINGPARAM(
275 "com.sun.star.configuration.GroupUpdate")));
280 RTL_CONSTASCII_USTRINGPARAM(
281 "com.sun.star.configuration.SetAccess")));
284 RTL_CONSTASCII_USTRINGPARAM(
285 "com.sun.star.configuration.SimpleSetAccess")));
286 if (getRootAccess()->isUpdate()) {
289 RTL_CONSTASCII_USTRINGPARAM(
290 "com.sun.star.configuration.SetUpdate")));
293 RTL_CONSTASCII_USTRINGPARAM(
294 "com.sun.star.configuration.SimpleSetUpdate")));
297 addSupportedServiceNames(&services
);
298 return services
.getAsConstList();
301 void Access::dispose() throw (css::uno::RuntimeException
) {
302 assert(thisIs(IS_ANY
));
305 osl::MutexGuard
g(*lock_
);
306 checkLocalizedPropertyAccess();
307 if (getParentAccess().is()) {
308 throw css::uno::RuntimeException(
310 RTL_CONSTASCII_USTRINGPARAM(
311 "configmgr dispose inappropriate Access")),
312 static_cast< cppu::OWeakObject
* >(this));
317 initDisposeBroadcaster(&bc
);
324 void Access::addEventListener(
325 css::uno::Reference
< css::lang::XEventListener
> const & xListener
)
326 throw (css::uno::RuntimeException
)
328 assert(thisIs(IS_ANY
));
330 osl::MutexGuard
g(*lock_
);
331 checkLocalizedPropertyAccess();
332 if (!xListener
.is()) {
333 throw css::uno::RuntimeException(
334 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
335 static_cast< cppu::OWeakObject
* >(this));
338 disposeListeners_
.insert(xListener
);
343 xListener
->disposing(
344 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
345 } catch (css::lang::DisposedException
&) {}
348 void Access::removeEventListener(
349 css::uno::Reference
< css::lang::XEventListener
> const & aListener
)
350 throw (css::uno::RuntimeException
)
352 assert(thisIs(IS_ANY
));
353 osl::MutexGuard
g(*lock_
);
354 checkLocalizedPropertyAccess();
355 DisposeListeners::iterator
i(disposeListeners_
.find(aListener
));
356 if (i
!= disposeListeners_
.end()) {
357 disposeListeners_
.erase(i
);
361 css::uno::Type
Access::getElementType() throw (css::uno::RuntimeException
) {
362 assert(thisIs(IS_ANY
));
363 osl::MutexGuard
g(*lock_
);
364 checkLocalizedPropertyAccess();
365 rtl::Reference
< Node
> p(getNode());
367 case Node::KIND_LOCALIZED_PROPERTY
:
369 dynamic_cast< LocalizedPropertyNode
* >(p
.get())->getStaticType());
370 case Node::KIND_GROUP
:
371 //TODO: Should a specific type be returned for a non-extensible group
372 // with homogeneous members or for an extensible group that currently
373 // has only homegeneous members?
374 return cppu::UnoType
< cppu::UnoVoidType
>::get();
376 return cppu::UnoType
< cppu::UnoVoidType
>::get(); //TODO: correct?
379 throw css::uno::RuntimeException(
380 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
381 static_cast< cppu::OWeakObject
* >(this));
385 sal_Bool
Access::hasElements() throw (css::uno::RuntimeException
) {
386 assert(thisIs(IS_ANY
));
387 osl::MutexGuard
g(*lock_
);
388 checkLocalizedPropertyAccess();
389 return !getAllChildren().empty(); //TODO: optimize
392 css::uno::Any
Access::getByName(rtl::OUString
const & aName
)
394 css::container::NoSuchElementException
,
395 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
397 assert(thisIs(IS_ANY
));
398 osl::MutexGuard
g(*lock_
);
399 checkLocalizedPropertyAccess();
400 rtl::Reference
< ChildAccess
> child(getChild(aName
));
402 throw css::container::NoSuchElementException(
403 aName
, static_cast< cppu::OWeakObject
* >(this));
405 return child
->asValue();
408 css::uno::Sequence
< rtl::OUString
> Access::getElementNames()
409 throw (css::uno::RuntimeException
)
411 assert(thisIs(IS_ANY
));
412 osl::MutexGuard
g(*lock_
);
413 checkLocalizedPropertyAccess();
414 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
415 comphelper::SequenceAsVector
< rtl::OUString
> names
;
416 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
418 i
!= children
.end(); ++i
)
420 names
.push_back((*i
)->getNameInternal());
422 return names
.getAsConstList();
425 sal_Bool
Access::hasByName(rtl::OUString
const & aName
)
426 throw (css::uno::RuntimeException
)
428 assert(thisIs(IS_ANY
));
429 osl::MutexGuard
g(*lock_
);
430 checkLocalizedPropertyAccess();
431 return getChild(aName
).is();
434 css::uno::Any
Access::getByHierarchicalName(rtl::OUString
const & aName
)
435 throw (css::container::NoSuchElementException
, css::uno::RuntimeException
)
437 assert(thisIs(IS_ANY
));
438 osl::MutexGuard
g(*lock_
);
439 checkLocalizedPropertyAccess();
440 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
442 throw css::container::NoSuchElementException(
443 aName
, static_cast< cppu::OWeakObject
* >(this));
445 return child
->asValue();
448 sal_Bool
Access::hasByHierarchicalName(rtl::OUString
const & aName
)
449 throw (css::uno::RuntimeException
)
451 assert(thisIs(IS_ANY
));
452 osl::MutexGuard
g(*lock_
);
453 checkLocalizedPropertyAccess();
454 return getSubChild(aName
).is();
457 void Access::replaceByHierarchicalName(
458 rtl::OUString
const & aName
, css::uno::Any
const & aElement
)
460 css::lang::IllegalArgumentException
,
461 css::container::NoSuchElementException
,
462 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
464 //TODO: Actually support sets and combine with replaceByName:
465 assert(thisIs(IS_UPDATE
));
468 osl::MutexGuard
g(*lock_
);
469 checkLocalizedPropertyAccess();
470 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
472 throw css::container::NoSuchElementException(
473 aName
, static_cast< cppu::OWeakObject
* >(this));
475 child
->checkFinalized();
476 rtl::Reference
< Node
> parent(child
->getParentNode());
478 Modifications localMods
;
479 switch (parent
->kind()) {
480 case Node::KIND_LOCALIZED_PROPERTY
:
481 case Node::KIND_GROUP
:
482 child
->setProperty(aElement
, &localMods
);
485 throw css::lang::IllegalArgumentException(
487 RTL_CONSTASCII_USTRINGPARAM(
488 "configmgr::Access::replaceByHierarchicalName does not"
489 " currently support set members")),
490 static_cast< cppu::OWeakObject
* >(this), 0);
491 case Node::KIND_ROOT
:
492 throw css::lang::IllegalArgumentException(
494 RTL_CONSTASCII_USTRINGPARAM(
495 "configmgr::Access::replaceByHierarchicalName does not"
496 " allow changing component "))
498 static_cast< cppu::OWeakObject
* >(this), 0);
500 assert(false); // this cannot happen
503 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
508 void Access::addContainerListener(
509 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
510 throw (css::uno::RuntimeException
)
512 assert(thisIs(IS_ANY
));
514 osl::MutexGuard
g(*lock_
);
515 checkLocalizedPropertyAccess();
516 if (!xListener
.is()) {
517 throw css::uno::RuntimeException(
518 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
519 static_cast< cppu::OWeakObject
* >(this));
522 containerListeners_
.insert(xListener
);
527 xListener
->disposing(
528 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
529 } catch (css::lang::DisposedException
&) {}
532 void Access::removeContainerListener(
533 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
534 throw (css::uno::RuntimeException
)
536 assert(thisIs(IS_ANY
));
537 osl::MutexGuard
g(*lock_
);
538 checkLocalizedPropertyAccess();
539 ContainerListeners::iterator
i(containerListeners_
.find(xListener
));
540 if (i
!= containerListeners_
.end()) {
541 containerListeners_
.erase(i
);
545 rtl::OUString
Access::getExactName(rtl::OUString
const & aApproximateName
)
546 throw (css::uno::RuntimeException
)
548 assert(thisIs(IS_ANY
));
549 osl::MutexGuard
g(*lock_
);
550 checkLocalizedPropertyAccess();
551 return aApproximateName
;
554 css::uno::Sequence
< css::beans::Property
> Access::getProperties()
555 throw (css::uno::RuntimeException
)
557 assert(thisIs(IS_GROUP
));
558 osl::MutexGuard
g(*lock_
);
559 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
560 comphelper::SequenceAsVector
< css::beans::Property
> properties
;
561 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
563 i
!= children
.end(); ++i
)
565 properties
.push_back((*i
)->asProperty());
567 return properties
.getAsConstList();
570 css::beans::Property
Access::getPropertyByName(rtl::OUString
const & aName
)
571 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
)
573 assert(thisIs(IS_GROUP
));
574 osl::MutexGuard
g(*lock_
);
575 rtl::Reference
< ChildAccess
> child(getChild(aName
));
577 throw css::beans::UnknownPropertyException(
578 aName
, static_cast< cppu::OWeakObject
* >(this));
580 return child
->asProperty();
583 sal_Bool
Access::hasPropertyByName(rtl::OUString
const & Name
)
584 throw (css::uno::RuntimeException
)
586 assert(thisIs(IS_GROUP
));
587 osl::MutexGuard
g(*lock_
);
588 return getChild(Name
).is();
591 rtl::OUString
Access::getHierarchicalName() throw (css::uno::RuntimeException
) {
592 assert(thisIs(IS_ANY
));
593 osl::MutexGuard
g(*lock_
);
594 checkLocalizedPropertyAccess();
595 // For backwards compatibility, return an absolute path representation where
597 rtl::OUStringBuffer path
;
598 rtl::Reference
< RootAccess
> root(getRootAccess());
600 path
.append(root
->getAbsolutePathRepresentation());
602 rtl::OUString
rel(getRelativePathRepresentation());
603 if (path
.getLength() != 0 && !rel
.isEmpty()) {
604 path
.append(sal_Unicode('/'));
607 return path
.makeStringAndClear();
610 rtl::OUString
Access::composeHierarchicalName(
611 rtl::OUString
const & aRelativeName
)
613 css::lang::IllegalArgumentException
, css::lang::NoSupportException
,
614 css::uno::RuntimeException
)
616 assert(thisIs(IS_ANY
));
617 osl::MutexGuard
g(*lock_
);
618 checkLocalizedPropertyAccess();
619 if (aRelativeName
.isEmpty() || aRelativeName
[0] == '/') {
620 throw css::lang::IllegalArgumentException(
622 RTL_CONSTASCII_USTRINGPARAM(
623 "configmgr composeHierarchicalName inappropriate relative"
625 static_cast< cppu::OWeakObject
* >(this), -1);
627 rtl::OUStringBuffer
path(getRelativePathRepresentation());
628 if (path
.getLength() != 0) {
629 path
.append(sal_Unicode('/'));
631 path
.append(aRelativeName
);
632 return path
.makeStringAndClear();
635 rtl::OUString
Access::getName() throw (css::uno::RuntimeException
) {
636 assert(thisIs(IS_ANY
));
637 osl::MutexGuard
g(*lock_
);
638 checkLocalizedPropertyAccess();
639 return getNameInternal();
642 void Access::setName(rtl::OUString
const & aName
)
643 throw (css::uno::RuntimeException
)
645 assert(thisIs(IS_ANY
));
648 osl::MutexGuard
g(*lock_
);
649 checkLocalizedPropertyAccess();
651 Modifications localMods
;
652 switch (getNode()->kind()) {
653 case Node::KIND_GROUP
:
656 rtl::Reference
< Access
> parent(getParentAccess());
658 rtl::Reference
< Node
> node(getNode());
659 if (! node
->getTemplateName().isEmpty()) {
660 rtl::Reference
< ChildAccess
> other(
661 parent
->getChild(aName
));
662 if (other
.get() == this) {
665 if (node
->getMandatory() == Data::NO_LAYER
&&
666 !(other
.is() && other
->isFinalized()))
668 rtl::Reference
< RootAccess
> root(getRootAccess());
669 rtl::Reference
< ChildAccess
> childAccess(
670 dynamic_cast< ChildAccess
* >(this));
671 localMods
.add(getRelativePath());
672 // unbind() modifies the parent chain that
673 // markChildAsModified() walks, so order is
675 parent
->markChildAsModified(childAccess
);
676 //TODO: must not throw
677 childAccess
->unbind(); // must not throw
679 other
->unbind(); // must not throw
681 childAccess
->bind(root
, parent
, aName
);
683 parent
->markChildAsModified(childAccess
);
684 //TODO: must not throw
685 localMods
.add(getRelativePath());
692 case Node::KIND_LOCALIZED_PROPERTY
:
693 // renaming a property could only work for an extension property,
694 // but a localized property is never an extension property
695 throw css::uno::RuntimeException(
697 RTL_CONSTASCII_USTRINGPARAM(
698 "configmgr setName inappropriate node")),
699 static_cast< cppu::OWeakObject
* >(this));
701 assert(false); // this cannot happen
704 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
709 css::beans::Property
Access::getAsProperty() throw (css::uno::RuntimeException
)
711 assert(thisIs(IS_ANY
));
712 osl::MutexGuard
g(*lock_
);
713 checkLocalizedPropertyAccess();
717 css::uno::Reference
< css::beans::XPropertySetInfo
> Access::getPropertySetInfo()
718 throw (css::uno::RuntimeException
)
720 assert(thisIs(IS_GROUP
));
724 void Access::setPropertyValue(
725 rtl::OUString
const & aPropertyName
, css::uno::Any
const & aValue
)
727 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
728 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
729 css::uno::RuntimeException
)
731 assert(thisIs(IS_GROUP
));
734 osl::MutexGuard
g(*lock_
);
735 if (!getRootAccess()->isUpdate()) {
736 throw css::uno::RuntimeException(
738 RTL_CONSTASCII_USTRINGPARAM(
739 "configmgr setPropertyValue on non-update access")),
740 static_cast< cppu::OWeakObject
* >(this));
742 Modifications localMods
;
743 if (!setChildProperty(aPropertyName
, aValue
, &localMods
)) {
744 throw css::beans::UnknownPropertyException(
745 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
747 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
752 css::uno::Any
Access::getPropertyValue(rtl::OUString
const & PropertyName
)
754 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
755 css::uno::RuntimeException
)
757 assert(thisIs(IS_GROUP
));
758 osl::MutexGuard
g(*lock_
);
759 rtl::Reference
< ChildAccess
> child(getChild(PropertyName
));
761 throw css::beans::UnknownPropertyException(
762 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
764 return child
->asValue();
767 void Access::addPropertyChangeListener(
768 rtl::OUString
const & aPropertyName
,
769 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
772 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
773 css::uno::RuntimeException
)
775 assert(thisIs(IS_GROUP
));
777 osl::MutexGuard
g(*lock_
);
778 if (!xListener
.is()) {
779 throw css::uno::RuntimeException(
780 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
781 static_cast< cppu::OWeakObject
* >(this));
783 checkKnownProperty(aPropertyName
);
785 propertyChangeListeners_
[aPropertyName
].insert(xListener
);
790 xListener
->disposing(
791 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
792 } catch (css::lang::DisposedException
&) {}
795 void Access::removePropertyChangeListener(
796 rtl::OUString
const & aPropertyName
,
797 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
800 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
801 css::uno::RuntimeException
)
803 assert(thisIs(IS_GROUP
));
804 osl::MutexGuard
g(*lock_
);
805 checkKnownProperty(aPropertyName
);
806 PropertyChangeListeners::iterator
i(
807 propertyChangeListeners_
.find(aPropertyName
));
808 if (i
!= propertyChangeListeners_
.end()) {
809 PropertyChangeListenersElement::iterator
j(i
->second
.find(aListener
));
810 if (j
!= i
->second
.end()) {
812 if (i
->second
.empty()) {
813 propertyChangeListeners_
.erase(i
);
819 void Access::addVetoableChangeListener(
820 rtl::OUString
const & PropertyName
,
821 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
824 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
825 css::uno::RuntimeException
)
827 assert(thisIs(IS_GROUP
));
829 osl::MutexGuard
g(*lock_
);
830 if (!aListener
.is()) {
831 throw css::uno::RuntimeException(
832 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
833 static_cast< cppu::OWeakObject
* >(this));
835 checkKnownProperty(PropertyName
);
837 vetoableChangeListeners_
[PropertyName
].insert(aListener
);
838 //TODO: actually call vetoableChangeListeners_
843 aListener
->disposing(
844 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
845 } catch (css::lang::DisposedException
&) {}
848 void Access::removeVetoableChangeListener(
849 rtl::OUString
const & PropertyName
,
850 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
853 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
854 css::uno::RuntimeException
)
856 assert(thisIs(IS_GROUP
));
857 osl::MutexGuard
g(*lock_
);
858 checkKnownProperty(PropertyName
);
859 VetoableChangeListeners::iterator
i(
860 vetoableChangeListeners_
.find(PropertyName
));
861 if (i
!= vetoableChangeListeners_
.end()) {
862 VetoableChangeListenersElement::iterator
j(i
->second
.find(aListener
));
863 if (j
!= i
->second
.end()) {
865 if (i
->second
.empty()) {
866 vetoableChangeListeners_
.erase(i
);
872 void Access::setPropertyValues(
873 css::uno::Sequence
< rtl::OUString
> const & aPropertyNames
,
874 css::uno::Sequence
< css::uno::Any
> const & aValues
)
876 css::beans::PropertyVetoException
, css::lang::IllegalArgumentException
,
877 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
879 assert(thisIs(IS_GROUP
));
882 osl::MutexGuard
g(*lock_
);
883 if (!getRootAccess()->isUpdate()) {
884 throw css::uno::RuntimeException(
886 RTL_CONSTASCII_USTRINGPARAM(
887 "configmgr setPropertyValues on non-update access")),
888 static_cast< cppu::OWeakObject
* >(this));
890 if (aPropertyNames
.getLength() != aValues
.getLength()) {
891 throw css::lang::IllegalArgumentException(
893 RTL_CONSTASCII_USTRINGPARAM(
894 "configmgr setPropertyValues: aPropertyNames/aValues of"
895 " different length")),
896 static_cast< cppu::OWeakObject
* >(this), -1);
898 Modifications localMods
;
899 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
) {
900 if (!setChildProperty(aPropertyNames
[i
], aValues
[i
], &localMods
)) {
901 throw css::lang::IllegalArgumentException(
903 RTL_CONSTASCII_USTRINGPARAM(
904 "configmgr setPropertyValues inappropriate property"
906 static_cast< cppu::OWeakObject
* >(this), -1);
909 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
914 css::uno::Sequence
< css::uno::Any
> Access::getPropertyValues(
915 css::uno::Sequence
< rtl::OUString
> const & aPropertyNames
)
916 throw (css::uno::RuntimeException
)
918 assert(thisIs(IS_GROUP
));
919 osl::MutexGuard
g(*lock_
);
920 css::uno::Sequence
< css::uno::Any
> vals(aPropertyNames
.getLength());
921 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
) {
922 rtl::Reference
< ChildAccess
> child(getChild(aPropertyNames
[i
]));
924 throw css::uno::RuntimeException(
926 RTL_CONSTASCII_USTRINGPARAM(
927 "configmgr getPropertyValues inappropriate property"
929 static_cast< cppu::OWeakObject
* >(this));
931 vals
[i
] = child
->asValue();
936 void Access::addPropertiesChangeListener(
937 css::uno::Sequence
< rtl::OUString
> const &,
938 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
940 throw (css::uno::RuntimeException
)
942 assert(thisIs(IS_GROUP
));
944 osl::MutexGuard
g(*lock_
);
945 if (!xListener
.is()) {
946 throw css::uno::RuntimeException(
947 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
948 static_cast< cppu::OWeakObject
* >(this));
951 propertiesChangeListeners_
.insert(xListener
);
956 xListener
->disposing(
957 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
958 } catch (css::lang::DisposedException
&) {}
961 void Access::removePropertiesChangeListener(
962 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
964 throw (css::uno::RuntimeException
)
966 assert(thisIs(IS_GROUP
));
967 osl::MutexGuard
g(*lock_
);
968 PropertiesChangeListeners::iterator
i(
969 propertiesChangeListeners_
.find(xListener
));
970 if (i
!= propertiesChangeListeners_
.end()) {
971 propertiesChangeListeners_
.erase(i
);
975 void Access::firePropertiesChangeEvent(
976 css::uno::Sequence
< rtl::OUString
> const & aPropertyNames
,
977 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
979 throw (css::uno::RuntimeException
)
981 assert(thisIs(IS_GROUP
));
982 css::uno::Sequence
< css::beans::PropertyChangeEvent
> events(
983 aPropertyNames
.getLength());
984 for (sal_Int32 i
= 0; i
< events
.getLength(); ++i
) {
985 events
[i
].Source
= static_cast< cppu::OWeakObject
* >(this);
986 events
[i
].PropertyName
= aPropertyNames
[i
];
987 events
[i
].Further
= false;
988 events
[i
].PropertyHandle
= -1;
990 xListener
->propertiesChange(events
);
993 css::uno::Reference
< css::beans::XHierarchicalPropertySetInfo
>
994 Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException
) {
995 assert(thisIs(IS_GROUP
));
999 void Access::setHierarchicalPropertyValue(
1000 rtl::OUString
const & aHierarchicalPropertyName
,
1001 css::uno::Any
const & aValue
)
1003 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
1004 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1005 css::uno::RuntimeException
)
1007 assert(thisIs(IS_GROUP
));
1010 osl::MutexGuard
g(*lock_
);
1011 if (!getRootAccess()->isUpdate()) {
1012 throw css::uno::RuntimeException(
1014 RTL_CONSTASCII_USTRINGPARAM(
1015 "configmgr setHierarchicalPropertyName on non-update"
1017 static_cast< cppu::OWeakObject
* >(this));
1019 rtl::Reference
< ChildAccess
> child(
1020 getSubChild(aHierarchicalPropertyName
));
1022 throw css::beans::UnknownPropertyException(
1023 aHierarchicalPropertyName
,
1024 static_cast< cppu::OWeakObject
* >(this));
1026 child
->checkFinalized();
1027 Modifications localMods
;
1028 child
->setProperty(aValue
, &localMods
);
1029 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1034 css::uno::Any
Access::getHierarchicalPropertyValue(
1035 rtl::OUString
const & aHierarchicalPropertyName
)
1037 css::beans::UnknownPropertyException
,
1038 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1039 css::uno::RuntimeException
)
1041 assert(thisIs(IS_GROUP
));
1042 osl::MutexGuard
g(*lock_
);
1043 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalPropertyName
));
1045 throw css::beans::UnknownPropertyException(
1046 aHierarchicalPropertyName
,
1047 static_cast< cppu::OWeakObject
* >(this));
1049 return child
->asValue();
1052 void Access::setHierarchicalPropertyValues(
1053 css::uno::Sequence
< rtl::OUString
> const & aHierarchicalPropertyNames
,
1054 css::uno::Sequence
< css::uno::Any
> const & Values
)
1056 css::beans::PropertyVetoException
, css::lang::IllegalArgumentException
,
1057 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
1059 assert(thisIs(IS_GROUP
));
1062 osl::MutexGuard
g(*lock_
);
1063 if (!getRootAccess()->isUpdate()) {
1064 throw css::uno::RuntimeException(
1066 RTL_CONSTASCII_USTRINGPARAM(
1067 "configmgr setPropertyValues on non-update access")),
1068 static_cast< cppu::OWeakObject
* >(this));
1070 if (aHierarchicalPropertyNames
.getLength() != Values
.getLength()) {
1071 throw css::lang::IllegalArgumentException(
1073 RTL_CONSTASCII_USTRINGPARAM(
1074 "configmgr setHierarchicalPropertyValues:"
1075 " aHierarchicalPropertyNames/Values of different"
1077 static_cast< cppu::OWeakObject
* >(this), -1);
1079 Modifications localMods
;
1080 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1081 rtl::Reference
< ChildAccess
> child(
1082 getSubChild(aHierarchicalPropertyNames
[i
]));
1084 throw css::lang::IllegalArgumentException(
1086 RTL_CONSTASCII_USTRINGPARAM(
1087 "configmgr setHierarchicalPropertyValues"
1088 " inappropriate property name")),
1089 static_cast< cppu::OWeakObject
* >(this), -1);
1091 child
->checkFinalized();
1092 child
->setProperty(Values
[i
], &localMods
);
1094 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1099 css::uno::Sequence
< css::uno::Any
> Access::getHierarchicalPropertyValues(
1100 css::uno::Sequence
< rtl::OUString
> const & aHierarchicalPropertyNames
)
1102 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1103 css::uno::RuntimeException
)
1105 assert(thisIs(IS_GROUP
));
1106 osl::MutexGuard
g(*lock_
);
1107 css::uno::Sequence
< css::uno::Any
> vals(
1108 aHierarchicalPropertyNames
.getLength());
1109 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1110 rtl::Reference
< ChildAccess
> child(
1111 getSubChild(aHierarchicalPropertyNames
[i
]));
1113 throw css::lang::IllegalArgumentException(
1115 RTL_CONSTASCII_USTRINGPARAM(
1116 "configmgr getHierarchicalPropertyValues inappropriate"
1117 " hierarchical property name")),
1118 static_cast< cppu::OWeakObject
* >(this), -1);
1120 vals
[i
] = child
->asValue();
1125 css::beans::Property
Access::getPropertyByHierarchicalName(
1126 rtl::OUString
const & aHierarchicalName
)
1127 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
)
1129 assert(thisIs(IS_GROUP
));
1130 osl::MutexGuard
g(*lock_
);
1131 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalName
));
1133 throw css::beans::UnknownPropertyException(
1134 aHierarchicalName
, static_cast< cppu::OWeakObject
* >(this));
1136 return child
->asProperty();
1139 sal_Bool
Access::hasPropertyByHierarchicalName(
1140 rtl::OUString
const & aHierarchicalName
)
1141 throw (css::uno::RuntimeException
)
1143 assert(thisIs(IS_GROUP
));
1144 osl::MutexGuard
g(*lock_
);
1145 return getSubChild(aHierarchicalName
).is();
1148 void Access::replaceByName(
1149 rtl::OUString
const & aName
, css::uno::Any
const & aElement
)
1151 css::lang::IllegalArgumentException
,
1152 css::container::NoSuchElementException
,
1153 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
1155 assert(thisIs(IS_UPDATE
));
1158 osl::MutexGuard
g(*lock_
);
1159 checkLocalizedPropertyAccess();
1160 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1162 throw css::container::NoSuchElementException(
1163 aName
, static_cast< cppu::OWeakObject
* >(this));
1165 child
->checkFinalized();
1166 Modifications localMods
;
1167 switch (getNode()->kind()) {
1168 case Node::KIND_LOCALIZED_PROPERTY
:
1169 case Node::KIND_GROUP
:
1170 child
->setProperty(aElement
, &localMods
);
1172 case Node::KIND_SET
:
1174 rtl::Reference
< ChildAccess
> freeAcc(
1175 getFreeSetMember(aElement
));
1176 rtl::Reference
< RootAccess
> root(getRootAccess());
1177 localMods
.add(child
->getRelativePath());
1178 child
->unbind(); // must not throw
1179 freeAcc
->bind(root
, this, aName
); // must not throw
1180 markChildAsModified(freeAcc
); //TODO: must not throw
1184 assert(false); // this cannot happen
1187 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1192 void Access::insertByName(
1193 rtl::OUString
const & aName
, css::uno::Any
const & aElement
)
1195 css::lang::IllegalArgumentException
,
1196 css::container::ElementExistException
,
1197 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
1199 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1202 osl::MutexGuard
g(*lock_
);
1203 checkLocalizedPropertyAccess();
1205 if (getChild(aName
).is()) {
1206 throw css::container::ElementExistException(
1207 aName
, static_cast< cppu::OWeakObject
* >(this));
1209 Modifications localMods
;
1210 switch (getNode()->kind()) {
1211 case Node::KIND_LOCALIZED_PROPERTY
:
1212 insertLocalizedValueChild(aName
, aElement
, &localMods
);
1214 case Node::KIND_GROUP
:
1216 checkValue(aElement
, TYPE_ANY
, true);
1217 rtl::Reference
< ChildAccess
> child(
1219 components_
, getRootAccess(), this, aName
,
1221 Data::NO_LAYER
, TYPE_ANY
, true, aElement
, true)));
1222 markChildAsModified(child
);
1223 localMods
.add(child
->getRelativePath());
1226 case Node::KIND_SET
:
1228 rtl::Reference
< ChildAccess
> freeAcc(
1229 getFreeSetMember(aElement
));
1230 freeAcc
->bind(getRootAccess(), this, aName
); // must not throw
1231 markChildAsModified(freeAcc
); //TODO: must not throw
1232 localMods
.add(freeAcc
->getRelativePath());
1236 assert(false); // this cannot happen
1239 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1244 void Access::removeByName(rtl::OUString
const & aName
)
1246 css::container::NoSuchElementException
,
1247 css::lang::WrappedTargetException
, css::uno::RuntimeException
)
1249 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1252 osl::MutexGuard
g(*lock_
);
1253 checkLocalizedPropertyAccess();
1254 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1255 if (!child
.is() || child
->isFinalized() ||
1256 child
->getNode()->getMandatory() != Data::NO_LAYER
)
1258 throw css::container::NoSuchElementException(
1259 aName
, static_cast< cppu::OWeakObject
* >(this));
1261 if (getNode()->kind() == Node::KIND_GROUP
) {
1262 rtl::Reference
< Node
> p(child
->getNode());
1263 if (p
->kind() != Node::KIND_PROPERTY
||
1264 !dynamic_cast< PropertyNode
* >(p
.get())->isExtension())
1266 throw css::container::NoSuchElementException(
1267 aName
, static_cast< cppu::OWeakObject
* >(this));
1270 Modifications localMods
;
1271 localMods
.add(child
->getRelativePath());
1272 // unbind() modifies the parent chain that markChildAsModified() walks,
1273 // so order is important:
1274 markChildAsModified(child
); //TODO: must not throw
1276 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1281 css::uno::Reference
< css::uno::XInterface
> Access::createInstance()
1282 throw (css::uno::Exception
, css::uno::RuntimeException
)
1284 assert(thisIs(IS_SET
|IS_UPDATE
));
1285 rtl::OUString
tmplName(
1286 dynamic_cast< SetNode
* >(getNode().get())->getDefaultTemplateName());
1287 rtl::Reference
< Node
> tmpl(
1288 components_
.getTemplate(Data::NO_LAYER
, tmplName
));
1290 throw css::uno::Exception(
1291 (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) +
1293 static_cast< cppu::OWeakObject
* >(this));
1295 rtl::Reference
< Node
> node(tmpl
->clone(true));
1296 node
->setLayer(Data::NO_LAYER
);
1297 return static_cast< cppu::OWeakObject
* >(
1298 new ChildAccess(components_
, getRootAccess(), node
));
1301 css::uno::Reference
< css::uno::XInterface
> Access::createInstanceWithArguments(
1302 css::uno::Sequence
< css::uno::Any
> const & aArguments
)
1303 throw (css::uno::Exception
, css::uno::RuntimeException
)
1305 assert(thisIs(IS_SET
|IS_UPDATE
));
1306 if (aArguments
.getLength() != 0) {
1307 throw css::uno::Exception(
1309 RTL_CONSTASCII_USTRINGPARAM(
1310 "configuration SimpleSetUpdate createInstanceWithArguments"
1311 " must not specify any arguments")),
1312 static_cast< cppu::OWeakObject
* >(this));
1314 return createInstance();
1317 Access::Access(Components
& components
):
1318 components_(components
), disposed_(false)
1323 Access::~Access() {}
1325 void Access::initDisposeBroadcaster(Broadcaster
* broadcaster
) {
1326 assert(broadcaster
!= 0);
1327 for (DisposeListeners::iterator
i(disposeListeners_
.begin());
1328 i
!= disposeListeners_
.end(); ++i
)
1330 broadcaster
->addDisposeNotification(
1332 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1334 for (ContainerListeners::iterator
i(containerListeners_
.begin());
1335 i
!= containerListeners_
.end(); ++i
)
1337 broadcaster
->addDisposeNotification(
1339 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1341 for (PropertyChangeListeners::iterator
i(propertyChangeListeners_
.begin());
1342 i
!= propertyChangeListeners_
.end(); ++i
)
1344 for (PropertyChangeListenersElement::iterator
j(i
->second
.begin());
1345 j
!= i
->second
.end(); ++j
)
1347 broadcaster
->addDisposeNotification(
1349 css::lang::EventObject(
1350 static_cast< cppu::OWeakObject
* >(this)));
1353 for (VetoableChangeListeners::iterator
i(vetoableChangeListeners_
.begin());
1354 i
!= vetoableChangeListeners_
.end(); ++i
)
1356 for (VetoableChangeListenersElement::iterator
j(i
->second
.begin());
1357 j
!= i
->second
.end(); ++j
)
1359 broadcaster
->addDisposeNotification(
1361 css::lang::EventObject(
1362 static_cast< cppu::OWeakObject
* >(this)));
1365 for (PropertiesChangeListeners::iterator
i(
1366 propertiesChangeListeners_
.begin());
1367 i
!= propertiesChangeListeners_
.end(); ++i
)
1369 broadcaster
->addDisposeNotification(
1371 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1373 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1374 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1375 i
!= modifiedChildren_
.end(); ++i
)
1377 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1379 child
->initDisposeBroadcaster(broadcaster
);
1384 void Access::clearListeners() throw() {
1385 disposeListeners_
.clear();
1386 containerListeners_
.clear();
1387 propertyChangeListeners_
.clear();
1388 vetoableChangeListeners_
.clear();
1389 propertiesChangeListeners_
.clear();
1390 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1391 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1392 i
!= modifiedChildren_
.end(); ++i
)
1394 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1396 child
->clearListeners();
1401 css::uno::Any
Access::queryInterface(css::uno::Type
const & aType
)
1402 throw (css::uno::RuntimeException
)
1404 css::uno::Any
res(OWeakObject::queryInterface(aType
));
1405 if (res
.hasValue()) {
1408 res
= cppu::queryInterface(
1409 aType
, static_cast< css::lang::XTypeProvider
* >(this),
1410 static_cast< css::lang::XServiceInfo
* >(this),
1411 static_cast< css::lang::XComponent
* >(this),
1412 static_cast< css::container::XHierarchicalNameAccess
* >(this),
1413 static_cast< css::container::XContainer
* >(this),
1414 static_cast< css::beans::XExactName
* >(this),
1415 static_cast< css::container::XHierarchicalName
* >(this),
1416 static_cast< css::container::XNamed
* >(this),
1417 static_cast< css::beans::XProperty
* >(this),
1418 static_cast< css::container::XElementAccess
* >(this),
1419 static_cast< css::container::XNameAccess
* >(this));
1420 if (res
.hasValue()) {
1423 if (getNode()->kind() == Node::KIND_GROUP
) {
1424 res
= cppu::queryInterface(
1425 aType
, static_cast< css::beans::XPropertySetInfo
* >(this),
1426 static_cast< css::beans::XPropertySet
* >(this),
1427 static_cast< css::beans::XMultiPropertySet
* >(this),
1428 static_cast< css::beans::XHierarchicalPropertySet
* >(this),
1429 static_cast< css::beans::XMultiHierarchicalPropertySet
* >(this),
1430 static_cast< css::beans::XHierarchicalPropertySetInfo
* >(this));
1431 if (res
.hasValue()) {
1435 if (getRootAccess()->isUpdate()) {
1436 res
= cppu::queryInterface(
1437 aType
, static_cast< css::container::XNameReplace
* >(this),
1438 static_cast< css::container::XHierarchicalNameReplace
* >(this));
1439 if (res
.hasValue()) {
1442 if (getNode()->kind() != Node::KIND_GROUP
||
1443 dynamic_cast< GroupNode
* >(getNode().get())->isExtensible())
1445 res
= cppu::queryInterface(
1446 aType
, static_cast< css::container::XNameContainer
* >(this));
1447 if (res
.hasValue()) {
1451 if (getNode()->kind() == Node::KIND_SET
) {
1452 res
= cppu::queryInterface(
1453 aType
, static_cast< css::lang::XSingleServiceFactory
* >(this));
1459 Components
& Access::getComponents() const {
1463 void Access::checkLocalizedPropertyAccess() {
1464 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
&&
1465 !Components::allLocales(getRootAccess()->getLocale()))
1467 throw css::uno::RuntimeException(
1469 RTL_CONSTASCII_USTRINGPARAM(
1470 "configmgr Access to specialized LocalizedPropertyNode")),
1471 static_cast< cppu::OWeakObject
* >(this));
1475 rtl::Reference
< Node
> Access::getParentNode() {
1476 rtl::Reference
< Access
> parent(getParentAccess());
1477 return parent
.is() ? parent
->getNode() : rtl::Reference
< Node
>();
1480 rtl::Reference
< ChildAccess
> Access::getChild(rtl::OUString
const & name
) {
1481 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
&& name
.match("*")) {
1482 OUString
locale(name
.copy(1));
1483 if (locale
.match("*")) {
1486 ("access best-matching localized property value via"
1487 " \"*<locale>\" with <locale> \"")
1488 << locale
<< "\" recursively starting with \"*\"");
1489 return getChild(locale
);
1492 locale
.isEmpty(), "configmgr",
1493 ("access best-matching localized property value via \"*<locale>\""
1494 " with empty <locale>; falling back to defaults"));
1495 if (!locale
.isEmpty()) {
1496 // Find best match using an adaption of RFC 4647 lookup matching
1497 // rules, removing "-" or "_" delimited segments from the end:
1499 rtl::Reference
< ChildAccess
> child(getChild(locale
));
1503 sal_Int32 i
= locale
.getLength() - 1;
1504 while (i
> 0 && locale
[i
] != '-' && locale
[i
] != '_') {
1510 locale
= locale
.copy(0, i
);
1512 // As a workaround for broken xcu data that does not use shortest
1513 // xml:lang attributes, look for the first entry with the same first
1514 // segment as the requested language tag before falling back to
1515 // defaults (see fdo#33638):
1517 !locale
.isEmpty() && locale
.indexOf('-') == -1 &&
1518 locale
.indexOf('_') == -1);
1519 std::vector
< rtl::Reference
< ChildAccess
> > children(
1521 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
1523 i
!= children
.end(); ++i
)
1525 OUString
name2((*i
)->getNameInternal());
1526 if (name2
.match(locale
) &&
1527 (name2
.getLength() == locale
.getLength() ||
1528 name2
[locale
.getLength()] == '-' ||
1529 name2
[locale
.getLength()] == '_'))
1535 // Defaults are the "en-US" locale, the "en" locale, the empty string
1536 // locale, the first child (if any), or a null ChildAccess, in that
1538 rtl::Reference
< ChildAccess
> child(getChild("en-US"));
1542 child
= getChild("en");
1546 child
= getChild(OUString());
1550 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
1551 if (!children
.empty()) {
1552 return children
.front();
1554 return rtl::Reference
< ChildAccess
>();
1556 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
1557 return i
== modifiedChildren_
.end()
1558 ? getUnmodifiedChild(name
) : getModifiedChild(i
);
1561 std::vector
< rtl::Reference
< ChildAccess
> > Access::getAllChildren() {
1562 std::vector
< rtl::Reference
< ChildAccess
> > vec
;
1563 NodeMap
const & members
= getNode()->getMembers();
1564 for (NodeMap::const_iterator
i(members
.begin()); i
!= members
.end(); ++i
) {
1565 if (modifiedChildren_
.find(i
->first
) == modifiedChildren_
.end()) {
1566 vec
.push_back(getUnmodifiedChild(i
->first
));
1567 assert(vec
.back().is());
1570 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1571 i
!= modifiedChildren_
.end(); ++i
)
1573 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1575 vec
.push_back(child
);
1581 void Access::checkValue(css::uno::Any
const & value
, Type type
, bool nillable
) {
1586 // fall through (cannot happen)
1591 switch (getDynamicType(value
)) {
1594 // fall through (cannot happen)
1607 ok
= value
.hasValue() ? value
.isExtractableTo(mapType(type
)) : nillable
;
1611 throw css::lang::IllegalArgumentException(
1613 RTL_CONSTASCII_USTRINGPARAM(
1614 "configmgr inappropriate property value")),
1615 static_cast< cppu::OWeakObject
* >(this), -1);
1619 void Access::insertLocalizedValueChild(
1620 rtl::OUString
const & name
, css::uno::Any
const & value
,
1621 Modifications
* localModifications
)
1623 assert(localModifications
!= 0);
1624 LocalizedPropertyNode
* locprop
= dynamic_cast< LocalizedPropertyNode
* >(
1626 checkValue(value
, locprop
->getStaticType(), locprop
->isNillable());
1627 rtl::Reference
< ChildAccess
> child(
1629 components_
, getRootAccess(), this, name
,
1630 new LocalizedValueNode(Data::NO_LAYER
, value
)));
1631 markChildAsModified(child
);
1632 localModifications
->add(child
->getRelativePath());
1635 void Access::reportChildChanges(
1636 std::vector
< css::util::ElementChange
> * changes
)
1638 assert(changes
!= 0);
1639 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1640 i
!= modifiedChildren_
.end(); ++i
)
1642 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1644 child
->reportChildChanges(changes
);
1645 changes
->push_back(css::util::ElementChange());
1646 //TODO: changed value and/or inserted node
1648 changes
->push_back(css::util::ElementChange()); //TODO: removed node
1653 void Access::commitChildChanges(
1654 bool valid
, Modifications
* globalModifications
)
1656 assert(globalModifications
!= 0);
1657 while (!modifiedChildren_
.empty()) {
1658 bool childValid
= valid
;
1659 ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1660 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1662 childValid
= childValid
&& !child
->isFinalized();
1663 child
->commitChanges(childValid
, globalModifications
);
1664 //TODO: currently, this is called here for directly inserted
1665 // children as well as for children whose sub-children were
1666 // modified (and should never be called for directly removed
1667 // children); clarify what exactly should happen here for
1668 // directly inserted children
1670 NodeMap
& members
= getNode()->getMembers();
1671 NodeMap::iterator
j(members
.find(i
->first
));
1674 if (j
!= members
.end()) {
1675 childValid
= childValid
&&
1676 j
->second
->getFinalized() == Data::NO_LAYER
;
1678 child
->getNode()->setMandatory(j
->second
->getMandatory());
1682 members
[i
->first
] = child
->getNode();
1686 childValid
= childValid
&& j
!= members
.end() &&
1687 j
->second
->getFinalized() == Data::NO_LAYER
&&
1688 j
->second
->getMandatory() == Data::NO_LAYER
;
1693 if (childValid
&& i
->second
.directlyModified
) {
1694 Path
path(getAbsolutePath());
1695 path
.push_back(i
->first
);
1696 components_
.addModification(path
);
1697 globalModifications
->add(path
);
1699 i
->second
.child
->committed();
1700 modifiedChildren_
.erase(i
);
1704 void Access::initBroadcasterAndChanges(
1705 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
,
1706 std::vector
< css::util::ElementChange
> * allChanges
)
1708 assert(broadcaster
!= 0);
1709 comphelper::SequenceAsVector
< css::beans::PropertyChangeEvent
> propChanges
;
1710 bool collectPropChanges
= !propertiesChangeListeners_
.empty();
1711 for (Modifications::Node::Children::const_iterator
i(
1712 modifications
.children
.begin());
1713 i
!= modifications
.children
.end(); ++i
)
1715 rtl::Reference
< ChildAccess
> child(getChild(i
->first
));
1717 switch (child
->getNode()->kind()) {
1718 case Node::KIND_LOCALIZED_PROPERTY
:
1719 if (!i
->second
.children
.empty()) {
1720 if (Components::allLocales(getRootAccess()->getLocale())) {
1721 child
->initBroadcasterAndChanges(
1722 i
->second
, broadcaster
, allChanges
);
1723 //TODO: if allChanges==0, recurse only into children
1726 //TODO: filter child mods that are irrelevant for
1728 for (ContainerListeners::iterator
j(
1729 containerListeners_
.begin());
1730 j
!= containerListeners_
.end(); ++j
)
1733 addContainerElementReplacedNotification(
1735 css::container::ContainerEvent(
1736 static_cast< cppu::OWeakObject
* >(
1738 css::uno::makeAny(i
->first
),
1739 css::uno::Any(), css::uno::Any()));
1740 //TODO: non-void Element, ReplacedElement
1742 PropertyChangeListeners::iterator
j(
1743 propertyChangeListeners_
.find(i
->first
));
1744 if (j
!= propertyChangeListeners_
.end()) {
1745 for (PropertyChangeListenersElement::iterator
k(
1747 k
!= j
->second
.end(); ++k
)
1749 broadcaster
->addPropertyChangeNotification(
1751 css::beans::PropertyChangeEvent(
1752 static_cast< cppu::OWeakObject
* >(
1754 i
->first
, false, -1, css::uno::Any(),
1758 j
= propertyChangeListeners_
.find(rtl::OUString());
1759 if (j
!= propertyChangeListeners_
.end()) {
1760 for (PropertyChangeListenersElement::iterator
k(
1762 k
!= j
->second
.end(); ++k
)
1764 broadcaster
->addPropertyChangeNotification(
1766 css::beans::PropertyChangeEvent(
1767 static_cast< cppu::OWeakObject
* >(
1769 i
->first
, false, -1, css::uno::Any(),
1773 if (allChanges
!= 0) {
1774 allChanges
->push_back(
1775 css::util::ElementChange(
1777 child
->getRelativePathRepresentation()),
1778 css::uno::Any(), css::uno::Any()));
1779 //TODO: non-void Element, ReplacedElement
1781 if (collectPropChanges
) {
1782 propChanges
.push_back(
1783 css::beans::PropertyChangeEvent(
1784 static_cast< cppu::OWeakObject
* >(this),
1785 i
->first
, false, -1, css::uno::Any(),
1790 // else: spurious Modifications::Node not representing a change
1792 case Node::KIND_LOCALIZED_VALUE
:
1793 assert(Components::allLocales(getRootAccess()->getLocale()));
1794 for (ContainerListeners::iterator
j(
1795 containerListeners_
.begin());
1796 j
!= containerListeners_
.end(); ++j
)
1798 broadcaster
->addContainerElementReplacedNotification(
1800 css::container::ContainerEvent(
1801 static_cast< cppu::OWeakObject
* >(this),
1802 css::uno::makeAny(i
->first
), child
->asValue(),
1804 //TODO: distinguish add/modify; non-void ReplacedElement
1806 if (allChanges
!= 0) {
1807 allChanges
->push_back(
1808 css::util::ElementChange(
1810 child
->getRelativePathRepresentation()),
1811 child
->asValue(), css::uno::Any()));
1812 //TODO: non-void ReplacedElement
1814 assert(!collectPropChanges
);
1816 case Node::KIND_PROPERTY
:
1818 for (ContainerListeners::iterator
j(
1819 containerListeners_
.begin());
1820 j
!= containerListeners_
.end(); ++j
)
1822 broadcaster
->addContainerElementReplacedNotification(
1824 css::container::ContainerEvent(
1825 static_cast< cppu::OWeakObject
* >(this),
1826 css::uno::makeAny(i
->first
), child
->asValue(),
1828 //TODO: distinguish add/remove/modify; non-void
1831 PropertyChangeListeners::iterator
j(
1832 propertyChangeListeners_
.find(i
->first
));
1833 if (j
!= propertyChangeListeners_
.end()) {
1834 for (PropertyChangeListenersElement::iterator
k(
1836 k
!= j
->second
.end(); ++k
)
1838 broadcaster
->addPropertyChangeNotification(
1840 css::beans::PropertyChangeEvent(
1841 static_cast< cppu::OWeakObject
* >(this),
1842 i
->first
, false, -1, css::uno::Any(),
1846 j
= propertyChangeListeners_
.find(rtl::OUString());
1847 if (j
!= propertyChangeListeners_
.end()) {
1848 for (PropertyChangeListenersElement::iterator
k(
1850 k
!= j
->second
.end(); ++k
)
1852 broadcaster
->addPropertyChangeNotification(
1854 css::beans::PropertyChangeEvent(
1855 static_cast< cppu::OWeakObject
* >(this),
1856 i
->first
, false, -1, css::uno::Any(),
1860 if (allChanges
!= 0) {
1861 allChanges
->push_back(
1862 css::util::ElementChange(
1864 child
->getRelativePathRepresentation()),
1865 child
->asValue(), css::uno::Any()));
1866 //TODO: non-void ReplacedElement
1868 if (collectPropChanges
) {
1869 propChanges
.push_back(
1870 css::beans::PropertyChangeEvent(
1871 static_cast< cppu::OWeakObject
* >(this),
1872 i
->first
, false, -1, css::uno::Any(),
1877 case Node::KIND_GROUP
:
1878 case Node::KIND_SET
:
1879 if (i
->second
.children
.empty()) {
1880 if (!child
->getNode()->getTemplateName().isEmpty()) {
1881 for (ContainerListeners::iterator
j(
1882 containerListeners_
.begin());
1883 j
!= containerListeners_
.end(); ++j
)
1886 addContainerElementInsertedNotification(
1888 css::container::ContainerEvent(
1889 static_cast< cppu::OWeakObject
* >(
1891 css::uno::makeAny(i
->first
),
1892 child
->asValue(), css::uno::Any()));
1894 if (allChanges
!= 0) {
1895 allChanges
->push_back(
1896 css::util::ElementChange(
1898 child
->getRelativePathRepresentation()),
1899 css::uno::Any(), css::uno::Any()));
1900 //TODO: non-void Element, ReplacedElement
1903 // else: spurious Modifications::Node not representing a
1906 child
->initBroadcasterAndChanges(
1907 i
->second
, broadcaster
, allChanges
);
1908 //TODO: if allChanges==0, recurse only into children w/
1912 case Node::KIND_ROOT
:
1913 assert(false); // this cannot happen
1917 switch (getNode()->kind()) {
1918 case Node::KIND_LOCALIZED_PROPERTY
:
1919 // Removed localized property value:
1920 assert(Components::allLocales(getRootAccess()->getLocale()));
1921 for (ContainerListeners::iterator
j(
1922 containerListeners_
.begin());
1923 j
!= containerListeners_
.end(); ++j
)
1925 broadcaster
->addContainerElementRemovedNotification(
1927 css::container::ContainerEvent(
1928 static_cast< cppu::OWeakObject
* >(this),
1929 css::uno::makeAny(i
->first
), css::uno::Any(),
1931 //TODO: non-void ReplacedElement
1933 if (allChanges
!= 0) {
1934 rtl::OUStringBuffer
path(getRelativePathRepresentation());
1935 if (path
.getLength() != 0) {
1936 path
.append(sal_Unicode('/'));
1939 Data::createSegment(
1940 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")),
1942 allChanges
->push_back(
1943 css::util::ElementChange(
1944 css::uno::makeAny(path
.makeStringAndClear()),
1945 css::uno::Any(), css::uno::Any()));
1946 //TODO: non-void ReplacedElement
1948 assert(!collectPropChanges
);
1950 case Node::KIND_GROUP
:
1952 // Removed (non-localized) extension property:
1953 for (ContainerListeners::iterator
j(
1954 containerListeners_
.begin());
1955 j
!= containerListeners_
.end(); ++j
)
1957 broadcaster
->addContainerElementRemovedNotification(
1959 css::container::ContainerEvent(
1960 static_cast< cppu::OWeakObject
* >(this),
1961 css::uno::makeAny(i
->first
), css::uno::Any(),
1963 //TODO: non-void ReplacedElement
1965 PropertyChangeListeners::iterator
j(
1966 propertyChangeListeners_
.find(i
->first
));
1967 if (j
!= propertyChangeListeners_
.end()) {
1968 for (PropertyChangeListenersElement::iterator
k(
1970 k
!= j
->second
.end(); ++k
)
1972 broadcaster
->addPropertyChangeNotification(
1974 css::beans::PropertyChangeEvent(
1975 static_cast< cppu::OWeakObject
* >(this),
1976 i
->first
, false, -1, css::uno::Any(),
1980 j
= propertyChangeListeners_
.find(rtl::OUString());
1981 if (j
!= propertyChangeListeners_
.end()) {
1982 for (PropertyChangeListenersElement::iterator
k(
1984 k
!= j
->second
.end(); ++k
)
1986 broadcaster
->addPropertyChangeNotification(
1988 css::beans::PropertyChangeEvent(
1989 static_cast< cppu::OWeakObject
* >(this),
1990 i
->first
, false, -1, css::uno::Any(),
1994 if (allChanges
!= 0) {
1995 rtl::OUStringBuffer
path(
1996 getRelativePathRepresentation());
1997 if (path
.getLength() != 0) {
1998 path
.append(sal_Unicode('/'));
2000 path
.append(i
->first
);
2001 allChanges
->push_back(
2002 css::util::ElementChange(
2003 css::uno::makeAny(path
.makeStringAndClear()),
2004 css::uno::Any(), css::uno::Any()));
2005 //TODO: non-void ReplacedElement
2007 if (collectPropChanges
) {
2008 propChanges
.push_back(
2009 css::beans::PropertyChangeEvent(
2010 static_cast< cppu::OWeakObject
* >(this),
2011 i
->first
, false, -1, css::uno::Any(),
2016 case Node::KIND_SET
:
2017 // Removed set member:
2018 if (i
->second
.children
.empty()) {
2019 for (ContainerListeners::iterator
j(
2020 containerListeners_
.begin());
2021 j
!= containerListeners_
.end(); ++j
)
2023 broadcaster
->addContainerElementRemovedNotification(
2025 css::container::ContainerEvent(
2026 static_cast< cppu::OWeakObject
* >(this),
2027 css::uno::makeAny(i
->first
),
2028 css::uno::Any(), css::uno::Any()));
2029 //TODO: non-void ReplacedElement
2031 if (allChanges
!= 0) {
2032 rtl::OUStringBuffer
path(
2033 getRelativePathRepresentation());
2034 if (path
.getLength() != 0) {
2035 path
.append(sal_Unicode('/'));
2038 Data::createSegment(
2039 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")),
2041 allChanges
->push_back(
2042 css::util::ElementChange(
2043 css::uno::makeAny(path
.makeStringAndClear()),
2044 css::uno::Any(), css::uno::Any()));
2045 //TODO: non-void ReplacedElement
2048 // else: spurious Modifications::Node not representing a change
2051 assert(false); // this cannot happen
2056 if (!propChanges
.empty()) {
2057 css::uno::Sequence
< css::beans::PropertyChangeEvent
> seq(
2058 propChanges
.getAsConstList());
2059 for (PropertiesChangeListeners::iterator
i(
2060 propertiesChangeListeners_
.begin());
2061 i
!= propertiesChangeListeners_
.end(); ++i
)
2063 broadcaster
->addPropertiesChangeNotification(*i
, seq
);
2068 bool Access::isDisposed() const {
2072 Access::ModifiedChild::ModifiedChild() {}
2074 Access::ModifiedChild::ModifiedChild(
2075 rtl::Reference
< ChildAccess
> const & theChild
, bool theDirectlyModified
):
2076 child(theChild
), directlyModified(theDirectlyModified
)
2079 rtl::Reference
< ChildAccess
> Access::getModifiedChild(
2080 ModifiedChildren::iterator
const & childIterator
)
2082 return (childIterator
->second
.child
->getParentAccess() == this &&
2083 (childIterator
->second
.child
->getNameInternal() ==
2084 childIterator
->first
))
2085 ? childIterator
->second
.child
: rtl::Reference
< ChildAccess
>();
2088 rtl::Reference
< ChildAccess
> Access::getUnmodifiedChild(
2089 rtl::OUString
const & name
)
2091 assert(modifiedChildren_
.find(name
) == modifiedChildren_
.end());
2092 rtl::Reference
< Node
> node(getNode()->getMember(name
));
2094 return rtl::Reference
< ChildAccess
>();
2096 WeakChildMap::iterator
i(cachedChildren_
.find(name
));
2097 if (i
!= cachedChildren_
.end()) {
2098 rtl::Reference
< ChildAccess
> child
;
2099 if (i
->second
->acquireCounting() > 1) {
2100 child
.set(i
->second
); // must not throw
2102 i
->second
->releaseNondeleting();
2104 child
->setNode(node
);
2108 rtl::Reference
< ChildAccess
> child(
2109 new ChildAccess(components_
, getRootAccess(), this, name
, node
));
2110 cachedChildren_
[name
] = child
.get();
2114 rtl::Reference
< ChildAccess
> Access::getSubChild(rtl::OUString
const & path
) {
2116 // For backwards compatibility, allow absolute paths where meaningful:
2117 if (!path
.isEmpty() && path
[0] == '/') {
2119 if (!getRootAccess().is()) {
2120 return rtl::Reference
< ChildAccess
>();
2122 Path
abs(getAbsolutePath());
2123 for (Path::iterator
j(abs
.begin()); j
!= abs
.end(); ++j
) {
2124 rtl::OUString name1
;
2126 rtl::OUString templateName1
;
2127 i
= Data::parseSegment(
2128 path
, i
, &name1
, &setElement1
, &templateName1
);
2129 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2130 return rtl::Reference
< ChildAccess
>();
2132 rtl::OUString name2
;
2134 rtl::OUString templateName2
;
2135 Data::parseSegment(*j
, 0, &name2
, &setElement2
, &templateName2
);
2136 if (name1
!= name2
|| setElement1
!= setElement2
||
2138 !Data::equalTemplateNames(templateName1
, templateName2
)))
2140 return rtl::Reference
< ChildAccess
>();
2142 if (i
!= path
.getLength()) {
2147 for (rtl::Reference
< Access
> parent(this);;) {
2150 rtl::OUString templateName
;
2151 i
= Data::parseSegment(path
, i
, &name
, &setElement
, &templateName
);
2152 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2153 return rtl::Reference
< ChildAccess
>();
2155 rtl::Reference
< ChildAccess
> child(parent
->getChild(name
));
2157 return rtl::Reference
< ChildAccess
>();
2160 rtl::Reference
< Node
> p(parent
->getNode());
2161 switch (p
->kind()) {
2162 case Node::KIND_LOCALIZED_PROPERTY
:
2163 if (!Components::allLocales(getRootAccess()->getLocale()) ||
2164 !templateName
.isEmpty())
2166 return rtl::Reference
< ChildAccess
>();
2169 case Node::KIND_SET
:
2170 if (!templateName
.isEmpty() &&
2171 !dynamic_cast< SetNode
* >(p
.get())->isValidTemplate(
2174 return rtl::Reference
< ChildAccess
>();
2178 return rtl::Reference
< ChildAccess
>();
2181 // For backwards compatibility, ignore a final slash after non-value
2183 if (child
->isValue()) {
2184 return i
== path
.getLength()
2185 ? child
: rtl::Reference
< ChildAccess
>();
2186 } else if (i
>= path
.getLength() - 1) {
2190 parent
= child
.get();
2194 bool Access::setChildProperty(
2195 rtl::OUString
const & name
, css::uno::Any
const & value
,
2196 Modifications
* localModifications
)
2198 assert(localModifications
!= 0);
2199 rtl::Reference
< ChildAccess
> child(getChild(name
));
2203 child
->checkFinalized();
2204 child
->setProperty(value
, localModifications
);
2208 css::beans::Property
Access::asProperty() {
2209 css::uno::Type type
;
2212 rtl::Reference
< Node
> p(getNode());
2213 switch (p
->kind()) {
2214 case Node::KIND_PROPERTY
:
2216 PropertyNode
* prop
= dynamic_cast< PropertyNode
* >(p
.get());
2217 type
= mapType(prop
->getStaticType());
2218 nillable
= prop
->isNillable();
2219 removable
= prop
->isExtension();
2222 case Node::KIND_LOCALIZED_PROPERTY
:
2224 LocalizedPropertyNode
* locprop
=
2225 dynamic_cast< LocalizedPropertyNode
*>(p
.get());
2226 if (Components::allLocales(getRootAccess()->getLocale())) {
2227 type
= cppu::UnoType
< css::uno::XInterface
>::get();
2231 type
= mapType(locprop
->getStaticType());
2232 removable
= false; //TODO ???
2234 nillable
= locprop
->isNillable();
2237 case Node::KIND_LOCALIZED_VALUE
:
2239 LocalizedPropertyNode
* locprop
=
2240 dynamic_cast< LocalizedPropertyNode
* >(getParentNode().get());
2241 type
= mapType(locprop
->getStaticType());
2242 nillable
= locprop
->isNillable();
2243 removable
= false; //TODO ???
2247 type
= cppu::UnoType
< css::uno::XInterface
>::get(); //TODO: correct?
2249 rtl::Reference
< Node
> parent(getParentNode());
2250 removable
= parent
.is() && parent
->kind() == Node::KIND_SET
;
2253 return css::beans::Property(
2254 getNameInternal(), -1, type
,
2255 (css::beans::PropertyAttribute::BOUND
| //TODO: correct for group/set?
2256 css::beans::PropertyAttribute::CONSTRAINED
|
2257 (nillable
? css::beans::PropertyAttribute::MAYBEVOID
: 0) |
2258 (getRootAccess()->isUpdate()
2259 ? (removable
? css::beans::PropertyAttribute::REMOVEABLE
: 0)
2260 : css::beans::PropertyAttribute::READONLY
))); //TODO: MAYBEDEFAULT
2263 void Access::checkFinalized() {
2264 if (isFinalized()) {
2265 throw css::lang::IllegalArgumentException(
2267 RTL_CONSTASCII_USTRINGPARAM(
2268 "configmgr modification of finalized item")),
2269 static_cast< cppu::OWeakObject
* >(this), -1);
2273 void Access::checkKnownProperty(rtl::OUString
const & descriptor
) {
2274 if (descriptor
.isEmpty()) {
2277 rtl::Reference
< ChildAccess
> child(getChild(descriptor
));
2279 switch (child
->getNode()->kind()) {
2280 case Node::KIND_PROPERTY
:
2282 case Node::KIND_LOCALIZED_PROPERTY
:
2283 if (!Components::allLocales(getRootAccess()->getLocale())) {
2287 case Node::KIND_LOCALIZED_VALUE
:
2288 if (Components::allLocales(getRootAccess()->getLocale())) {
2296 throw css::beans::UnknownPropertyException(
2297 descriptor
, static_cast< cppu::OWeakObject
* >(this));
2300 rtl::Reference
< ChildAccess
> Access::getFreeSetMember(
2301 css::uno::Any
const & value
)
2303 rtl::Reference
< ChildAccess
> freeAcc
;
2304 css::uno::Reference
< css::lang::XUnoTunnel
> tunnel
;
2308 reinterpret_cast< ChildAccess
* >(
2309 tunnel
->getSomething(ChildAccess::getTunnelId())));
2311 if (!freeAcc
.is() || freeAcc
->getParentAccess().is() ||
2312 (freeAcc
->isInTransaction() &&
2313 freeAcc
->getRootAccess() != getRootAccess()))
2315 throw css::lang::IllegalArgumentException(
2317 RTL_CONSTASCII_USTRINGPARAM(
2318 "configmgr inappropriate set element")),
2319 static_cast< cppu::OWeakObject
* >(this), 1);
2321 assert(dynamic_cast< SetNode
* >(getNode().get()) != 0);
2322 if (!dynamic_cast< SetNode
* >(getNode().get())->isValidTemplate(
2323 freeAcc
->getNode()->getTemplateName()))
2325 throw css::lang::IllegalArgumentException(
2327 RTL_CONSTASCII_USTRINGPARAM(
2328 "configmgr inappropriate set element")),
2329 static_cast< cppu::OWeakObject
* >(this), 1);
2334 rtl::Reference
< Access
> Access::getNotificationRoot() {
2335 for (rtl::Reference
< Access
> p(this);;) {
2336 rtl::Reference
< Access
> parent(p
->getParentAccess());
2345 bool Access::thisIs(int what
) {
2346 osl::MutexGuard
g(*lock_
);
2347 rtl::Reference
< Node
> p(getNode());
2348 Node::Kind
k(p
->kind());
2349 return (k
!= Node::KIND_PROPERTY
&& k
!= Node::KIND_LOCALIZED_VALUE
&&
2350 ((what
& IS_GROUP
) == 0 || k
== Node::KIND_GROUP
) &&
2351 ((what
& IS_SET
) == 0 || k
== Node::KIND_SET
) &&
2352 ((what
& IS_EXTENSIBLE
) == 0 || k
!= Node::KIND_GROUP
||
2353 dynamic_cast< GroupNode
* >(p
.get())->isExtensible()) &&
2354 ((what
& IS_GROUP_MEMBER
) == 0 ||
2355 getParentNode()->kind() == Node::KIND_GROUP
)) ||
2356 ((what
& IS_SET_MEMBER
) == 0 ||
2357 getParentNode()->kind() == Node::KIND_SET
) ||
2358 ((what
& IS_UPDATE
) == 0 || getRootAccess()->isUpdate());
2364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */