From bcdea3b379637a98e5bbc304078149ca6c2b6e03 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Tue, 13 Dec 2011 12:37:00 +0100 Subject: Simplified, type-safe C++ configuration access. * New offapi com.sun.star.configuration entities to access the complete configuration read-only or read/write... * ...configmgr adapted to support those new services/singletons... * ...new unotools/configuration.hxx is the type-safe C++ plumbing on top of that... * ...officecfg now generates C++ headers to access all the properties and sets given in the .xcs files... * ...and svl's asiancfg.cxx exemplarily makes use of the new officecfg/Office/Common.hxx to access the configuration. * There is still TODOs: For one, see those listed in officecfg/registry/cppheader.xsl. For another, at least a notification mechanism for the new read-only configuration access and the C++ wrapper is missing. --- configmgr/source/access.cxx | 2994 ++++++++++++++-------------- configmgr/source/access.hxx | 136 +- configmgr/source/components.cxx | 6 +- configmgr/source/configmgr.component | 6 + configmgr/source/data.cxx | 18 +- configmgr/source/data.hxx | 4 + configmgr/source/groupnode.cxx | 4 +- configmgr/source/groupnode.hxx | 2 +- configmgr/source/localizedpropertynode.cxx | 4 +- configmgr/source/localizedpropertynode.hxx | 2 +- configmgr/source/makefile.mk | 3 + configmgr/source/node.cxx | 22 +- configmgr/source/node.hxx | 5 +- configmgr/source/readonlyaccess.cxx | 126 ++ configmgr/source/readonlyaccess.hxx | 61 + configmgr/source/readwriteaccess.cxx | 151 ++ configmgr/source/readwriteaccess.hxx | 61 + configmgr/source/rootaccess.cxx | 179 +- configmgr/source/rootaccess.hxx | 40 +- configmgr/source/rootnode.cxx | 66 + configmgr/source/rootnode.hxx | 65 + configmgr/source/services.cxx | 10 + configmgr/source/setnode.cxx | 4 +- configmgr/source/setnode.hxx | 2 +- configmgr/source/valueparser.cxx | 9 +- configmgr/source/writemodfile.cxx | 7 +- configmgr/source/xcsparser.cxx | 46 +- configmgr/source/xcuparser.cxx | 48 +- 28 files changed, 2371 insertions(+), 1710 deletions(-) create mode 100644 configmgr/source/readonlyaccess.cxx create mode 100644 configmgr/source/readonlyaccess.hxx create mode 100644 configmgr/source/readwriteaccess.cxx create mode 100644 configmgr/source/readwriteaccess.hxx create mode 100644 configmgr/source/rootnode.cxx create mode 100644 configmgr/source/rootnode.hxx (limited to 'configmgr') diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx index dab5e21c62fd..c34a8acc08be 100644 --- a/configmgr/source/access.cxx +++ b/configmgr/source/access.cxx @@ -54,6 +54,7 @@ #include "com/sun/star/container/XElementAccess.hpp" #include "com/sun/star/container/XHierarchicalName.hpp" #include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XHierarchicalNameReplace.hpp" #include "com/sun/star/container/XNameAccess.hpp" #include "com/sun/star/container/XNameContainer.hpp" #include "com/sun/star/container/XNamed.hpp" @@ -163,873 +164,640 @@ void Access::initBroadcaster( initBroadcasterAndChanges(modifications, broadcaster, 0); } -Access::Access(Components & components): - components_(components), disposed_(false) -{ - lock_ = lock(); -} - -Access::~Access() {} - -void Access::initDisposeBroadcaster(Broadcaster * broadcaster) { - assert(broadcaster != 0); - for (DisposeListeners::iterator i(disposeListeners_.begin()); - i != disposeListeners_.end(); ++i) - { - broadcaster->addDisposeNotification( - *i, - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } - for (ContainerListeners::iterator i(containerListeners_.begin()); - i != containerListeners_.end(); ++i) - { - broadcaster->addDisposeNotification( - i->get(), - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } - for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); - i != propertyChangeListeners_.end(); ++i) - { - for (PropertyChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addDisposeNotification( - j->get(), - css::lang::EventObject( - static_cast< cppu::OWeakObject * >(this))); - } - } - for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); - i != vetoableChangeListeners_.end(); ++i) - { - for (VetoableChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addDisposeNotification( - j->get(), - css::lang::EventObject( - static_cast< cppu::OWeakObject * >(this))); - } - } - for (PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.begin()); - i != propertiesChangeListeners_.end(); ++i) - { - broadcaster->addDisposeNotification( - i->get(), - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } - //TODO: iterate over children w/ listeners (incl. unmodified ones): - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) - { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - child->initDisposeBroadcaster(broadcaster); - } - } -} - -void Access::clearListeners() throw() { - disposeListeners_.clear(); - containerListeners_.clear(); - propertyChangeListeners_.clear(); - vetoableChangeListeners_.clear(); - propertiesChangeListeners_.clear(); - //TODO: iterate over children w/ listeners (incl. unmodified ones): - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) - { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - child->clearListeners(); - } - } -} - -css::uno::Any Access::queryInterface(css::uno::Type const & aType) +css::uno::Sequence< css::uno::Type > Access::getTypes() throw (css::uno::RuntimeException) { - css::uno::Any res(OWeakObject::queryInterface(aType)); - if (res.hasValue()) { - return res; - } - res = cppu::queryInterface( - aType, static_cast< css::lang::XTypeProvider * >(this), - static_cast< css::lang::XServiceInfo * >(this), - static_cast< css::lang::XComponent * >(this), - static_cast< css::container::XHierarchicalNameAccess * >(this), - static_cast< css::container::XContainer * >(this), - static_cast< css::beans::XExactName * >(this), - static_cast< css::container::XHierarchicalName * >(this), - static_cast< css::container::XNamed * >(this), - static_cast< css::beans::XProperty * >(this), - static_cast< css::container::XElementAccess * >(this), - static_cast< css::container::XNameAccess * >(this)); - if (res.hasValue()) { - return res; - } + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< css::uno::Type > types; + types.push_back(cppu::UnoType< css::uno::XInterface >::get()); + types.push_back(cppu::UnoType< css::uno::XWeak >::get()); + types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get()); + types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get()); + types.push_back(cppu::UnoType< css::lang::XComponent >::get()); + types.push_back(cppu::UnoType< css::container::XContainer >::get()); + types.push_back(cppu::UnoType< css::beans::XExactName >::get()); + types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get()); + types.push_back(cppu::UnoType< css::container::XNamed >::get()); + types.push_back(cppu::UnoType< css::beans::XProperty >::get()); + types.push_back(cppu::UnoType< css::container::XElementAccess >::get()); + types.push_back(cppu::UnoType< css::container::XNameAccess >::get()); if (getNode()->kind() == Node::KIND_GROUP) { - res = cppu::queryInterface( - aType, static_cast< css::beans::XPropertySetInfo * >(this), - static_cast< css::beans::XPropertySet * >(this), - static_cast< css::beans::XMultiPropertySet * >(this), - static_cast< css::beans::XHierarchicalPropertySet * >(this), - static_cast< css::beans::XMultiHierarchicalPropertySet * >(this), - static_cast< css::beans::XHierarchicalPropertySetInfo * >(this)); - if (res.hasValue()) { - return res; - } + types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get()); + types.push_back(cppu::UnoType< css::beans::XPropertySet >::get()); + types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XHierarchicalPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get()); + types.push_back( + cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get()); } if (getRootAccess()->isUpdate()) { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameReplace * >(this)); - if (res.hasValue()) { - return res; - } + types.push_back(cppu::UnoType< css::container::XNameReplace >::get()); + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameReplace >::get()); if (getNode()->kind() != Node::KIND_GROUP || dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) { - res = cppu::queryInterface( - aType, static_cast< css::container::XNameContainer * >(this)); - if (res.hasValue()) { - return res; - } + types.push_back( + cppu::UnoType< css::container::XNameContainer >::get()); } if (getNode()->kind() == Node::KIND_SET) { - res = cppu::queryInterface( - aType, static_cast< css::lang::XSingleServiceFactory * >(this)); + types.push_back( + cppu::UnoType< css::lang::XSingleServiceFactory >::get()); } + } else { + types.push_back( + cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); } - return res; -} - -Components & Access::getComponents() const { - return components_; -} - -void Access::checkLocalizedPropertyAccess() { - if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && - !Components::allLocales(getRootAccess()->getLocale())) - { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr Access to specialized LocalizedPropertyNode")), - static_cast< cppu::OWeakObject * >(this)); - } + addTypes(&types); + return types.getAsConstList(); } -rtl::Reference< Node > Access::getParentNode() { - rtl::Reference< Access > parent(getParentAccess()); - return parent.is() ? parent->getNode() : rtl::Reference< Node >(); +css::uno::Sequence< sal_Int8 > Access::getImplementationId() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return css::uno::Sequence< sal_Int8 >(); } -rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) { - ModifiedChildren::iterator i(modifiedChildren_.find(name)); - return i == modifiedChildren_.end() - ? getUnmodifiedChild(name) : getModifiedChild(i); +rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("org.openoffice-configmgr::Access")); } -std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() { - std::vector< rtl::Reference< ChildAccess > > vec; - NodeMap & members = getNode()->getMembers(); - for (NodeMap::iterator i(members.begin()); i != members.end(); ++i) { - if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) { - vec.push_back(getUnmodifiedChild(i->first)); - assert(vec.back().is()); - } - } - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) - { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - vec.push_back(child); +sal_Bool Access::supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames()); + for (sal_Int32 i = 0; i < names.getLength(); ++i) { + if (names[i] == ServiceName) { + return true; } } - return vec; + return false; } -void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) { - bool ok; - switch (type) { - case TYPE_NIL: - assert(false); - // fall through (cannot happen) - case TYPE_ERROR: - ok = false; - break; - case TYPE_ANY: - switch (getDynamicType(value)) { - case TYPE_ANY: - assert(false); - // fall through (cannot happen) - case TYPE_ERROR: - ok = false; - break; - case TYPE_NIL: - ok = nillable; - break; - default: - ok = true; - break; - } - break; - default: - ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable; - break; - } - if (!ok) { - throw css::lang::IllegalArgumentException( - rtl::OUString( +css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< rtl::OUString > services; + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr inappropriate property value")), - static_cast< cppu::OWeakObject * >(this), -1); + "com.sun.star.configuration.ConfigurationUpdateAccess"))); + } + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.HierarchyAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.HierarchyElement"))); + if (getNode()->kind() == Node::KIND_GROUP) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.GroupAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.PropertyHierarchy"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.GroupUpdate"))); + } + } else { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SetAccess"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SimpleSetAccess"))); + if (getRootAccess()->isUpdate()) { + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SetUpdate"))); + services.push_back( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.SimpleSetUpdate"))); + } } + addSupportedServiceNames(&services); + return services.getAsConstList(); } -void Access::insertLocalizedValueChild( - rtl::OUString const & name, css::uno::Any const & value, - Modifications * localModifications) -{ - assert(localModifications != 0); - LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >( - getNode().get()); - checkValue(value, locprop->getStaticType(), locprop->isNillable()); - rtl::Reference< ChildAccess > child( - new ChildAccess( - components_, getRootAccess(), this, name, - new LocalizedValueNode(Data::NO_LAYER, value))); - markChildAsModified(child); - localModifications->add(child->getRelativePath()); +void Access::dispose() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + if (getParentAccess().is()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr dispose inappropriate Access")), + static_cast< cppu::OWeakObject * >(this)); + } + if (disposed_) { + return; + } + initDisposeBroadcaster(&bc); + clearListeners(); + disposed_ = true; + } + bc.send(); } -void Access::reportChildChanges( - std::vector< css::util::ElementChange > * changes) +void Access::addEventListener( + css::uno::Reference< css::lang::XEventListener > const & xListener) + throw (css::uno::RuntimeException) { - assert(changes != 0); - for (ModifiedChildren::iterator i(modifiedChildren_.begin()); - i != modifiedChildren_.end(); ++i) + assert(thisIs(IS_ANY)); { - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - child->reportChildChanges(changes); - changes->push_back(css::util::ElementChange()); - //TODO: changed value and/or inserted node - } else { - changes->push_back(css::util::ElementChange()); //TODO: removed node + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!disposed_) { + disposeListeners_.insert(xListener); + return; } } + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } -void Access::commitChildChanges( - bool valid, Modifications * globalModifications) +void Access::removeEventListener( + css::uno::Reference< css::lang::XEventListener > const & aListener) + throw (css::uno::RuntimeException) { - assert(globalModifications != 0); - while (!modifiedChildren_.empty()) { - bool childValid = valid; - ModifiedChildren::iterator i(modifiedChildren_.begin()); - rtl::Reference< ChildAccess > child(getModifiedChild(i)); - if (child.is()) { - childValid = childValid && !child->isFinalized(); - child->commitChanges(childValid, globalModifications); - //TODO: currently, this is called here for directly inserted - // children as well as for children whose sub-children were - // modified (and should never be called for directly removed - // children); clarify what exactly should happen here for - // directly inserted children - } - NodeMap & members = getNode()->getMembers(); - NodeMap::iterator j(members.find(i->first)); - if (child.is()) { - // Inserted: - if (j != members.end()) { - childValid = childValid && - j->second->getFinalized() == Data::NO_LAYER; - if (childValid) { - child->getNode()->setMandatory(j->second->getMandatory()); - } - } - if (childValid) { - members[i->first] = child->getNode(); - } - } else { - // Removed: - childValid = childValid && j != members.end() && - j->second->getFinalized() == Data::NO_LAYER && - j->second->getMandatory() == Data::NO_LAYER; - if (childValid) { - members.erase(j); - } - } - if (childValid && i->second.directlyModified) { - Path path(getAbsolutePath()); - path.push_back(i->first); - components_.addModification(path); - globalModifications->add(path); - } - i->second.child->committed(); - modifiedChildren_.erase(i); + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + DisposeListeners::iterator i(disposeListeners_.find(aListener)); + if (i != disposeListeners_.end()) { + disposeListeners_.erase(i); } } -void Access::initBroadcasterAndChanges( - Modifications::Node const & modifications, Broadcaster * broadcaster, - std::vector< css::util::ElementChange > * allChanges) +css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< Node > p(getNode()); + switch (p->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + return mapType( + dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType()); + case Node::KIND_GROUP: + //TODO: Should a specific type be returned for a non-extensible group + // with homogeneous members or for an extensible group that currently + // has only homegeneous members? + return cppu::UnoType< cppu::UnoVoidType >::get(); + case Node::KIND_SET: + return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct? + default: + assert(false); + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), + static_cast< cppu::OWeakObject * >(this)); + } +} + +sal_Bool Access::hasElements() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return !getAllChildren().empty(); //TODO: optimize +} + +css::uno::Any Access::getByName(rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(broadcaster != 0); - comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges; - bool collectPropChanges = !propertiesChangeListeners_.empty(); - for (Modifications::Node::Children::const_iterator i( - modifications.children.begin()); - i != modifications.children.end(); ++i) + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +css::uno::Sequence< rtl::OUString > Access::getElementNames() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); + comphelper::SequenceAsVector< rtl::OUString > names; + for (std::vector< rtl::Reference< ChildAccess > >::iterator i( + children.begin()); + i != children.end(); ++i) { - rtl::Reference< ChildAccess > child(getChild(i->first)); - if (child.is()) { - switch (child->getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - if (!i->second.children.empty()) { - if (Components::allLocales(getRootAccess()->getLocale())) { - child->initBroadcasterAndChanges( - i->second, broadcaster, allChanges); - //TODO: if allChanges==0, recurse only into children - // w/ listeners - } else { - //TODO: filter child mods that are irrelevant for - // locale: - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster-> - addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >( - this), - css::uno::makeAny(i->first), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >( - this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >( - this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - } - // else: spurious Modifications::Node not representing a change - break; - case Node::KIND_LOCALIZED_VALUE: - assert(Components::allLocales(getRootAccess()->getLocale())); - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), child->asValue(), - css::uno::Any())); - //TODO: distinguish add/modify; non-void ReplacedElement - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - child->asValue(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - assert(!collectPropChanges); - break; - case Node::KIND_PROPERTY: - { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementReplacedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), child->asValue(), - css::uno::Any())); - //TODO: distinguish add/remove/modify; non-void - // ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - child->asValue(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - break; - case Node::KIND_GROUP: - case Node::KIND_SET: - if (i->second.children.empty()) { - if (child->getNode()->getTemplateName().getLength() != 0) { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster-> - addContainerElementInsertedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >( - this), - css::uno::makeAny(i->first), - child->asValue(), css::uno::Any())); - } - if (allChanges != 0) { - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny( - child->getRelativePathRepresentation()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void Element, ReplacedElement - } - } - // else: spurious Modifications::Node not representing a - // change - } else { - child->initBroadcasterAndChanges( - i->second, broadcaster, allChanges); - //TODO: if allChanges==0, recurse only into children w/ - // listeners - } - break; - } - } else { - switch (getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - // Removed localized property value: - assert(Components::allLocales(getRootAccess()->getLocale())); - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), css::uno::Any(), - css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (allChanges != 0) { - rtl::OUStringBuffer path(getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append( - Data::createSegment( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), - i->first)); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - assert(!collectPropChanges); - break; - case Node::KIND_GROUP: - { - // Removed (non-localized) extension property: - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), css::uno::Any(), - css::uno::Any())); - //TODO: non-void ReplacedElement - } - PropertyChangeListeners::iterator j( - propertyChangeListeners_.find(i->first)); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - j = propertyChangeListeners_.find(rtl::OUString()); - if (j != propertyChangeListeners_.end()) { - for (PropertyChangeListenersElement::iterator k( - j->second.begin()); - k != j->second.end(); ++k) - { - broadcaster->addPropertyChangeNotification( - *k, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - if (allChanges != 0) { - rtl::OUStringBuffer path( - getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(i->first); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (collectPropChanges) { - propChanges.push_back( - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), - i->first, false, -1, css::uno::Any(), - css::uno::Any())); - } - } - break; - case Node::KIND_SET: - // Removed set member: - if (i->second.children.empty()) { - for (ContainerListeners::iterator j( - containerListeners_.begin()); - j != containerListeners_.end(); ++j) - { - broadcaster->addContainerElementRemovedNotification( - *j, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny(i->first), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - if (allChanges != 0) { - rtl::OUStringBuffer path( - getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append( - Data::createSegment( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), - i->first)); - allChanges->push_back( - css::util::ElementChange( - css::uno::makeAny(path.makeStringAndClear()), - css::uno::Any(), css::uno::Any())); - //TODO: non-void ReplacedElement - } - } - // else: spurious Modifications::Node not representing a change - break; - default: - assert(false); // this cannot happen - break; - } - } + names.push_back((*i)->getNameInternal()); } - if (!propChanges.empty()) { - css::uno::Sequence< css::beans::PropertyChangeEvent > seq( - propChanges.getAsConstList()); - for (PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.begin()); - i != propertiesChangeListeners_.end(); ++i) - { - broadcaster->addPropertiesChangeNotification(*i, seq); + return names.getAsConstList(); +} + +sal_Bool Access::hasByName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getChild(aName).is(); +} + +css::uno::Any Access::getByHierarchicalName(rtl::OUString const & aName) + throw (css::container::NoSuchElementException, css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getSubChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getSubChild(aName).is(); +} + +void Access::replaceByHierarchicalName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + //TODO: Actually support sets and combine with replaceByName: + assert(thisIs(IS_UPDATE)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getSubChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + child->checkFinalized(); + rtl::Reference< Node > parent(child->getParentNode()); + assert(parent.is()); + Modifications localMods; + switch (parent->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + case Node::KIND_GROUP: + child->setProperty(aElement, &localMods); + break; + case Node::KIND_SET: + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr::Access::replaceByHierarchicalName does not" + " currently support set members")), + static_cast< cppu::OWeakObject * >(this), 0); + case Node::KIND_ROOT: + throw css::lang::IllegalArgumentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr::Access::replaceByHierarchicalName does not" + " allow changing component ")) + + aName), + static_cast< cppu::OWeakObject * >(this), 0); + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } + bc.send(); } -bool Access::isDisposed() const { - return disposed_; -} - -Access::ModifiedChild::ModifiedChild() {} - -Access::ModifiedChild::ModifiedChild( - rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified): - child(theChild), directlyModified(theDirectlyModified) -{} - -css::uno::Sequence< css::uno::Type > Access::getTypes() +void Access::addContainerListener( + css::uno::Reference< css::container::XContainerListener > const & xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - comphelper::SequenceAsVector< css::uno::Type > types; - types.push_back(cppu::UnoType< css::uno::XInterface >::get()); - types.push_back(cppu::UnoType< css::uno::XWeak >::get()); - types.push_back(cppu::UnoType< css::lang::XTypeProvider >::get()); - types.push_back(cppu::UnoType< css::lang::XServiceInfo >::get()); - types.push_back(cppu::UnoType< css::lang::XComponent >::get()); - types.push_back( - cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); - types.push_back(cppu::UnoType< css::container::XContainer >::get()); - types.push_back(cppu::UnoType< css::beans::XExactName >::get()); - types.push_back(cppu::UnoType< css::container::XHierarchicalName >::get()); - types.push_back(cppu::UnoType< css::container::XNamed >::get()); - types.push_back(cppu::UnoType< css::beans::XProperty >::get()); - types.push_back(cppu::UnoType< css::container::XElementAccess >::get()); - types.push_back(cppu::UnoType< css::container::XNameAccess >::get()); - if (getNode()->kind() == Node::KIND_GROUP) { - types.push_back(cppu::UnoType< css::beans::XPropertySetInfo >::get()); - types.push_back(cppu::UnoType< css::beans::XPropertySet >::get()); - types.push_back(cppu::UnoType< css::beans::XMultiPropertySet >::get()); - types.push_back( - cppu::UnoType< css::beans::XHierarchicalPropertySet >::get()); - types.push_back( - cppu::UnoType< css::beans::XMultiHierarchicalPropertySet >::get()); - types.push_back( - cppu::UnoType< css::beans::XHierarchicalPropertySetInfo >::get()); - } - if (getRootAccess()->isUpdate()) { - types.push_back(cppu::UnoType< css::container::XNameReplace >::get()); - if (getNode()->kind() != Node::KIND_GROUP || - dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) - { - types.push_back( - cppu::UnoType< css::container::XNameContainer >::get()); + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + if (!xListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); } - if (getNode()->kind() == Node::KIND_SET) { - types.push_back( - cppu::UnoType< css::lang::XSingleServiceFactory >::get()); + if (!disposed_) { + containerListeners_.insert(xListener); + return; } } - addTypes(&types); - return types.getAsConstList(); + try { + xListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } -css::uno::Sequence< sal_Int8 > Access::getImplementationId() +void Access::removeContainerListener( + css::uno::Reference< css::container::XContainerListener > const & xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return css::uno::Sequence< sal_Int8 >(); + ContainerListeners::iterator i(containerListeners_.find(xListener)); + if (i != containerListeners_.end()) { + containerListeners_.erase(i); + } } -rtl::OUString Access::getImplementationName() throw (css::uno::RuntimeException) +rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName) + throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("org.openoffice-configmgr::Access")); + return aApproximateName; } -sal_Bool Access::supportsService(rtl::OUString const & ServiceName) +css::uno::Sequence< css::beans::Property > Access::getProperties() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); + comphelper::SequenceAsVector< css::beans::Property > properties; + for (std::vector< rtl::Reference< ChildAccess > >::iterator i( + children.begin()); + i != children.end(); ++i) + { + properties.push_back((*i)->asProperty()); + } + return properties.getAsConstList(); +} + +css::beans::Property Access::getPropertyByName(rtl::OUString const & aName) + throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asProperty(); +} + +sal_Bool Access::hasPropertyByName(rtl::OUString const & Name) throw (css::uno::RuntimeException) { + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + return getChild(Name).is(); +} + +rtl::OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames()); - for (sal_Int32 i = 0; i < names.getLength(); ++i) { - if (names[i] == ServiceName) { - return true; - } + // For backwards compatibility, return an absolute path representation where + // available: + rtl::OUStringBuffer path; + rtl::Reference< RootAccess > root(getRootAccess()); + if (root.is()) { + path.append(root->getAbsolutePathRepresentation()); } - return false; + rtl::OUString rel(getRelativePathRepresentation()); + if (path.getLength() != 0 && rel.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(rel); + return path.makeStringAndClear(); } -css::uno::Sequence< rtl::OUString > Access::getSupportedServiceNames() - throw (css::uno::RuntimeException) +rtl::OUString Access::composeHierarchicalName( + rtl::OUString const & aRelativeName) + throw ( + css::lang::IllegalArgumentException, css::lang::NoSupportException, + css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - comphelper::SequenceAsVector< rtl::OUString > services; - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationAccess"))); - if (getRootAccess()->isUpdate()) { - services.push_back( + if (aRelativeName.getLength() == 0 || aRelativeName[0] == '/') { + throw css::lang::IllegalArgumentException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.ConfigurationUpdateAccess"))); + "configmgr composeHierarchicalName inappropriate relative" + " name")), + static_cast< cppu::OWeakObject * >(this), -1); } - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.HierarchyAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.HierarchyElement"))); - if (getNode()->kind() == Node::KIND_GROUP) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.GroupAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.PropertyHierarchy"))); - if (getRootAccess()->isUpdate()) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.GroupUpdate"))); - } - } else { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SetAccess"))); - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SimpleSetAccess"))); - if (getRootAccess()->isUpdate()) { - services.push_back( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SetUpdate"))); - services.push_back( + rtl::OUStringBuffer path(getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(aRelativeName); + return path.makeStringAndClear(); +} + +rtl::OUString Access::getName() throw (css::uno::RuntimeException) { + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return getNameInternal(); +} + +void Access::setName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + checkFinalized(); + Modifications localMods; + switch (getNode()->kind()) { + case Node::KIND_GROUP: + case Node::KIND_SET: + { + rtl::Reference< Access > parent(getParentAccess()); + if (parent.is()) { + rtl::Reference< Node > node(getNode()); + if (node->getTemplateName().getLength() != 0) { + rtl::Reference< ChildAccess > other( + parent->getChild(aName)); + if (other.get() == this) { + break; + } + if (node->getMandatory() == Data::NO_LAYER && + !(other.is() && other->isFinalized())) + { + rtl::Reference< RootAccess > root(getRootAccess()); + rtl::Reference< ChildAccess > childAccess( + dynamic_cast< ChildAccess * >(this)); + localMods.add(getRelativePath()); + // unbind() modifies the parent chain that + // markChildAsModified() walks, so order is + // important: + parent->markChildAsModified(childAccess); + //TODO: must not throw + childAccess->unbind(); // must not throw + if (other.is()) { + other->unbind(); // must not throw + } + childAccess->bind(root, parent, aName); + // must not throw + parent->markChildAsModified(childAccess); + //TODO: must not throw + localMods.add(getRelativePath()); + break; + } + } + } + } + // fall through + case Node::KIND_LOCALIZED_PROPERTY: + // renaming a property could only work for an extension property, + // but a localized property is never an extension property + throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.configuration.SimpleSetUpdate"))); + "configmgr setName inappropriate node")), + static_cast< cppu::OWeakObject * >(this)); + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - addSupportedServiceNames(&services); - return services.getAsConstList(); + bc.send(); } -void Access::dispose() throw (css::uno::RuntimeException) { +css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException) +{ assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + return asProperty(); +} + +css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + return this; +} + +void Access::setPropertyValue( + rtl::OUString const & aPropertyName, css::uno::Any const & aValue) + throw ( + css::beans::UnknownPropertyException, css::beans::PropertyVetoException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); Broadcaster bc; { osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - if (getParentAccess().is()) { + if (!getRootAccess()->isUpdate()) { throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr dispose inappropriate Access")), + "configmgr setPropertyValue on non-update access")), static_cast< cppu::OWeakObject * >(this)); } - if (disposed_) { - return; + Modifications localMods; + if (!setChildProperty(aPropertyName, aValue, &localMods)) { + throw css::beans::UnknownPropertyException( + aPropertyName, static_cast< cppu::OWeakObject * >(this)); } - initDisposeBroadcaster(&bc); - clearListeners(); - disposed_ = true; + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -void Access::addEventListener( - css::uno::Reference< css::lang::XEventListener > const & xListener) - throw (css::uno::RuntimeException) +css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getChild(PropertyName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + PropertyName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asValue(); +} + +void Access::addPropertyChangeListener( + rtl::OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + xListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); { osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); if (!xListener.is()) { throw css::uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), static_cast< cppu::OWeakObject * >(this)); } + checkKnownProperty(aPropertyName); if (!disposed_) { - disposeListeners_.insert(xListener); + propertyChangeListeners_[aPropertyName].insert(xListener); return; } } @@ -1039,130 +807,163 @@ void Access::addEventListener( } catch (css::lang::DisposedException &) {} } -void Access::removeEventListener( - css::uno::Reference< css::lang::XEventListener > const & aListener) - throw (css::uno::RuntimeException) +void Access::removePropertyChangeListener( + rtl::OUString const & aPropertyName, + css::uno::Reference< css::beans::XPropertyChangeListener > const & + aListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - DisposeListeners::iterator i(disposeListeners_.find(aListener)); - if (i != disposeListeners_.end()) { - disposeListeners_.erase(i); + checkKnownProperty(aPropertyName); + PropertyChangeListeners::iterator i( + propertyChangeListeners_.find(aPropertyName)); + if (i != propertyChangeListeners_.end()) { + PropertyChangeListenersElement::iterator j(i->second.find(aListener)); + if (j != i->second.end()) { + i->second.erase(j); + if (i->second.empty()) { + propertyChangeListeners_.erase(i); + } + } } } -css::uno::Type Access::getElementType() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< Node > p(getNode()); - switch (p->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - return mapType( - dynamic_cast< LocalizedPropertyNode * >(p.get())->getStaticType()); - case Node::KIND_GROUP: - //TODO: Should a specific type be returned for a non-extensible group - // with homogeneous members or for an extensible group that currently - // has only homegeneous members? - return cppu::UnoType< cppu::UnoVoidType >::get(); - case Node::KIND_SET: - return cppu::UnoType< cppu::UnoVoidType >::get(); //TODO: correct? - default: - assert(false); - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), - static_cast< cppu::OWeakObject * >(this)); +void Access::addVetoableChangeListener( + rtl::OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) + throw ( + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + { + osl::MutexGuard g(*lock_); + if (!aListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + checkKnownProperty(PropertyName); + if (!disposed_) { + vetoableChangeListeners_[PropertyName].insert(aListener); + //TODO: actually call vetoableChangeListeners_ + return; + } } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} } -sal_Bool Access::hasElements() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return !getAllChildren().empty(); //TODO: optimize -} - -css::uno::Any Access::getByName(rtl::OUString const & aName) +void Access::removeVetoableChangeListener( + rtl::OUString const & PropertyName, + css::uno::Reference< css::beans::XVetoableChangeListener > const & + aListener) throw ( - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) + css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is()) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); + checkKnownProperty(PropertyName); + VetoableChangeListeners::iterator i( + vetoableChangeListeners_.find(PropertyName)); + if (i != vetoableChangeListeners_.end()) { + VetoableChangeListenersElement::iterator j(i->second.find(aListener)); + if (j != i->second.end()) { + i->second.erase(j); + if (i->second.empty()) { + vetoableChangeListeners_.erase(i); + } + } } - return child->asValue(); } -css::uno::Sequence< rtl::OUString > Access::getElementNames() - throw (css::uno::RuntimeException) +void Access::setPropertyValues( + css::uno::Sequence< rtl::OUString > const & aPropertyNames, + css::uno::Sequence< css::uno::Any > const & aValues) + throw ( + css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); - comphelper::SequenceAsVector< rtl::OUString > names; - for (std::vector< rtl::Reference< ChildAccess > >::iterator i( - children.begin()); - i != children.end(); ++i) + assert(thisIs(IS_GROUP)); + Broadcaster bc; { - names.push_back((*i)->getNameInternal()); + osl::MutexGuard g(*lock_); + if (!getRootAccess()->isUpdate()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues on non-update access")), + static_cast< cppu::OWeakObject * >(this)); + } + if (aPropertyNames.getLength() != aValues.getLength()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues: aPropertyNames/aValues of" + " different length")), + static_cast< cppu::OWeakObject * >(this), -1); + } + Modifications localMods; + for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { + if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues inappropriate property" + " name")), + static_cast< cppu::OWeakObject * >(this), -1); + } + } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - return names.getAsConstList(); + bc.send(); } -sal_Bool Access::hasByName(rtl::OUString const & aName) +css::uno::Sequence< css::uno::Any > Access::getPropertyValues( + css::uno::Sequence< rtl::OUString > const & aPropertyNames) throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getChild(aName).is(); -} - -css::uno::Any Access::getByHierarchicalName(rtl::OUString const & aName) - throw (css::container::NoSuchElementException, css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getSubChild(aName)); - if (!child.is()) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); + css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength()); + for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i])); + if (!child.is()) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr getPropertyValues inappropriate property" + " name")), + static_cast< cppu::OWeakObject * >(this)); + } + vals[i] = child->asValue(); } - return child->asValue(); -} - -sal_Bool Access::hasByHierarchicalName(rtl::OUString const & aName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getSubChild(aName).is(); + return vals; } -void Access::addContainerListener( - css::uno::Reference< css::container::XContainerListener > const & xListener) +void Access::addPropertiesChangeListener( + css::uno::Sequence< rtl::OUString > const &, + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); + assert(thisIs(IS_GROUP)); { osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); if (!xListener.is()) { throw css::uno::RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), static_cast< cppu::OWeakObject * >(this)); } if (!disposed_) { - containerListeners_.insert(xListener); + propertiesChangeListeners_.insert(xListener); return; } } @@ -1172,200 +973,47 @@ void Access::addContainerListener( } catch (css::lang::DisposedException &) {} } -void Access::removeContainerListener( - css::uno::Reference< css::container::XContainerListener > const & xListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - ContainerListeners::iterator i(containerListeners_.find(xListener)); - if (i != containerListeners_.end()) { - containerListeners_.erase(i); - } -} - -rtl::OUString Access::getExactName(rtl::OUString const & aApproximateName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return aApproximateName; -} - -css::uno::Sequence< css::beans::Property > Access::getProperties() +void Access::removePropertiesChangeListener( + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - std::vector< rtl::Reference< ChildAccess > > children(getAllChildren()); - comphelper::SequenceAsVector< css::beans::Property > properties; - for (std::vector< rtl::Reference< ChildAccess > >::iterator i( - children.begin()); - i != children.end(); ++i) - { - properties.push_back((*i)->asProperty()); - } - return properties.getAsConstList(); -} - -css::beans::Property Access::getPropertyByName(rtl::OUString const & aName) - throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aName, static_cast< cppu::OWeakObject * >(this)); + PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.find(xListener)); + if (i != propertiesChangeListeners_.end()) { + propertiesChangeListeners_.erase(i); } - return child->asProperty(); } -sal_Bool Access::hasPropertyByName(rtl::OUString const & Name) +void Access::firePropertiesChangeEvent( + css::uno::Sequence< rtl::OUString > const & aPropertyNames, + css::uno::Reference< css::beans::XPropertiesChangeListener > const & + xListener) throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - return getChild(Name).is(); -} - -rtl::OUString Access::getHierarchicalName() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - // For backwards compatibility, return an absolute path representation where - // available: - rtl::OUStringBuffer path; - rtl::Reference< RootAccess > root(getRootAccess()); - if (root.is()) { - path.append(root->getAbsolutePathRepresentation()); - } - rtl::OUString rel(getRelativePathRepresentation()); - if (path.getLength() != 0 && rel.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(rel); - return path.makeStringAndClear(); -} - -rtl::OUString Access::composeHierarchicalName( - rtl::OUString const & aRelativeName) - throw ( - css::lang::IllegalArgumentException, css::lang::NoSupportException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - if (aRelativeName.getLength() == 0 || aRelativeName[0] == '/') { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr composeHierarchicalName inappropriate relative" - " name")), - static_cast< cppu::OWeakObject * >(this), -1); - } - rtl::OUStringBuffer path(getRelativePathRepresentation()); - if (path.getLength() != 0) { - path.append(sal_Unicode('/')); - } - path.append(aRelativeName); - return path.makeStringAndClear(); -} - -rtl::OUString Access::getName() throw (css::uno::RuntimeException) { - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return getNameInternal(); -} - -void Access::setName(rtl::OUString const & aName) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - checkFinalized(); - Modifications localMods; - switch (getNode()->kind()) { - case Node::KIND_GROUP: - case Node::KIND_SET: - { - rtl::Reference< Access > parent(getParentAccess()); - if (parent.is()) { - rtl::Reference< Node > node(getNode()); - if (node->getTemplateName().getLength() != 0) { - rtl::Reference< ChildAccess > other( - parent->getChild(aName)); - if (other.get() == this) { - break; - } - if (node->getMandatory() == Data::NO_LAYER && - !(other.is() && other->isFinalized())) - { - rtl::Reference< RootAccess > root(getRootAccess()); - rtl::Reference< ChildAccess > childAccess( - dynamic_cast< ChildAccess * >(this)); - localMods.add(getRelativePath()); - // unbind() modifies the parent chain that - // markChildAsModified() walks, so order is - // important: - parent->markChildAsModified(childAccess); - //TODO: must not throw - childAccess->unbind(); // must not throw - if (other.is()) { - other->unbind(); // must not throw - } - childAccess->bind(root, parent, aName); - // must not throw - parent->markChildAsModified(childAccess); - //TODO: must not throw - localMods.add(getRelativePath()); - break; - } - } - } - } - // fall through - case Node::KIND_LOCALIZED_PROPERTY: - // renaming a property could only work for an extension property, - // but a localized property is never an extension property - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setName inappropriate node")), - static_cast< cppu::OWeakObject * >(this)); - default: - assert(false); // this cannot happen - break; - } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + css::uno::Sequence< css::beans::PropertyChangeEvent > events( + aPropertyNames.getLength()); + for (sal_Int32 i = 0; i < events.getLength(); ++i) { + events[i].Source = static_cast< cppu::OWeakObject * >(this); + events[i].PropertyName = aPropertyNames[i]; + events[i].Further = false; + events[i].PropertyHandle = -1; } - bc.send(); -} - -css::beans::Property Access::getAsProperty() throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - return asProperty(); + xListener->propertiesChange(events); } -css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo() - throw (css::uno::RuntimeException) -{ +css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > +Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); return this; } -void Access::setPropertyValue( - rtl::OUString const & aPropertyName, css::uno::Any const & aValue) +void Access::setHierarchicalPropertyValue( + rtl::OUString const & aHierarchicalPropertyName, + css::uno::Any const & aValue) throw ( css::beans::UnknownPropertyException, css::beans::PropertyVetoException, css::lang::IllegalArgumentException, css::lang::WrappedTargetException, @@ -1379,583 +1027,997 @@ void Access::setPropertyValue( throw css::uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValue on non-update access")), + "configmgr setHierarchicalPropertyName on non-update" + " access")), static_cast< cppu::OWeakObject * >(this)); } - Modifications localMods; - if (!setChildProperty(aPropertyName, aValue, &localMods)) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyName)); + if (!child.is()) { throw css::beans::UnknownPropertyException( - aPropertyName, static_cast< cppu::OWeakObject * >(this)); + aHierarchicalPropertyName, + static_cast< cppu::OWeakObject * >(this)); } + child->checkFinalized(); + Modifications localMods; + child->setProperty(aValue, &localMods); getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -css::uno::Any Access::getPropertyValue(rtl::OUString const & PropertyName) +css::uno::Any Access::getHierarchicalPropertyValue( + rtl::OUString const & aHierarchicalPropertyName) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::beans::UnknownPropertyException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getChild(PropertyName)); + rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName)); if (!child.is()) { throw css::beans::UnknownPropertyException( - PropertyName, static_cast< cppu::OWeakObject * >(this)); + aHierarchicalPropertyName, + static_cast< cppu::OWeakObject * >(this)); } return child->asValue(); } -void Access::addPropertyChangeListener( - rtl::OUString const & aPropertyName, - css::uno::Reference< css::beans::XPropertyChangeListener > const & - xListener) +void Access::setHierarchicalPropertyValues( + css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames, + css::uno::Sequence< css::uno::Any > const & Values) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) + css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); + Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!xListener.is()) { + if (!getRootAccess()->isUpdate()) { throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setPropertyValues on non-update access")), static_cast< cppu::OWeakObject * >(this)); } - checkKnownProperty(aPropertyName); - if (!disposed_) { - propertyChangeListeners_[aPropertyName].insert(xListener); - return; + if (aHierarchicalPropertyNames.getLength() != Values.getLength()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setHierarchicalPropertyValues:" + " aHierarchicalPropertyNames/Values of different" + " length")), + static_cast< cppu::OWeakObject * >(this), -1); + } + Modifications localMods; + for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyNames[i])); + if (!child.is()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr setHierarchicalPropertyValues" + " inappropriate property name")), + static_cast< cppu::OWeakObject * >(this), -1); + } + child->checkFinalized(); + child->setProperty(Values[i], &localMods); } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - try { - xListener->disposing( - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + bc.send(); } -void Access::removePropertyChangeListener( - rtl::OUString const & aPropertyName, - css::uno::Reference< css::beans::XPropertyChangeListener > const & - aListener) +css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues( + css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, + css::lang::IllegalArgumentException, css::lang::WrappedTargetException, css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); osl::MutexGuard g(*lock_); - checkKnownProperty(aPropertyName); - PropertyChangeListeners::iterator i( - propertyChangeListeners_.find(aPropertyName)); - if (i != propertyChangeListeners_.end()) { - PropertyChangeListenersElement::iterator j(i->second.find(aListener)); - if (j != i->second.end()) { - i->second.erase(j); - if (i->second.empty()) { - propertyChangeListeners_.erase(i); - } + css::uno::Sequence< css::uno::Any > vals( + aHierarchicalPropertyNames.getLength()); + for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { + rtl::Reference< ChildAccess > child( + getSubChild(aHierarchicalPropertyNames[i])); + if (!child.is()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr getHierarchicalPropertyValues inappropriate" + " hierarchical property name")), + static_cast< cppu::OWeakObject * >(this), -1); } + vals[i] = child->asValue(); } + return vals; } -void Access::addVetoableChangeListener( - rtl::OUString const & PropertyName, - css::uno::Reference< css::beans::XVetoableChangeListener > const & - aListener) - throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) +css::beans::Property Access::getPropertyByHierarchicalName( + rtl::OUString const & aHierarchicalName) + throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +{ + assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName)); + if (!child.is()) { + throw css::beans::UnknownPropertyException( + aHierarchicalName, static_cast< cppu::OWeakObject * >(this)); + } + return child->asProperty(); +} + +sal_Bool Access::hasPropertyByHierarchicalName( + rtl::OUString const & aHierarchicalName) + throw (css::uno::RuntimeException) { assert(thisIs(IS_GROUP)); + osl::MutexGuard g(*lock_); + return getSubChild(aHierarchicalName).is(); +} + +void Access::replaceByName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!aListener.is()) { - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), - static_cast< cppu::OWeakObject * >(this)); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } - checkKnownProperty(PropertyName); - if (!disposed_) { - vetoableChangeListeners_[PropertyName].insert(aListener); - //TODO: actually call vetoableChangeListeners_ - return; + child->checkFinalized(); + Modifications localMods; + switch (getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + case Node::KIND_GROUP: + child->setProperty(aElement, &localMods); + break; + case Node::KIND_SET: + { + rtl::Reference< ChildAccess > freeAcc( + getFreeSetMember(aElement)); + rtl::Reference< RootAccess > root(getRootAccess()); + localMods.add(child->getRelativePath()); + child->unbind(); // must not throw + freeAcc->bind(root, this, aName); // must not throw + markChildAsModified(freeAcc); //TODO: must not throw + } + break; + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - try { - aListener->disposing( - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + bc.send(); } -void Access::removeVetoableChangeListener( - rtl::OUString const & PropertyName, - css::uno::Reference< css::beans::XVetoableChangeListener > const & - aListener) +void Access::insertByName( + rtl::OUString const & aName, css::uno::Any const & aElement) throw ( - css::beans::UnknownPropertyException, css::lang::WrappedTargetException, - css::uno::RuntimeException) + css::lang::IllegalArgumentException, + css::container::ElementExistException, + css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - checkKnownProperty(PropertyName); - VetoableChangeListeners::iterator i( - vetoableChangeListeners_.find(PropertyName)); - if (i != vetoableChangeListeners_.end()) { - VetoableChangeListenersElement::iterator j(i->second.find(aListener)); - if (j != i->second.end()) { - i->second.erase(j); - if (i->second.empty()) { - vetoableChangeListeners_.erase(i); + assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + checkFinalized(); + if (getChild(aName).is()) { + throw css::container::ElementExistException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + Modifications localMods; + switch (getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + insertLocalizedValueChild(aName, aElement, &localMods); + break; + case Node::KIND_GROUP: + { + checkValue(aElement, TYPE_ANY, true); + rtl::Reference< ChildAccess > child( + new ChildAccess( + components_, getRootAccess(), this, aName, + new PropertyNode( + Data::NO_LAYER, TYPE_ANY, true, aElement, true))); + markChildAsModified(child); + localMods.add(child->getRelativePath()); + } + break; + case Node::KIND_SET: + { + rtl::Reference< ChildAccess > freeAcc( + getFreeSetMember(aElement)); + freeAcc->bind(getRootAccess(), this, aName); // must not throw + markChildAsModified(freeAcc); //TODO: must not throw + localMods.add(freeAcc->getRelativePath()); } + break; + default: + assert(false); // this cannot happen + break; } + getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } + bc.send(); } -void Access::setPropertyValues( - css::uno::Sequence< rtl::OUString > const & aPropertyNames, - css::uno::Sequence< css::uno::Any > const & aValues) +void Access::removeByName(rtl::OUString const & aName) throw ( - css::beans::PropertyVetoException, css::lang::IllegalArgumentException, + css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); + assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); Broadcaster bc; { osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues on non-update access")), - static_cast< cppu::OWeakObject * >(this)); - } - if (aPropertyNames.getLength() != aValues.getLength()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues: aPropertyNames/aValues of" - " different length")), - static_cast< cppu::OWeakObject * >(this), -1); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getChild(aName)); + if (!child.is() || child->isFinalized() || + child->getNode()->getMandatory() != Data::NO_LAYER) + { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } - Modifications localMods; - for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { - if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues inappropriate property" - " name")), - static_cast< cppu::OWeakObject * >(this), -1); + if (getNode()->kind() == Node::KIND_GROUP) { + rtl::Reference< Node > p(child->getNode()); + if (p->kind() != Node::KIND_PROPERTY || + !dynamic_cast< PropertyNode * >(p.get())->isExtension()) + { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); } } + Modifications localMods; + localMods.add(child->getRelativePath()); + // unbind() modifies the parent chain that markChildAsModified() walks, + // so order is important: + markChildAsModified(child); //TODO: must not throw + child->unbind(); getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } bc.send(); } -css::uno::Sequence< css::uno::Any > Access::getPropertyValues( - css::uno::Sequence< rtl::OUString > const & aPropertyNames) - throw (css::uno::RuntimeException) +css::uno::Reference< css::uno::XInterface > Access::createInstance() + throw (css::uno::Exception, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength()); - for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child(getChild(aPropertyNames[i])); - if (!child.is()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr getPropertyValues inappropriate property" - " name")), - static_cast< cppu::OWeakObject * >(this)); - } - vals[i] = child->asValue(); + assert(thisIs(IS_SET|IS_UPDATE)); + rtl::OUString tmplName( + dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName()); + rtl::Reference< Node > tmpl( + components_.getTemplate(Data::NO_LAYER, tmplName)); + if (!tmpl.is()) { + throw css::uno::Exception( + (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) + + tmplName), + static_cast< cppu::OWeakObject * >(this)); } - return vals; + rtl::Reference< Node > node(tmpl->clone(true)); + node->setLayer(Data::NO_LAYER); + return static_cast< cppu::OWeakObject * >( + new ChildAccess(components_, getRootAccess(), node)); } -void Access::addPropertiesChangeListener( - css::uno::Sequence< rtl::OUString > const &, - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) - throw (css::uno::RuntimeException) +css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments( + css::uno::Sequence< css::uno::Any > const & aArguments) + throw (css::uno::Exception, css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); + assert(thisIs(IS_SET|IS_UPDATE)); + if (aArguments.getLength() != 0) { + throw css::uno::Exception( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configuration SimpleSetUpdate createInstanceWithArguments" + " must not specify any arguments")), + static_cast< cppu::OWeakObject * >(this)); + } + return createInstance(); +} + +Access::Access(Components & components): + components_(components), disposed_(false) +{ + lock_ = lock(); +} + +Access::~Access() {} + +void Access::initDisposeBroadcaster(Broadcaster * broadcaster) { + assert(broadcaster != 0); + for (DisposeListeners::iterator i(disposeListeners_.begin()); + i != disposeListeners_.end(); ++i) { - osl::MutexGuard g(*lock_); - if (!xListener.is()) { - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), - static_cast< cppu::OWeakObject * >(this)); + broadcaster->addDisposeNotification( + *i, + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + for (ContainerListeners::iterator i(containerListeners_.begin()); + i != containerListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } + for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); + i != propertyChangeListeners_.end(); ++i) + { + for (PropertyChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addDisposeNotification( + j->get(), + css::lang::EventObject( + static_cast< cppu::OWeakObject * >(this))); } - if (!disposed_) { - propertiesChangeListeners_.insert(xListener); - return; + } + for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); + i != vetoableChangeListeners_.end(); ++i) + { + for (VetoableChangeListenersElement::iterator j(i->second.begin()); + j != i->second.end(); ++j) + { + broadcaster->addDisposeNotification( + j->get(), + css::lang::EventObject( + static_cast< cppu::OWeakObject * >(this))); } } - try { - xListener->disposing( + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) + { + broadcaster->addDisposeNotification( + i->get(), css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} + } + //TODO: iterate over children w/ listeners (incl. unmodified ones): + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->initDisposeBroadcaster(broadcaster); + } + } } -void Access::removePropertiesChangeListener( - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.find(xListener)); - if (i != propertiesChangeListeners_.end()) { - propertiesChangeListeners_.erase(i); +void Access::clearListeners() throw() { + disposeListeners_.clear(); + containerListeners_.clear(); + propertyChangeListeners_.clear(); + vetoableChangeListeners_.clear(); + propertiesChangeListeners_.clear(); + //TODO: iterate over children w/ listeners (incl. unmodified ones): + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->clearListeners(); + } } } -void Access::firePropertiesChangeEvent( - css::uno::Sequence< rtl::OUString > const & aPropertyNames, - css::uno::Reference< css::beans::XPropertiesChangeListener > const & - xListener) +css::uno::Any Access::queryInterface(css::uno::Type const & aType) throw (css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - css::uno::Sequence< css::beans::PropertyChangeEvent > events( - aPropertyNames.getLength()); - for (sal_Int32 i = 0; i < events.getLength(); ++i) { - events[i].Source = static_cast< cppu::OWeakObject * >(this); - events[i].PropertyName = aPropertyNames[i]; - events[i].Further = false; - events[i].PropertyHandle = -1; + css::uno::Any res(OWeakObject::queryInterface(aType)); + if (res.hasValue()) { + return res; + } + res = cppu::queryInterface( + aType, static_cast< css::lang::XTypeProvider * >(this), + static_cast< css::lang::XServiceInfo * >(this), + static_cast< css::lang::XComponent * >(this), + static_cast< css::container::XHierarchicalNameAccess * >(this), + static_cast< css::container::XContainer * >(this), + static_cast< css::beans::XExactName * >(this), + static_cast< css::container::XHierarchicalName * >(this), + static_cast< css::container::XNamed * >(this), + static_cast< css::beans::XProperty * >(this), + static_cast< css::container::XElementAccess * >(this), + static_cast< css::container::XNameAccess * >(this)); + if (res.hasValue()) { + return res; + } + if (getNode()->kind() == Node::KIND_GROUP) { + res = cppu::queryInterface( + aType, static_cast< css::beans::XPropertySetInfo * >(this), + static_cast< css::beans::XPropertySet * >(this), + static_cast< css::beans::XMultiPropertySet * >(this), + static_cast< css::beans::XHierarchicalPropertySet * >(this), + static_cast< css::beans::XMultiHierarchicalPropertySet * >(this), + static_cast< css::beans::XHierarchicalPropertySetInfo * >(this)); + if (res.hasValue()) { + return res; + } + } + if (getRootAccess()->isUpdate()) { + res = cppu::queryInterface( + aType, static_cast< css::container::XNameReplace * >(this), + static_cast< css::container::XHierarchicalNameReplace * >(this)); + if (res.hasValue()) { + return res; + } + if (getNode()->kind() != Node::KIND_GROUP || + dynamic_cast< GroupNode * >(getNode().get())->isExtensible()) + { + res = cppu::queryInterface( + aType, static_cast< css::container::XNameContainer * >(this)); + if (res.hasValue()) { + return res; + } + } + if (getNode()->kind() == Node::KIND_SET) { + res = cppu::queryInterface( + aType, static_cast< css::lang::XSingleServiceFactory * >(this)); + } } - xListener->propertiesChange(events); + return res; } -css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > -Access::getHierarchicalPropertySetInfo() throw (css::uno::RuntimeException) { - assert(thisIs(IS_GROUP)); - return this; +Components & Access::getComponents() const { + return components_; } -void Access::setHierarchicalPropertyValue( - rtl::OUString const & aHierarchicalPropertyName, - css::uno::Any const & aValue) - throw ( - css::beans::UnknownPropertyException, css::beans::PropertyVetoException, - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - Broadcaster bc; +void Access::checkLocalizedPropertyAccess() { + if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY && + !Components::allLocales(getRootAccess()->getLocale())) { - osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyName on non-update" - " access")), - static_cast< cppu::OWeakObject * >(this)); - } - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalPropertyName, - static_cast< cppu::OWeakObject * >(this)); - } - child->checkFinalized(); - Modifications localMods; - child->setProperty(aValue, &localMods); - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr Access to specialized LocalizedPropertyNode")), + static_cast< cppu::OWeakObject * >(this)); } - bc.send(); } -css::uno::Any Access::getHierarchicalPropertyValue( - rtl::OUString const & aHierarchicalPropertyName) - throw ( - css::beans::UnknownPropertyException, - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalPropertyName, - static_cast< cppu::OWeakObject * >(this)); - } - return child->asValue(); +rtl::Reference< Node > Access::getParentNode() { + rtl::Reference< Access > parent(getParentAccess()); + return parent.is() ? parent->getNode() : rtl::Reference< Node >(); } -void Access::setHierarchicalPropertyValues( - css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames, - css::uno::Sequence< css::uno::Any > const & Values) - throw ( - css::beans::PropertyVetoException, css::lang::IllegalArgumentException, - css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - if (!getRootAccess()->isUpdate()) { - throw css::uno::RuntimeException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setPropertyValues on non-update access")), - static_cast< cppu::OWeakObject * >(this)); - } - if (aHierarchicalPropertyNames.getLength() != Values.getLength()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyValues:" - " aHierarchicalPropertyNames/Values of different" - " length")), - static_cast< cppu::OWeakObject * >(this), -1); +rtl::Reference< ChildAccess > Access::getChild(rtl::OUString const & name) { + ModifiedChildren::iterator i(modifiedChildren_.find(name)); + return i == modifiedChildren_.end() + ? getUnmodifiedChild(name) : getModifiedChild(i); +} + +std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() { + std::vector< rtl::Reference< ChildAccess > > vec; + NodeMap const & members = getNode()->getMembers(); + for (NodeMap::const_iterator i(members.begin()); i != members.end(); ++i) { + if (modifiedChildren_.find(i->first) == modifiedChildren_.end()) { + vec.push_back(getUnmodifiedChild(i->first)); + assert(vec.back().is()); } - Modifications localMods; - for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyNames[i])); - if (!child.is()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr setHierarchicalPropertyValues" - " inappropriate property name")), - static_cast< cppu::OWeakObject * >(this), -1); - } - child->checkFinalized(); - child->setProperty(Values[i], &localMods); + } + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + vec.push_back(child); } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); + return vec; } -css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues( - css::uno::Sequence< rtl::OUString > const & aHierarchicalPropertyNames) - throw ( - css::lang::IllegalArgumentException, css::lang::WrappedTargetException, - css::uno::RuntimeException) -{ - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - css::uno::Sequence< css::uno::Any > vals( - aHierarchicalPropertyNames.getLength()); - for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) { - rtl::Reference< ChildAccess > child( - getSubChild(aHierarchicalPropertyNames[i])); - if (!child.is()) { - throw css::lang::IllegalArgumentException( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configmgr getHierarchicalPropertyValues inappropriate" - " hierarchical property name")), - static_cast< cppu::OWeakObject * >(this), -1); +void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) { + bool ok; + switch (type) { + case TYPE_NIL: + assert(false); + // fall through (cannot happen) + case TYPE_ERROR: + ok = false; + break; + case TYPE_ANY: + switch (getDynamicType(value)) { + case TYPE_ANY: + assert(false); + // fall through (cannot happen) + case TYPE_ERROR: + ok = false; + break; + case TYPE_NIL: + ok = nillable; + break; + default: + ok = true; + break; } - vals[i] = child->asValue(); + break; + default: + ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable; + break; + } + if (!ok) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "configmgr inappropriate property value")), + static_cast< cppu::OWeakObject * >(this), -1); } - return vals; } -css::beans::Property Access::getPropertyByHierarchicalName( - rtl::OUString const & aHierarchicalName) - throw (css::beans::UnknownPropertyException, css::uno::RuntimeException) +void Access::insertLocalizedValueChild( + rtl::OUString const & name, css::uno::Any const & value, + Modifications * localModifications) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName)); - if (!child.is()) { - throw css::beans::UnknownPropertyException( - aHierarchicalName, static_cast< cppu::OWeakObject * >(this)); - } - return child->asProperty(); + assert(localModifications != 0); + LocalizedPropertyNode * locprop = dynamic_cast< LocalizedPropertyNode * >( + getNode().get()); + checkValue(value, locprop->getStaticType(), locprop->isNillable()); + rtl::Reference< ChildAccess > child( + new ChildAccess( + components_, getRootAccess(), this, name, + new LocalizedValueNode(Data::NO_LAYER, value))); + markChildAsModified(child); + localModifications->add(child->getRelativePath()); } -sal_Bool Access::hasPropertyByHierarchicalName( - rtl::OUString const & aHierarchicalName) - throw (css::uno::RuntimeException) +void Access::reportChildChanges( + std::vector< css::util::ElementChange > * changes) { - assert(thisIs(IS_GROUP)); - osl::MutexGuard g(*lock_); - return getSubChild(aHierarchicalName).is(); + assert(changes != 0); + for (ModifiedChildren::iterator i(modifiedChildren_.begin()); + i != modifiedChildren_.end(); ++i) + { + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + child->reportChildChanges(changes); + changes->push_back(css::util::ElementChange()); + //TODO: changed value and/or inserted node + } else { + changes->push_back(css::util::ElementChange()); //TODO: removed node + } + } } -void Access::replaceByName( - rtl::OUString const & aName, css::uno::Any const & aElement) - throw ( - css::lang::IllegalArgumentException, - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) +void Access::commitChildChanges( + bool valid, Modifications * globalModifications) { - assert(thisIs(IS_UPDATE)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is()) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); + assert(globalModifications != 0); + while (!modifiedChildren_.empty()) { + bool childValid = valid; + ModifiedChildren::iterator i(modifiedChildren_.begin()); + rtl::Reference< ChildAccess > child(getModifiedChild(i)); + if (child.is()) { + childValid = childValid && !child->isFinalized(); + child->commitChanges(childValid, globalModifications); + //TODO: currently, this is called here for directly inserted + // children as well as for children whose sub-children were + // modified (and should never be called for directly removed + // children); clarify what exactly should happen here for + // directly inserted children } - child->checkFinalized(); - Modifications localMods; - switch (getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - case Node::KIND_GROUP: - child->setProperty(aElement, &localMods); - break; - case Node::KIND_SET: - { - rtl::Reference< ChildAccess > freeAcc( - getFreeSetMember(aElement)); - rtl::Reference< RootAccess > root(getRootAccess()); - localMods.add(child->getRelativePath()); - child->unbind(); // must not throw - freeAcc->bind(root, this, aName); // must not throw - markChildAsModified(freeAcc); //TODO: must not throw + NodeMap * members = getNode()->getMemberMap(); + if (members != 0) { + NodeMap::const_iterator j(members->find(i->first)); + if (child.is()) { + // Inserted: + if (j != members->end()) { + childValid = childValid && + j->second->getFinalized() == Data::NO_LAYER; + if (childValid) { + child->getNode()->setMandatory( + j->second->getMandatory()); + } + } + if (childValid) { + (*members)[i->first] = child->getNode(); + } + } else { + // Removed: + childValid = childValid && j != members->end() && + j->second->getFinalized() == Data::NO_LAYER && + j->second->getMandatory() == Data::NO_LAYER; + if (childValid) { + members->erase(j); + } } - break; - default: - assert(false); // this cannot happen - break; } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); + if (childValid && i->second.directlyModified) { + Path path(getAbsolutePath()); + path.push_back(i->first); + components_.addModification(path); + globalModifications->add(path); + } + i->second.child->committed(); + modifiedChildren_.erase(i); } - bc.send(); } -void Access::insertByName( - rtl::OUString const & aName, css::uno::Any const & aElement) - throw ( - css::lang::IllegalArgumentException, - css::container::ElementExistException, - css::lang::WrappedTargetException, css::uno::RuntimeException) +void Access::initBroadcasterAndChanges( + Modifications::Node const & modifications, Broadcaster * broadcaster, + std::vector< css::util::ElementChange > * allChanges) { - assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); - Broadcaster bc; + assert(broadcaster != 0); + comphelper::SequenceAsVector< css::beans::PropertyChangeEvent > propChanges; + bool collectPropChanges = !propertiesChangeListeners_.empty(); + for (Modifications::Node::Children::const_iterator i( + modifications.children.begin()); + i != modifications.children.end(); ++i) { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - checkFinalized(); - if (getChild(aName).is()) { - throw css::container::ElementExistException( - aName, static_cast< cppu::OWeakObject * >(this)); - } - Modifications localMods; - switch (getNode()->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - insertLocalizedValueChild(aName, aElement, &localMods); - break; - case Node::KIND_GROUP: - { - checkValue(aElement, TYPE_ANY, true); - rtl::Reference< ChildAccess > child( - new ChildAccess( - components_, getRootAccess(), this, aName, - new PropertyNode( - Data::NO_LAYER, TYPE_ANY, true, aElement, true))); - markChildAsModified(child); - localMods.add(child->getRelativePath()); + rtl::Reference< ChildAccess > child(getChild(i->first)); + if (child.is()) { + switch (child->getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + if (!i->second.children.empty()) { + if (Components::allLocales(getRootAccess()->getLocale())) { + child->initBroadcasterAndChanges( + i->second, broadcaster, allChanges); + //TODO: if allChanges==0, recurse only into children + // w/ listeners + } else { + //TODO: filter child mods that are irrelevant for + // locale: + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster-> + addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >( + this), + css::uno::makeAny(i->first), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( + this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( + this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + } + // else: spurious Modifications::Node not representing a change + break; + case Node::KIND_LOCALIZED_VALUE: + assert(Components::allLocales(getRootAccess()->getLocale())); + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), child->asValue(), + css::uno::Any())); + //TODO: distinguish add/modify; non-void ReplacedElement + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + child->asValue(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + assert(!collectPropChanges); + break; + case Node::KIND_PROPERTY: + { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementReplacedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), child->asValue(), + css::uno::Any())); + //TODO: distinguish add/remove/modify; non-void + // ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + child->asValue(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + break; + case Node::KIND_GROUP: + case Node::KIND_SET: + if (i->second.children.empty()) { + if (child->getNode()->getTemplateName().getLength() != 0) { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster-> + addContainerElementInsertedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >( + this), + css::uno::makeAny(i->first), + child->asValue(), css::uno::Any())); + } + if (allChanges != 0) { + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny( + child->getRelativePathRepresentation()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void Element, ReplacedElement + } + } + // else: spurious Modifications::Node not representing a + // change + } else { + child->initBroadcasterAndChanges( + i->second, broadcaster, allChanges); + //TODO: if allChanges==0, recurse only into children w/ + // listeners + } + break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } - break; - case Node::KIND_SET: - { - rtl::Reference< ChildAccess > freeAcc( - getFreeSetMember(aElement)); - freeAcc->bind(getRootAccess(), this, aName); // must not throw - markChildAsModified(freeAcc); //TODO: must not throw - localMods.add(freeAcc->getRelativePath()); + } else { + switch (getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + // Removed localized property value: + assert(Components::allLocales(getRootAccess()->getLocale())); + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), css::uno::Any(), + css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (allChanges != 0) { + rtl::OUStringBuffer path(getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append( + Data::createSegment( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), + i->first)); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + assert(!collectPropChanges); + break; + case Node::KIND_GROUP: + { + // Removed (non-localized) extension property: + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), css::uno::Any(), + css::uno::Any())); + //TODO: non-void ReplacedElement + } + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + j = propertyChangeListeners_.find(rtl::OUString()); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + if (allChanges != 0) { + rtl::OUStringBuffer path( + getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append(i->first); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (collectPropChanges) { + propChanges.push_back( + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + break; + case Node::KIND_SET: + // Removed set member: + if (i->second.children.empty()) { + for (ContainerListeners::iterator j( + containerListeners_.begin()); + j != containerListeners_.end(); ++j) + { + broadcaster->addContainerElementRemovedNotification( + *j, + css::container::ContainerEvent( + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(i->first), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + if (allChanges != 0) { + rtl::OUStringBuffer path( + getRelativePathRepresentation()); + if (path.getLength() != 0) { + path.append(sal_Unicode('/')); + } + path.append( + Data::createSegment( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), + i->first)); + allChanges->push_back( + css::util::ElementChange( + css::uno::makeAny(path.makeStringAndClear()), + css::uno::Any(), css::uno::Any())); + //TODO: non-void ReplacedElement + } + } + // else: spurious Modifications::Node not representing a change + break; + default: + assert(false); // this cannot happen + break; } - break; - default: - assert(false); // this cannot happen - break; } - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); -} - -void Access::removeByName(rtl::OUString const & aName) - throw ( - css::container::NoSuchElementException, - css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_EXTENSIBLE|IS_UPDATE)); - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - rtl::Reference< ChildAccess > child(getChild(aName)); - if (!child.is() || child->isFinalized() || - child->getNode()->getMandatory() != Data::NO_LAYER) + if (!propChanges.empty()) { + css::uno::Sequence< css::beans::PropertyChangeEvent > seq( + propChanges.getAsConstList()); + for (PropertiesChangeListeners::iterator i( + propertiesChangeListeners_.begin()); + i != propertiesChangeListeners_.end(); ++i) { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); - } - if (getNode()->kind() == Node::KIND_GROUP) { - rtl::Reference< Node > p(child->getNode()); - if (p->kind() != Node::KIND_PROPERTY || - !dynamic_cast< PropertyNode * >(p.get())->isExtension()) - { - throw css::container::NoSuchElementException( - aName, static_cast< cppu::OWeakObject * >(this)); - } + broadcaster->addPropertiesChangeNotification(*i, seq); } - Modifications localMods; - localMods.add(child->getRelativePath()); - // unbind() modifies the parent chain that markChildAsModified() walks, - // so order is important: - markChildAsModified(child); //TODO: must not throw - child->unbind(); - getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc); } - bc.send(); } -css::uno::Reference< css::uno::XInterface > Access::createInstance() - throw (css::uno::Exception, css::uno::RuntimeException) -{ - assert(thisIs(IS_SET|IS_UPDATE)); - rtl::OUString tmplName( - dynamic_cast< SetNode * >(getNode().get())->getDefaultTemplateName()); - rtl::Reference< Node > tmpl( - components_.getTemplate(Data::NO_LAYER, tmplName)); - if (!tmpl.is()) { - throw css::uno::Exception( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown template ")) + - tmplName), - static_cast< cppu::OWeakObject * >(this)); - } - rtl::Reference< Node > node(tmpl->clone(true)); - node->setLayer(Data::NO_LAYER); - return static_cast< cppu::OWeakObject * >( - new ChildAccess(components_, getRootAccess(), node)); +bool Access::isDisposed() const { + return disposed_; } -css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments( - css::uno::Sequence< css::uno::Any > const & aArguments) - throw (css::uno::Exception, css::uno::RuntimeException) -{ - assert(thisIs(IS_SET|IS_UPDATE)); - if (aArguments.getLength() != 0) { - throw css::uno::Exception( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "configuration SimpleSetUpdate createInstanceWithArguments" - " must not specify any arguments")), - static_cast< cppu::OWeakObject * >(this)); - } - return createInstance(); -} +Access::ModifiedChild::ModifiedChild() {} + +Access::ModifiedChild::ModifiedChild( + rtl::Reference< ChildAccess > const & theChild, bool theDirectlyModified): + child(theChild), directlyModified(theDirectlyModified) +{} rtl::Reference< ChildAccess > Access::getModifiedChild( ModifiedChildren::iterator const & childIterator) diff --git a/configmgr/source/access.hxx b/configmgr/source/access.hxx index d2409cbb2f1d..6401df3f8344 100644 --- a/configmgr/source/access.hxx +++ b/configmgr/source/access.hxx @@ -51,7 +51,7 @@ #include "com/sun/star/container/NoSuchElementException.hpp" #include "com/sun/star/container/XContainer.hpp" #include "com/sun/star/container/XHierarchicalName.hpp" -#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XHierarchicalNameReplace.hpp" #include "com/sun/star/container/XNameContainer.hpp" #include "com/sun/star/container/XNamed.hpp" #include "com/sun/star/lang/IllegalArgumentException.hpp" @@ -106,7 +106,7 @@ class Access: public cppu::OWeakObject, public com::sun::star::lang::XTypeProvider, public com::sun::star::lang::XServiceInfo, public com::sun::star::lang::XComponent, - public com::sun::star::container::XHierarchicalNameAccess, + public com::sun::star::container::XHierarchicalNameReplace, public com::sun::star::container::XContainer, public com::sun::star::beans::XExactName, public com::sun::star::beans::XPropertySetInfo, @@ -146,68 +146,6 @@ public: using OWeakObject::acquire; using OWeakObject::release; -protected: - Access(Components & components); - - virtual ~Access(); - - virtual rtl::OUString getNameInternal() = 0; - virtual rtl::Reference< RootAccess > getRootAccess() = 0; - virtual rtl::Reference< Access > getParentAccess() = 0; - - virtual void addTypes(std::vector< com::sun::star::uno::Type > * types) - const = 0; - - virtual void addSupportedServiceNames( - std::vector< rtl::OUString > * services) = 0; - - virtual void initDisposeBroadcaster(Broadcaster * broadcaster); - virtual void clearListeners() throw (); - - virtual com::sun::star::uno::Any SAL_CALL queryInterface( - com::sun::star::uno::Type const & aType) - throw (com::sun::star::uno::RuntimeException); - - Components & getComponents() const; - - void checkLocalizedPropertyAccess(); - - rtl::Reference< Node > getParentNode(); - rtl::Reference< ChildAccess > getChild(rtl::OUString const & name); - std::vector< rtl::Reference< ChildAccess > > getAllChildren(); - - void checkValue( - com::sun::star::uno::Any const & value, Type type, bool nillable); - - void insertLocalizedValueChild( - rtl::OUString const & name, com::sun::star::uno::Any const & value, - Modifications * localModifications); - - void reportChildChanges( - std::vector< com::sun::star::util::ElementChange > * changes); - - void commitChildChanges(bool valid, Modifications * globalModifications); - - void initBroadcasterAndChanges( - Modifications::Node const & modifications, Broadcaster * broadcaster, - std::vector< com::sun::star::util::ElementChange > * changes); - - bool isDisposed() const; - -private: - struct ModifiedChild { - rtl::Reference< ChildAccess > child; - bool directlyModified; - - ModifiedChild(); - - ModifiedChild( - rtl::Reference< ChildAccess > const & theChild, - bool theDirectlyModified); - }; - - typedef std::map< rtl::OUString, ModifiedChild > ModifiedChildren; - virtual com::sun::star::uno::Sequence< com::sun::star::uno::Type > SAL_CALL getTypes() throw (com::sun::star::uno::RuntimeException); @@ -264,6 +202,14 @@ private: virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL replaceByHierarchicalName( + rtl::OUString const & aName, com::sun::star::uno::Any const & aElement) + throw ( + com::sun::star::lang::IllegalArgumentException, + com::sun::star::container::NoSuchElementException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addContainerListener( com::sun::star::uno::Reference< com::sun::star::container::XContainerListener > const & xListener) @@ -491,6 +437,68 @@ private: com::sun::star::uno::Exception, com::sun::star::uno::RuntimeException); +protected: + Access(Components & components); + + virtual ~Access(); + + virtual rtl::OUString getNameInternal() = 0; + virtual rtl::Reference< RootAccess > getRootAccess() = 0; + virtual rtl::Reference< Access > getParentAccess() = 0; + + virtual void addTypes(std::vector< com::sun::star::uno::Type > * types) + const = 0; + + virtual void addSupportedServiceNames( + std::vector< rtl::OUString > * services) = 0; + + virtual void initDisposeBroadcaster(Broadcaster * broadcaster); + virtual void clearListeners() throw (); + + virtual com::sun::star::uno::Any SAL_CALL queryInterface( + com::sun::star::uno::Type const & aType) + throw (com::sun::star::uno::RuntimeException); + + Components & getComponents() const; + + void checkLocalizedPropertyAccess(); + + rtl::Reference< Node > getParentNode(); + rtl::Reference< ChildAccess > getChild(rtl::OUString const & name); + std::vector< rtl::Reference< ChildAccess > > getAllChildren(); + + void checkValue( + com::sun::star::uno::Any const & value, Type type, bool nillable); + + void insertLocalizedValueChild( + rtl::OUString const & name, com::sun::star::uno::Any const & value, + Modifications * localModifications); + + void reportChildChanges( + std::vector< com::sun::star::util::ElementChange > * changes); + + void commitChildChanges(bool valid, Modifications * globalModifications); + + void initBroadcasterAndChanges( + Modifications::Node const & modifications, Broadcaster * broadcaster, + std::vector< com::sun::star::util::ElementChange > * changes); + + bool isDisposed() const; + +private: + struct ModifiedChild { + rtl::Reference< ChildAccess > child; + bool directlyModified; + + ModifiedChild(); + + ModifiedChild( + rtl::Reference< ChildAccess > const & theChild, + bool theDirectlyModified); + }; + + typedef std::map< rtl::OUString, ModifiedChild > ModifiedChildren; + rtl::Reference< ChildAccess > getModifiedChild( ModifiedChildren::iterator const & childIterator); diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index 48d555e3236e..56c597593395 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -137,7 +137,7 @@ bool canRemoveFromLayer(int layer, rtl::Reference< Node > const & node) { switch (node->kind()) { case Node::KIND_LOCALIZED_PROPERTY: case Node::KIND_GROUP: - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { if (!canRemoveFromLayer(layer, i->second)) { @@ -402,7 +402,9 @@ void Components::removeExtensionXcuFile( node->kind() == Node::KIND_GROUP || node->kind() == Node::KIND_SET); if (canRemoveFromLayer(item->layer, node)) { - parent->getMembers().erase(i->back()); + NodeMap * members = parent->getMemberMap(); + assert(members != 0); + members->erase(i->back()); data_.modifications.remove(*i); modifications->add(*i); } diff --git a/configmgr/source/configmgr.component b/configmgr/source/configmgr.component index 6ed51257005d..9ad4c79eed0b 100755 --- a/configmgr/source/configmgr.component +++ b/configmgr/source/configmgr.component @@ -38,6 +38,12 @@ + + + + + + diff --git a/configmgr/source/data.cxx b/configmgr/source/data.cxx index 0fdc1e5eba92..fcc42e97cecc 100644 --- a/configmgr/source/data.cxx +++ b/configmgr/source/data.cxx @@ -48,6 +48,7 @@ #include "groupnode.hxx" #include "node.hxx" #include "nodemap.hxx" +#include "rootnode.hxx" #include "setnode.hxx" namespace configmgr { @@ -207,6 +208,8 @@ rtl::Reference< Node > Data::findNode( ? rtl::Reference< Node >() : i->second; } +Data::Data(): root_(new RootNode(components)) {} + rtl::Reference< Node > Data::resolvePathRepresentation( rtl::OUString const & pathRepresentation, rtl::OUString * canonicRepresentation, Path * path, int * finalizedLayer) @@ -218,6 +221,18 @@ rtl::Reference< Node > Data::resolvePathRepresentation( pathRepresentation), css::uno::Reference< css::uno::XInterface >()); } + if (path != 0) { + path->clear(); + } + if (pathRepresentation.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) { + if (canonicRepresentation != 0) { + *canonicRepresentation = pathRepresentation; + } + if (finalizedLayer != 0) { + *finalizedLayer = NO_LAYER; + } + return root_; + } rtl::OUString seg; bool setElement; rtl::OUString templateName; @@ -231,9 +246,6 @@ rtl::Reference< Node > Data::resolvePathRepresentation( } NodeMap::const_iterator i(components.find(seg)); rtl::OUStringBuffer canonic; - if (path != 0) { - path->clear(); - } rtl::Reference< Node > parent; int finalized = NO_LAYER; for (rtl::Reference< Node > p(i == components.end() ? 0 : i->second);;) { diff --git a/configmgr/source/data.hxx b/configmgr/source/data.hxx index f60ecfa1e807..64980eef4056 100644 --- a/configmgr/source/data.hxx +++ b/configmgr/source/data.hxx @@ -81,6 +81,8 @@ struct Data: private boost::noncopyable { static rtl::Reference< Node > findNode( int layer, NodeMap const & map, rtl::OUString const & name); + Data(); + rtl::Reference< Node > resolvePathRepresentation( rtl::OUString const & pathRepresentation, rtl::OUString * canonicRepresenation, Path * path, int * finalizedLayer) @@ -99,6 +101,8 @@ private: typedef std::map< rtl::OUString, rtl::Reference< ExtensionXcu > > ExtensionXcuAdditions; + rtl::Reference< Node > root_; + ExtensionXcuAdditions extensionXcuAdditions_; }; diff --git a/configmgr/source/groupnode.cxx b/configmgr/source/groupnode.cxx index 5591acbe606d..09658567b4c3 100644 --- a/configmgr/source/groupnode.cxx +++ b/configmgr/source/groupnode.cxx @@ -48,8 +48,8 @@ rtl::Reference< Node > GroupNode::clone(bool keepTemplateName) const { return new GroupNode(*this, keepTemplateName); } -NodeMap & GroupNode::getMembers() { - return members_; +NodeMap * GroupNode::getMemberMap() { + return &members_; } rtl::OUString GroupNode::getTemplateName() const { diff --git a/configmgr/source/groupnode.hxx b/configmgr/source/groupnode.hxx index 02f1679998a2..1d14a9293a6b 100644 --- a/configmgr/source/groupnode.hxx +++ b/configmgr/source/groupnode.hxx @@ -45,7 +45,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; diff --git a/configmgr/source/localizedpropertynode.cxx b/configmgr/source/localizedpropertynode.cxx index 270485835228..196e57f6a6f9 100644 --- a/configmgr/source/localizedpropertynode.cxx +++ b/configmgr/source/localizedpropertynode.cxx @@ -55,8 +55,8 @@ rtl::Reference< Node > LocalizedPropertyNode::clone(bool) const { return new LocalizedPropertyNode(*this); } -NodeMap & LocalizedPropertyNode::getMembers() { - return members_; +NodeMap * LocalizedPropertyNode::getMemberMap() { + return &members_; } Type LocalizedPropertyNode::getStaticType() const { diff --git a/configmgr/source/localizedpropertynode.hxx b/configmgr/source/localizedpropertynode.hxx index bbe934e36bcd..b49f375c43c2 100644 --- a/configmgr/source/localizedpropertynode.hxx +++ b/configmgr/source/localizedpropertynode.hxx @@ -50,7 +50,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); Type getStaticType() const; diff --git a/configmgr/source/makefile.mk b/configmgr/source/makefile.mk index e75af0dde734..f52b4f4c0af0 100644 --- a/configmgr/source/makefile.mk +++ b/configmgr/source/makefile.mk @@ -55,7 +55,10 @@ SLOFILES = \ $(SLO)/parsemanager.obj \ $(SLO)/partial.obj \ $(SLO)/propertynode.obj \ + $(SLO)/readonlyaccess.obj \ + $(SLO)/readwriteaccess.obj \ $(SLO)/rootaccess.obj \ + $(SLO)/rootnode.obj \ $(SLO)/services.obj \ $(SLO)/setnode.obj \ $(SLO)/type.obj \ diff --git a/configmgr/source/node.cxx b/configmgr/source/node.cxx index 892cdaa622fd..b6480820aedc 100644 --- a/configmgr/source/node.cxx +++ b/configmgr/source/node.cxx @@ -30,11 +30,7 @@ #include -#include "com/sun/star/uno/Reference.hxx" -#include "com/sun/star/uno/RuntimeException.hpp" -#include "com/sun/star/uno/XInterface.hpp" #include "rtl/ref.hxx" -#include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "data.hxx" @@ -43,17 +39,15 @@ namespace configmgr { -namespace { - -namespace css = com::sun::star; - +NodeMap const & Node::getMembers() const { + NodeMap * members = const_cast< Node * >(this)->getMemberMap(); + assert(members != 0); + return *members; } -NodeMap & Node::getMembers() { +NodeMap * Node::getMemberMap() { assert(false); - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), - css::uno::Reference< css::uno::XInterface >()); + return 0; } rtl::OUString Node::getTemplateName() const { @@ -87,8 +81,8 @@ int Node::getFinalized() const { } rtl::Reference< Node > Node::getMember(rtl::OUString const & name) { - NodeMap & members = getMembers(); - NodeMap::iterator i(members.find(name)); + NodeMap const & members = getMembers(); + NodeMap::const_iterator i(members.find(name)); return i == members.end() ? rtl::Reference< Node >() : i->second; } diff --git a/configmgr/source/node.hxx b/configmgr/source/node.hxx index 932d11cf3744..01aef18c7a6a 100644 --- a/configmgr/source/node.hxx +++ b/configmgr/source/node.hxx @@ -44,13 +44,14 @@ class Node: public salhelper::SimpleReferenceObject { public: enum Kind { KIND_PROPERTY, KIND_LOCALIZED_PROPERTY, KIND_LOCALIZED_VALUE, - KIND_GROUP, KIND_SET }; + KIND_GROUP, KIND_SET, KIND_ROOT }; virtual Kind kind() const = 0; virtual rtl::Reference< Node > clone(bool keepTemplateName) const = 0; - virtual NodeMap & getMembers(); + virtual NodeMap const & getMembers() const; + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; virtual void setMandatory(int layer); diff --git a/configmgr/source/readonlyaccess.cxx b/configmgr/source/readonlyaccess.cxx new file mode 100644 index 000000000000..d9ab2dccd837 --- /dev/null +++ b/configmgr/source/readonlyaccess.cxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "components.hxx" +#include "lock.hxx" +#include "readonlyaccess.hxx" +#include "rootaccess.hxx" + +namespace configmgr { namespace read_only_access { + +namespace { + +namespace css = com::sun::star; + +class Service: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::container::XHierarchicalNameAccess >, + private boost::noncopyable +{ +public: + Service(css::uno::Reference< css::uno::XComponentContext > const & context); + +private: + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return read_only_access::getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return read_only_access::getSupportedServiceNames(); } + + virtual css::uno::Any SAL_CALL getByHierarchicalName( + rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException) + { return root_->getByHierarchicalName(aName); } + + virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) + { return root_->hasByHierarchicalName(aName); } + + rtl::Reference< RootAccess > root_; +}; + +Service::Service( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + osl::MutexGuard guard(*lock()); + Components & components = Components::getSingleton(context); + root_ = new RootAccess( + components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), false); + components.addRootAccess(root_); +} + +} + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.configuration.ReadOnlyAccess")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readonlyaccess.hxx b/configmgr/source/readonlyaccess.hxx new file mode 100644 index 000000000000..9549789469b4 --- /dev/null +++ b/configmgr/source/readonlyaccess.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_READONLYACCESS_HXX +#define INCLUDED_CONFIGMGR_SOURCE_READONLYACCESS_HXX + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + class XInterface; + } +} } } +namespace rtl { class OUString; } + +namespace configmgr { namespace read_only_access { + +com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL +create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const &); + +rtl::OUString SAL_CALL getImplementationName(); + +com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL +getSupportedServiceNames(); + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readwriteaccess.cxx b/configmgr/source/readwriteaccess.cxx new file mode 100644 index 000000000000..0e4415fd44ed --- /dev/null +++ b/configmgr/source/readwriteaccess.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "cppuhelper/implbase2.hxx" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/configuration/XReadWriteAccess.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/ChangesSet.hpp" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "components.hxx" +#include "lock.hxx" +#include "readwriteaccess.hxx" +#include "rootaccess.hxx" + +namespace configmgr { namespace read_write_access { + +namespace { + +namespace css = com::sun::star; + +class Service: + public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::configuration::XReadWriteAccess >, + private boost::noncopyable +{ +public: + Service(css::uno::Reference< css::uno::XComponentContext > const & context); + +private: + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return read_write_access::getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const &) + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return read_write_access::getSupportedServiceNames(); } + + virtual css::uno::Any SAL_CALL getByHierarchicalName( + rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException) + { return root_->getByHierarchicalName(aName); } + + virtual sal_Bool SAL_CALL hasByHierarchicalName(rtl::OUString const & aName) + throw (css::uno::RuntimeException) + { return root_->hasByHierarchicalName(aName); } + + virtual void SAL_CALL replaceByHierarchicalName( + rtl::OUString const & aName, css::uno::Any const & aElement) + throw ( + css::lang::IllegalArgumentException, + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) + { root_->replaceByHierarchicalName(aName, aElement); } + + virtual void SAL_CALL commitChanges() + throw (css::lang::WrappedTargetException, css::uno::RuntimeException) + { root_->commitChanges(); } + + virtual sal_Bool SAL_CALL hasPendingChanges() + throw (css::uno::RuntimeException) + { return root_->hasPendingChanges(); } + + virtual css::util::ChangesSet SAL_CALL getPendingChanges() + throw (css::uno::RuntimeException) + { return root_->getPendingChanges(); } + + rtl::Reference< RootAccess > root_; +}; + +Service::Service( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + osl::MutexGuard guard(*lock()); + Components & components = Components::getSingleton(context); + root_ = new RootAccess( + components, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")), true); + components.addRootAccess(root_); +} + +} + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.configuration.ReadWriteAccess")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ReadWriteAccess")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/readwriteaccess.hxx b/configmgr/source/readwriteaccess.hxx new file mode 100644 index 000000000000..b559b2a51f9f --- /dev/null +++ b/configmgr/source/readwriteaccess.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_READWRITEACCESS_HXX +#define INCLUDED_CONFIGMGR_SOURCE_READWRITEACCESS_HXX + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + class XInterface; + } +} } } +namespace rtl { class OUString; } + +namespace configmgr { namespace read_write_access { + +com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL +create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const &); + +rtl::OUString SAL_CALL getImplementationName(); + +com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL +getSupportedServiceNames(); + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/rootaccess.cxx b/configmgr/source/rootaccess.cxx index fc1fe39e8073..03ee3b88e29a 100644 --- a/configmgr/source/rootaccess.cxx +++ b/configmgr/source/rootaccess.cxx @@ -133,6 +133,91 @@ void RootAccess::setAlive(bool b) { alive_ = b; } +void RootAccess::addChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + { + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + if (!aListener.is()) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), + static_cast< cppu::OWeakObject * >(this)); + } + if (!isDisposed()) { + changesListeners_.insert(aListener); + return; + } + } + try { + aListener->disposing( + css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); + } catch (css::lang::DisposedException &) {} +} + +void RootAccess::removeChangesListener( + css::uno::Reference< css::util::XChangesListener > const & aListener) + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + ChangesListeners::iterator i(changesListeners_.find(aListener)); + if (i != changesListeners_.end()) { + changesListeners_.erase(i); + } +} + +void RootAccess::commitChanges() + throw (css::lang::WrappedTargetException, css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + if (!alive_) + { + return; + } + Broadcaster bc; + { + osl::MutexGuard g(*lock_); + + checkLocalizedPropertyAccess(); + int finalizedLayer; + Modifications globalMods; + commitChildChanges( + ((getComponents().resolvePathRepresentation( + pathRepresentation_, 0, 0, &finalizedLayer) + == node_) && + finalizedLayer == Data::NO_LAYER), + &globalMods); + getComponents().writeModifications(); + getComponents().initGlobalBroadcaster(globalMods, this, &bc); + } + bc.send(); +} + +sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + //TODO: Optimize: + std::vector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return !changes.empty(); +} + +css::util::ChangesSet RootAccess::getPendingChanges() + throw (css::uno::RuntimeException) +{ + assert(thisIs(IS_UPDATE)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + comphelper::SequenceAsVector< css::util::ElementChange > changes; + reportChildChanges(&changes); + return changes.getAsConstList(); +} + RootAccess::~RootAccess() { osl::MutexGuard g(*lock_); @@ -166,8 +251,10 @@ rtl::Reference< Node > RootAccess::getNode() { // RuntimeException.Context is left null here } pathRepresentation_ = canonic; - assert(!path_.empty()); - name_ = path_.back(); + assert(!path_.empty() || node_->kind() == Node::KIND_ROOT); + if (!path_.empty()) { + name_ = path_.back(); + } finalized_ = finalizedLayer != Data::NO_LAYER; } return node_; @@ -252,97 +339,13 @@ css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType) return res; } -void RootAccess::addChangesListener( - css::uno::Reference< css::util::XChangesListener > const & aListener) +rtl::OUString RootAccess::getImplementationName() throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - { - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - if (!aListener.is()) { - throw css::uno::RuntimeException( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), - static_cast< cppu::OWeakObject * >(this)); - } - if (!isDisposed()) { - changesListeners_.insert(aListener); - return; - } - } - try { - aListener->disposing( - css::lang::EventObject(static_cast< cppu::OWeakObject * >(this))); - } catch (css::lang::DisposedException &) {} -} - -void RootAccess::removeChangesListener( - css::uno::Reference< css::util::XChangesListener > const & aListener) - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_ANY)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - ChangesListeners::iterator i(changesListeners_.find(aListener)); - if (i != changesListeners_.end()) { - changesListeners_.erase(i); - } -} - -void RootAccess::commitChanges() - throw (css::lang::WrappedTargetException, css::uno::RuntimeException) -{ - assert(thisIs(IS_UPDATE)); - if (!alive_) - { - return; - } - Broadcaster bc; - { - osl::MutexGuard g(*lock_); - - checkLocalizedPropertyAccess(); - int finalizedLayer; - Modifications globalMods; - commitChildChanges( - ((getComponents().resolvePathRepresentation( - pathRepresentation_, 0, 0, &finalizedLayer) - == node_) && - finalizedLayer == Data::NO_LAYER), - &globalMods); - getComponents().writeModifications(); - getComponents().initGlobalBroadcaster(globalMods, this, &bc); - } - bc.send(); -} - -sal_Bool RootAccess::hasPendingChanges() throw (css::uno::RuntimeException) { - assert(thisIs(IS_UPDATE)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - //TODO: Optimize: - std::vector< css::util::ElementChange > changes; - reportChildChanges(&changes); - return !changes.empty(); -} - -css::util::ChangesSet RootAccess::getPendingChanges() - throw (css::uno::RuntimeException) -{ - assert(thisIs(IS_UPDATE)); - osl::MutexGuard g(*lock_); - checkLocalizedPropertyAccess(); - comphelper::SequenceAsVector< css::util::ElementChange > changes; - reportChildChanges(&changes); - return changes.getAsConstList(); -} - -rtl::OUString RootAccess::getImplementationName() throw (css::uno::RuntimeException) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); - return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "configmgr.RootAccess" ) ); + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("configmgr.RootAccess")); } } diff --git a/configmgr/source/rootaccess.hxx b/configmgr/source/rootaccess.hxx index 1290519b5d99..3b9ab7bbfa94 100644 --- a/configmgr/source/rootaccess.hxx +++ b/configmgr/source/rootaccess.hxx @@ -88,9 +88,25 @@ public: void setAlive(bool b); -protected: + virtual void SAL_CALL addChangesListener( + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + const & aListener) + throw (com::sun::star::uno::RuntimeException); - virtual rtl::OUString SAL_CALL getImplementationName() + virtual void SAL_CALL removeChangesListener( + com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > + const & aListener) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL commitChanges() + throw ( + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasPendingChanges() + throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::util::ChangesSet SAL_CALL getPendingChanges() throw (com::sun::star::uno::RuntimeException); private: @@ -124,25 +140,7 @@ private: com::sun::star::uno::Type const & aType) throw (com::sun::star::uno::RuntimeException); - virtual void SAL_CALL addChangesListener( - com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > - const & aListener) - throw (com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL removeChangesListener( - com::sun::star::uno::Reference< com::sun::star::util::XChangesListener > - const & aListener) - throw (com::sun::star::uno::RuntimeException); - - virtual void SAL_CALL commitChanges() - throw ( - com::sun::star::lang::WrappedTargetException, - com::sun::star::uno::RuntimeException); - - virtual sal_Bool SAL_CALL hasPendingChanges() - throw (com::sun::star::uno::RuntimeException); - - virtual com::sun::star::util::ChangesSet SAL_CALL getPendingChanges() + virtual rtl::OUString SAL_CALL getImplementationName() throw (com::sun::star::uno::RuntimeException); typedef diff --git a/configmgr/source/rootnode.cxx b/configmgr/source/rootnode.cxx new file mode 100644 index 000000000000..3188ea1228dc --- /dev/null +++ b/configmgr/source/rootnode.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include "sal/config.h" + +#include "rtl/ref.hxx" + +#include "data.hxx" +#include "node.hxx" +#include "nodemap.hxx" +#include "rootnode.hxx" + +namespace configmgr { + +RootNode::RootNode(NodeMap const & members): + Node(Data::NO_LAYER), members_(members) +{} + +RootNode::~RootNode() {} + +Node::Kind RootNode::kind() const { + return KIND_ROOT; +} + +rtl::Reference< Node > RootNode::clone(bool) const { + assert(false); // this cannot happen + return rtl::Reference< Node >(); +} + +NodeMap const & RootNode::getMembers() const { + return members_; +} + +NodeMap * RootNode::getMemberMap() { + return 0; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/rootnode.hxx b/configmgr/source/rootnode.hxx new file mode 100644 index 000000000000..97244e470737 --- /dev/null +++ b/configmgr/source/rootnode.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 Red Hat, Inc., Stephan Bergmann + * (initial developer) + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef INCLUDED_CONFIGMGR_SOURCE_ROOTNODE_HXX +#define INCLUDED_CONFIGMGR_SOURCE_ROOTNODE_HXX + +#include "sal/config.h" + +#include "rtl/ref.hxx" + +#include "node.hxx" +#include "nodemap.hxx" + +namespace configmgr { + +class RootNode: public Node { +public: + RootNode(NodeMap const & members); + +private: + RootNode(RootNode const & other); + + virtual ~RootNode(); + + virtual Kind kind() const; + + virtual rtl::Reference< Node > clone(bool keepTemplateName) const; + + virtual NodeMap const & getMembers() const; + virtual NodeMap * getMemberMap(); + + NodeMap const & members_; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/configmgr/source/services.cxx b/configmgr/source/services.cxx index 365c50c0e064..5c58eb719ac2 100644 --- a/configmgr/source/services.cxx +++ b/configmgr/source/services.cxx @@ -42,6 +42,8 @@ #include "configurationprovider.hxx" #include "configurationregistry.hxx" #include "defaultprovider.hxx" +#include "readonlyaccess.hxx" +#include "readwriteaccess.hxx" #include "update.hxx" namespace { @@ -68,6 +70,14 @@ static cppu::ImplementationEntry const services[] = { &configmgr::configuration_registry::getImplementationName, &configmgr::configuration_registry::getSupportedServiceNames, &cppu::createSingleComponentFactory, 0, 0 }, + { &configmgr::read_only_access::create, + &configmgr::read_only_access::getImplementationName, + &configmgr::read_only_access::getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, + { &configmgr::read_write_access::create, + &configmgr::read_write_access::getImplementationName, + &configmgr::read_write_access::getSupportedServiceNames, + &cppu::createSingleComponentFactory, 0, 0 }, { &configmgr::update::create, &configmgr::update::getImplementationName, &configmgr::update::getSupportedServiceNames, &cppu::createSingleComponentFactory, 0, 0 }, diff --git a/configmgr/source/setnode.cxx b/configmgr/source/setnode.cxx index e2a8b2c888eb..214885fff66f 100644 --- a/configmgr/source/setnode.cxx +++ b/configmgr/source/setnode.cxx @@ -73,8 +73,8 @@ rtl::Reference< Node > SetNode::clone(bool keepTemplateName) const { return new SetNode(*this, keepTemplateName); } -NodeMap & SetNode::getMembers() { - return members_; +NodeMap * SetNode::getMemberMap() { + return &members_; } rtl::OUString SetNode::getTemplateName() const { diff --git a/configmgr/source/setnode.hxx b/configmgr/source/setnode.hxx index 00bcab2a55a1..59bd2587a5ab 100644 --- a/configmgr/source/setnode.hxx +++ b/configmgr/source/setnode.hxx @@ -49,7 +49,7 @@ public: virtual rtl::Reference< Node > clone(bool keepTemplateName) const; - virtual NodeMap & getMembers(); + virtual NodeMap * getMemberMap(); virtual rtl::OUString getTemplateName() const; diff --git a/configmgr/source/valueparser.cxx b/configmgr/source/valueparser.cxx index a98aae6ccf03..105d9ef323b8 100644 --- a/configmgr/source/valueparser.cxx +++ b/configmgr/source/valueparser.cxx @@ -413,10 +413,11 @@ bool ValueParser::endElement() { break; case Node::KIND_LOCALIZED_PROPERTY: { - NodeMap::iterator i( - node_->getMembers().find(localizedName_)); - if (i == node_->getMembers().end()) { - node_->getMembers().insert( + NodeMap * members = node_->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(localizedName_)); + if (i == members->end()) { + members->insert( NodeMap::value_type( localizedName_, new LocalizedValueNode(layer_, value))); diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx index 1bae01ab88c5..eb896fffbf34 100644 --- a/configmgr/source/writemodfile.cxx +++ b/configmgr/source/writemodfile.cxx @@ -395,7 +395,7 @@ void writeNode( writeData(handle, RTL_CONSTASCII_STRINGPARAM("")); - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { writeNode(components, handle, node, i->first, i->second); @@ -443,13 +443,16 @@ void writeNode( handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace")); } writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">")); - for (NodeMap::iterator i(node->getMembers().begin()); + for (NodeMap::const_iterator i(node->getMembers().begin()); i != node->getMembers().end(); ++i) { writeNode(components, handle, node, i->first, i->second); } writeData(handle, RTL_CONSTASCII_STRINGPARAM("")); break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } diff --git a/configmgr/source/xcsparser.cxx b/configmgr/source/xcsparser.cxx index 95d994327b85..66f3f2891713 100644 --- a/configmgr/source/xcsparser.cxx +++ b/configmgr/source/xcsparser.cxx @@ -79,16 +79,18 @@ void merge( case Node::KIND_LOCALIZED_VALUE: break; //TODO: merge certain parts? case Node::KIND_GROUP: - for (NodeMap::iterator i2(update->getMembers().begin()); + for (NodeMap::const_iterator i2(update->getMembers().begin()); i2 != update->getMembers().end(); ++i2) { - NodeMap::iterator i1(original->getMembers().find(i2->first)); - if (i1 == original->getMembers().end()) { + NodeMap * members = original->getMemberMap(); + assert(members != 0); + NodeMap::iterator i1(members->find(i2->first)); + if (i1 == members->end()) { if (i2->second->kind() == Node::KIND_PROPERTY && dynamic_cast< GroupNode * >( original.get())->isExtensible()) { - original->getMembers().insert(*i2); + members->insert(*i2); } } else if (i2->second->kind() == i1->second->kind()) { merge(i1->second, i2->second); @@ -96,15 +98,17 @@ void merge( } break; case Node::KIND_SET: - for (NodeMap::iterator i2(update->getMembers().begin()); + for (NodeMap::const_iterator i2(update->getMembers().begin()); i2 != update->getMembers().end(); ++i2) { - NodeMap::iterator i1(original->getMembers().find(i2->first)); - if (i1 == original->getMembers().end()) { + NodeMap * members = original->getMemberMap(); + assert(members != 0); + NodeMap::iterator i1(members->find(i2->first)); + if (i1 == members->end()) { if (dynamic_cast< SetNode * >(original.get())-> isValidTemplate(i2->second->getTemplateName())) { - original->getMembers().insert(*i2); + members->insert(*i2); } } else if (i2->second->kind() == i1->second->kind() && (i2->second->getTemplateName() == @@ -114,6 +118,9 @@ void merge( } } break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } } @@ -308,15 +315,20 @@ void XcsParser::endElement(xmlreader::XmlReader const & reader) { RTL_CONSTASCII_USTRINGPARAM("this cannot happen")), css::uno::Reference< css::uno::XInterface >()); } - } else if (!elements_.top().node->getMembers().insert( - NodeMap::value_type(top.name, top.node)).second) - { - throw css::uno::RuntimeException( - (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("duplicate ")) + - top.name + - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + - reader.getUrl()), - css::uno::Reference< css::uno::XInterface >()); + } else { + NodeMap * members = elements_.top().node->getMemberMap(); + assert(members != 0); + if (!members->insert(NodeMap::value_type(top.name, top.node)). + second) + { + throw css::uno::RuntimeException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("duplicate ")) + + top.name + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) + + reader.getUrl()), + css::uno::Reference< css::uno::XInterface >()); + } } } } else { diff --git a/configmgr/source/xcuparser.cxx b/configmgr/source/xcuparser.cxx index 764cf8ce36f3..b05fe0e7e3c5 100644 --- a/configmgr/source/xcuparser.cxx +++ b/configmgr/source/xcuparser.cxx @@ -218,6 +218,9 @@ bool XcuParser::startElement( css::uno::Reference< css::uno::XInterface >()); } break; + case Node::KIND_ROOT: + assert(false); // this cannot happen + break; } } return true; @@ -239,7 +242,9 @@ void XcuParser::endElement(xmlreader::XmlReader const &) { state_.pop(); if (insert.is()) { assert(!state_.empty() && state_.top().node.is()); - state_.top().node->getMembers()[name] = insert; + NodeMap * members = state_.top().node->getMemberMap(); + assert(members != 0); + (*members)[name] = insert; } if (pop && !path_.empty()) { path_.pop_back(); @@ -590,9 +595,10 @@ void XcuParser::handleLocpropValue( return; } } - NodeMap::iterator i(locprop->getMembers().find(name)); - if (i != locprop->getMembers().end() && - i->second->getLayer() > valueParser_.getLayer()) + NodeMap * members = locprop->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i != members->end() && i->second->getLayer() > valueParser_.getLayer()) { state_.push(State(true)); // ignored return; @@ -610,8 +616,8 @@ void XcuParser::handleLocpropValue( { bool pop = false; if (nil) { - if (i == locprop->getMembers().end()) { - locprop->getMembers()[name] = new LocalizedValueNode( + if (i == members->end()) { + (*members)[name] = new LocalizedValueNode( valueParser_.getLayer(), css::uno::Any()); } else { dynamic_cast< LocalizedValueNode * >( @@ -635,8 +641,8 @@ void XcuParser::handleLocpropValue( case OPERATION_REMOVE: //TODO: only allow if parent.op == OPERATION_FUSE //TODO: disallow removing when e.g. lang=""? - if (i != locprop->getMembers().end()) { - locprop->getMembers().erase(i); + if (i != members->end()) { + members->erase(i); } state_.push(State(true)); recordModification(false); @@ -702,8 +708,10 @@ void XcuParser::handleGroupProp( return; } } - NodeMap::iterator i(group->getMembers().find(name)); - if (i == group->getMembers().end()) { + NodeMap * members = group->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i == members->end()) { handleUnknownGroupProp(reader, group, name, type, op, finalized); } else { switch (i->second->kind()) { @@ -814,7 +822,9 @@ void XcuParser::handlePlainGroupProp( reader.getUrl()), css::uno::Reference< css::uno::XInterface >()); } - group->getMembers().erase(propertyIndex); + NodeMap * members = group->getMemberMap(); + assert(members != 0); + members->erase(propertyIndex); state_.push(State(true)); // ignore children recordModification(false); break; @@ -1035,8 +1045,10 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { } int finalizedLayer = finalized ? valueParser_.getLayer() : Data::NO_LAYER; int mandatoryLayer = mandatory ? valueParser_.getLayer() : Data::NO_LAYER; - NodeMap::iterator i(set->getMembers().find(name)); - if (i != set->getMembers().end()) { + NodeMap * members = set->getMemberMap(); + assert(members != 0); + NodeMap::iterator i(members->find(name)); + if (i != members->end()) { finalizedLayer = std::min(finalizedLayer, i->second->getFinalized()); i->second->setFinalized(finalizedLayer); mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory()); @@ -1048,7 +1060,7 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { } switch (op) { case OPERATION_MODIFY: - if (i == set->getMembers().end()) { + if (i == members->end()) { SAL_WARN( "configmgr", "ignoring modify of unknown set member node \"" << name @@ -1071,11 +1083,11 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { member->setFinalized(finalizedLayer); member->setMandatory(mandatoryLayer); state_.push(State(member, name, false)); - recordModification(i == set->getMembers().end()); + recordModification(i == members->end()); } break; case OPERATION_FUSE: - if (i == set->getMembers().end()) { + if (i == members->end()) { if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) { state_.push(State(true)); // ignored @@ -1102,13 +1114,13 @@ void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) { // forget about user-layer removals that no longer remove anything // (so that paired additions/removals in the user layer do not grow // registrymodifications.xcu unbounded): - bool known = i != set->getMembers().end(); + bool known = i != members->end(); if (known && !state_.top().locked && finalizedLayer >= valueParser_.getLayer() && (mandatoryLayer == Data::NO_LAYER || mandatoryLayer > valueParser_.getLayer())) { - set->getMembers().erase(i); + members->erase(i); } state_.push(State(true)); if (known) { -- cgit