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/sequence.hxx>
73 #include <cppu/unotype.hxx>
74 #include <cppuhelper/queryinterface.hxx>
75 #include <cppuhelper/supportsservice.hxx>
76 #include <cppuhelper/weak.hxx>
77 #include <osl/interlck.h>
78 #include <osl/mutex.hxx>
79 #include <rtl/ref.hxx>
80 #include <rtl/ustrbuf.hxx>
81 #include <rtl/ustring.h>
82 #include <rtl/ustring.hxx>
83 #include <sal/log.hxx>
84 #include <sal/types.h>
87 #include "broadcaster.hxx"
88 #include "childaccess.hxx"
89 #include "components.hxx"
91 #include "groupnode.hxx"
92 #include "localizedpropertynode.hxx"
93 #include "localizedvaluenode.hxx"
95 #include "modifications.hxx"
97 #include "nodemap.hxx"
99 #include "propertynode.hxx"
100 #include "rootaccess.hxx"
101 #include "setnode.hxx"
104 namespace configmgr
{
106 oslInterlockedCount
Access::acquireCounting() {
107 return osl_atomic_increment(&m_refCount
);
110 void Access::releaseNondeleting() {
111 osl_atomic_decrement(&m_refCount
);
114 bool Access::isValue() {
115 rtl::Reference
< Node
> p(getNode());
117 case Node::KIND_PROPERTY
:
118 case Node::KIND_LOCALIZED_VALUE
:
120 case Node::KIND_LOCALIZED_PROPERTY
:
121 return !Components::allLocales(getRootAccess()->getLocale());
127 void Access::markChildAsModified(rtl::Reference
< ChildAccess
> const & child
) {
128 assert(child
.is() && child
->getParentAccess() == this);
129 modifiedChildren_
[child
->getNameInternal()] = ModifiedChild(child
, true);
130 for (rtl::Reference
< Access
> p(this);;) {
131 rtl::Reference
< Access
> parent(p
->getParentAccess());
135 assert(dynamic_cast< ChildAccess
* >(p
.get()) != 0);
136 parent
->modifiedChildren_
.insert(
137 ModifiedChildren::value_type(
138 p
->getNameInternal(),
139 ModifiedChild(static_cast< ChildAccess
* >(p
.get()), false)));
144 void Access::releaseChild(OUString
const & name
) {
145 cachedChildren_
.erase(name
);
148 void Access::initBroadcaster(
149 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
)
151 initBroadcasterAndChanges(modifications
, broadcaster
, 0);
154 css::uno::Sequence
< css::uno::Type
> Access::getTypes()
155 throw (css::uno::RuntimeException
, std::exception
)
157 assert(thisIs(IS_ANY
));
158 osl::MutexGuard
g(*lock_
);
159 checkLocalizedPropertyAccess();
160 std::vector
< css::uno::Type
> types
;
161 types
.push_back(cppu::UnoType
< css::uno::XInterface
>::get());
162 types
.push_back(cppu::UnoType
< css::uno::XWeak
>::get());
163 types
.push_back(cppu::UnoType
< css::lang::XTypeProvider
>::get());
164 types
.push_back(cppu::UnoType
< css::lang::XServiceInfo
>::get());
165 types
.push_back(cppu::UnoType
< css::lang::XComponent
>::get());
166 types
.push_back(cppu::UnoType
< css::container::XContainer
>::get());
167 types
.push_back(cppu::UnoType
< css::beans::XExactName
>::get());
168 types
.push_back(cppu::UnoType
< css::container::XHierarchicalName
>::get());
169 types
.push_back(cppu::UnoType
< css::container::XNamed
>::get());
170 types
.push_back(cppu::UnoType
< css::beans::XProperty
>::get());
171 types
.push_back(cppu::UnoType
< css::container::XElementAccess
>::get());
172 types
.push_back(cppu::UnoType
< css::container::XNameAccess
>::get());
173 if (getNode()->kind() == Node::KIND_GROUP
) {
174 types
.push_back(cppu::UnoType
< css::beans::XPropertySetInfo
>::get());
175 types
.push_back(cppu::UnoType
< css::beans::XPropertySet
>::get());
176 types
.push_back(cppu::UnoType
< css::beans::XMultiPropertySet
>::get());
178 cppu::UnoType
< css::beans::XHierarchicalPropertySet
>::get());
180 cppu::UnoType
< css::beans::XMultiHierarchicalPropertySet
>::get());
182 cppu::UnoType
< css::beans::XHierarchicalPropertySetInfo
>::get());
184 if (getRootAccess()->isUpdate()) {
185 types
.push_back(cppu::UnoType
< css::container::XNameReplace
>::get());
187 cppu::UnoType
< css::container::XHierarchicalNameReplace
>::get());
188 if (getNode()->kind() != Node::KIND_GROUP
||
189 static_cast< GroupNode
* >(getNode().get())->isExtensible())
192 cppu::UnoType
< css::container::XNameContainer
>::get());
194 if (getNode()->kind() == Node::KIND_SET
) {
196 cppu::UnoType
< css::lang::XSingleServiceFactory
>::get());
200 cppu::UnoType
< css::container::XHierarchicalNameAccess
>::get());
203 return comphelper::containerToSequence(types
);
206 css::uno::Sequence
< sal_Int8
> Access::getImplementationId()
207 throw (css::uno::RuntimeException
, std::exception
)
209 assert(thisIs(IS_ANY
));
210 osl::MutexGuard
g(*lock_
);
211 checkLocalizedPropertyAccess();
212 return css::uno::Sequence
< sal_Int8
>();
215 OUString
Access::getImplementationName() throw (css::uno::RuntimeException
, std::exception
)
217 assert(thisIs(IS_ANY
));
218 osl::MutexGuard
g(*lock_
);
219 checkLocalizedPropertyAccess();
220 return OUString("org.openoffice-configmgr::Access");
223 sal_Bool
Access::supportsService(OUString
const & ServiceName
)
224 throw (css::uno::RuntimeException
, std::exception
)
226 return cppu::supportsService(this, ServiceName
);
229 css::uno::Sequence
< OUString
> Access::getSupportedServiceNames()
230 throw (css::uno::RuntimeException
, std::exception
)
232 assert(thisIs(IS_ANY
));
233 osl::MutexGuard
g(*lock_
);
234 checkLocalizedPropertyAccess();
235 std::vector
< OUString
> services
;
236 services
.push_back("com.sun.star.configuration.ConfigurationAccess");
237 if (getRootAccess()->isUpdate()) {
239 "com.sun.star.configuration.ConfigurationUpdateAccess");
241 services
.push_back("com.sun.star.configuration.HierarchyAccess");
242 services
.push_back("com.sun.star.configuration.HierarchyElement");
243 if (getNode()->kind() == Node::KIND_GROUP
) {
244 services
.push_back("com.sun.star.configuration.GroupAccess");
245 services
.push_back("com.sun.star.configuration.PropertyHierarchy");
246 if (getRootAccess()->isUpdate()) {
247 services
.push_back("com.sun.star.configuration.GroupUpdate");
250 services
.push_back("com.sun.star.configuration.SetAccess");
251 services
.push_back("com.sun.star.configuration.SimpleSetAccess");
252 if (getRootAccess()->isUpdate()) {
253 services
.push_back("com.sun.star.configuration.SetUpdate");
254 services
.push_back("com.sun.star.configuration.SimpleSetUpdate");
257 addSupportedServiceNames(&services
);
258 return comphelper::containerToSequence(services
);
261 void Access::dispose() throw (css::uno::RuntimeException
, std::exception
) {
262 assert(thisIs(IS_ANY
));
265 osl::MutexGuard
g(*lock_
);
266 checkLocalizedPropertyAccess();
267 if (getParentAccess().is()) {
268 throw css::uno::RuntimeException(
269 "configmgr dispose inappropriate Access",
270 static_cast< cppu::OWeakObject
* >(this));
275 initDisposeBroadcaster(&bc
);
282 void Access::addEventListener(
283 css::uno::Reference
< css::lang::XEventListener
> const & xListener
)
284 throw (css::uno::RuntimeException
, std::exception
)
286 assert(thisIs(IS_ANY
));
288 osl::MutexGuard
g(*lock_
);
289 checkLocalizedPropertyAccess();
290 if (!xListener
.is()) {
291 throw css::uno::RuntimeException(
292 "null listener", static_cast< cppu::OWeakObject
* >(this));
295 disposeListeners_
.insert(xListener
);
300 xListener
->disposing(
301 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
302 } catch (css::lang::DisposedException
&) {}
305 void Access::removeEventListener(
306 css::uno::Reference
< css::lang::XEventListener
> const & aListener
)
307 throw (css::uno::RuntimeException
, std::exception
)
309 assert(thisIs(IS_ANY
));
310 osl::MutexGuard
g(*lock_
);
311 checkLocalizedPropertyAccess();
312 DisposeListeners::iterator
i(disposeListeners_
.find(aListener
));
313 if (i
!= disposeListeners_
.end()) {
314 disposeListeners_
.erase(i
);
318 css::uno::Type
Access::getElementType() throw (css::uno::RuntimeException
, std::exception
) {
319 assert(thisIs(IS_ANY
));
320 osl::MutexGuard
g(*lock_
);
321 checkLocalizedPropertyAccess();
322 rtl::Reference
< Node
> p(getNode());
324 case Node::KIND_LOCALIZED_PROPERTY
:
326 static_cast< LocalizedPropertyNode
* >(p
.get())->getStaticType());
327 case Node::KIND_GROUP
:
328 //TODO: Should a specific type be returned for a non-extensible group
329 // with homogeneous members or for an extensible group that currently
330 // has only homegeneous members?
331 return cppu::UnoType
<void>::get();
333 return cppu::UnoType
<void>::get(); //TODO: correct?
336 throw css::uno::RuntimeException(
337 "this cannot happen", static_cast< cppu::OWeakObject
* >(this));
341 sal_Bool
Access::hasElements() throw (css::uno::RuntimeException
, std::exception
) {
342 assert(thisIs(IS_ANY
));
343 osl::MutexGuard
g(*lock_
);
344 checkLocalizedPropertyAccess();
345 return !getAllChildren().empty(); //TODO: optimize
348 bool Access::getByNameFast(const OUString
& name
, css::uno::Any
& value
)
350 bool bGotValue
= false;
351 rtl::Reference
< ChildAccess
> child
;
353 if (getNode()->kind() != Node::KIND_LOCALIZED_PROPERTY
)
354 { // try to get it directly
355 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
356 if (i
!= modifiedChildren_
.end())
358 child
= getModifiedChild(i
);
361 value
= child
->asValue();
367 rtl::Reference
< Node
> node(getNode()->getMember(name
));
370 bGotValue
= ChildAccess::asSimpleValue(node
, value
, components_
);
376 child
= getChild(name
);
379 value
= child
->asValue();
384 css::uno::Any
Access::getByName(OUString
const & aName
)
386 css::container::NoSuchElementException
,
387 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
389 assert(thisIs(IS_ANY
));
390 osl::MutexGuard
g(*lock_
);
391 checkLocalizedPropertyAccess();
393 if (!getByNameFast(aName
, value
))
394 throw css::container::NoSuchElementException(
395 aName
, static_cast< cppu::OWeakObject
* >(this));
399 css::uno::Sequence
< OUString
> Access::getElementNames()
400 throw (css::uno::RuntimeException
, std::exception
)
402 assert(thisIs(IS_ANY
));
403 osl::MutexGuard
g(*lock_
);
404 checkLocalizedPropertyAccess();
405 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
406 std::vector
< OUString
> names
;
407 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
409 i
!= children
.end(); ++i
)
411 names
.push_back((*i
)->getNameInternal());
413 return comphelper::containerToSequence(names
);
416 sal_Bool
Access::hasByName(OUString
const & aName
)
417 throw (css::uno::RuntimeException
, std::exception
)
419 assert(thisIs(IS_ANY
));
420 osl::MutexGuard
g(*lock_
);
421 checkLocalizedPropertyAccess();
422 return getChild(aName
).is();
425 css::uno::Any
Access::getByHierarchicalName(OUString
const & aName
)
426 throw (css::container::NoSuchElementException
, css::uno::RuntimeException
, std::exception
)
428 assert(thisIs(IS_ANY
));
429 osl::MutexGuard
g(*lock_
);
430 checkLocalizedPropertyAccess();
431 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
433 throw css::container::NoSuchElementException(
434 aName
, static_cast< cppu::OWeakObject
* >(this));
436 return child
->asValue();
439 sal_Bool
Access::hasByHierarchicalName(OUString
const & aName
)
440 throw (css::uno::RuntimeException
, std::exception
)
442 assert(thisIs(IS_ANY
));
443 osl::MutexGuard
g(*lock_
);
444 checkLocalizedPropertyAccess();
445 return getSubChild(aName
).is();
448 void Access::replaceByHierarchicalName(
449 OUString
const & aName
, css::uno::Any
const & aElement
)
451 css::lang::IllegalArgumentException
,
452 css::container::NoSuchElementException
,
453 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
455 //TODO: Actually support sets and combine with replaceByName:
456 assert(thisIs(IS_UPDATE
));
459 osl::MutexGuard
g(*lock_
);
460 checkLocalizedPropertyAccess();
461 rtl::Reference
< ChildAccess
> child(getSubChild(aName
));
463 throw css::container::NoSuchElementException(
464 aName
, static_cast< cppu::OWeakObject
* >(this));
466 child
->checkFinalized();
467 rtl::Reference
< Node
> parent(child
->getParentNode());
469 Modifications localMods
;
470 switch (parent
->kind()) {
471 case Node::KIND_LOCALIZED_PROPERTY
:
472 case Node::KIND_GROUP
:
473 child
->setProperty(aElement
, &localMods
);
476 throw css::lang::IllegalArgumentException(
477 ("configmgr::Access::replaceByHierarchicalName does not"
478 " currently support set members"),
479 static_cast< cppu::OWeakObject
* >(this), 0);
480 case Node::KIND_ROOT
:
481 throw css::lang::IllegalArgumentException(
482 ("configmgr::Access::replaceByHierarchicalName does not allow"
483 " changing component " + aName
),
484 static_cast< cppu::OWeakObject
* >(this), 0);
486 assert(false); // this cannot happen
489 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
494 void Access::addContainerListener(
495 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
496 throw (css::uno::RuntimeException
, std::exception
)
498 assert(thisIs(IS_ANY
));
500 osl::MutexGuard
g(*lock_
);
501 checkLocalizedPropertyAccess();
502 if (!xListener
.is()) {
503 throw css::uno::RuntimeException(
504 "null listener", static_cast< cppu::OWeakObject
* >(this));
507 containerListeners_
.insert(xListener
);
512 xListener
->disposing(
513 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
514 } catch (css::lang::DisposedException
&) {}
517 void Access::removeContainerListener(
518 css::uno::Reference
< css::container::XContainerListener
> const & xListener
)
519 throw (css::uno::RuntimeException
, std::exception
)
521 assert(thisIs(IS_ANY
));
522 osl::MutexGuard
g(*lock_
);
523 checkLocalizedPropertyAccess();
524 ContainerListeners::iterator
i(containerListeners_
.find(xListener
));
525 if (i
!= containerListeners_
.end()) {
526 containerListeners_
.erase(i
);
530 OUString
Access::getExactName(OUString
const & aApproximateName
)
531 throw (css::uno::RuntimeException
, std::exception
)
533 assert(thisIs(IS_ANY
));
534 osl::MutexGuard
g(*lock_
);
535 checkLocalizedPropertyAccess();
536 return aApproximateName
;
539 css::uno::Sequence
< css::beans::Property
> Access::getProperties()
540 throw (css::uno::RuntimeException
, std::exception
)
542 assert(thisIs(IS_GROUP
));
543 osl::MutexGuard
g(*lock_
);
544 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
545 std::vector
< css::beans::Property
> properties
;
546 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
548 i
!= children
.end(); ++i
)
550 properties
.push_back((*i
)->asProperty());
552 return comphelper::containerToSequence(properties
);
555 css::beans::Property
Access::getPropertyByName(OUString
const & aName
)
556 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
)
558 assert(thisIs(IS_GROUP
));
559 osl::MutexGuard
g(*lock_
);
560 rtl::Reference
< ChildAccess
> child(getChild(aName
));
562 throw css::beans::UnknownPropertyException(
563 aName
, static_cast< cppu::OWeakObject
* >(this));
565 return child
->asProperty();
568 sal_Bool
Access::hasPropertyByName(OUString
const & Name
)
569 throw (css::uno::RuntimeException
, std::exception
)
571 assert(thisIs(IS_GROUP
));
572 osl::MutexGuard
g(*lock_
);
573 return getChild(Name
).is();
576 OUString
Access::getHierarchicalName() throw (css::uno::RuntimeException
, std::exception
) {
577 assert(thisIs(IS_ANY
));
578 osl::MutexGuard
g(*lock_
);
579 checkLocalizedPropertyAccess();
580 // For backwards compatibility, return an absolute path representation where
583 rtl::Reference
< RootAccess
> root(getRootAccess());
585 rootPath
= root
->getAbsolutePathRepresentation();
587 OUString
rel(getRelativePathRepresentation());
588 OUStringBuffer
path(rootPath
);
589 if (!rootPath
.isEmpty() && rootPath
!= "/" && !rel
.isEmpty()) {
593 return path
.makeStringAndClear();
596 OUString
Access::composeHierarchicalName(
597 OUString
const & aRelativeName
)
599 css::lang::IllegalArgumentException
, css::lang::NoSupportException
,
600 css::uno::RuntimeException
, std::exception
)
602 assert(thisIs(IS_ANY
));
603 osl::MutexGuard
g(*lock_
);
604 checkLocalizedPropertyAccess();
605 if (aRelativeName
.isEmpty() || aRelativeName
[0] == '/') {
606 throw css::lang::IllegalArgumentException(
607 "configmgr composeHierarchicalName inappropriate relative name",
608 static_cast< cppu::OWeakObject
* >(this), -1);
610 OUStringBuffer
path(getRelativePathRepresentation());
611 if (!path
.isEmpty()) {
614 path
.append(aRelativeName
);
615 return path
.makeStringAndClear();
618 OUString
Access::getName() throw (css::uno::RuntimeException
, std::exception
) {
619 assert(thisIs(IS_ANY
));
620 osl::MutexGuard
g(*lock_
);
621 checkLocalizedPropertyAccess();
622 return getNameInternal();
625 void Access::setName(OUString
const & aName
)
626 throw (css::uno::RuntimeException
, std::exception
)
628 assert(thisIs(IS_ANY
));
631 osl::MutexGuard
g(*lock_
);
632 checkLocalizedPropertyAccess();
634 Modifications localMods
;
635 switch (getNode()->kind()) {
636 case Node::KIND_GROUP
:
639 rtl::Reference
< Access
> parent(getParentAccess());
641 rtl::Reference
< Node
> node(getNode());
642 if (! node
->getTemplateName().isEmpty()) {
643 rtl::Reference
< ChildAccess
> other(
644 parent
->getChild(aName
));
645 if (other
.get() == this) {
648 if (node
->getMandatory() == Data::NO_LAYER
&&
649 !(other
.is() && other
->isFinalized()))
651 rtl::Reference
< RootAccess
> root(getRootAccess());
652 rtl::Reference
< ChildAccess
> childAccess(
653 static_cast< ChildAccess
* >(this));
654 localMods
.add(getRelativePath());
655 // unbind() modifies the parent chain that
656 // markChildAsModified() walks, so order is
658 parent
->markChildAsModified(childAccess
);
659 //TODO: must not throw
660 childAccess
->unbind(); // must not throw
662 other
->unbind(); // must not throw
664 childAccess
->bind(root
, parent
, aName
);
666 parent
->markChildAsModified(childAccess
);
667 //TODO: must not throw
668 localMods
.add(getRelativePath());
675 case Node::KIND_LOCALIZED_PROPERTY
:
676 // renaming a property could only work for an extension property,
677 // but a localized property is never an extension property
678 throw css::uno::RuntimeException(
679 "configmgr setName inappropriate node",
680 static_cast< cppu::OWeakObject
* >(this));
682 assert(false); // this cannot happen
685 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
690 css::beans::Property
Access::getAsProperty() throw (css::uno::RuntimeException
, std::exception
)
692 assert(thisIs(IS_ANY
));
693 osl::MutexGuard
g(*lock_
);
694 checkLocalizedPropertyAccess();
698 css::uno::Reference
< css::beans::XPropertySetInfo
> Access::getPropertySetInfo()
699 throw (css::uno::RuntimeException
, std::exception
)
701 assert(thisIs(IS_GROUP
));
705 void Access::setPropertyValue(
706 OUString
const & aPropertyName
, css::uno::Any
const & aValue
)
708 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
709 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
710 css::uno::RuntimeException
, std::exception
)
712 assert(thisIs(IS_GROUP
));
715 osl::MutexGuard
g(*lock_
);
716 if (!getRootAccess()->isUpdate()) {
717 throw css::uno::RuntimeException(
718 "configmgr setPropertyValue on non-update access",
719 static_cast< cppu::OWeakObject
* >(this));
721 Modifications localMods
;
722 if (!setChildProperty(aPropertyName
, aValue
, &localMods
)) {
723 throw css::beans::UnknownPropertyException(
724 aPropertyName
, static_cast< cppu::OWeakObject
* >(this));
726 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
731 css::uno::Any
Access::getPropertyValue(OUString
const & PropertyName
)
733 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
734 css::uno::RuntimeException
, std::exception
)
736 assert(thisIs(IS_GROUP
));
737 osl::MutexGuard
g(*lock_
);
740 if (!getByNameFast(PropertyName
, value
))
741 throw css::beans::UnknownPropertyException(
742 PropertyName
, static_cast< cppu::OWeakObject
* >(this));
746 void Access::addPropertyChangeListener(
747 OUString
const & aPropertyName
,
748 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
751 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
752 css::uno::RuntimeException
, std::exception
)
754 assert(thisIs(IS_GROUP
));
756 osl::MutexGuard
g(*lock_
);
757 if (!xListener
.is()) {
758 throw css::uno::RuntimeException(
759 "null listener", static_cast< cppu::OWeakObject
* >(this));
761 checkKnownProperty(aPropertyName
);
763 propertyChangeListeners_
[aPropertyName
].insert(xListener
);
768 xListener
->disposing(
769 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
770 } catch (css::lang::DisposedException
&) {}
773 void Access::removePropertyChangeListener(
774 OUString
const & aPropertyName
,
775 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
778 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
779 css::uno::RuntimeException
, std::exception
)
781 assert(thisIs(IS_GROUP
));
782 osl::MutexGuard
g(*lock_
);
783 checkKnownProperty(aPropertyName
);
784 PropertyChangeListeners::iterator
i(
785 propertyChangeListeners_
.find(aPropertyName
));
786 if (i
!= propertyChangeListeners_
.end()) {
787 PropertyChangeListenersElement::iterator
j(i
->second
.find(aListener
));
788 if (j
!= i
->second
.end()) {
790 if (i
->second
.empty()) {
791 propertyChangeListeners_
.erase(i
);
797 void Access::addVetoableChangeListener(
798 OUString
const & PropertyName
,
799 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
802 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
803 css::uno::RuntimeException
, std::exception
)
805 assert(thisIs(IS_GROUP
));
807 osl::MutexGuard
g(*lock_
);
808 if (!aListener
.is()) {
809 throw css::uno::RuntimeException(
810 "null listener", static_cast< cppu::OWeakObject
* >(this));
812 checkKnownProperty(PropertyName
);
814 vetoableChangeListeners_
[PropertyName
].insert(aListener
);
815 //TODO: actually call vetoableChangeListeners_
820 aListener
->disposing(
821 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
822 } catch (css::lang::DisposedException
&) {}
825 void Access::removeVetoableChangeListener(
826 OUString
const & PropertyName
,
827 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
830 css::beans::UnknownPropertyException
, css::lang::WrappedTargetException
,
831 css::uno::RuntimeException
, std::exception
)
833 assert(thisIs(IS_GROUP
));
834 osl::MutexGuard
g(*lock_
);
835 checkKnownProperty(PropertyName
);
836 VetoableChangeListeners::iterator
i(
837 vetoableChangeListeners_
.find(PropertyName
));
838 if (i
!= vetoableChangeListeners_
.end()) {
839 VetoableChangeListenersElement::iterator
j(i
->second
.find(aListener
));
840 if (j
!= i
->second
.end()) {
842 if (i
->second
.empty()) {
843 vetoableChangeListeners_
.erase(i
);
849 void Access::setPropertyValues(
850 css::uno::Sequence
< OUString
> const & aPropertyNames
,
851 css::uno::Sequence
< css::uno::Any
> const & aValues
)
853 css::beans::PropertyVetoException
, css::lang::IllegalArgumentException
,
854 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
856 assert(thisIs(IS_GROUP
));
859 osl::MutexGuard
g(*lock_
);
860 if (!getRootAccess()->isUpdate()) {
861 throw css::uno::RuntimeException(
862 "configmgr setPropertyValues on non-update access",
863 static_cast< cppu::OWeakObject
* >(this));
865 if (aPropertyNames
.getLength() != aValues
.getLength()) {
866 throw css::lang::IllegalArgumentException(
867 ("configmgr setPropertyValues: aPropertyNames/aValues of"
868 " different length"),
869 static_cast< cppu::OWeakObject
* >(this), -1);
871 Modifications localMods
;
872 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
) {
873 if (!setChildProperty(aPropertyNames
[i
], aValues
[i
], &localMods
)) {
874 throw css::lang::IllegalArgumentException(
875 "configmgr setPropertyValues inappropriate property name",
876 static_cast< cppu::OWeakObject
* >(this), -1);
879 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
884 css::uno::Sequence
< css::uno::Any
> Access::getPropertyValues(
885 css::uno::Sequence
< OUString
> const & aPropertyNames
)
886 throw (css::uno::RuntimeException
, std::exception
)
888 assert(thisIs(IS_GROUP
));
889 osl::MutexGuard
g(*lock_
);
890 css::uno::Sequence
< css::uno::Any
> vals(aPropertyNames
.getLength());
892 for (sal_Int32 i
= 0; i
< aPropertyNames
.getLength(); ++i
)
894 if (!getByNameFast(aPropertyNames
[i
], vals
[i
]))
895 throw css::uno::RuntimeException(
896 "configmgr getPropertyValues inappropriate property name",
897 static_cast< cppu::OWeakObject
* >(this));
903 void Access::addPropertiesChangeListener(
904 css::uno::Sequence
< OUString
> const &,
905 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
907 throw (css::uno::RuntimeException
, std::exception
)
909 assert(thisIs(IS_GROUP
));
911 osl::MutexGuard
g(*lock_
);
912 if (!xListener
.is()) {
913 throw css::uno::RuntimeException(
914 "null listener", static_cast< cppu::OWeakObject
* >(this));
917 propertiesChangeListeners_
.insert(xListener
);
922 xListener
->disposing(
923 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
924 } catch (css::lang::DisposedException
&) {}
927 void Access::removePropertiesChangeListener(
928 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
930 throw (css::uno::RuntimeException
, std::exception
)
932 assert(thisIs(IS_GROUP
));
933 osl::MutexGuard
g(*lock_
);
934 PropertiesChangeListeners::iterator
i(
935 propertiesChangeListeners_
.find(xListener
));
936 if (i
!= propertiesChangeListeners_
.end()) {
937 propertiesChangeListeners_
.erase(i
);
941 void Access::firePropertiesChangeEvent(
942 css::uno::Sequence
< OUString
> const & aPropertyNames
,
943 css::uno::Reference
< css::beans::XPropertiesChangeListener
> const &
945 throw (css::uno::RuntimeException
, std::exception
)
947 assert(thisIs(IS_GROUP
));
948 css::uno::Sequence
< css::beans::PropertyChangeEvent
> events(
949 aPropertyNames
.getLength());
950 for (sal_Int32 i
= 0; i
< events
.getLength(); ++i
) {
951 events
[i
].Source
= static_cast< cppu::OWeakObject
* >(this);
952 events
[i
].PropertyName
= aPropertyNames
[i
];
953 events
[i
].Further
= false;
954 events
[i
].PropertyHandle
= -1;
956 xListener
->propertiesChange(events
);
959 css::uno::Reference
< css::beans::XHierarchicalPropertySetInfo
>
960 Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException
, std::exception
) {
961 assert(thisIs(IS_GROUP
));
965 void Access::setHierarchicalPropertyValue(
966 OUString
const & aHierarchicalPropertyName
,
967 css::uno::Any
const & aValue
)
969 css::beans::UnknownPropertyException
, css::beans::PropertyVetoException
,
970 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
971 css::uno::RuntimeException
, std::exception
)
973 assert(thisIs(IS_GROUP
));
976 osl::MutexGuard
g(*lock_
);
977 if (!getRootAccess()->isUpdate()) {
978 throw css::uno::RuntimeException(
979 "configmgr setHierarchicalPropertyName on non-update access",
980 static_cast< cppu::OWeakObject
* >(this));
982 rtl::Reference
< ChildAccess
> child(
983 getSubChild(aHierarchicalPropertyName
));
985 throw css::beans::UnknownPropertyException(
986 aHierarchicalPropertyName
,
987 static_cast< cppu::OWeakObject
* >(this));
989 child
->checkFinalized();
990 Modifications localMods
;
991 child
->setProperty(aValue
, &localMods
);
992 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
997 css::uno::Any
Access::getHierarchicalPropertyValue(
998 OUString
const & aHierarchicalPropertyName
)
1000 css::beans::UnknownPropertyException
,
1001 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1002 css::uno::RuntimeException
, std::exception
)
1004 assert(thisIs(IS_GROUP
));
1005 osl::MutexGuard
g(*lock_
);
1006 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalPropertyName
));
1008 throw css::beans::UnknownPropertyException(
1009 aHierarchicalPropertyName
,
1010 static_cast< cppu::OWeakObject
* >(this));
1012 return child
->asValue();
1015 void Access::setHierarchicalPropertyValues(
1016 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
,
1017 css::uno::Sequence
< css::uno::Any
> const & Values
)
1019 css::beans::PropertyVetoException
, css::lang::IllegalArgumentException
,
1020 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
1022 assert(thisIs(IS_GROUP
));
1025 osl::MutexGuard
g(*lock_
);
1026 if (!getRootAccess()->isUpdate()) {
1027 throw css::uno::RuntimeException(
1028 "configmgr setPropertyValues on non-update access",
1029 static_cast< cppu::OWeakObject
* >(this));
1031 if (aHierarchicalPropertyNames
.getLength() != Values
.getLength()) {
1032 throw css::lang::IllegalArgumentException(
1033 ("configmgr setHierarchicalPropertyValues:"
1034 " aHierarchicalPropertyNames/Values of different length"),
1035 static_cast< cppu::OWeakObject
* >(this), -1);
1037 Modifications localMods
;
1038 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1039 rtl::Reference
< ChildAccess
> child(
1040 getSubChild(aHierarchicalPropertyNames
[i
]));
1042 throw css::lang::IllegalArgumentException(
1043 ("configmgr setHierarchicalPropertyValues inappropriate"
1045 static_cast< cppu::OWeakObject
* >(this), -1);
1047 child
->checkFinalized();
1048 child
->setProperty(Values
[i
], &localMods
);
1050 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1055 css::uno::Sequence
< css::uno::Any
> Access::getHierarchicalPropertyValues(
1056 css::uno::Sequence
< OUString
> const & aHierarchicalPropertyNames
)
1058 css::lang::IllegalArgumentException
, css::lang::WrappedTargetException
,
1059 css::uno::RuntimeException
, std::exception
)
1061 assert(thisIs(IS_GROUP
));
1062 osl::MutexGuard
g(*lock_
);
1063 css::uno::Sequence
< css::uno::Any
> vals(
1064 aHierarchicalPropertyNames
.getLength());
1065 for (sal_Int32 i
= 0; i
< aHierarchicalPropertyNames
.getLength(); ++i
) {
1066 rtl::Reference
< ChildAccess
> child(
1067 getSubChild(aHierarchicalPropertyNames
[i
]));
1069 throw css::lang::IllegalArgumentException(
1070 ("configmgr getHierarchicalPropertyValues inappropriate"
1071 " hierarchical property name"),
1072 static_cast< cppu::OWeakObject
* >(this), -1);
1074 vals
[i
] = child
->asValue();
1079 css::beans::Property
Access::getPropertyByHierarchicalName(
1080 OUString
const & aHierarchicalName
)
1081 throw (css::beans::UnknownPropertyException
, css::uno::RuntimeException
, std::exception
)
1083 assert(thisIs(IS_GROUP
));
1084 osl::MutexGuard
g(*lock_
);
1085 rtl::Reference
< ChildAccess
> child(getSubChild(aHierarchicalName
));
1087 throw css::beans::UnknownPropertyException(
1088 aHierarchicalName
, static_cast< cppu::OWeakObject
* >(this));
1090 return child
->asProperty();
1093 sal_Bool
Access::hasPropertyByHierarchicalName(
1094 OUString
const & aHierarchicalName
)
1095 throw (css::uno::RuntimeException
, std::exception
)
1097 assert(thisIs(IS_GROUP
));
1098 osl::MutexGuard
g(*lock_
);
1099 return getSubChild(aHierarchicalName
).is();
1102 void Access::replaceByName(
1103 OUString
const & aName
, css::uno::Any
const & aElement
)
1105 css::lang::IllegalArgumentException
,
1106 css::container::NoSuchElementException
,
1107 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
1109 assert(thisIs(IS_UPDATE
));
1112 osl::MutexGuard
g(*lock_
);
1113 checkLocalizedPropertyAccess();
1114 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1116 throw css::container::NoSuchElementException(
1117 aName
, static_cast< cppu::OWeakObject
* >(this));
1119 child
->checkFinalized();
1120 Modifications localMods
;
1121 switch (getNode()->kind()) {
1122 case Node::KIND_LOCALIZED_PROPERTY
:
1123 case Node::KIND_GROUP
:
1124 child
->setProperty(aElement
, &localMods
);
1126 case Node::KIND_SET
:
1128 rtl::Reference
< ChildAccess
> freeAcc(
1129 getFreeSetMember(aElement
));
1130 rtl::Reference
< RootAccess
> root(getRootAccess());
1131 localMods
.add(child
->getRelativePath());
1132 child
->unbind(); // must not throw
1133 freeAcc
->bind(root
, this, aName
); // must not throw
1134 markChildAsModified(freeAcc
); //TODO: must not throw
1138 assert(false); // this cannot happen
1141 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1146 void Access::insertByName(
1147 OUString
const & aName
, css::uno::Any
const & aElement
)
1149 css::lang::IllegalArgumentException
,
1150 css::container::ElementExistException
,
1151 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
1153 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1156 osl::MutexGuard
g(*lock_
);
1157 checkLocalizedPropertyAccess();
1159 if (getChild(aName
).is()) {
1160 throw css::container::ElementExistException(
1161 aName
, static_cast< cppu::OWeakObject
* >(this));
1163 Modifications localMods
;
1164 switch (getNode()->kind()) {
1165 case Node::KIND_LOCALIZED_PROPERTY
:
1166 insertLocalizedValueChild(aName
, aElement
, &localMods
);
1168 case Node::KIND_GROUP
:
1170 checkValue(aElement
, TYPE_ANY
, true);
1171 rtl::Reference
< ChildAccess
> child(
1173 components_
, getRootAccess(), this, aName
,
1175 Data::NO_LAYER
, TYPE_ANY
, true, aElement
, true)));
1176 markChildAsModified(child
);
1177 localMods
.add(child
->getRelativePath());
1180 case Node::KIND_SET
:
1182 rtl::Reference
< ChildAccess
> freeAcc(
1183 getFreeSetMember(aElement
));
1184 freeAcc
->bind(getRootAccess(), this, aName
); // must not throw
1185 markChildAsModified(freeAcc
); //TODO: must not throw
1186 localMods
.add(freeAcc
->getRelativePath());
1190 assert(false); // this cannot happen
1193 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1198 void Access::removeByName(OUString
const & aName
)
1200 css::container::NoSuchElementException
,
1201 css::lang::WrappedTargetException
, css::uno::RuntimeException
, std::exception
)
1203 assert(thisIs(IS_EXTENSIBLE
|IS_UPDATE
));
1206 osl::MutexGuard
g(*lock_
);
1207 checkLocalizedPropertyAccess();
1208 rtl::Reference
< ChildAccess
> child(getChild(aName
));
1209 if (!child
.is() || child
->isFinalized() ||
1210 child
->getNode()->getMandatory() != Data::NO_LAYER
)
1212 throw css::container::NoSuchElementException(
1213 aName
, static_cast< cppu::OWeakObject
* >(this));
1215 if (getNode()->kind() == Node::KIND_GROUP
) {
1216 rtl::Reference
< Node
> p(child
->getNode());
1217 if (p
->kind() != Node::KIND_PROPERTY
||
1218 !static_cast< PropertyNode
* >(p
.get())->isExtension())
1220 throw css::container::NoSuchElementException(
1221 aName
, static_cast< cppu::OWeakObject
* >(this));
1224 Modifications localMods
;
1225 localMods
.add(child
->getRelativePath());
1226 // unbind() modifies the parent chain that markChildAsModified() walks,
1227 // so order is important:
1228 markChildAsModified(child
); //TODO: must not throw
1230 getNotificationRoot()->initBroadcaster(localMods
.getRoot(), &bc
);
1235 css::uno::Reference
< css::uno::XInterface
> Access::createInstance()
1236 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1238 assert(thisIs(IS_SET
|IS_UPDATE
));
1240 static_cast< SetNode
* >(getNode().get())->getDefaultTemplateName());
1241 rtl::Reference
< Node
> tmpl(
1242 components_
.getTemplate(Data::NO_LAYER
, tmplName
));
1244 throw css::uno::Exception(
1245 "unknown template " + tmplName
,
1246 static_cast< cppu::OWeakObject
* >(this));
1248 rtl::Reference
< Node
> node(tmpl
->clone(true));
1249 node
->setLayer(Data::NO_LAYER
);
1250 return static_cast< cppu::OWeakObject
* >(
1251 new ChildAccess(components_
, getRootAccess(), node
));
1254 css::uno::Reference
< css::uno::XInterface
> Access::createInstanceWithArguments(
1255 css::uno::Sequence
< css::uno::Any
> const & aArguments
)
1256 throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
1258 assert(thisIs(IS_SET
|IS_UPDATE
));
1259 if (aArguments
.getLength() != 0) {
1260 throw css::uno::Exception(
1261 ("configuration SimpleSetUpdate createInstanceWithArguments"
1262 " must not specify any arguments"),
1263 static_cast< cppu::OWeakObject
* >(this));
1265 return createInstance();
1268 Access::Access(Components
& components
):
1269 components_(components
), disposed_(false)
1274 Access::~Access() {}
1276 void Access::initDisposeBroadcaster(Broadcaster
* broadcaster
) {
1277 assert(broadcaster
!= 0);
1278 for (DisposeListeners::iterator
i(disposeListeners_
.begin());
1279 i
!= disposeListeners_
.end(); ++i
)
1281 broadcaster
->addDisposeNotification(
1283 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1285 for (ContainerListeners::iterator
i(containerListeners_
.begin());
1286 i
!= containerListeners_
.end(); ++i
)
1288 broadcaster
->addDisposeNotification(
1290 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1292 for (PropertyChangeListeners::iterator
i(propertyChangeListeners_
.begin());
1293 i
!= propertyChangeListeners_
.end(); ++i
)
1295 for (PropertyChangeListenersElement::iterator
j(i
->second
.begin());
1296 j
!= i
->second
.end(); ++j
)
1298 broadcaster
->addDisposeNotification(
1300 css::lang::EventObject(
1301 static_cast< cppu::OWeakObject
* >(this)));
1304 for (VetoableChangeListeners::iterator
i(vetoableChangeListeners_
.begin());
1305 i
!= vetoableChangeListeners_
.end(); ++i
)
1307 for (VetoableChangeListenersElement::iterator
j(i
->second
.begin());
1308 j
!= i
->second
.end(); ++j
)
1310 broadcaster
->addDisposeNotification(
1312 css::lang::EventObject(
1313 static_cast< cppu::OWeakObject
* >(this)));
1316 for (PropertiesChangeListeners::iterator
i(
1317 propertiesChangeListeners_
.begin());
1318 i
!= propertiesChangeListeners_
.end(); ++i
)
1320 broadcaster
->addDisposeNotification(
1322 css::lang::EventObject(static_cast< cppu::OWeakObject
* >(this)));
1324 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1325 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1326 i
!= modifiedChildren_
.end(); ++i
)
1328 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1330 child
->initDisposeBroadcaster(broadcaster
);
1335 void Access::clearListeners() throw() {
1336 disposeListeners_
.clear();
1337 containerListeners_
.clear();
1338 propertyChangeListeners_
.clear();
1339 vetoableChangeListeners_
.clear();
1340 propertiesChangeListeners_
.clear();
1341 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1342 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1343 i
!= modifiedChildren_
.end(); ++i
)
1345 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1347 child
->clearListeners();
1352 css::uno::Any
Access::queryInterface(css::uno::Type
const & aType
)
1353 throw (css::uno::RuntimeException
, std::exception
)
1355 css::uno::Any
res(OWeakObject::queryInterface(aType
));
1356 if (res
.hasValue()) {
1359 res
= cppu::queryInterface(
1360 aType
, static_cast< css::lang::XTypeProvider
* >(this),
1361 static_cast< css::lang::XServiceInfo
* >(this),
1362 static_cast< css::lang::XComponent
* >(this),
1363 static_cast< css::container::XHierarchicalNameAccess
* >(this),
1364 static_cast< css::container::XContainer
* >(this),
1365 static_cast< css::beans::XExactName
* >(this),
1366 static_cast< css::container::XHierarchicalName
* >(this),
1367 static_cast< css::container::XNamed
* >(this),
1368 static_cast< css::beans::XProperty
* >(this),
1369 static_cast< css::container::XElementAccess
* >(this),
1370 static_cast< css::container::XNameAccess
* >(this));
1371 if (res
.hasValue()) {
1374 if (getNode()->kind() == Node::KIND_GROUP
) {
1375 res
= cppu::queryInterface(
1376 aType
, static_cast< css::beans::XPropertySetInfo
* >(this),
1377 static_cast< css::beans::XPropertySet
* >(this),
1378 static_cast< css::beans::XMultiPropertySet
* >(this),
1379 static_cast< css::beans::XHierarchicalPropertySet
* >(this),
1380 static_cast< css::beans::XMultiHierarchicalPropertySet
* >(this),
1381 static_cast< css::beans::XHierarchicalPropertySetInfo
* >(this));
1382 if (res
.hasValue()) {
1386 if (getRootAccess()->isUpdate()) {
1387 res
= cppu::queryInterface(
1388 aType
, static_cast< css::container::XNameReplace
* >(this),
1389 static_cast< css::container::XHierarchicalNameReplace
* >(this));
1390 if (res
.hasValue()) {
1393 if (getNode()->kind() != Node::KIND_GROUP
||
1394 static_cast< GroupNode
* >(getNode().get())->isExtensible())
1396 res
= cppu::queryInterface(
1397 aType
, static_cast< css::container::XNameContainer
* >(this));
1398 if (res
.hasValue()) {
1402 if (getNode()->kind() == Node::KIND_SET
) {
1403 res
= cppu::queryInterface(
1404 aType
, static_cast< css::lang::XSingleServiceFactory
* >(this));
1411 void Access::checkLocalizedPropertyAccess() {
1412 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
&&
1413 !Components::allLocales(getRootAccess()->getLocale()))
1415 throw css::uno::RuntimeException(
1416 "configmgr Access to specialized LocalizedPropertyNode",
1417 static_cast< cppu::OWeakObject
* >(this));
1421 rtl::Reference
< Node
> Access::getParentNode() {
1422 rtl::Reference
< Access
> parent(getParentAccess());
1423 return parent
.is() ? parent
->getNode() : rtl::Reference
< Node
>();
1426 rtl::Reference
< ChildAccess
> Access::getChild(OUString
const & name
) {
1428 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
1429 && name
.startsWith("*", &locale
))
1431 if (locale
.startsWith("*")) {
1434 ("access best-matching localized property value via"
1435 " \"*<locale>\" with <locale> \"")
1436 << locale
<< "\" recursively starting with \"*\"");
1437 return getChild(locale
);
1440 locale
.isEmpty(), "configmgr",
1441 ("access best-matching localized property value via \"*<locale>\""
1442 " with empty <locale>; falling back to defaults"));
1443 if (!locale
.isEmpty()) {
1444 // Find best match using an adaption of RFC 4647 lookup matching
1445 // rules, removing "-" or "_" delimited segments from the end:
1447 rtl::Reference
< ChildAccess
> child(getChild(locale
));
1451 sal_Int32 i
= locale
.getLength() - 1;
1452 while (i
> 0 && locale
[i
] != '-' && locale
[i
] != '_') {
1458 locale
= locale
.copy(0, i
);
1460 // As a workaround for broken xcu data that does not use shortest
1461 // xml:lang attributes, look for the first entry with the same first
1462 // segment as the requested language tag before falling back to
1463 // defaults (see fdo#33638):
1465 !locale
.isEmpty() && locale
.indexOf('-') == -1 &&
1466 locale
.indexOf('_') == -1);
1467 std::vector
< rtl::Reference
< ChildAccess
> > children(
1469 for (std::vector
< rtl::Reference
< ChildAccess
> >::iterator
i(
1471 i
!= children
.end(); ++i
)
1473 OUString
name2((*i
)->getNameInternal());
1474 if (name2
.startsWith(locale
) &&
1475 (name2
.getLength() == locale
.getLength() ||
1476 name2
[locale
.getLength()] == '-' ||
1477 name2
[locale
.getLength()] == '_'))
1483 // Defaults are the "en-US" locale, the "en" locale, the empty string
1484 // locale, the first child (if any), or a null ChildAccess, in that
1486 rtl::Reference
< ChildAccess
> child(getChild("en-US"));
1490 child
= getChild("en");
1494 child
= getChild("");
1498 std::vector
< rtl::Reference
< ChildAccess
> > children(getAllChildren());
1499 if (!children
.empty()) {
1500 return children
.front();
1502 return rtl::Reference
< ChildAccess
>();
1504 ModifiedChildren::iterator
i(modifiedChildren_
.find(name
));
1505 return i
== modifiedChildren_
.end()
1506 ? getUnmodifiedChild(name
) : getModifiedChild(i
);
1509 std::vector
< rtl::Reference
< ChildAccess
> > Access::getAllChildren() {
1510 std::vector
< rtl::Reference
< ChildAccess
> > vec
;
1511 NodeMap
const & members
= getNode()->getMembers();
1512 for (NodeMap::const_iterator
i(members
.begin()); i
!= members
.end(); ++i
) {
1513 if (modifiedChildren_
.find(i
->first
) == modifiedChildren_
.end()) {
1514 vec
.push_back(getUnmodifiedChild(i
->first
));
1515 assert(vec
.back().is());
1518 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1519 i
!= modifiedChildren_
.end(); ++i
)
1521 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1523 vec
.push_back(child
);
1529 void Access::checkValue(css::uno::Any
const & value
, Type type
, bool nillable
) {
1534 // fall through (cannot happen)
1539 switch (getDynamicType(value
)) {
1542 // fall through (cannot happen)
1555 ok
= value
.hasValue() ? value
.isExtractableTo(mapType(type
)) : nillable
;
1559 throw css::lang::IllegalArgumentException(
1560 "configmgr inappropriate property value",
1561 static_cast< cppu::OWeakObject
* >(this), -1);
1565 void Access::insertLocalizedValueChild(
1566 OUString
const & name
, css::uno::Any
const & value
,
1567 Modifications
* localModifications
)
1569 assert(localModifications
!= 0);
1570 LocalizedPropertyNode
* locprop
= static_cast< LocalizedPropertyNode
* >(
1572 checkValue(value
, locprop
->getStaticType(), locprop
->isNillable());
1573 rtl::Reference
< ChildAccess
> child(
1575 components_
, getRootAccess(), this, name
,
1576 new LocalizedValueNode(Data::NO_LAYER
, value
)));
1577 markChildAsModified(child
);
1578 localModifications
->add(child
->getRelativePath());
1581 void Access::reportChildChanges(
1582 std::vector
< css::util::ElementChange
> * changes
)
1584 assert(changes
!= 0);
1585 for (ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1586 i
!= modifiedChildren_
.end(); ++i
)
1588 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1590 child
->reportChildChanges(changes
);
1591 changes
->push_back(css::util::ElementChange());
1592 //TODO: changed value and/or inserted node
1594 changes
->push_back(css::util::ElementChange()); //TODO: removed node
1599 void Access::commitChildChanges(
1600 bool valid
, Modifications
* globalModifications
)
1602 assert(globalModifications
!= 0);
1603 while (!modifiedChildren_
.empty()) {
1604 bool childValid
= valid
;
1605 ModifiedChildren::iterator
i(modifiedChildren_
.begin());
1606 rtl::Reference
< ChildAccess
> child(getModifiedChild(i
));
1608 childValid
= childValid
&& !child
->isFinalized();
1609 child
->commitChanges(childValid
, globalModifications
);
1610 //TODO: currently, this is called here for directly inserted
1611 // children as well as for children whose sub-children were
1612 // modified (and should never be called for directly removed
1613 // children); clarify what exactly should happen here for
1614 // directly inserted children
1616 NodeMap
& members
= getNode()->getMembers();
1617 NodeMap::iterator
j(members
.find(i
->first
));
1620 if (j
!= members
.end()) {
1621 childValid
= childValid
&&
1622 j
->second
->getFinalized() == Data::NO_LAYER
;
1624 child
->getNode()->setMandatory(j
->second
->getMandatory());
1628 members
[i
->first
] = child
->getNode();
1632 childValid
= childValid
&& j
!= members
.end() &&
1633 j
->second
->getFinalized() == Data::NO_LAYER
&&
1634 j
->second
->getMandatory() == Data::NO_LAYER
;
1639 if (childValid
&& i
->second
.directlyModified
) {
1640 Path
path(getAbsolutePath());
1641 path
.push_back(i
->first
);
1642 components_
.addModification(path
);
1643 globalModifications
->add(path
);
1645 i
->second
.child
->committed();
1646 modifiedChildren_
.erase(i
);
1650 void Access::initBroadcasterAndChanges(
1651 Modifications::Node
const & modifications
, Broadcaster
* broadcaster
,
1652 std::vector
< css::util::ElementChange
> * allChanges
)
1654 assert(broadcaster
!= 0);
1655 std::vector
< css::beans::PropertyChangeEvent
> propChanges
;
1656 bool collectPropChanges
= !propertiesChangeListeners_
.empty();
1657 for (Modifications::Node::Children::const_iterator
i(
1658 modifications
.children
.begin());
1659 i
!= modifications
.children
.end(); ++i
)
1661 rtl::Reference
< ChildAccess
> child(getChild(i
->first
));
1663 switch (child
->getNode()->kind()) {
1664 case Node::KIND_LOCALIZED_PROPERTY
:
1665 if (!i
->second
.children
.empty()) {
1666 if (Components::allLocales(getRootAccess()->getLocale())) {
1667 child
->initBroadcasterAndChanges(
1668 i
->second
, broadcaster
, allChanges
);
1669 //TODO: if allChanges==0, recurse only into children
1672 //TODO: filter child mods that are irrelevant for
1674 for (ContainerListeners::iterator
j(
1675 containerListeners_
.begin());
1676 j
!= containerListeners_
.end(); ++j
)
1679 addContainerElementReplacedNotification(
1681 css::container::ContainerEvent(
1682 static_cast< cppu::OWeakObject
* >(
1684 css::uno::makeAny(i
->first
),
1685 css::uno::Any(), css::uno::Any()));
1686 //TODO: non-void Element, ReplacedElement
1688 PropertyChangeListeners::iterator
j(
1689 propertyChangeListeners_
.find(i
->first
));
1690 if (j
!= propertyChangeListeners_
.end()) {
1691 for (PropertyChangeListenersElement::iterator
k(
1693 k
!= j
->second
.end(); ++k
)
1695 broadcaster
->addPropertyChangeNotification(
1697 css::beans::PropertyChangeEvent(
1698 static_cast< cppu::OWeakObject
* >(
1700 i
->first
, false, -1, css::uno::Any(),
1704 j
= propertyChangeListeners_
.find("");
1705 if (j
!= propertyChangeListeners_
.end()) {
1706 for (PropertyChangeListenersElement::iterator
k(
1708 k
!= j
->second
.end(); ++k
)
1710 broadcaster
->addPropertyChangeNotification(
1712 css::beans::PropertyChangeEvent(
1713 static_cast< cppu::OWeakObject
* >(
1715 i
->first
, false, -1, css::uno::Any(),
1719 if (allChanges
!= 0) {
1720 allChanges
->push_back(
1721 css::util::ElementChange(
1723 child
->getRelativePathRepresentation()),
1724 css::uno::Any(), css::uno::Any()));
1725 //TODO: non-void Element, ReplacedElement
1727 if (collectPropChanges
) {
1728 propChanges
.push_back(
1729 css::beans::PropertyChangeEvent(
1730 static_cast< cppu::OWeakObject
* >(this),
1731 i
->first
, false, -1, css::uno::Any(),
1736 // else: spurious Modifications::Node not representing a change
1738 case Node::KIND_LOCALIZED_VALUE
:
1739 assert(Components::allLocales(getRootAccess()->getLocale()));
1740 for (ContainerListeners::iterator
j(
1741 containerListeners_
.begin());
1742 j
!= containerListeners_
.end(); ++j
)
1744 broadcaster
->addContainerElementReplacedNotification(
1746 css::container::ContainerEvent(
1747 static_cast< cppu::OWeakObject
* >(this),
1748 css::uno::makeAny(i
->first
), child
->asValue(),
1750 //TODO: distinguish add/modify; non-void ReplacedElement
1752 if (allChanges
!= 0) {
1753 allChanges
->push_back(
1754 css::util::ElementChange(
1756 child
->getRelativePathRepresentation()),
1757 child
->asValue(), css::uno::Any()));
1758 //TODO: non-void ReplacedElement
1760 assert(!collectPropChanges
);
1762 case Node::KIND_PROPERTY
:
1764 for (ContainerListeners::iterator
j(
1765 containerListeners_
.begin());
1766 j
!= containerListeners_
.end(); ++j
)
1768 broadcaster
->addContainerElementReplacedNotification(
1770 css::container::ContainerEvent(
1771 static_cast< cppu::OWeakObject
* >(this),
1772 css::uno::makeAny(i
->first
), child
->asValue(),
1774 //TODO: distinguish add/remove/modify; non-void
1777 PropertyChangeListeners::iterator
j(
1778 propertyChangeListeners_
.find(i
->first
));
1779 if (j
!= propertyChangeListeners_
.end()) {
1780 for (PropertyChangeListenersElement::iterator
k(
1782 k
!= j
->second
.end(); ++k
)
1784 broadcaster
->addPropertyChangeNotification(
1786 css::beans::PropertyChangeEvent(
1787 static_cast< cppu::OWeakObject
* >(this),
1788 i
->first
, false, -1, css::uno::Any(),
1792 j
= propertyChangeListeners_
.find("");
1793 if (j
!= propertyChangeListeners_
.end()) {
1794 for (PropertyChangeListenersElement::iterator
k(
1796 k
!= j
->second
.end(); ++k
)
1798 broadcaster
->addPropertyChangeNotification(
1800 css::beans::PropertyChangeEvent(
1801 static_cast< cppu::OWeakObject
* >(this),
1802 i
->first
, false, -1, css::uno::Any(),
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 if (collectPropChanges
) {
1815 propChanges
.push_back(
1816 css::beans::PropertyChangeEvent(
1817 static_cast< cppu::OWeakObject
* >(this),
1818 i
->first
, false, -1, css::uno::Any(),
1823 case Node::KIND_GROUP
:
1824 case Node::KIND_SET
:
1825 if (i
->second
.children
.empty()) {
1826 if (!child
->getNode()->getTemplateName().isEmpty()) {
1827 for (ContainerListeners::iterator
j(
1828 containerListeners_
.begin());
1829 j
!= containerListeners_
.end(); ++j
)
1832 addContainerElementInsertedNotification(
1834 css::container::ContainerEvent(
1835 static_cast< cppu::OWeakObject
* >(
1837 css::uno::makeAny(i
->first
),
1838 child
->asValue(), css::uno::Any()));
1840 if (allChanges
!= 0) {
1841 allChanges
->push_back(
1842 css::util::ElementChange(
1844 child
->getRelativePathRepresentation()),
1845 css::uno::Any(), css::uno::Any()));
1846 //TODO: non-void Element, ReplacedElement
1849 // else: spurious Modifications::Node not representing a
1852 child
->initBroadcasterAndChanges(
1853 i
->second
, broadcaster
, allChanges
);
1854 //TODO: if allChanges==0, recurse only into children w/
1858 case Node::KIND_ROOT
:
1859 assert(false); // this cannot happen
1863 switch (getNode()->kind()) {
1864 case Node::KIND_LOCALIZED_PROPERTY
:
1865 // Removed localized property value:
1866 assert(Components::allLocales(getRootAccess()->getLocale()));
1867 for (ContainerListeners::iterator
j(
1868 containerListeners_
.begin());
1869 j
!= containerListeners_
.end(); ++j
)
1871 broadcaster
->addContainerElementRemovedNotification(
1873 css::container::ContainerEvent(
1874 static_cast< cppu::OWeakObject
* >(this),
1875 css::uno::makeAny(i
->first
), css::uno::Any(),
1877 //TODO: non-void ReplacedElement
1879 if (allChanges
!= 0) {
1880 OUStringBuffer
path(getRelativePathRepresentation());
1881 if (!path
.isEmpty()) {
1884 path
.append(Data::createSegment("*", i
->first
));
1885 allChanges
->push_back(
1886 css::util::ElementChange(
1887 css::uno::makeAny(path
.makeStringAndClear()),
1888 css::uno::Any(), css::uno::Any()));
1889 //TODO: non-void ReplacedElement
1891 assert(!collectPropChanges
);
1893 case Node::KIND_GROUP
:
1895 // Removed (non-localized) extension property:
1896 for (ContainerListeners::iterator
j(
1897 containerListeners_
.begin());
1898 j
!= containerListeners_
.end(); ++j
)
1900 broadcaster
->addContainerElementRemovedNotification(
1902 css::container::ContainerEvent(
1903 static_cast< cppu::OWeakObject
* >(this),
1904 css::uno::makeAny(i
->first
), css::uno::Any(),
1906 //TODO: non-void ReplacedElement
1908 PropertyChangeListeners::iterator
j(
1909 propertyChangeListeners_
.find(i
->first
));
1910 if (j
!= propertyChangeListeners_
.end()) {
1911 for (PropertyChangeListenersElement::iterator
k(
1913 k
!= j
->second
.end(); ++k
)
1915 broadcaster
->addPropertyChangeNotification(
1917 css::beans::PropertyChangeEvent(
1918 static_cast< cppu::OWeakObject
* >(this),
1919 i
->first
, false, -1, css::uno::Any(),
1923 j
= propertyChangeListeners_
.find("");
1924 if (j
!= propertyChangeListeners_
.end()) {
1925 for (PropertyChangeListenersElement::iterator
k(
1927 k
!= j
->second
.end(); ++k
)
1929 broadcaster
->addPropertyChangeNotification(
1931 css::beans::PropertyChangeEvent(
1932 static_cast< cppu::OWeakObject
* >(this),
1933 i
->first
, false, -1, css::uno::Any(),
1937 if (allChanges
!= 0) {
1938 OUStringBuffer
path(
1939 getRelativePathRepresentation());
1940 if (!path
.isEmpty()) {
1943 path
.append(i
->first
);
1944 allChanges
->push_back(
1945 css::util::ElementChange(
1946 css::uno::makeAny(path
.makeStringAndClear()),
1947 css::uno::Any(), css::uno::Any()));
1948 //TODO: non-void ReplacedElement
1950 if (collectPropChanges
) {
1951 propChanges
.push_back(
1952 css::beans::PropertyChangeEvent(
1953 static_cast< cppu::OWeakObject
* >(this),
1954 i
->first
, false, -1, css::uno::Any(),
1959 case Node::KIND_SET
:
1960 // Removed set member:
1961 if (i
->second
.children
.empty()) {
1962 for (ContainerListeners::iterator
j(
1963 containerListeners_
.begin());
1964 j
!= containerListeners_
.end(); ++j
)
1966 broadcaster
->addContainerElementRemovedNotification(
1968 css::container::ContainerEvent(
1969 static_cast< cppu::OWeakObject
* >(this),
1970 css::uno::makeAny(i
->first
),
1971 css::uno::Any(), css::uno::Any()));
1972 //TODO: non-void ReplacedElement
1974 if (allChanges
!= 0) {
1975 OUStringBuffer
path(
1976 getRelativePathRepresentation());
1977 if (!path
.isEmpty()) {
1980 path
.append(Data::createSegment("*", i
->first
));
1981 allChanges
->push_back(
1982 css::util::ElementChange(
1983 css::uno::makeAny(path
.makeStringAndClear()),
1984 css::uno::Any(), css::uno::Any()));
1985 //TODO: non-void ReplacedElement
1988 // else: spurious Modifications::Node not representing a change
1991 assert(false); // this cannot happen
1996 if (!propChanges
.empty()) {
1997 css::uno::Sequence
< css::beans::PropertyChangeEvent
> seq(
1998 comphelper::containerToSequence(propChanges
));
1999 for (PropertiesChangeListeners::iterator
i(
2000 propertiesChangeListeners_
.begin());
2001 i
!= propertiesChangeListeners_
.end(); ++i
)
2003 broadcaster
->addPropertiesChangeNotification(*i
, seq
);
2009 Access::ModifiedChild::ModifiedChild():
2010 directlyModified(false)
2013 Access::ModifiedChild::ModifiedChild(
2014 rtl::Reference
< ChildAccess
> const & theChild
, bool theDirectlyModified
):
2015 child(theChild
), directlyModified(theDirectlyModified
)
2018 rtl::Reference
< ChildAccess
> Access::getModifiedChild(
2019 ModifiedChildren::iterator
const & childIterator
)
2021 return (childIterator
->second
.child
->getParentAccess() == this &&
2022 (childIterator
->second
.child
->getNameInternal() ==
2023 childIterator
->first
))
2024 ? childIterator
->second
.child
: rtl::Reference
< ChildAccess
>();
2027 rtl::Reference
< ChildAccess
> Access::createUnmodifiedChild(
2028 const OUString
&name
, const rtl::Reference
< Node
> &node
)
2030 rtl::Reference
< ChildAccess
> child(
2031 new ChildAccess(components_
, getRootAccess(), this, name
, node
));
2032 cachedChildren_
[name
] = child
.get();
2036 rtl::Reference
< ChildAccess
> Access::getUnmodifiedChild(
2037 OUString
const & name
)
2039 assert(modifiedChildren_
.find(name
) == modifiedChildren_
.end());
2040 rtl::Reference
< Node
> node(getNode()->getMember(name
));
2042 return rtl::Reference
< ChildAccess
>();
2044 WeakChildMap::iterator
i(cachedChildren_
.find(name
));
2045 if (i
!= cachedChildren_
.end()) {
2046 rtl::Reference
< ChildAccess
> child
;
2047 if (i
->second
->acquireCounting() > 1) {
2048 child
.set(i
->second
); // must not throw
2050 i
->second
->releaseNondeleting();
2052 child
->setNode(node
);
2056 return createUnmodifiedChild(name
,node
);
2059 rtl::Reference
< ChildAccess
> Access::getSubChild(OUString
const & path
) {
2061 // For backwards compatibility, allow absolute paths where meaningful:
2062 if( path
.startsWith("/") ) {
2064 if (!getRootAccess().is()) {
2065 return rtl::Reference
< ChildAccess
>();
2067 Path
abs(getAbsolutePath());
2068 for (Path::iterator
j(abs
.begin()); j
!= abs
.end(); ++j
) {
2071 OUString templateName1
;
2072 i
= Data::parseSegment(
2073 path
, i
, &name1
, &setElement1
, &templateName1
);
2074 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2075 return rtl::Reference
< ChildAccess
>();
2079 OUString templateName2
;
2080 Data::parseSegment(*j
, 0, &name2
, &setElement2
, &templateName2
);
2081 if (name1
!= name2
|| setElement1
!= setElement2
||
2083 !Data::equalTemplateNames(templateName1
, templateName2
)))
2085 return rtl::Reference
< ChildAccess
>();
2087 if (i
!= path
.getLength()) {
2092 for (rtl::Reference
< Access
> parent(this);;) {
2095 OUString templateName
;
2096 i
= Data::parseSegment(path
, i
, &name
, &setElement
, &templateName
);
2097 if (i
== -1 || (i
!= path
.getLength() && path
[i
] != '/')) {
2098 return rtl::Reference
< ChildAccess
>();
2100 rtl::Reference
< ChildAccess
> child(parent
->getChild(name
));
2102 return rtl::Reference
< ChildAccess
>();
2105 rtl::Reference
< Node
> p(parent
->getNode());
2106 switch (p
->kind()) {
2107 case Node::KIND_LOCALIZED_PROPERTY
:
2108 if (!Components::allLocales(getRootAccess()->getLocale()) ||
2109 !templateName
.isEmpty())
2111 return rtl::Reference
< ChildAccess
>();
2114 case Node::KIND_SET
:
2115 if (!templateName
.isEmpty() &&
2116 !static_cast< SetNode
* >(p
.get())->isValidTemplate(
2119 return rtl::Reference
< ChildAccess
>();
2123 return rtl::Reference
< ChildAccess
>();
2126 // For backwards compatibility, ignore a final slash after non-value
2128 if (child
->isValue()) {
2129 return i
== path
.getLength()
2130 ? child
: rtl::Reference
< ChildAccess
>();
2131 } else if (i
>= path
.getLength() - 1) {
2135 parent
= child
.get();
2139 bool Access::setChildProperty(
2140 OUString
const & name
, css::uno::Any
const & value
,
2141 Modifications
* localModifications
)
2143 assert(localModifications
!= 0);
2144 rtl::Reference
< ChildAccess
> child(getChild(name
));
2148 child
->checkFinalized();
2149 child
->setProperty(value
, localModifications
);
2153 css::beans::Property
Access::asProperty() {
2154 css::uno::Type type
;
2157 rtl::Reference
< Node
> p(getNode());
2158 switch (p
->kind()) {
2159 case Node::KIND_PROPERTY
:
2161 PropertyNode
* prop
= static_cast< PropertyNode
* >(p
.get());
2162 type
= mapType(prop
->getStaticType());
2163 nillable
= prop
->isNillable();
2164 removable
= prop
->isExtension();
2167 case Node::KIND_LOCALIZED_PROPERTY
:
2169 LocalizedPropertyNode
* locprop
=
2170 static_cast< LocalizedPropertyNode
*>(p
.get());
2171 if (Components::allLocales(getRootAccess()->getLocale())) {
2172 type
= cppu::UnoType
< css::uno::XInterface
>::get();
2176 type
= mapType(locprop
->getStaticType());
2177 removable
= false; //TODO ???
2179 nillable
= locprop
->isNillable();
2182 case Node::KIND_LOCALIZED_VALUE
:
2184 LocalizedPropertyNode
* locprop
=
2185 static_cast< LocalizedPropertyNode
* >(getParentNode().get());
2186 type
= mapType(locprop
->getStaticType());
2187 nillable
= locprop
->isNillable();
2188 removable
= false; //TODO ???
2192 type
= cppu::UnoType
< css::uno::XInterface
>::get(); //TODO: correct?
2194 rtl::Reference
< Node
> parent(getParentNode());
2195 removable
= parent
.is() && parent
->kind() == Node::KIND_SET
;
2198 return css::beans::Property(
2199 getNameInternal(), -1, type
,
2200 (css::beans::PropertyAttribute::BOUND
| //TODO: correct for group/set?
2201 css::beans::PropertyAttribute::CONSTRAINED
|
2202 (nillable
? css::beans::PropertyAttribute::MAYBEVOID
: 0) |
2203 (getRootAccess()->isUpdate() && removable
2204 ? css::beans::PropertyAttribute::REMOVABLE
: 0) |
2205 (!getRootAccess()->isUpdate() || p
->getFinalized() != Data::NO_LAYER
2206 ? css::beans::PropertyAttribute::READONLY
: 0))); //TODO: MAYBEDEFAULT
2209 void Access::checkFinalized() {
2210 if (isFinalized()) {
2211 throw css::lang::IllegalArgumentException(
2212 "configmgr modification of finalized item",
2213 static_cast< cppu::OWeakObject
* >(this), -1);
2217 void Access::checkKnownProperty(OUString
const & descriptor
) {
2218 if (descriptor
.isEmpty()) {
2221 rtl::Reference
< ChildAccess
> child(getChild(descriptor
));
2223 switch (child
->getNode()->kind()) {
2224 case Node::KIND_PROPERTY
:
2226 case Node::KIND_LOCALIZED_PROPERTY
:
2227 if (!Components::allLocales(getRootAccess()->getLocale())) {
2231 case Node::KIND_LOCALIZED_VALUE
:
2232 if (Components::allLocales(getRootAccess()->getLocale())) {
2240 throw css::beans::UnknownPropertyException(
2241 descriptor
, static_cast< cppu::OWeakObject
* >(this));
2244 rtl::Reference
< ChildAccess
> Access::getFreeSetMember(
2245 css::uno::Any
const & value
)
2247 rtl::Reference
< ChildAccess
> freeAcc
;
2248 css::uno::Reference
< css::lang::XUnoTunnel
> tunnel
;
2252 reinterpret_cast< ChildAccess
* >(
2253 tunnel
->getSomething(ChildAccess::getTunnelId())));
2255 if (!freeAcc
.is() || freeAcc
->getParentAccess().is() ||
2256 (freeAcc
->isInTransaction() &&
2257 freeAcc
->getRootAccess() != getRootAccess()))
2259 throw css::lang::IllegalArgumentException(
2260 "configmgr inappropriate set element",
2261 static_cast< cppu::OWeakObject
* >(this), 1);
2263 assert(dynamic_cast< SetNode
* >(getNode().get()) != 0);
2264 if (!static_cast< SetNode
* >(getNode().get())->isValidTemplate(
2265 freeAcc
->getNode()->getTemplateName()))
2267 throw css::lang::IllegalArgumentException(
2268 "configmgr inappropriate set element",
2269 static_cast< cppu::OWeakObject
* >(this), 1);
2274 rtl::Reference
< Access
> Access::getNotificationRoot() {
2275 for (rtl::Reference
< Access
> p(this);;) {
2276 rtl::Reference
< Access
> parent(p
->getParentAccess());
2285 bool Access::thisIs(int what
) {
2286 osl::MutexGuard
g(*lock_
);
2287 rtl::Reference
< Node
> p(getNode());
2288 Node::Kind
k(p
->kind());
2289 return (k
!= Node::KIND_PROPERTY
&& k
!= Node::KIND_LOCALIZED_VALUE
&&
2290 ((what
& IS_GROUP
) == 0 || k
== Node::KIND_GROUP
) &&
2291 ((what
& IS_SET
) == 0 || k
== Node::KIND_SET
) &&
2292 ((what
& IS_EXTENSIBLE
) == 0 || k
!= Node::KIND_GROUP
||
2293 static_cast< GroupNode
* >(p
.get())->isExtensible()) &&
2294 ((what
& IS_GROUP_MEMBER
) == 0 ||
2295 getParentNode()->kind() == Node::KIND_GROUP
)) ||
2296 ((what
& IS_SET_MEMBER
) == 0 ||
2297 getParentNode()->kind() == Node::KIND_SET
) ||
2298 ((what
& IS_UPDATE
) == 0 || getRootAccess()->isUpdate());
2304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */