LCOV - code coverage report
Current view: top level - libreoffice/configmgr/source - access.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 465 1088 42.7 %
Date: 2012-12-27 Functions: 47 85 55.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "sal/config.h"
      21             : 
      22             : #include <cassert>
      23             : #include <vector>
      24             : 
      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"
      83             : 
      84             : #include "access.hxx"
      85             : #include "broadcaster.hxx"
      86             : #include "childaccess.hxx"
      87             : #include "components.hxx"
      88             : #include "data.hxx"
      89             : #include "groupnode.hxx"
      90             : #include "localizedpropertynode.hxx"
      91             : #include "localizedvaluenode.hxx"
      92             : #include "lock.hxx"
      93             : #include "modifications.hxx"
      94             : #include "node.hxx"
      95             : #include "nodemap.hxx"
      96             : #include "path.hxx"
      97             : #include "propertynode.hxx"
      98             : #include "rootaccess.hxx"
      99             : #include "setnode.hxx"
     100             : #include "type.hxx"
     101             : 
     102             : namespace configmgr {
     103             : 
     104      110522 : oslInterlockedCount Access::acquireCounting() {
     105      110522 :     return osl_atomic_increment(&m_refCount);
     106             : }
     107             : 
     108      110522 : void Access::releaseNondeleting() {
     109      110522 :     osl_atomic_decrement(&m_refCount);
     110      110522 : }
     111             : 
     112       84302 : bool Access::isValue() {
     113       84302 :     rtl::Reference< Node > p(getNode());
     114       84302 :     switch (p->kind()) {
     115             :     case Node::KIND_PROPERTY:
     116             :     case Node::KIND_LOCALIZED_VALUE:
     117       25908 :         return true;
     118             :     case Node::KIND_LOCALIZED_PROPERTY:
     119         426 :         return !Components::allLocales(getRootAccess()->getLocale());
     120             :     default:
     121       57968 :         return false;
     122       84302 :     }
     123             : }
     124             : 
     125        5110 : void Access::markChildAsModified(rtl::Reference< ChildAccess > const & child) {
     126             :     assert(child.is() && child->getParentAccess() == this);
     127        5110 :     modifiedChildren_[child->getNameInternal()] = ModifiedChild(child, true);
     128       19563 :     for (rtl::Reference< Access > p(this);;) {
     129       19563 :         rtl::Reference< Access > parent(p->getParentAccess());
     130       19563 :         if (!parent.is()) {
     131             :             break;
     132             :         }
     133             :         assert(dynamic_cast< ChildAccess * >(p.get()) != 0);
     134       14453 :         parent->modifiedChildren_.insert(
     135             :             ModifiedChildren::value_type(
     136       14453 :                 p->getNameInternal(),
     137       43359 :                 ModifiedChild(dynamic_cast< ChildAccess * >(p.get()), false)));
     138       14453 :         p = parent;
     139       24673 :     }
     140        5110 : }
     141             : 
     142      379154 : void Access::releaseChild(OUString const & name) {
     143      379154 :     cachedChildren_.erase(name);
     144      379154 : }
     145             : 
     146           0 : void Access::initBroadcaster(
     147             :     Modifications::Node const & modifications, Broadcaster * broadcaster)
     148             : {
     149           0 :     initBroadcasterAndChanges(modifications, broadcaster, 0);
     150           0 : }
     151             : 
     152           0 : css::uno::Sequence< css::uno::Type > Access::getTypes()
     153             :     throw (css::uno::RuntimeException)
     154             : {
     155             :     assert(thisIs(IS_ANY));
     156           0 :     osl::MutexGuard g(*lock_);
     157           0 :     checkLocalizedPropertyAccess();
     158           0 :     comphelper::SequenceAsVector< css::uno::Type > types;
     159           0 :     types.push_back(cppu::UnoType< css::uno::XInterface >::get());
     160           0 :     types.push_back(cppu::UnoType< css::uno::XWeak >::get());
     161           0 :     types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get());
     162           0 :     types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get());
     163           0 :     types.push_back(cppu::UnoType< css::lang::XComponent >::get());
     164           0 :     types.push_back(cppu::UnoType< css::container::XContainer >::get());
     165           0 :     types.push_back(cppu::UnoType< css::beans::XExactName >::get());
     166           0 :     types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get());
     167           0 :     types.push_back(cppu::UnoType< css::container::XNamed >::get());
     168           0 :     types.push_back(cppu::UnoType< css::beans::XProperty >::get());
     169           0 :     types.push_back(cppu::UnoType< css::container::XElementAccess >::get());
     170           0 :     types.push_back(cppu::UnoType< css::container::XNameAccess >::get());
     171           0 :     if (getNode()->kind() == Node::KIND_GROUP) {
     172           0 :         types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get());
     173           0 :         types.push_back(cppu::UnoType< css::beans::XPropertySet >::get());
     174           0 :         types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get());
     175             :         types.push_back(
     176           0 :             cppu::UnoType< css::beans::XHierarchicalPropertySet >::get());
     177             :         types.push_back(
     178           0 :             cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get());
     179             :         types.push_back(
     180           0 :             cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get());
     181             :     }
     182           0 :     if (getRootAccess()->isUpdate()) {
     183           0 :         types.push_back(cppu::UnoType< css::container::XNameReplace >::get());
     184             :         types.push_back(
     185           0 :             cppu::UnoType< css::container::XHierarchicalNameReplace >::get());
     186           0 :         if (getNode()->kind() != Node::KIND_GROUP ||
     187           0 :             dynamic_cast< GroupNode * >(getNode().get())->isExtensible())
     188             :         {
     189             :             types.push_back(
     190           0 :                 cppu::UnoType< css::container::XNameContainer >::get());
     191             :         }
     192           0 :         if (getNode()->kind() == Node::KIND_SET) {
     193             :             types.push_back(
     194           0 :                 cppu::UnoType< css::lang::XSingleServiceFactory >::get());
     195             :         }
     196             :     } else {
     197             :         types.push_back(
     198           0 :             cppu::UnoType< css::container::XHierarchicalNameAccess >::get());
     199             :     }
     200           0 :     addTypes(&types);
     201           0 :     return types.getAsConstList();
     202             : }
     203             : 
     204           0 : css::uno::Sequence< sal_Int8 > Access::getImplementationId()
     205             :     throw (css::uno::RuntimeException)
     206             : {
     207             :     assert(thisIs(IS_ANY));
     208           0 :     osl::MutexGuard g(*lock_);
     209           0 :     checkLocalizedPropertyAccess();
     210           0 :     return css::uno::Sequence< sal_Int8 >();
     211             : }
     212             : 
     213           0 : OUString Access::getImplementationName() throw (css::uno::RuntimeException)
     214             : {
     215             :     assert(thisIs(IS_ANY));
     216           0 :     osl::MutexGuard g(*lock_);
     217           0 :     checkLocalizedPropertyAccess();
     218           0 :     return OUString("org.openoffice-configmgr::Access");
     219             : }
     220             : 
     221         111 : sal_Bool Access::supportsService(OUString const & ServiceName)
     222             :     throw (css::uno::RuntimeException)
     223             : {
     224             :     assert(thisIs(IS_ANY));
     225         111 :     osl::MutexGuard g(*lock_);
     226         111 :     checkLocalizedPropertyAccess();
     227         111 :     css::uno::Sequence< OUString > names(getSupportedServiceNames());
     228         725 :     for (sal_Int32 i = 0; i < names.getLength(); ++i) {
     229         691 :         if (names[i] == ServiceName) {
     230          77 :             return true;
     231             :         }
     232             :     }
     233          34 :     return false;
     234             : }
     235             : 
     236         111 : css::uno::Sequence< OUString > Access::getSupportedServiceNames()
     237             :     throw (css::uno::RuntimeException)
     238             : {
     239             :     assert(thisIs(IS_ANY));
     240         111 :     osl::MutexGuard g(*lock_);
     241         111 :     checkLocalizedPropertyAccess();
     242         111 :     comphelper::SequenceAsVector< OUString > services;
     243             :     services.push_back(
     244         111 :         OUString("com.sun.star.configuration.ConfigurationAccess"));
     245         111 :     if (getRootAccess()->isUpdate()) {
     246             :         services.push_back(
     247         111 :             OUString("com.sun.star.configuration.ConfigurationUpdateAccess"));
     248             :     }
     249             :     services.push_back(
     250         111 :         OUString("com.sun.star.configuration.HierarchyAccess"));
     251             :     services.push_back(
     252         111 :         OUString("com.sun.star.configuration.HierarchyElement"));
     253         111 :     if (getNode()->kind() == Node::KIND_GROUP) {
     254             :         services.push_back(
     255          34 :             OUString("com.sun.star.configuration.GroupAccess"));
     256             :         services.push_back(
     257          34 :             OUString("com.sun.star.configuration.PropertyHierarchy"));
     258          34 :         if (getRootAccess()->isUpdate()) {
     259             :             services.push_back(
     260          34 :                 OUString("com.sun.star.configuration.GroupUpdate"));
     261             :         }
     262             :     } else {
     263             :         services.push_back(
     264          77 :             OUString("com.sun.star.configuration.SetAccess"));
     265             :         services.push_back(
     266          77 :             OUString("com.sun.star.configuration.SimpleSetAccess"));
     267          77 :         if (getRootAccess()->isUpdate()) {
     268             :             services.push_back(
     269          77 :                 OUString("com.sun.star.configuration.SetUpdate"));
     270             :             services.push_back(
     271          77 :                 OUString("com.sun.star.configuration.SimpleSetUpdate"));
     272             :         }
     273             :     }
     274         111 :     addSupportedServiceNames(&services);
     275         111 :     return services.getAsConstList();
     276             : }
     277             : 
     278           0 : void Access::dispose() throw (css::uno::RuntimeException) {
     279             :     assert(thisIs(IS_ANY));
     280           0 :     Broadcaster bc;
     281             :     {
     282           0 :         osl::MutexGuard g(*lock_);
     283           0 :         checkLocalizedPropertyAccess();
     284           0 :         if (getParentAccess().is()) {
     285             :             throw css::uno::RuntimeException(
     286             :                 OUString("configmgr dispose inappropriate Access"),
     287           0 :                 static_cast< cppu::OWeakObject * >(this));
     288             :         }
     289           0 :         if (disposed_) {
     290           0 :             return;
     291             :         }
     292           0 :         initDisposeBroadcaster(&bc);
     293           0 :         clearListeners();
     294           0 :         disposed_ = true;
     295             :     }
     296           0 :     bc.send();
     297             : }
     298             : 
     299          68 : void Access::addEventListener(
     300             :     css::uno::Reference< css::lang::XEventListener > const & xListener)
     301             :     throw (css::uno::RuntimeException)
     302             : {
     303             :     assert(thisIs(IS_ANY));
     304             :     {
     305          68 :         osl::MutexGuard g(*lock_);
     306          68 :         checkLocalizedPropertyAccess();
     307          68 :         if (!xListener.is()) {
     308             :             throw css::uno::RuntimeException(
     309             :                 OUString("null listener"),
     310           0 :                 static_cast< cppu::OWeakObject * >(this));
     311             :         }
     312          68 :         if (!disposed_) {
     313          68 :             disposeListeners_.insert(xListener);
     314          68 :             return;
     315          68 :         }
     316             :     }
     317             :     try {
     318           0 :         xListener->disposing(
     319           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
     320           0 :     } catch (css::lang::DisposedException &) {}
     321             : }
     322             : 
     323          68 : void Access::removeEventListener(
     324             :     css::uno::Reference< css::lang::XEventListener > const & aListener)
     325             :     throw (css::uno::RuntimeException)
     326             : {
     327             :     assert(thisIs(IS_ANY));
     328          68 :     osl::MutexGuard g(*lock_);
     329          68 :     checkLocalizedPropertyAccess();
     330          68 :     DisposeListeners::iterator i(disposeListeners_.find(aListener));
     331          68 :     if (i != disposeListeners_.end()) {
     332          68 :         disposeListeners_.erase(i);
     333          68 :     }
     334          68 : }
     335             : 
     336           0 : css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) {
     337             :     assert(thisIs(IS_ANY));
     338           0 :     osl::MutexGuard g(*lock_);
     339           0 :     checkLocalizedPropertyAccess();
     340           0 :     rtl::Reference< Node > p(getNode());
     341           0 :     switch (p->kind()) {
     342             :     case Node::KIND_LOCALIZED_PROPERTY:
     343             :         return mapType(
     344           0 :             dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType());
     345             :     case Node::KIND_GROUP:
     346             :         //TODO: Should a specific type be returned for a non-extensible group
     347             :         // with homogeneous members or for an extensible group that currently
     348             :         // has only homegeneous members?
     349           0 :         return cppu::UnoType< cppu::UnoVoidType >::get();
     350             :     case Node::KIND_SET:
     351           0 :         return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct?
     352             :     default:
     353             :         assert(false);
     354             :         throw css::uno::RuntimeException(
     355             :             OUString("this cannot happen"),
     356           0 :             static_cast< cppu::OWeakObject * >(this));
     357           0 :     }
     358             : }
     359             : 
     360           0 : sal_Bool Access::hasElements() throw (css::uno::RuntimeException) {
     361             :     assert(thisIs(IS_ANY));
     362           0 :     osl::MutexGuard g(*lock_);
     363           0 :     checkLocalizedPropertyAccess();
     364           0 :     return !getAllChildren().empty(); //TODO: optimize
     365             : }
     366             : 
     367      173746 : css::uno::Any Access::getByName(OUString const & aName)
     368             :     throw (
     369             :         css::container::NoSuchElementException,
     370             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
     371             : {
     372             :     assert(thisIs(IS_ANY));
     373      173746 :     osl::MutexGuard g(*lock_);
     374      173746 :     checkLocalizedPropertyAccess();
     375      173746 :     rtl::Reference< ChildAccess > child(getChild(aName));
     376      173746 :     if (!child.is()) {
     377             :         throw css::container::NoSuchElementException(
     378          20 :             aName, static_cast< cppu::OWeakObject * >(this));
     379             :     }
     380      173746 :     return child->asValue();
     381             : }
     382             : 
     383        8762 : css::uno::Sequence< OUString > Access::getElementNames()
     384             :     throw (css::uno::RuntimeException)
     385             : {
     386             :     assert(thisIs(IS_ANY));
     387        8762 :     osl::MutexGuard g(*lock_);
     388        8762 :     checkLocalizedPropertyAccess();
     389        8762 :     std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
     390        8762 :     comphelper::SequenceAsVector< OUString > names;
     391      184548 :     for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
     392        8762 :              children.begin());
     393      123032 :          i != children.end(); ++i)
     394             :     {
     395       52754 :         names.push_back((*i)->getNameInternal());
     396             :     }
     397        8762 :     return names.getAsConstList();
     398             : }
     399             : 
     400       70926 : sal_Bool Access::hasByName(OUString const & aName)
     401             :     throw (css::uno::RuntimeException)
     402             : {
     403             :     assert(thisIs(IS_ANY));
     404       70926 :     osl::MutexGuard g(*lock_);
     405       70926 :     checkLocalizedPropertyAccess();
     406       70926 :     return getChild(aName).is();
     407             : }
     408             : 
     409       30566 : css::uno::Any Access::getByHierarchicalName(OUString const & aName)
     410             :     throw (css::container::NoSuchElementException, css::uno::RuntimeException)
     411             : {
     412             :     assert(thisIs(IS_ANY));
     413       30566 :     osl::MutexGuard g(*lock_);
     414       30566 :     checkLocalizedPropertyAccess();
     415       30566 :     rtl::Reference< ChildAccess > child(getSubChild(aName));
     416       30566 :     if (!child.is()) {
     417             :         throw css::container::NoSuchElementException(
     418           4 :             aName, static_cast< cppu::OWeakObject * >(this));
     419             :     }
     420       30566 :     return child->asValue();
     421             : }
     422             : 
     423         124 : sal_Bool Access::hasByHierarchicalName(OUString const & aName)
     424             :     throw (css::uno::RuntimeException)
     425             : {
     426             :     assert(thisIs(IS_ANY));
     427         124 :     osl::MutexGuard g(*lock_);
     428         124 :     checkLocalizedPropertyAccess();
     429         124 :     return getSubChild(aName).is();
     430             : }
     431             : 
     432           0 : void Access::replaceByHierarchicalName(
     433             :     OUString const & aName, css::uno::Any const & aElement)
     434             :     throw (
     435             :         css::lang::IllegalArgumentException,
     436             :         css::container::NoSuchElementException,
     437             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
     438             : {
     439             :     //TODO: Actually support sets and combine with replaceByName:
     440             :     assert(thisIs(IS_UPDATE));
     441           0 :     Broadcaster bc;
     442             :     {
     443           0 :         osl::MutexGuard g(*lock_);
     444           0 :         checkLocalizedPropertyAccess();
     445           0 :         rtl::Reference< ChildAccess > child(getSubChild(aName));
     446           0 :         if (!child.is()) {
     447             :             throw css::container::NoSuchElementException(
     448           0 :                 aName, static_cast< cppu::OWeakObject * >(this));
     449             :         }
     450           0 :         child->checkFinalized();
     451           0 :         rtl::Reference< Node > parent(child->getParentNode());
     452             :         assert(parent.is());
     453           0 :         Modifications localMods;
     454           0 :         switch (parent->kind()) {
     455             :         case Node::KIND_LOCALIZED_PROPERTY:
     456             :         case Node::KIND_GROUP:
     457           0 :             child->setProperty(aElement, &localMods);
     458           0 :             break;
     459             :         case Node::KIND_SET:
     460             :             throw css::lang::IllegalArgumentException(
     461             :                 OUString("configmgr::Access::replaceByHierarchicalName does not"
     462             :                         " currently support set members"),
     463           0 :                 static_cast< cppu::OWeakObject * >(this), 0);
     464             :         case Node::KIND_ROOT:
     465             :             throw css::lang::IllegalArgumentException(
     466             :                 (OUString("configmgr::Access::replaceByHierarchicalName does not"
     467             :                         " allow changing component ")
     468           0 :                  + aName),
     469           0 :                 static_cast< cppu::OWeakObject * >(this), 0);
     470             :         default:
     471             :             assert(false); // this cannot happen
     472           0 :             break;
     473             :         }
     474           0 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
     475             :     }
     476           0 :     bc.send();
     477           0 : }
     478             : 
     479          42 : void Access::addContainerListener(
     480             :     css::uno::Reference< css::container::XContainerListener > const & xListener)
     481             :     throw (css::uno::RuntimeException)
     482             : {
     483             :     assert(thisIs(IS_ANY));
     484             :     {
     485          42 :         osl::MutexGuard g(*lock_);
     486          42 :         checkLocalizedPropertyAccess();
     487          42 :         if (!xListener.is()) {
     488             :             throw css::uno::RuntimeException(
     489             :                 OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")),
     490           0 :                 static_cast< cppu::OWeakObject * >(this));
     491             :         }
     492          42 :         if (!disposed_) {
     493          42 :             containerListeners_.insert(xListener);
     494          42 :             return;
     495          42 :         }
     496             :     }
     497             :     try {
     498           0 :         xListener->disposing(
     499           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
     500           0 :     } catch (css::lang::DisposedException &) {}
     501             : }
     502             : 
     503           5 : void Access::removeContainerListener(
     504             :     css::uno::Reference< css::container::XContainerListener > const & xListener)
     505             :     throw (css::uno::RuntimeException)
     506             : {
     507             :     assert(thisIs(IS_ANY));
     508           5 :     osl::MutexGuard g(*lock_);
     509           5 :     checkLocalizedPropertyAccess();
     510           5 :     ContainerListeners::iterator i(containerListeners_.find(xListener));
     511           5 :     if (i != containerListeners_.end()) {
     512           5 :         containerListeners_.erase(i);
     513           5 :     }
     514           5 : }
     515             : 
     516           0 : OUString Access::getExactName(OUString const & aApproximateName)
     517             :     throw (css::uno::RuntimeException)
     518             : {
     519             :     assert(thisIs(IS_ANY));
     520           0 :     osl::MutexGuard g(*lock_);
     521           0 :     checkLocalizedPropertyAccess();
     522           0 :     return aApproximateName;
     523             : }
     524             : 
     525           0 : css::uno::Sequence< css::beans::Property > Access::getProperties()
     526             :     throw (css::uno::RuntimeException)
     527             : {
     528             :     assert(thisIs(IS_GROUP));
     529           0 :     osl::MutexGuard g(*lock_);
     530           0 :     std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
     531           0 :     comphelper::SequenceAsVector< css::beans::Property > properties;
     532           0 :     for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
     533           0 :              children.begin());
     534           0 :          i != children.end(); ++i)
     535             :     {
     536           0 :         properties.push_back((*i)->asProperty());
     537             :     }
     538           0 :     return properties.getAsConstList();
     539             : }
     540             : 
     541        1437 : css::beans::Property Access::getPropertyByName(OUString const & aName)
     542             :     throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
     543             : {
     544             :     assert(thisIs(IS_GROUP));
     545        1437 :     osl::MutexGuard g(*lock_);
     546        1437 :     rtl::Reference< ChildAccess > child(getChild(aName));
     547        1437 :     if (!child.is()) {
     548             :         throw css::beans::UnknownPropertyException(
     549           0 :             aName, static_cast< cppu::OWeakObject * >(this));
     550             :     }
     551        1437 :     return child->asProperty();
     552             : }
     553             : 
     554           0 : sal_Bool Access::hasPropertyByName(OUString const & Name)
     555             :     throw (css::uno::RuntimeException)
     556             : {
     557             :     assert(thisIs(IS_GROUP));
     558           0 :     osl::MutexGuard g(*lock_);
     559           0 :     return getChild(Name).is();
     560             : }
     561             : 
     562           0 : OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) {
     563             :     assert(thisIs(IS_ANY));
     564           0 :     osl::MutexGuard g(*lock_);
     565           0 :     checkLocalizedPropertyAccess();
     566             :     // For backwards compatibility, return an absolute path representation where
     567             :     // available:
     568           0 :     OUStringBuffer path;
     569           0 :     rtl::Reference< RootAccess > root(getRootAccess());
     570           0 :     if (root.is()) {
     571           0 :         path.append(root->getAbsolutePathRepresentation());
     572             :     }
     573           0 :     OUString rel(getRelativePathRepresentation());
     574           0 :     if (path.getLength() != 0 && !rel.isEmpty()) {
     575           0 :         path.append(sal_Unicode('/'));
     576             :     }
     577           0 :     path.append(rel);
     578           0 :     return path.makeStringAndClear();
     579             : }
     580             : 
     581           0 : OUString Access::composeHierarchicalName(
     582             :     OUString const & aRelativeName)
     583             :     throw (
     584             :         css::lang::IllegalArgumentException, css::lang::NoSupportException,
     585             :         css::uno::RuntimeException)
     586             : {
     587             :     assert(thisIs(IS_ANY));
     588           0 :     osl::MutexGuard g(*lock_);
     589           0 :     checkLocalizedPropertyAccess();
     590           0 :     if (aRelativeName.isEmpty() || aRelativeName[0] == '/') {
     591             :         throw css::lang::IllegalArgumentException(
     592             :             OUString("configmgr composeHierarchicalName inappropriate relative"
     593             :                     " name"),
     594           0 :             static_cast< cppu::OWeakObject * >(this), -1);
     595             :     }
     596           0 :     OUStringBuffer path(getRelativePathRepresentation());
     597           0 :     if (path.getLength() != 0) {
     598           0 :         path.append(sal_Unicode('/'));
     599             :     }
     600           0 :     path.append(aRelativeName);
     601           0 :     return path.makeStringAndClear();
     602             : }
     603             : 
     604           0 : OUString Access::getName() throw (css::uno::RuntimeException) {
     605             :     assert(thisIs(IS_ANY));
     606           0 :     osl::MutexGuard g(*lock_);
     607           0 :     checkLocalizedPropertyAccess();
     608           0 :     return getNameInternal();
     609             : }
     610             : 
     611           0 : void Access::setName(OUString const & aName)
     612             :     throw (css::uno::RuntimeException)
     613             : {
     614             :     assert(thisIs(IS_ANY));
     615           0 :     Broadcaster bc;
     616             :     {
     617           0 :         osl::MutexGuard g(*lock_);
     618           0 :         checkLocalizedPropertyAccess();
     619           0 :         checkFinalized();
     620           0 :         Modifications localMods;
     621           0 :         switch (getNode()->kind()) {
     622             :         case Node::KIND_GROUP:
     623             :         case Node::KIND_SET:
     624             :             {
     625           0 :                 rtl::Reference< Access > parent(getParentAccess());
     626           0 :                 if (parent.is()) {
     627           0 :                     rtl::Reference< Node > node(getNode());
     628           0 :                     if (! node->getTemplateName().isEmpty()) {
     629             :                         rtl::Reference< ChildAccess > other(
     630           0 :                             parent->getChild(aName));
     631           0 :                         if (other.get() == this) {
     632             :                             break;
     633             :                         }
     634           0 :                         if (node->getMandatory() == Data::NO_LAYER &&
     635           0 :                             !(other.is() && other->isFinalized()))
     636             :                         {
     637           0 :                             rtl::Reference< RootAccess > root(getRootAccess());
     638             :                             rtl::Reference< ChildAccess > childAccess(
     639           0 :                                 dynamic_cast< ChildAccess * >(this));
     640           0 :                             localMods.add(getRelativePath());
     641             :                             // unbind() modifies the parent chain that
     642             :                             // markChildAsModified() walks, so order is
     643             :                             // important:
     644           0 :                             parent->markChildAsModified(childAccess);
     645             :                                 //TODO: must not throw
     646           0 :                             childAccess->unbind(); // must not throw
     647           0 :                             if (other.is()) {
     648           0 :                                 other->unbind(); // must not throw
     649             :                             }
     650           0 :                             childAccess->bind(root, parent, aName);
     651             :                                 // must not throw
     652           0 :                             parent->markChildAsModified(childAccess);
     653             :                                 //TODO: must not throw
     654           0 :                             localMods.add(getRelativePath());
     655           0 :                             break;
     656           0 :                         }
     657           0 :                     }
     658           0 :                 }
     659             :             }
     660             :             // fall through
     661             :         case Node::KIND_LOCALIZED_PROPERTY:
     662             :             // renaming a property could only work for an extension property,
     663             :             // but a localized property is never an extension property
     664             :             throw css::uno::RuntimeException(
     665             :                 OUString("configmgr setName inappropriate node"),
     666           0 :                 static_cast< cppu::OWeakObject * >(this));
     667             :         default:
     668             :             assert(false); // this cannot happen
     669           0 :             break;
     670             :         }
     671           0 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
     672             :     }
     673           0 :     bc.send();
     674           0 : }
     675             : 
     676        4656 : css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException)
     677             : {
     678             :     assert(thisIs(IS_ANY));
     679        4656 :     osl::MutexGuard g(*lock_);
     680        4656 :     checkLocalizedPropertyAccess();
     681        4656 :     return asProperty();
     682             : }
     683             : 
     684        1437 : css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo()
     685             :     throw (css::uno::RuntimeException)
     686             : {
     687             :     assert(thisIs(IS_GROUP));
     688        1437 :     return this;
     689             : }
     690             : 
     691        4147 : void Access::setPropertyValue(
     692             :     OUString const & aPropertyName, css::uno::Any const & aValue)
     693             :     throw (
     694             :         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
     695             :         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
     696             :         css::uno::RuntimeException)
     697             : {
     698             :     assert(thisIs(IS_GROUP));
     699        4147 :     Broadcaster bc;
     700             :     {
     701        4147 :         osl::MutexGuard g(*lock_);
     702        4147 :         if (!getRootAccess()->isUpdate()) {
     703             :             throw css::uno::RuntimeException(
     704             :                 OUString("configmgr setPropertyValue on non-update access"),
     705           0 :                 static_cast< cppu::OWeakObject * >(this));
     706             :         }
     707        4147 :         Modifications localMods;
     708        4147 :         if (!setChildProperty(aPropertyName, aValue, &localMods)) {
     709             :             throw css::beans::UnknownPropertyException(
     710           0 :                 aPropertyName, static_cast< cppu::OWeakObject * >(this));
     711             :         }
     712        4147 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
     713             :     }
     714        4147 :     bc.send();
     715        4147 : }
     716             : 
     717       12649 : css::uno::Any Access::getPropertyValue(OUString const & PropertyName)
     718             :     throw (
     719             :         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
     720             :         css::uno::RuntimeException)
     721             : {
     722             :     assert(thisIs(IS_GROUP));
     723       12649 :     osl::MutexGuard g(*lock_);
     724       12649 :     rtl::Reference< ChildAccess > child(getChild(PropertyName));
     725       12649 :     if (!child.is()) {
     726             :         throw css::beans::UnknownPropertyException(
     727           0 :             PropertyName, static_cast< cppu::OWeakObject * >(this));
     728             :     }
     729       12649 :     return child->asValue();
     730             : }
     731             : 
     732           0 : void Access::addPropertyChangeListener(
     733             :     OUString const & aPropertyName,
     734             :     css::uno::Reference< css::beans::XPropertyChangeListener > const &
     735             :         xListener)
     736             :     throw (
     737             :         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
     738             :         css::uno::RuntimeException)
     739             : {
     740             :     assert(thisIs(IS_GROUP));
     741             :     {
     742           0 :         osl::MutexGuard g(*lock_);
     743           0 :         if (!xListener.is()) {
     744             :             throw css::uno::RuntimeException(
     745             :                 OUString("null listener"),
     746           0 :                 static_cast< cppu::OWeakObject * >(this));
     747             :         }
     748           0 :         checkKnownProperty(aPropertyName);
     749           0 :         if (!disposed_) {
     750           0 :             propertyChangeListeners_[aPropertyName].insert(xListener);
     751           0 :             return;
     752           0 :         }
     753             :     }
     754             :     try {
     755           0 :         xListener->disposing(
     756           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
     757           0 :     } catch (css::lang::DisposedException &) {}
     758             : }
     759             : 
     760           0 : void Access::removePropertyChangeListener(
     761             :     OUString const & aPropertyName,
     762             :     css::uno::Reference< css::beans::XPropertyChangeListener > const &
     763             :         aListener)
     764             :     throw (
     765             :         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
     766             :         css::uno::RuntimeException)
     767             : {
     768             :     assert(thisIs(IS_GROUP));
     769           0 :     osl::MutexGuard g(*lock_);
     770           0 :     checkKnownProperty(aPropertyName);
     771             :     PropertyChangeListeners::iterator i(
     772           0 :         propertyChangeListeners_.find(aPropertyName));
     773           0 :     if (i != propertyChangeListeners_.end()) {
     774           0 :         PropertyChangeListenersElement::iterator j(i->second.find(aListener));
     775           0 :         if (j != i->second.end()) {
     776           0 :             i->second.erase(j);
     777           0 :             if (i->second.empty()) {
     778           0 :                 propertyChangeListeners_.erase(i);
     779             :             }
     780             :         }
     781           0 :     }
     782           0 : }
     783             : 
     784           0 : void Access::addVetoableChangeListener(
     785             :     OUString const & PropertyName,
     786             :     css::uno::Reference< css::beans::XVetoableChangeListener > const &
     787             :         aListener)
     788             :     throw (
     789             :         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
     790             :         css::uno::RuntimeException)
     791             : {
     792             :     assert(thisIs(IS_GROUP));
     793             :     {
     794           0 :         osl::MutexGuard g(*lock_);
     795           0 :         if (!aListener.is()) {
     796             :             throw css::uno::RuntimeException(
     797             :                 OUString("null listener"),
     798           0 :                 static_cast< cppu::OWeakObject * >(this));
     799             :         }
     800           0 :         checkKnownProperty(PropertyName);
     801           0 :         if (!disposed_) {
     802           0 :             vetoableChangeListeners_[PropertyName].insert(aListener);
     803             :             //TODO: actually call vetoableChangeListeners_
     804           0 :             return;
     805           0 :         }
     806             :     }
     807             :     try {
     808           0 :         aListener->disposing(
     809           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
     810           0 :     } catch (css::lang::DisposedException &) {}
     811             : }
     812             : 
     813           0 : void Access::removeVetoableChangeListener(
     814             :     OUString const & PropertyName,
     815             :     css::uno::Reference< css::beans::XVetoableChangeListener > const &
     816             :         aListener)
     817             :     throw (
     818             :         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
     819             :         css::uno::RuntimeException)
     820             : {
     821             :     assert(thisIs(IS_GROUP));
     822           0 :     osl::MutexGuard g(*lock_);
     823           0 :     checkKnownProperty(PropertyName);
     824             :     VetoableChangeListeners::iterator i(
     825           0 :         vetoableChangeListeners_.find(PropertyName));
     826           0 :     if (i != vetoableChangeListeners_.end()) {
     827           0 :         VetoableChangeListenersElement::iterator j(i->second.find(aListener));
     828           0 :         if (j != i->second.end()) {
     829           0 :             i->second.erase(j);
     830           0 :             if (i->second.empty()) {
     831           0 :                 vetoableChangeListeners_.erase(i);
     832             :             }
     833             :         }
     834           0 :     }
     835           0 : }
     836             : 
     837           0 : void Access::setPropertyValues(
     838             :     css::uno::Sequence< OUString > const & aPropertyNames,
     839             :     css::uno::Sequence< css::uno::Any > const & aValues)
     840             :     throw (
     841             :         css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
     842             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
     843             : {
     844             :     assert(thisIs(IS_GROUP));
     845           0 :     Broadcaster bc;
     846             :     {
     847           0 :         osl::MutexGuard g(*lock_);
     848           0 :         if (!getRootAccess()->isUpdate()) {
     849             :             throw css::uno::RuntimeException(
     850             :                 OUString("configmgr setPropertyValues on non-update access"),
     851           0 :                 static_cast< cppu::OWeakObject * >(this));
     852             :         }
     853           0 :         if (aPropertyNames.getLength() != aValues.getLength()) {
     854             :             throw css::lang::IllegalArgumentException(
     855             :                 OUString("configmgr setPropertyValues: aPropertyNames/aValues of"
     856             :                         " different length"),
     857           0 :                 static_cast< cppu::OWeakObject * >(this), -1);
     858             :         }
     859           0 :         Modifications localMods;
     860           0 :         for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
     861           0 :             if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) {
     862             :                 throw css::lang::IllegalArgumentException(
     863             :                     OUString("configmgr setPropertyValues inappropriate property"
     864             :                             " name"),
     865           0 :                     static_cast< cppu::OWeakObject * >(this), -1);
     866             :             }
     867             :         }
     868           0 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
     869             :     }
     870           0 :     bc.send();
     871           0 : }
     872             : 
     873           0 : css::uno::Sequence< css::uno::Any > Access::getPropertyValues(
     874             :     css::uno::Sequence< OUString > const & aPropertyNames)
     875             :     throw (css::uno::RuntimeException)
     876             : {
     877             :     assert(thisIs(IS_GROUP));
     878           0 :     osl::MutexGuard g(*lock_);
     879           0 :     css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength());
     880           0 :     for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
     881           0 :         rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i]));
     882           0 :         if (!child.is()) {
     883             :             throw css::uno::RuntimeException(
     884             :                 OUString("configmgr getPropertyValues inappropriate property"
     885             :                         " name"),
     886           0 :                 static_cast< cppu::OWeakObject * >(this));
     887             :         }
     888           0 :         vals[i] = child->asValue();
     889           0 :     }
     890           0 :     return vals;
     891             : }
     892             : 
     893           0 : void Access::addPropertiesChangeListener(
     894             :     css::uno::Sequence< OUString > const &,
     895             :     css::uno::Reference< css::beans::XPropertiesChangeListener > const &
     896             :         xListener)
     897             :     throw (css::uno::RuntimeException)
     898             : {
     899             :     assert(thisIs(IS_GROUP));
     900             :     {
     901           0 :         osl::MutexGuard g(*lock_);
     902           0 :         if (!xListener.is()) {
     903             :             throw css::uno::RuntimeException(
     904             :                 OUString("null listener"),
     905           0 :                 static_cast< cppu::OWeakObject * >(this));
     906             :         }
     907           0 :         if (!disposed_) {
     908           0 :             propertiesChangeListeners_.insert(xListener);
     909           0 :             return;
     910           0 :         }
     911             :     }
     912             :     try {
     913           0 :         xListener->disposing(
     914           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
     915           0 :     } catch (css::lang::DisposedException &) {}
     916             : }
     917             : 
     918           0 : void Access::removePropertiesChangeListener(
     919             :     css::uno::Reference< css::beans::XPropertiesChangeListener > const &
     920             :         xListener)
     921             :     throw (css::uno::RuntimeException)
     922             : {
     923             :     assert(thisIs(IS_GROUP));
     924           0 :     osl::MutexGuard g(*lock_);
     925             :     PropertiesChangeListeners::iterator i(
     926           0 :         propertiesChangeListeners_.find(xListener));
     927           0 :     if (i != propertiesChangeListeners_.end()) {
     928           0 :         propertiesChangeListeners_.erase(i);
     929           0 :     }
     930           0 : }
     931             : 
     932           0 : void Access::firePropertiesChangeEvent(
     933             :     css::uno::Sequence< OUString > const & aPropertyNames,
     934             :     css::uno::Reference< css::beans::XPropertiesChangeListener > const &
     935             :         xListener)
     936             :     throw (css::uno::RuntimeException)
     937             : {
     938             :     assert(thisIs(IS_GROUP));
     939             :     css::uno::Sequence< css::beans::PropertyChangeEvent > events(
     940           0 :         aPropertyNames.getLength());
     941           0 :     for (sal_Int32 i = 0; i < events.getLength(); ++i) {
     942           0 :         events[i].Source = static_cast< cppu::OWeakObject * >(this);
     943           0 :         events[i].PropertyName = aPropertyNames[i];
     944           0 :         events[i].Further = false;
     945           0 :         events[i].PropertyHandle = -1;
     946             :     }
     947           0 :     xListener->propertiesChange(events);
     948           0 : }
     949             : 
     950             : css::uno::Reference< css::beans::XHierarchicalPropertySetInfo >
     951           0 : Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) {
     952             :     assert(thisIs(IS_GROUP));
     953           0 :     return this;
     954             : }
     955             : 
     956           0 : void Access::setHierarchicalPropertyValue(
     957             :     OUString const & aHierarchicalPropertyName,
     958             :     css::uno::Any const & aValue)
     959             :     throw (
     960             :         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
     961             :         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
     962             :         css::uno::RuntimeException)
     963             : {
     964             :     assert(thisIs(IS_GROUP));
     965           0 :     Broadcaster bc;
     966             :     {
     967           0 :         osl::MutexGuard g(*lock_);
     968           0 :         if (!getRootAccess()->isUpdate()) {
     969             :             throw css::uno::RuntimeException(
     970             :                 OUString("configmgr setHierarchicalPropertyName on non-update"
     971             :                         " access"),
     972           0 :                 static_cast< cppu::OWeakObject * >(this));
     973             :         }
     974             :         rtl::Reference< ChildAccess > child(
     975           0 :             getSubChild(aHierarchicalPropertyName));
     976           0 :         if (!child.is()) {
     977             :             throw css::beans::UnknownPropertyException(
     978             :                 aHierarchicalPropertyName,
     979           0 :                 static_cast< cppu::OWeakObject * >(this));
     980             :         }
     981           0 :         child->checkFinalized();
     982           0 :         Modifications localMods;
     983           0 :         child->setProperty(aValue, &localMods);
     984           0 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
     985             :     }
     986           0 :     bc.send();
     987           0 : }
     988             : 
     989           0 : css::uno::Any Access::getHierarchicalPropertyValue(
     990             :     OUString const & aHierarchicalPropertyName)
     991             :     throw (
     992             :         css::beans::UnknownPropertyException,
     993             :         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
     994             :         css::uno::RuntimeException)
     995             : {
     996             :     assert(thisIs(IS_GROUP));
     997           0 :     osl::MutexGuard g(*lock_);
     998           0 :     rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName));
     999           0 :     if (!child.is()) {
    1000             :         throw css::beans::UnknownPropertyException(
    1001             :             aHierarchicalPropertyName,
    1002           0 :             static_cast< cppu::OWeakObject * >(this));
    1003             :     }
    1004           0 :     return child->asValue();
    1005             : }
    1006             : 
    1007           0 : void Access::setHierarchicalPropertyValues(
    1008             :     css::uno::Sequence< OUString > const & aHierarchicalPropertyNames,
    1009             :     css::uno::Sequence< css::uno::Any > const & Values)
    1010             :     throw (
    1011             :         css::beans::PropertyVetoException, css::lang::IllegalArgumentException,
    1012             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
    1013             : {
    1014             :     assert(thisIs(IS_GROUP));
    1015           0 :     Broadcaster bc;
    1016             :     {
    1017           0 :         osl::MutexGuard g(*lock_);
    1018           0 :         if (!getRootAccess()->isUpdate()) {
    1019             :             throw css::uno::RuntimeException(
    1020             :                 OUString("configmgr setPropertyValues on non-update access"),
    1021           0 :                 static_cast< cppu::OWeakObject * >(this));
    1022             :         }
    1023           0 :         if (aHierarchicalPropertyNames.getLength() != Values.getLength()) {
    1024             :             throw css::lang::IllegalArgumentException(
    1025             :                 OUString("configmgr setHierarchicalPropertyValues:"
    1026             :                         " aHierarchicalPropertyNames/Values of different"
    1027             :                         " length"),
    1028           0 :                 static_cast< cppu::OWeakObject * >(this), -1);
    1029             :         }
    1030           0 :         Modifications localMods;
    1031           0 :         for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
    1032             :             rtl::Reference< ChildAccess > child(
    1033           0 :                 getSubChild(aHierarchicalPropertyNames[i]));
    1034           0 :             if (!child.is()) {
    1035             :                 throw css::lang::IllegalArgumentException(
    1036             :                     OUString("configmgr setHierarchicalPropertyValues"
    1037             :                             " inappropriate property name"),
    1038           0 :                     static_cast< cppu::OWeakObject * >(this), -1);
    1039             :             }
    1040           0 :             child->checkFinalized();
    1041           0 :             child->setProperty(Values[i], &localMods);
    1042           0 :         }
    1043           0 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
    1044             :     }
    1045           0 :     bc.send();
    1046           0 : }
    1047             : 
    1048           0 : css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues(
    1049             :     css::uno::Sequence< OUString > const & aHierarchicalPropertyNames)
    1050             :     throw (
    1051             :         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
    1052             :         css::uno::RuntimeException)
    1053             : {
    1054             :     assert(thisIs(IS_GROUP));
    1055           0 :     osl::MutexGuard g(*lock_);
    1056             :     css::uno::Sequence< css::uno::Any > vals(
    1057           0 :         aHierarchicalPropertyNames.getLength());
    1058           0 :     for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
    1059             :         rtl::Reference< ChildAccess > child(
    1060           0 :             getSubChild(aHierarchicalPropertyNames[i]));
    1061           0 :         if (!child.is()) {
    1062             :             throw css::lang::IllegalArgumentException(
    1063             :                 OUString("configmgr getHierarchicalPropertyValues inappropriate"
    1064             :                         " hierarchical property name"),
    1065           0 :                 static_cast< cppu::OWeakObject * >(this), -1);
    1066             :         }
    1067           0 :         vals[i] = child->asValue();
    1068           0 :     }
    1069           0 :     return vals;
    1070             : }
    1071             : 
    1072           0 : css::beans::Property Access::getPropertyByHierarchicalName(
    1073             :     OUString const & aHierarchicalName)
    1074             :     throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
    1075             : {
    1076             :     assert(thisIs(IS_GROUP));
    1077           0 :     osl::MutexGuard g(*lock_);
    1078           0 :     rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName));
    1079           0 :     if (!child.is()) {
    1080             :         throw css::beans::UnknownPropertyException(
    1081           0 :             aHierarchicalName, static_cast< cppu::OWeakObject * >(this));
    1082             :     }
    1083           0 :     return child->asProperty();
    1084             : }
    1085             : 
    1086           0 : sal_Bool Access::hasPropertyByHierarchicalName(
    1087             :     OUString const & aHierarchicalName)
    1088             :     throw (css::uno::RuntimeException)
    1089             : {
    1090             :     assert(thisIs(IS_GROUP));
    1091           0 :     osl::MutexGuard g(*lock_);
    1092           0 :     return getSubChild(aHierarchicalName).is();
    1093             : }
    1094             : 
    1095         511 : void Access::replaceByName(
    1096             :     OUString const & aName, css::uno::Any const & aElement)
    1097             :     throw (
    1098             :         css::lang::IllegalArgumentException,
    1099             :         css::container::NoSuchElementException,
    1100             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
    1101             : {
    1102             :     assert(thisIs(IS_UPDATE));
    1103         511 :     Broadcaster bc;
    1104             :     {
    1105         511 :         osl::MutexGuard g(*lock_);
    1106         511 :         checkLocalizedPropertyAccess();
    1107         511 :         rtl::Reference< ChildAccess > child(getChild(aName));
    1108         511 :         if (!child.is()) {
    1109             :             throw css::container::NoSuchElementException(
    1110           0 :                 aName, static_cast< cppu::OWeakObject * >(this));
    1111             :         }
    1112         511 :         child->checkFinalized();
    1113         511 :         Modifications localMods;
    1114         511 :         switch (getNode()->kind()) {
    1115             :         case Node::KIND_LOCALIZED_PROPERTY:
    1116             :         case Node::KIND_GROUP:
    1117         511 :             child->setProperty(aElement, &localMods);
    1118         511 :             break;
    1119             :         case Node::KIND_SET:
    1120             :             {
    1121             :                 rtl::Reference< ChildAccess > freeAcc(
    1122           0 :                     getFreeSetMember(aElement));
    1123           0 :                 rtl::Reference< RootAccess > root(getRootAccess());
    1124           0 :                 localMods.add(child->getRelativePath());
    1125           0 :                 child->unbind(); // must not throw
    1126           0 :                 freeAcc->bind(root, this, aName); // must not throw
    1127           0 :                 markChildAsModified(freeAcc); //TODO: must not throw
    1128             :             }
    1129           0 :             break;
    1130             :         default:
    1131             :             assert(false); // this cannot happen
    1132           0 :             break;
    1133             :         }
    1134         511 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
    1135             :     }
    1136         511 :     bc.send();
    1137         511 : }
    1138             : 
    1139         417 : void Access::insertByName(
    1140             :     OUString const & aName, css::uno::Any const & aElement)
    1141             :     throw (
    1142             :         css::lang::IllegalArgumentException,
    1143             :         css::container::ElementExistException,
    1144             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
    1145             : {
    1146             :     assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
    1147         417 :     Broadcaster bc;
    1148             :     {
    1149         417 :         osl::MutexGuard g(*lock_);
    1150         417 :         checkLocalizedPropertyAccess();
    1151         417 :         checkFinalized();
    1152         417 :         if (getChild(aName).is()) {
    1153             :             throw css::container::ElementExistException(
    1154           0 :                 aName, static_cast< cppu::OWeakObject * >(this));
    1155             :         }
    1156         417 :         Modifications localMods;
    1157         417 :         switch (getNode()->kind()) {
    1158             :         case Node::KIND_LOCALIZED_PROPERTY:
    1159           0 :             insertLocalizedValueChild(aName, aElement, &localMods);
    1160           0 :             break;
    1161             :         case Node::KIND_GROUP:
    1162             :             {
    1163          40 :                 checkValue(aElement, TYPE_ANY, true);
    1164             :                 rtl::Reference< ChildAccess > child(
    1165             :                     new ChildAccess(
    1166          40 :                         components_, getRootAccess(), this, aName,
    1167             :                         new PropertyNode(
    1168          40 :                             Data::NO_LAYER, TYPE_ANY, true, aElement, true)));
    1169          40 :                 markChildAsModified(child);
    1170          40 :                 localMods.add(child->getRelativePath());
    1171             :             }
    1172          40 :             break;
    1173             :         case Node::KIND_SET:
    1174             :             {
    1175             :                 rtl::Reference< ChildAccess > freeAcc(
    1176         377 :                     getFreeSetMember(aElement));
    1177         377 :                 freeAcc->bind(getRootAccess(), this, aName); // must not throw
    1178         377 :                 markChildAsModified(freeAcc); //TODO: must not throw
    1179         377 :                 localMods.add(freeAcc->getRelativePath());
    1180             :             }
    1181         377 :             break;
    1182             :         default:
    1183             :             assert(false); // this cannot happen
    1184           0 :             break;
    1185             :         }
    1186         417 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
    1187             :     }
    1188         417 :     bc.send();
    1189         417 : }
    1190             : 
    1191          35 : void Access::removeByName(OUString const & aName)
    1192             :     throw (
    1193             :         css::container::NoSuchElementException,
    1194             :         css::lang::WrappedTargetException, css::uno::RuntimeException)
    1195             : {
    1196             :     assert(thisIs(IS_EXTENSIBLE|IS_UPDATE));
    1197          35 :     Broadcaster bc;
    1198             :     {
    1199          35 :         osl::MutexGuard g(*lock_);
    1200          35 :         checkLocalizedPropertyAccess();
    1201          35 :         rtl::Reference< ChildAccess > child(getChild(aName));
    1202         140 :         if (!child.is() || child->isFinalized() ||
    1203         105 :             child->getNode()->getMandatory() != Data::NO_LAYER)
    1204             :         {
    1205             :             throw css::container::NoSuchElementException(
    1206           0 :                 aName, static_cast< cppu::OWeakObject * >(this));
    1207             :         }
    1208          35 :         if (getNode()->kind() == Node::KIND_GROUP) {
    1209           0 :             rtl::Reference< Node > p(child->getNode());
    1210           0 :             if (p->kind() != Node::KIND_PROPERTY ||
    1211           0 :                 !dynamic_cast< PropertyNode * >(p.get())->isExtension())
    1212             :             {
    1213             :                 throw css::container::NoSuchElementException(
    1214           0 :                     aName, static_cast< cppu::OWeakObject * >(this));
    1215           0 :             }
    1216             :         }
    1217          35 :         Modifications localMods;
    1218          35 :         localMods.add(child->getRelativePath());
    1219             :         // unbind() modifies the parent chain that markChildAsModified() walks,
    1220             :         // so order is important:
    1221          35 :         markChildAsModified(child); //TODO: must not throw
    1222          35 :         child->unbind();
    1223          35 :         getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
    1224             :     }
    1225          35 :     bc.send();
    1226          35 : }
    1227             : 
    1228         377 : css::uno::Reference< css::uno::XInterface > Access::createInstance()
    1229             :     throw (css::uno::Exception, css::uno::RuntimeException)
    1230             : {
    1231             :     assert(thisIs(IS_SET|IS_UPDATE));
    1232             :     OUString tmplName(
    1233         377 :         dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName());
    1234             :     rtl::Reference< Node > tmpl(
    1235         377 :         components_.getTemplate(Data::NO_LAYER, tmplName));
    1236         377 :     if (!tmpl.is()) {
    1237             :         throw css::uno::Exception(
    1238             :             (OUString("unknown template ") +
    1239           0 :              tmplName),
    1240           0 :             static_cast< cppu::OWeakObject * >(this));
    1241             :     }
    1242         377 :     rtl::Reference< Node > node(tmpl->clone(true));
    1243         377 :     node->setLayer(Data::NO_LAYER);
    1244             :     return static_cast< cppu::OWeakObject * >(
    1245         377 :         new ChildAccess(components_, getRootAccess(), node));
    1246             : }
    1247             : 
    1248           0 : css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments(
    1249             :     css::uno::Sequence< css::uno::Any > const & aArguments)
    1250             :     throw (css::uno::Exception, css::uno::RuntimeException)
    1251             : {
    1252             :     assert(thisIs(IS_SET|IS_UPDATE));
    1253           0 :     if (aArguments.getLength() != 0) {
    1254             :         throw css::uno::Exception(
    1255             :             OUString("configuration SimpleSetUpdate createInstanceWithArguments"
    1256             :                     " must not specify any arguments"),
    1257           0 :             static_cast< cppu::OWeakObject * >(this));
    1258             :     }
    1259           0 :     return createInstance();
    1260             : }
    1261             : 
    1262      388336 : Access::Access(Components & components):
    1263      388336 :     components_(components), disposed_(false)
    1264             : {
    1265      388336 :     lock_ = lock();
    1266      388336 : }
    1267             : 
    1268      387493 : Access::~Access() {}
    1269             : 
    1270           0 : void Access::initDisposeBroadcaster(Broadcaster * broadcaster) {
    1271             :     assert(broadcaster != 0);
    1272           0 :     for (DisposeListeners::iterator i(disposeListeners_.begin());
    1273           0 :          i != disposeListeners_.end(); ++i)
    1274             :     {
    1275             :         broadcaster->addDisposeNotification(
    1276           0 :             *i,
    1277           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
    1278             :     }
    1279           0 :     for (ContainerListeners::iterator i(containerListeners_.begin());
    1280           0 :          i != containerListeners_.end(); ++i)
    1281             :     {
    1282             :         broadcaster->addDisposeNotification(
    1283           0 :             i->get(),
    1284           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
    1285             :     }
    1286           0 :     for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin());
    1287           0 :          i != propertyChangeListeners_.end(); ++i)
    1288             :     {
    1289           0 :         for (PropertyChangeListenersElement::iterator j(i->second.begin());
    1290           0 :              j != i->second.end(); ++j)
    1291             :         {
    1292             :             broadcaster->addDisposeNotification(
    1293           0 :                 j->get(),
    1294             :                 css::lang::EventObject(
    1295           0 :                     static_cast< cppu::OWeakObject * >(this)));
    1296             :         }
    1297             :     }
    1298           0 :     for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin());
    1299           0 :          i != vetoableChangeListeners_.end(); ++i)
    1300             :     {
    1301           0 :         for (VetoableChangeListenersElement::iterator j(i->second.begin());
    1302           0 :              j != i->second.end(); ++j)
    1303             :         {
    1304             :             broadcaster->addDisposeNotification(
    1305           0 :                 j->get(),
    1306             :                 css::lang::EventObject(
    1307           0 :                     static_cast< cppu::OWeakObject * >(this)));
    1308             :         }
    1309             :     }
    1310           0 :     for (PropertiesChangeListeners::iterator i(
    1311           0 :              propertiesChangeListeners_.begin());
    1312           0 :          i != propertiesChangeListeners_.end(); ++i)
    1313             :     {
    1314             :         broadcaster->addDisposeNotification(
    1315           0 :             i->get(),
    1316           0 :             css::lang::EventObject(static_cast< cppu::OWeakObject * >(this)));
    1317             :     }
    1318             :     //TODO: iterate over children w/ listeners (incl. unmodified ones):
    1319           0 :     for (ModifiedChildren::iterator i(modifiedChildren_.begin());
    1320           0 :          i != modifiedChildren_.end(); ++i)
    1321             :     {
    1322           0 :         rtl::Reference< ChildAccess > child(getModifiedChild(i));
    1323           0 :         if (child.is()) {
    1324           0 :             child->initDisposeBroadcaster(broadcaster);
    1325             :         }
    1326           0 :     }
    1327           0 : }
    1328             : 
    1329           0 : void Access::clearListeners() throw() {
    1330           0 :     disposeListeners_.clear();
    1331           0 :     containerListeners_.clear();
    1332           0 :     propertyChangeListeners_.clear();
    1333           0 :     vetoableChangeListeners_.clear();
    1334           0 :     propertiesChangeListeners_.clear();
    1335             :     //TODO: iterate over children w/ listeners (incl. unmodified ones):
    1336           0 :     for (ModifiedChildren::iterator i(modifiedChildren_.begin());
    1337           0 :          i != modifiedChildren_.end(); ++i)
    1338             :     {
    1339           0 :         rtl::Reference< ChildAccess > child(getModifiedChild(i));
    1340           0 :         if (child.is()) {
    1341           0 :             child->clearListeners();
    1342             :         }
    1343           0 :     }
    1344           0 : }
    1345             : 
    1346       77255 : css::uno::Any Access::queryInterface(css::uno::Type const & aType)
    1347             :     throw (css::uno::RuntimeException)
    1348             : {
    1349       77255 :     css::uno::Any res(OWeakObject::queryInterface(aType));
    1350       77255 :     if (res.hasValue()) {
    1351         743 :         return res;
    1352             :     }
    1353             :     res = cppu::queryInterface(
    1354             :         aType, static_cast< css::lang::XTypeProvider * >(this),
    1355             :         static_cast< css::lang::XServiceInfo * >(this),
    1356             :         static_cast< css::lang::XComponent * >(this),
    1357             :         static_cast< css::container::XHierarchicalNameAccess * >(this),
    1358             :         static_cast< css::container::XContainer * >(this),
    1359             :         static_cast< css::beans::XExactName * >(this),
    1360             :         static_cast< css::container::XHierarchicalName * >(this),
    1361             :         static_cast< css::container::XNamed * >(this),
    1362             :         static_cast< css::beans::XProperty * >(this),
    1363             :         static_cast< css::container::XElementAccess * >(this),
    1364       76512 :         static_cast< css::container::XNameAccess * >(this));
    1365       76512 :     if (res.hasValue()) {
    1366       55998 :         return res;
    1367             :     }
    1368       20514 :     if (getNode()->kind() == Node::KIND_GROUP) {
    1369             :         res = cppu::queryInterface(
    1370             :             aType, static_cast< css::beans::XPropertySetInfo * >(this),
    1371             :             static_cast< css::beans::XPropertySet * >(this),
    1372             :             static_cast< css::beans::XMultiPropertySet * >(this),
    1373             :             static_cast< css::beans::XHierarchicalPropertySet * >(this),
    1374             :             static_cast< css::beans::XMultiHierarchicalPropertySet * >(this),
    1375       18611 :             static_cast< css::beans::XHierarchicalPropertySetInfo * >(this));
    1376       18611 :         if (res.hasValue()) {
    1377       14347 :             return res;
    1378             :         }
    1379             :     }
    1380        6167 :     if (getRootAccess()->isUpdate()) {
    1381             :         res = cppu::queryInterface(
    1382             :             aType, static_cast< css::container::XNameReplace * >(this),
    1383        5915 :             static_cast< css::container::XHierarchicalNameReplace * >(this));
    1384        5915 :         if (res.hasValue()) {
    1385          41 :             return res;
    1386             :         }
    1387       15847 :         if (getNode()->kind() != Node::KIND_GROUP ||
    1388        9973 :             dynamic_cast< GroupNode * >(getNode().get())->isExtensible())
    1389             :         {
    1390             :             res = cppu::queryInterface(
    1391        2439 :                 aType, static_cast< css::container::XNameContainer * >(this));
    1392        2439 :             if (res.hasValue()) {
    1393        1580 :                 return res;
    1394             :             }
    1395             :         }
    1396        4294 :         if (getNode()->kind() == Node::KIND_SET) {
    1397             :             res = cppu::queryInterface(
    1398         771 :                 aType, static_cast< css::lang::XSingleServiceFactory * >(this));
    1399             :         }
    1400             :     }
    1401        4546 :     return res;
    1402             : }
    1403             : 
    1404      190500 : Components & Access::getComponents() const {
    1405      190500 :     return components_;
    1406             : }
    1407             : 
    1408      370198 : void Access::checkLocalizedPropertyAccess() {
    1409      763470 :     if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY &&
    1410      393272 :         !Components::allLocales(getRootAccess()->getLocale()))
    1411             :     {
    1412             :         throw css::uno::RuntimeException(
    1413             :             OUString("configmgr Access to specialized LocalizedPropertyNode"),
    1414           0 :             static_cast< cppu::OWeakObject * >(this));
    1415             :     }
    1416      370198 : }
    1417             : 
    1418        4748 : rtl::Reference< Node > Access::getParentNode() {
    1419        4748 :     rtl::Reference< Access > parent(getParentAccess());
    1420        4748 :     return parent.is() ? parent->getNode() : rtl::Reference< Node >();
    1421             : }
    1422             : 
    1423      388157 : rtl::Reference< ChildAccess > Access::getChild(OUString const & name) {
    1424      388157 :     if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && name.match("*")) {
    1425        2768 :         OUString locale(name.copy(1));
    1426        2768 :         if (locale.match("*")) {
    1427             :             SAL_WARN(
    1428             :                 "configmgr",
    1429             :                 ("access best-matching localized property value via"
    1430             :                  " \"*<locale>\" with <locale> \"")
    1431             :                     << locale << "\" recursively starting with \"*\"");
    1432           0 :             return getChild(locale);
    1433             :         }
    1434             :         SAL_WARN_IF(
    1435             :             locale.isEmpty(), "configmgr",
    1436             :             ("access best-matching localized property value via \"*<locale>\""
    1437             :              " with empty <locale>; falling back to defaults"));
    1438        2768 :         if (!locale.isEmpty()) {
    1439             :             // Find best match using an adaption of RFC 4647 lookup matching
    1440             :             // rules, removing "-" or "_" delimited segments from the end:
    1441         854 :             for (;;) {
    1442        3511 :                 rtl::Reference< ChildAccess > child(getChild(locale));
    1443        3511 :                 if (child.is()) {
    1444        1803 :                     return child;
    1445             :                 }
    1446        1708 :                 sal_Int32 i = locale.getLength() - 1;
    1447        5978 :                 while (i > 0 && locale[i] != '-' && locale[i] != '_') {
    1448        2562 :                     --i;
    1449             :                 }
    1450        1708 :                 if (i <= 0) {
    1451             :                     break;
    1452             :                 }
    1453         854 :                 locale = locale.copy(0, i);
    1454        3511 :             }
    1455             :             // As a workaround for broken xcu data that does not use shortest
    1456             :             // xml:lang attributes, look for the first entry with the same first
    1457             :             // segment as the requested language tag before falling back to
    1458             :             // defaults (see fdo#33638):
    1459             :             assert(
    1460             :                 !locale.isEmpty() && locale.indexOf('-') == -1 &&
    1461             :                 locale.indexOf('_') == -1);
    1462             :             std::vector< rtl::Reference< ChildAccess > > children(
    1463         854 :                 getAllChildren());
    1464        4270 :             for (std::vector< rtl::Reference< ChildAccess > >::iterator i(
    1465         854 :                      children.begin());
    1466        3416 :                  i != children.end(); ++i)
    1467             :             {
    1468         854 :                 OUString name2((*i)->getNameInternal());
    1469         854 :                 if (name2.match(locale) &&
    1470           0 :                     (name2.getLength() == locale.getLength() ||
    1471           0 :                      name2[locale.getLength()] == '-' ||
    1472           0 :                      name2[locale.getLength()] == '_'))
    1473             :                 {
    1474           0 :                     return *i;
    1475             :                 }
    1476        1708 :             }
    1477             :         }
    1478             :         // Defaults are the "en-US" locale, the "en" locale, the empty string
    1479             :         // locale, the first child (if any), or a null ChildAccess, in that
    1480             :         // order:
    1481         965 :         rtl::Reference< ChildAccess > child(getChild("en-US"));
    1482         965 :         if (child.is()) {
    1483         111 :             return child;
    1484             :         }
    1485         854 :         child = getChild("en");
    1486         854 :         if (child.is()) {
    1487           0 :             return child;
    1488             :         }
    1489         854 :         child = getChild(OUString());
    1490         854 :         if (child.is()) {
    1491         854 :             return child;
    1492             :         }
    1493           0 :         std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
    1494           0 :         if (!children.empty()) {
    1495           0 :             return children.front();
    1496             :         }
    1497           0 :         return rtl::Reference< ChildAccess >();
    1498             :     }
    1499      385389 :     ModifiedChildren::iterator i(modifiedChildren_.find(name));
    1500      770778 :     return i == modifiedChildren_.end()
    1501      385389 :         ? getUnmodifiedChild(name) : getModifiedChild(i);
    1502             : }
    1503             : 
    1504        9616 : std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() {
    1505        9616 :     std::vector< rtl::Reference< ChildAccess > > vec;
    1506        9616 :     NodeMap const & members = getNode()->getMembers();
    1507       63224 :     for (NodeMap::const_iterator i(members.begin()); i != members.end(); ++i) {
    1508       53608 :         if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) {
    1509       53608 :             vec.push_back(getUnmodifiedChild(i->first));
    1510             :             assert(vec.back().is());
    1511             :         }
    1512             :     }
    1513       28848 :     for (ModifiedChildren::iterator i(modifiedChildren_.begin());
    1514       19232 :          i != modifiedChildren_.end(); ++i)
    1515             :     {
    1516           0 :         rtl::Reference< ChildAccess > child(getModifiedChild(i));
    1517           0 :         if (child.is()) {
    1518           0 :             vec.push_back(child);
    1519             :         }
    1520           0 :     }
    1521        9616 :     return vec;
    1522             : }
    1523             : 
    1524        4698 : void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) {
    1525             :     bool ok;
    1526        4698 :     switch (type) {
    1527             :     case TYPE_NIL:
    1528             :         assert(false);
    1529             :         // fall through (cannot happen)
    1530             :     case TYPE_ERROR:
    1531           0 :         ok = false;
    1532           0 :         break;
    1533             :     case TYPE_ANY:
    1534         488 :         switch (getDynamicType(value)) {
    1535             :         case TYPE_ANY:
    1536             :             assert(false);
    1537             :             // fall through (cannot happen)
    1538             :         case TYPE_ERROR:
    1539           0 :             ok = false;
    1540           0 :             break;
    1541             :         case TYPE_NIL:
    1542           0 :             ok = nillable;
    1543           0 :             break;
    1544             :         default:
    1545         488 :             ok = true;
    1546         488 :             break;
    1547             :         }
    1548         488 :         break;
    1549             :     default:
    1550        4210 :         ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable;
    1551        4210 :         break;
    1552             :     }
    1553        4698 :     if (!ok) {
    1554             :         throw css::lang::IllegalArgumentException(
    1555             :             OUString("configmgr inappropriate property value"),
    1556           0 :             static_cast< cppu::OWeakObject * >(this), -1);
    1557             :     }
    1558        4698 : }
    1559             : 
    1560           0 : void Access::insertLocalizedValueChild(
    1561             :     OUString const & name, css::uno::Any const & value,
    1562             :     Modifications * localModifications)
    1563             : {
    1564             :     assert(localModifications != 0);
    1565             :     LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >(
    1566           0 :         getNode().get());
    1567           0 :     checkValue(value, locprop->getStaticType(), locprop->isNillable());
    1568             :     rtl::Reference< ChildAccess > child(
    1569             :         new ChildAccess(
    1570           0 :             components_, getRootAccess(), this, name,
    1571           0 :             new LocalizedValueNode(Data::NO_LAYER, value)));
    1572           0 :     markChildAsModified(child);
    1573           0 :     localModifications->add(child->getRelativePath());
    1574           0 : }
    1575             : 
    1576           0 : void Access::reportChildChanges(
    1577             :     std::vector< css::util::ElementChange > * changes)
    1578             : {
    1579             :     assert(changes != 0);
    1580           0 :     for (ModifiedChildren::iterator i(modifiedChildren_.begin());
    1581           0 :          i != modifiedChildren_.end(); ++i)
    1582             :     {
    1583           0 :         rtl::Reference< ChildAccess > child(getModifiedChild(i));
    1584           0 :         if (child.is()) {
    1585           0 :             child->reportChildChanges(changes);
    1586           0 :             changes->push_back(css::util::ElementChange());
    1587             :                 //TODO: changed value and/or inserted node
    1588             :         } else {
    1589           0 :             changes->push_back(css::util::ElementChange()); //TODO: removed node
    1590             :         }
    1591           0 :     }
    1592           0 : }
    1593             : 
    1594       12178 : void Access::commitChildChanges(
    1595             :     bool valid, Modifications * globalModifications)
    1596             : {
    1597             :     assert(globalModifications != 0);
    1598       35358 :     while (!modifiedChildren_.empty()) {
    1599       11002 :         bool childValid = valid;
    1600       11002 :         ModifiedChildren::iterator i(modifiedChildren_.begin());
    1601       11002 :         rtl::Reference< ChildAccess > child(getModifiedChild(i));
    1602       11002 :         if (child.is()) {
    1603       10967 :             childValid = childValid && !child->isFinalized();
    1604       10967 :             child->commitChanges(childValid, globalModifications);
    1605             :                 //TODO: currently, this is called here for directly inserted
    1606             :                 // children as well as for children whose sub-children were
    1607             :                 // modified (and should never be called for directly removed
    1608             :                 // children); clarify what exactly should happen here for
    1609             :                 // directly inserted children
    1610             :         }
    1611       11002 :         NodeMap & members = getNode()->getMembers();
    1612       11002 :         NodeMap::iterator j(members.find(i->first));
    1613       11002 :         if (child.is()) {
    1614             :             // Inserted:
    1615       10967 :             if (j != members.end()) {
    1616             :                 childValid = childValid &&
    1617       10550 :                     j->second->getFinalized() == Data::NO_LAYER;
    1618       10550 :                 if (childValid) {
    1619       10550 :                     child->getNode()->setMandatory(j->second->getMandatory());
    1620             :                 }
    1621             :             }
    1622       10967 :             if (childValid) {
    1623       10967 :                 members[i->first] = child->getNode();
    1624             :             }
    1625             :         } else {
    1626             :             // Removed:
    1627         105 :             childValid = childValid && j != members.end() &&
    1628          35 :                 j->second->getFinalized() == Data::NO_LAYER &&
    1629         140 :                 j->second->getMandatory() == Data::NO_LAYER;
    1630          35 :             if (childValid) {
    1631          35 :                 members.erase(j);
    1632             :             }
    1633             :         }
    1634       11002 :         if (childValid && i->second.directlyModified) {
    1635        5110 :             Path path(getAbsolutePath());
    1636        5110 :             path.push_back(i->first);
    1637        5110 :             components_.addModification(path);
    1638        5110 :             globalModifications->add(path);
    1639             :         }
    1640       11002 :         i->second.child->committed();
    1641       11002 :         modifiedChildren_.erase(i);
    1642       11002 :     }
    1643       12178 : }
    1644             : 
    1645       36172 : void Access::initBroadcasterAndChanges(
    1646             :     Modifications::Node const & modifications, Broadcaster * broadcaster,
    1647             :     std::vector< css::util::ElementChange > * allChanges)
    1648             : {
    1649             :     assert(broadcaster != 0);
    1650       36172 :     comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges;
    1651       36172 :     bool collectPropChanges = !propertiesChangeListeners_.empty();
    1652      226485 :     for (Modifications::Node::Children::const_iterator i(
    1653       36172 :              modifications.children.begin());
    1654      150990 :          i != modifications.children.end(); ++i)
    1655             :     {
    1656       39323 :         rtl::Reference< ChildAccess > child(getChild(i->first));
    1657       39323 :         if (child.is()) {
    1658       39253 :             switch (child->getNode()->kind()) {
    1659             :             case Node::KIND_LOCALIZED_PROPERTY:
    1660           0 :                 if (!i->second.children.empty()) {
    1661           0 :                     if (Components::allLocales(getRootAccess()->getLocale())) {
    1662           0 :                         child->initBroadcasterAndChanges(
    1663           0 :                             i->second, broadcaster, allChanges);
    1664             :                             //TODO: if allChanges==0, recurse only into children
    1665             :                             // w/ listeners
    1666             :                     } else {
    1667             :                         //TODO: filter child mods that are irrelevant for
    1668             :                         // locale:
    1669           0 :                         for (ContainerListeners::iterator j(
    1670           0 :                                  containerListeners_.begin());
    1671           0 :                              j != containerListeners_.end(); ++j)
    1672             :                         {
    1673             :                             broadcaster->
    1674             :                                 addContainerElementReplacedNotification(
    1675           0 :                                     *j,
    1676             :                                     css::container::ContainerEvent(
    1677             :                                         static_cast< cppu::OWeakObject * >(
    1678             :                                             this),
    1679           0 :                                         css::uno::makeAny(i->first),
    1680           0 :                                         css::uno::Any(), css::uno::Any()));
    1681             :                                 //TODO: non-void Element, ReplacedElement
    1682             :                         }
    1683             :                         PropertyChangeListeners::iterator j(
    1684           0 :                             propertyChangeListeners_.find(i->first));
    1685           0 :                         if (j != propertyChangeListeners_.end()) {
    1686           0 :                             for (PropertyChangeListenersElement::iterator k(
    1687           0 :                                      j->second.begin());
    1688           0 :                                  k != j->second.end(); ++k)
    1689             :                             {
    1690             :                                 broadcaster->addPropertyChangeNotification(
    1691           0 :                                     *k,
    1692             :                                     css::beans::PropertyChangeEvent(
    1693             :                                         static_cast< cppu::OWeakObject * >(
    1694             :                                             this),
    1695           0 :                                         i->first, false, -1, css::uno::Any(),
    1696           0 :                                         css::uno::Any()));
    1697             :                             }
    1698             :                         }
    1699           0 :                         j = propertyChangeListeners_.find(OUString());
    1700           0 :                         if (j != propertyChangeListeners_.end()) {
    1701           0 :                             for (PropertyChangeListenersElement::iterator k(
    1702           0 :                                      j->second.begin());
    1703           0 :                                  k != j->second.end(); ++k)
    1704             :                             {
    1705             :                                 broadcaster->addPropertyChangeNotification(
    1706           0 :                                     *k,
    1707             :                                     css::beans::PropertyChangeEvent(
    1708             :                                         static_cast< cppu::OWeakObject * >(
    1709             :                                             this),
    1710           0 :                                         i->first, false, -1, css::uno::Any(),
    1711           0 :                                         css::uno::Any()));
    1712             :                             }
    1713             :                         }
    1714           0 :                         if (allChanges != 0) {
    1715             :                             allChanges->push_back(
    1716             :                                 css::util::ElementChange(
    1717             :                                     css::uno::makeAny(
    1718           0 :                                         child->getRelativePathRepresentation()),
    1719           0 :                                     css::uno::Any(), css::uno::Any()));
    1720             :                                 //TODO: non-void Element, ReplacedElement
    1721             :                         }
    1722           0 :                         if (collectPropChanges) {
    1723             :                             propChanges.push_back(
    1724             :                                 css::beans::PropertyChangeEvent(
    1725             :                                     static_cast< cppu::OWeakObject * >(this),
    1726           0 :                                     i->first, false, -1, css::uno::Any(),
    1727           0 :                                     css::uno::Any()));
    1728             :                         }
    1729             :                     }
    1730             :                 }
    1731             :                 // else: spurious Modifications::Node not representing a change
    1732           0 :                 break;
    1733             :             case Node::KIND_LOCALIZED_VALUE:
    1734             :                 assert(Components::allLocales(getRootAccess()->getLocale()));
    1735           0 :                 for (ContainerListeners::iterator j(
    1736           0 :                          containerListeners_.begin());
    1737           0 :                      j != containerListeners_.end(); ++j)
    1738             :                 {
    1739             :                     broadcaster->addContainerElementReplacedNotification(
    1740           0 :                         *j,
    1741             :                         css::container::ContainerEvent(
    1742             :                             static_cast< cppu::OWeakObject * >(this),
    1743           0 :                             css::uno::makeAny(i->first), child->asValue(),
    1744           0 :                             css::uno::Any()));
    1745             :                         //TODO: distinguish add/modify; non-void ReplacedElement
    1746             :                 }
    1747           0 :                 if (allChanges != 0) {
    1748             :                     allChanges->push_back(
    1749             :                         css::util::ElementChange(
    1750             :                             css::uno::makeAny(
    1751           0 :                                 child->getRelativePathRepresentation()),
    1752           0 :                             child->asValue(), css::uno::Any()));
    1753             :                         //TODO: non-void ReplacedElement
    1754             :                 }
    1755             :                 assert(!collectPropChanges);
    1756           0 :                 break;
    1757             :             case Node::KIND_PROPERTY:
    1758             :                 {
    1759       32844 :                     for (ContainerListeners::iterator j(
    1760       10948 :                              containerListeners_.begin());
    1761       21896 :                          j != containerListeners_.end(); ++j)
    1762             :                     {
    1763             :                         broadcaster->addContainerElementReplacedNotification(
    1764           0 :                             *j,
    1765             :                             css::container::ContainerEvent(
    1766             :                                 static_cast< cppu::OWeakObject * >(this),
    1767           0 :                                 css::uno::makeAny(i->first), child->asValue(),
    1768           0 :                                 css::uno::Any()));
    1769             :                             //TODO: distinguish add/remove/modify; non-void
    1770             :                             // ReplacedElement
    1771             :                     }
    1772             :                     PropertyChangeListeners::iterator j(
    1773       10948 :                         propertyChangeListeners_.find(i->first));
    1774       10948 :                     if (j != propertyChangeListeners_.end()) {
    1775           0 :                         for (PropertyChangeListenersElement::iterator k(
    1776           0 :                                  j->second.begin());
    1777           0 :                              k != j->second.end(); ++k)
    1778             :                         {
    1779             :                             broadcaster->addPropertyChangeNotification(
    1780           0 :                                 *k,
    1781             :                                 css::beans::PropertyChangeEvent(
    1782             :                                     static_cast< cppu::OWeakObject * >(this),
    1783           0 :                                     i->first, false, -1, css::uno::Any(),
    1784           0 :                                     css::uno::Any()));
    1785             :                         }
    1786             :                     }
    1787       10948 :                     j = propertyChangeListeners_.find(OUString());
    1788       10948 :                     if (j != propertyChangeListeners_.end()) {
    1789           0 :                         for (PropertyChangeListenersElement::iterator k(
    1790           0 :                                  j->second.begin());
    1791           0 :                              k != j->second.end(); ++k)
    1792             :                         {
    1793             :                             broadcaster->addPropertyChangeNotification(
    1794           0 :                                 *k,
    1795             :                                 css::beans::PropertyChangeEvent(
    1796             :                                     static_cast< cppu::OWeakObject * >(this),
    1797           0 :                                     i->first, false, -1, css::uno::Any(),
    1798           0 :                                     css::uno::Any()));
    1799             :                         }
    1800             :                     }
    1801       10948 :                     if (allChanges != 0) {
    1802             :                         allChanges->push_back(
    1803             :                             css::util::ElementChange(
    1804             :                                 css::uno::makeAny(
    1805         126 :                                     child->getRelativePathRepresentation()),
    1806         252 :                                 child->asValue(), css::uno::Any()));
    1807             :                             //TODO: non-void ReplacedElement
    1808             :                     }
    1809       10948 :                     if (collectPropChanges) {
    1810             :                         propChanges.push_back(
    1811             :                             css::beans::PropertyChangeEvent(
    1812             :                                 static_cast< cppu::OWeakObject * >(this),
    1813           0 :                                 i->first, false, -1, css::uno::Any(),
    1814           0 :                                 css::uno::Any()));
    1815             :                     }
    1816             :                 }
    1817       10948 :                 break;
    1818             :             case Node::KIND_GROUP:
    1819             :             case Node::KIND_SET:
    1820       28305 :                 if (i->second.children.empty()) {
    1821         874 :                     if (!child->getNode()->getTemplateName().isEmpty()) {
    1822        2622 :                         for (ContainerListeners::iterator j(
    1823         874 :                                  containerListeners_.begin());
    1824        1748 :                              j != containerListeners_.end(); ++j)
    1825             :                         {
    1826             :                             broadcaster->
    1827             :                                 addContainerElementInsertedNotification(
    1828           0 :                                     *j,
    1829             :                                     css::container::ContainerEvent(
    1830             :                                         static_cast< cppu::OWeakObject * >(
    1831             :                                             this),
    1832           0 :                                         css::uno::makeAny(i->first),
    1833           0 :                                         child->asValue(), css::uno::Any()));
    1834             :                         }
    1835         874 :                         if (allChanges != 0) {
    1836             :                             allChanges->push_back(
    1837             :                                 css::util::ElementChange(
    1838             :                                     css::uno::makeAny(
    1839           0 :                                         child->getRelativePathRepresentation()),
    1840           0 :                                     css::uno::Any(), css::uno::Any()));
    1841             :                                 //TODO: non-void Element, ReplacedElement
    1842             :                         }
    1843             :                     }
    1844             :                     // else: spurious Modifications::Node not representing a
    1845             :                     // change
    1846             :                 } else {
    1847       27431 :                     child->initBroadcasterAndChanges(
    1848       54862 :                         i->second, broadcaster, allChanges);
    1849             :                         //TODO: if allChanges==0, recurse only into children w/
    1850             :                         // listeners
    1851             :                 }
    1852       28305 :                 break;
    1853             :             case Node::KIND_ROOT:
    1854             :                 assert(false); // this cannot happen
    1855           0 :                 break;
    1856             :             }
    1857             :         } else {
    1858          70 :             switch (getNode()->kind()) {
    1859             :             case Node::KIND_LOCALIZED_PROPERTY:
    1860             :                 // Removed localized property value:
    1861             :                 assert(Components::allLocales(getRootAccess()->getLocale()));
    1862           0 :                 for (ContainerListeners::iterator j(
    1863           0 :                          containerListeners_.begin());
    1864           0 :                      j != containerListeners_.end(); ++j)
    1865             :                 {
    1866             :                     broadcaster->addContainerElementRemovedNotification(
    1867           0 :                         *j,
    1868             :                         css::container::ContainerEvent(
    1869             :                             static_cast< cppu::OWeakObject * >(this),
    1870           0 :                             css::uno::makeAny(i->first), css::uno::Any(),
    1871           0 :                             css::uno::Any()));
    1872             :                         //TODO: non-void ReplacedElement
    1873             :                 }
    1874           0 :                 if (allChanges != 0) {
    1875           0 :                     OUStringBuffer path(getRelativePathRepresentation());
    1876           0 :                     if (path.getLength() != 0) {
    1877           0 :                         path.append(sal_Unicode('/'));
    1878             :                     }
    1879             :                     path.append(
    1880             :                         Data::createSegment(
    1881             :                             OUString("*"),
    1882           0 :                             i->first));
    1883             :                     allChanges->push_back(
    1884             :                         css::util::ElementChange(
    1885             :                             css::uno::makeAny(path.makeStringAndClear()),
    1886           0 :                             css::uno::Any(), css::uno::Any()));
    1887             :                         //TODO: non-void ReplacedElement
    1888             :                 }
    1889             :                 assert(!collectPropChanges);
    1890           0 :                 break;
    1891             :             case Node::KIND_GROUP:
    1892             :                 {
    1893             :                     // Removed (non-localized) extension property:
    1894           0 :                     for (ContainerListeners::iterator j(
    1895           0 :                              containerListeners_.begin());
    1896           0 :                          j != containerListeners_.end(); ++j)
    1897             :                     {
    1898             :                         broadcaster->addContainerElementRemovedNotification(
    1899           0 :                             *j,
    1900             :                             css::container::ContainerEvent(
    1901             :                                 static_cast< cppu::OWeakObject * >(this),
    1902           0 :                                 css::uno::makeAny(i->first), css::uno::Any(),
    1903           0 :                                 css::uno::Any()));
    1904             :                             //TODO: non-void ReplacedElement
    1905             :                     }
    1906             :                     PropertyChangeListeners::iterator j(
    1907           0 :                         propertyChangeListeners_.find(i->first));
    1908           0 :                     if (j != propertyChangeListeners_.end()) {
    1909           0 :                         for (PropertyChangeListenersElement::iterator k(
    1910           0 :                                  j->second.begin());
    1911           0 :                              k != j->second.end(); ++k)
    1912             :                         {
    1913             :                             broadcaster->addPropertyChangeNotification(
    1914           0 :                                 *k,
    1915             :                                 css::beans::PropertyChangeEvent(
    1916             :                                     static_cast< cppu::OWeakObject * >(this),
    1917           0 :                                     i->first, false, -1, css::uno::Any(),
    1918           0 :                                     css::uno::Any()));
    1919             :                         }
    1920             :                     }
    1921           0 :                     j = propertyChangeListeners_.find(OUString());
    1922           0 :                     if (j != propertyChangeListeners_.end()) {
    1923           0 :                         for (PropertyChangeListenersElement::iterator k(
    1924           0 :                                  j->second.begin());
    1925           0 :                              k != j->second.end(); ++k)
    1926             :                         {
    1927             :                             broadcaster->addPropertyChangeNotification(
    1928           0 :                                 *k,
    1929             :                                 css::beans::PropertyChangeEvent(
    1930             :                                     static_cast< cppu::OWeakObject * >(this),
    1931           0 :                                     i->first, false, -1, css::uno::Any(),
    1932           0 :                                     css::uno::Any()));
    1933             :                         }
    1934             :                     }
    1935           0 :                     if (allChanges != 0) {
    1936             :                         OUStringBuffer path(
    1937           0 :                             getRelativePathRepresentation());
    1938           0 :                         if (path.getLength() != 0) {
    1939           0 :                             path.append(sal_Unicode('/'));
    1940             :                         }
    1941           0 :                         path.append(i->first);
    1942             :                         allChanges->push_back(
    1943             :                             css::util::ElementChange(
    1944             :                                 css::uno::makeAny(path.makeStringAndClear()),
    1945           0 :                                 css::uno::Any(), css::uno::Any()));
    1946             :                             //TODO: non-void ReplacedElement
    1947             :                     }
    1948           0 :                     if (collectPropChanges) {
    1949             :                         propChanges.push_back(
    1950             :                             css::beans::PropertyChangeEvent(
    1951             :                                 static_cast< cppu::OWeakObject * >(this),
    1952           0 :                                 i->first, false, -1, css::uno::Any(),
    1953           0 :                                 css::uno::Any()));
    1954             :                     }
    1955             :                 }
    1956           0 :                 break;
    1957             :             case Node::KIND_SET:
    1958             :                 // Removed set member:
    1959          70 :                 if (i->second.children.empty()) {
    1960         210 :                     for (ContainerListeners::iterator j(
    1961          70 :                              containerListeners_.begin());
    1962         140 :                          j != containerListeners_.end(); ++j)
    1963             :                     {
    1964             :                         broadcaster->addContainerElementRemovedNotification(
    1965           0 :                             *j,
    1966             :                             css::container::ContainerEvent(
    1967             :                                 static_cast< cppu::OWeakObject * >(this),
    1968           0 :                                 css::uno::makeAny(i->first),
    1969           0 :                                 css::uno::Any(), css::uno::Any()));
    1970             :                             //TODO: non-void ReplacedElement
    1971             :                     }
    1972          70 :                     if (allChanges != 0) {
    1973             :                         OUStringBuffer path(
    1974           0 :                             getRelativePathRepresentation());
    1975           0 :                         if (path.getLength() != 0) {
    1976           0 :                             path.append(sal_Unicode('/'));
    1977             :                         }
    1978             :                         path.append(
    1979             :                             Data::createSegment(
    1980             :                                 OUString("*"),
    1981           0 :                                 i->first));
    1982             :                         allChanges->push_back(
    1983             :                             css::util::ElementChange(
    1984             :                                 css::uno::makeAny(path.makeStringAndClear()),
    1985           0 :                                 css::uno::Any(), css::uno::Any()));
    1986             :                             //TODO: non-void ReplacedElement
    1987             :                     }
    1988             :                 }
    1989             :                 // else: spurious Modifications::Node not representing a change
    1990          70 :                 break;
    1991             :             default:
    1992             :                 assert(false); // this cannot happen
    1993           0 :                 break;
    1994             :             }
    1995             :         }
    1996       39323 :     }
    1997       36172 :     if (!propChanges.empty()) {
    1998             :         css::uno::Sequence< css::beans::PropertyChangeEvent > seq(
    1999           0 :             propChanges.getAsConstList());
    2000           0 :         for (PropertiesChangeListeners::iterator i(
    2001           0 :                  propertiesChangeListeners_.begin());
    2002           0 :              i != propertiesChangeListeners_.end(); ++i)
    2003             :         {
    2004           0 :             broadcaster->addPropertiesChangeNotification(*i, seq);
    2005           0 :         }
    2006       36172 :     }
    2007       36172 : }
    2008             : 
    2009         803 : bool Access::isDisposed() const {
    2010         803 :     return disposed_;
    2011             : }
    2012             : 
    2013        5110 : Access::ModifiedChild::ModifiedChild() {}
    2014             : 
    2015       19563 : Access::ModifiedChild::ModifiedChild(
    2016             :     rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified):
    2017       19563 :     child(theChild), directlyModified(theDirectlyModified)
    2018       19563 : {}
    2019             : 
    2020       30716 : rtl::Reference< ChildAccess > Access::getModifiedChild(
    2021             :     ModifiedChildren::iterator const & childIterator)
    2022             : {
    2023       92148 :     return (childIterator->second.child->getParentAccess() == this &&
    2024       30646 :             (childIterator->second.child->getNameInternal() ==
    2025      122654 :              childIterator->first))
    2026      184156 :         ? childIterator->second.child : rtl::Reference< ChildAccess >();
    2027             : }
    2028             : 
    2029      419283 : rtl::Reference< ChildAccess > Access::getUnmodifiedChild(
    2030             :     OUString const & name)
    2031             : {
    2032             :     assert(modifiedChildren_.find(name) == modifiedChildren_.end());
    2033      419283 :     rtl::Reference< Node > node(getNode()->getMember(name));
    2034      419283 :     if (!node.is()) {
    2035       36522 :         return rtl::Reference< ChildAccess >();
    2036             :     }
    2037      382761 :     WeakChildMap::iterator i(cachedChildren_.find(name));
    2038      382761 :     if (i != cachedChildren_.end()) {
    2039        3948 :         rtl::Reference< ChildAccess > child;
    2040        3948 :         if (i->second->acquireCounting() > 1) {
    2041        3948 :             child.set(i->second); // must not throw
    2042             :         }
    2043        3948 :         i->second->releaseNondeleting();
    2044        3948 :         if (child.is()) {
    2045        3948 :             child->setNode(node);
    2046        3948 :             return child;
    2047        3948 :         }
    2048             :     }
    2049             :     rtl::Reference< ChildAccess > child(
    2050      378813 :         new ChildAccess(components_, getRootAccess(), this, name, node));
    2051      378813 :     cachedChildren_[name] = child.get();
    2052      378813 :     return child;
    2053             : }
    2054             : 
    2055       30690 : rtl::Reference< ChildAccess > Access::getSubChild(OUString const & path) {
    2056       30690 :     sal_Int32 i = 0;
    2057             :     // For backwards compatibility, allow absolute paths where meaningful:
    2058       30690 :     if (!path.isEmpty() && path[0] == '/') {
    2059        6023 :         ++i;
    2060        6023 :         if (!getRootAccess().is()) {
    2061           0 :             return rtl::Reference< ChildAccess >();
    2062             :         }
    2063        6023 :         Path abs(getAbsolutePath());
    2064        6023 :         for (Path::iterator j(abs.begin()); j != abs.end(); ++j) {
    2065           0 :             OUString name1;
    2066             :             bool setElement1;
    2067           0 :             OUString templateName1;
    2068             :             i = Data::parseSegment(
    2069           0 :                 path, i, &name1, &setElement1, &templateName1);
    2070           0 :             if (i == -1 || (i != path.getLength() && path[i] != '/')) {
    2071           0 :                 return rtl::Reference< ChildAccess >();
    2072             :             }
    2073           0 :             OUString name2;
    2074             :             bool setElement2;
    2075           0 :             OUString templateName2;
    2076           0 :             Data::parseSegment(*j, 0, &name2, &setElement2, &templateName2);
    2077           0 :             if (name1 != name2 || setElement1 != setElement2 ||
    2078             :                 (setElement1 &&
    2079           0 :                  !Data::equalTemplateNames(templateName1, templateName2)))
    2080             :             {
    2081           0 :                 return rtl::Reference< ChildAccess >();
    2082             :             }
    2083           0 :             if (i != path.getLength()) {
    2084           0 :                 ++i;
    2085             :             }
    2086        6023 :         }
    2087             :     }
    2088       76014 :     for (rtl::Reference< Access > parent(this);;) {
    2089       76014 :         OUString name;
    2090             :         bool setElement;
    2091       76014 :         OUString templateName;
    2092       76014 :         i = Data::parseSegment(path, i, &name, &setElement, &templateName);
    2093       76014 :         if (i == -1 || (i != path.getLength() && path[i] != '/')) {
    2094           0 :             return rtl::Reference< ChildAccess >();
    2095             :         }
    2096       76014 :         rtl::Reference< ChildAccess > child(parent->getChild(name));
    2097       76014 :         if (!child.is()) {
    2098           4 :             return rtl::Reference< ChildAccess >();
    2099             :         }
    2100       76010 :         if (setElement) {
    2101        1437 :             rtl::Reference< Node > p(parent->getNode());
    2102        1437 :             switch (p->kind()) {
    2103             :             case Node::KIND_LOCALIZED_PROPERTY:
    2104           0 :                 if (!Components::allLocales(getRootAccess()->getLocale()) ||
    2105           0 :                     !templateName.isEmpty())
    2106             :                 {
    2107           0 :                     return rtl::Reference< ChildAccess >();
    2108             :                 }
    2109           0 :                 break;
    2110             :             case Node::KIND_SET:
    2111        1437 :                 if (!templateName.isEmpty() &&
    2112           0 :                     !dynamic_cast< SetNode * >(p.get())->isValidTemplate(
    2113           0 :                         templateName))
    2114             :                 {
    2115           0 :                     return rtl::Reference< ChildAccess >();
    2116             :                 }
    2117        1437 :                 break;
    2118             :             default:
    2119           0 :                 return rtl::Reference< ChildAccess >();
    2120        1437 :             }
    2121             :         }
    2122             :         // For backwards compatibility, ignore a final slash after non-value
    2123             :         // nodes:
    2124       76010 :         if (child->isValue()) {
    2125       26334 :             return i == path.getLength()
    2126       26334 :                 ? child : rtl::Reference< ChildAccess >();
    2127       49676 :         } else if (i >= path.getLength() - 1) {
    2128        4352 :             return child;
    2129             :         }
    2130       45324 :         ++i;
    2131       45324 :         parent = child.get();
    2132      106704 :     }
    2133             : }
    2134             : 
    2135        4147 : bool Access::setChildProperty(
    2136             :     OUString const & name, css::uno::Any const & value,
    2137             :     Modifications * localModifications)
    2138             : {
    2139             :     assert(localModifications != 0);
    2140        4147 :     rtl::Reference< ChildAccess > child(getChild(name));
    2141        4147 :     if (!child.is()) {
    2142           0 :         return false;
    2143             :     }
    2144        4147 :     child->checkFinalized();
    2145        4147 :     child->setProperty(value, localModifications);
    2146        4147 :     return true;
    2147             : }
    2148             : 
    2149        6093 : css::beans::Property Access::asProperty() {
    2150        6093 :     css::uno::Type type;
    2151             :     bool nillable;
    2152             :     bool removable;
    2153        6093 :     rtl::Reference< Node > p(getNode());
    2154        6093 :     switch (p->kind()) {
    2155             :     case Node::KIND_PROPERTY:
    2156             :         {
    2157        1422 :             PropertyNode * prop = dynamic_cast< PropertyNode * >(p.get());
    2158        1422 :             type = mapType(prop->getStaticType());
    2159        1422 :             nillable = prop->isNillable();
    2160        1422 :             removable = prop->isExtension();
    2161             :         }
    2162             :         break;
    2163             :     case Node::KIND_LOCALIZED_PROPERTY:
    2164             :         {
    2165             :             LocalizedPropertyNode * locprop =
    2166           0 :                 dynamic_cast< LocalizedPropertyNode *>(p.get());
    2167           0 :             if (Components::allLocales(getRootAccess()->getLocale())) {
    2168           0 :                 type = cppu::UnoType< css::uno::XInterface >::get();
    2169             :                     //TODO: correct?
    2170           0 :                 removable = false;
    2171             :             } else {
    2172           0 :                 type = mapType(locprop->getStaticType());
    2173           0 :                 removable = false; //TODO ???
    2174             :             }
    2175           0 :             nillable = locprop->isNillable();
    2176             :         }
    2177             :         break;
    2178             :     case Node::KIND_LOCALIZED_VALUE:
    2179             :         {
    2180             :             LocalizedPropertyNode * locprop =
    2181           0 :                 dynamic_cast< LocalizedPropertyNode * >(getParentNode().get());
    2182           0 :             type = mapType(locprop->getStaticType());
    2183           0 :             nillable = locprop->isNillable();
    2184           0 :             removable = false; //TODO ???
    2185             :         }
    2186             :         break;
    2187             :     default:
    2188        4671 :         type = cppu::UnoType< css::uno::XInterface >::get(); //TODO: correct?
    2189        4671 :         nillable = false;
    2190        4671 :         rtl::Reference< Node > parent(getParentNode());
    2191        4671 :         removable = parent.is() && parent->kind() == Node::KIND_SET;
    2192        4671 :         break;
    2193             :     }
    2194             :     return css::beans::Property(
    2195        6093 :         getNameInternal(), -1, type,
    2196             :         (css::beans::PropertyAttribute::BOUND | //TODO: correct for group/set?
    2197             :          css::beans::PropertyAttribute::CONSTRAINED |
    2198             :          (nillable ? css::beans::PropertyAttribute::MAYBEVOID : 0) |
    2199       12186 :          (getRootAccess()->isUpdate()
    2200             :           ? (removable ? css::beans::PropertyAttribute::REMOVEABLE : 0)
    2201       24372 :           : css::beans::PropertyAttribute::READONLY))); //TODO: MAYBEDEFAULT
    2202             : }
    2203             : 
    2204        5075 : void Access::checkFinalized() {
    2205        5075 :     if (isFinalized()) {
    2206             :         throw css::lang::IllegalArgumentException(
    2207             :             OUString("configmgr modification of finalized item"),
    2208           0 :             static_cast< cppu::OWeakObject * >(this), -1);
    2209             :     }
    2210        5075 : }
    2211             : 
    2212           0 : void Access::checkKnownProperty(OUString const & descriptor) {
    2213           0 :     if (descriptor.isEmpty()) {
    2214             :         return;
    2215             :     }
    2216           0 :     rtl::Reference< ChildAccess > child(getChild(descriptor));
    2217           0 :     if (child.is()) {
    2218           0 :         switch (child->getNode()->kind()) {
    2219             :         case Node::KIND_PROPERTY:
    2220             :             return;
    2221             :         case Node::KIND_LOCALIZED_PROPERTY:
    2222           0 :             if (!Components::allLocales(getRootAccess()->getLocale())) {
    2223             :                 return;
    2224             :             }
    2225           0 :             break;
    2226             :         case Node::KIND_LOCALIZED_VALUE:
    2227           0 :             if (Components::allLocales(getRootAccess()->getLocale())) {
    2228             :                 return;
    2229             :             }
    2230           0 :             break;
    2231             :         default:
    2232           0 :             break;
    2233             :         }
    2234             :     }
    2235             :     throw css::beans::UnknownPropertyException(
    2236           0 :         descriptor, static_cast< cppu::OWeakObject * >(this));
    2237             : }
    2238             : 
    2239         377 : rtl::Reference< ChildAccess > Access::getFreeSetMember(
    2240             :     css::uno::Any const & value)
    2241             : {
    2242         377 :     rtl::Reference< ChildAccess > freeAcc;
    2243         377 :     css::uno::Reference< css::lang::XUnoTunnel > tunnel;
    2244         377 :     value >>= tunnel;
    2245         377 :     if (tunnel.is()) {
    2246             :         freeAcc.set(
    2247             :             reinterpret_cast< ChildAccess * >(
    2248         377 :                 tunnel->getSomething(ChildAccess::getTunnelId())));
    2249             :     }
    2250        1131 :     if (!freeAcc.is() || freeAcc->getParentAccess().is() ||
    2251         377 :         (freeAcc->isInTransaction() &&
    2252         377 :          freeAcc->getRootAccess() != getRootAccess()))
    2253             :     {
    2254             :         throw css::lang::IllegalArgumentException(
    2255             :             OUString("configmgr inappropriate set element"),
    2256           0 :             static_cast< cppu::OWeakObject * >(this), 1);
    2257             :     }
    2258             :     assert(dynamic_cast< SetNode * >(getNode().get()) != 0);
    2259        1131 :     if (!dynamic_cast< SetNode * >(getNode().get())->isValidTemplate(
    2260        1131 :             freeAcc->getNode()->getTemplateName()))
    2261             :     {
    2262             :         throw css::lang::IllegalArgumentException(
    2263             :             OUString("configmgr inappropriate set element"),
    2264           0 :             static_cast< cppu::OWeakObject * >(this), 1);
    2265             :     }
    2266         377 :     return freeAcc;
    2267             : }
    2268             : 
    2269        5110 : rtl::Reference< Access > Access::getNotificationRoot() {
    2270       19563 :     for (rtl::Reference< Access > p(this);;) {
    2271       19563 :         rtl::Reference< Access > parent(p->getParentAccess());
    2272       19563 :         if (!parent.is()) {
    2273       10220 :             return p;
    2274             :         }
    2275       14453 :         p = parent;
    2276       24673 :     }
    2277             : }
    2278             : 
    2279             : #if !defined NDEBUG
    2280             : bool Access::thisIs(int what) {
    2281             :     osl::MutexGuard g(*lock_);
    2282             :     rtl::Reference< Node > p(getNode());
    2283             :     Node::Kind k(p->kind());
    2284             :     return (k != Node::KIND_PROPERTY && k != Node::KIND_LOCALIZED_VALUE &&
    2285             :         ((what & IS_GROUP) == 0 || k == Node::KIND_GROUP) &&
    2286             :         ((what & IS_SET) == 0 || k == Node::KIND_SET) &&
    2287             :         ((what & IS_EXTENSIBLE) == 0 || k != Node::KIND_GROUP ||
    2288             :          dynamic_cast< GroupNode * >(p.get())->isExtensible()) &&
    2289             :         ((what & IS_GROUP_MEMBER) == 0 ||
    2290             :          getParentNode()->kind() == Node::KIND_GROUP)) ||
    2291             :         ((what & IS_SET_MEMBER) == 0 ||
    2292             :          getParentNode()->kind() == Node::KIND_SET) ||
    2293             :         ((what & IS_UPDATE) == 0 || getRootAccess()->isUpdate());
    2294             : }
    2295             : #endif
    2296             : 
    2297             : }
    2298             : 
    2299             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10