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

Generated by: LCOV version 1.10