diff options
author | sb <sb@openoffice.org> | 2009-09-23 16:07:30 +0200 |
---|---|---|
committer | sb <sb@openoffice.org> | 2009-09-23 16:07:30 +0200 |
commit | d6688c4ca3b0f7c4fdda24f183fe60894840b6dc (patch) | |
tree | 6382529fe4923031e1254ea9cbca398e158455f7 | |
parent | 5ab6b21f22098727d905bae8b9c8eb6286c8edee (diff) |
#i101955# notification support, continued (still to be continued; at least no longer fails miserably now)
-rw-r--r-- | configmgr2/source/access.cxx | 313 | ||||
-rw-r--r-- | configmgr2/source/access.hxx | 6 | ||||
-rw-r--r-- | configmgr2/source/components.cxx | 22 | ||||
-rw-r--r-- | configmgr2/source/components.hxx | 2 | ||||
-rw-r--r-- | configmgr2/source/modifications.cxx | 41 | ||||
-rw-r--r-- | configmgr2/source/modifications.hxx | 13 | ||||
-rw-r--r-- | configmgr2/source/rootaccess.cxx | 52 | ||||
-rw-r--r-- | configmgr2/source/rootaccess.hxx | 8 | ||||
-rw-r--r-- | configmgr2/source/writemodfile.cxx | 202 |
9 files changed, 378 insertions, 281 deletions
diff --git a/configmgr2/source/access.cxx b/configmgr2/source/access.cxx index f6aa7296f156..385e0f0d70cd 100644 --- a/configmgr2/source/access.cxx +++ b/configmgr2/source/access.cxx @@ -160,61 +160,100 @@ void Access::releaseChild(rtl::OUString const & name) { } void Access::initGlobalBroadcaster( - Modifications const & globalModifications, Broadcaster * broadcaster) + Modifications const & modifications, Broadcaster * broadcaster) { OSL_ASSERT(broadcaster != 0); - //TODO: only for matching modifications: - for (ContainerListeners::iterator i(containerListeners_.begin()); - i != containerListeners_.end(); ++i) - { - broadcaster->addContainerNotification( - *i, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::Any()/*TODO*/, css::uno::Any()/*TODO*/, - css::uno::Any()/*TODO*/)); - } - for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); - i != propertyChangeListeners_.end(); ++i) - { - for (PropertyChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addPropertyChangeNotification( - *j, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), getNameInternal(), - false, -1, css::uno::Any(), css::uno::Any())); - } - } - for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); - i != vetoableChangeListeners_.end(); ++i) + //TODO: handle containerListeners_, vetoableChangeListeners_, + // propertiesChangeListeners_ + for (Modifications::Children::const_iterator i( + modifications.children.begin()); + i != modifications.children.end(); ++i) { - for (VetoableChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addVetoableChangeNotification( - *j, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), getNameInternal(), - false, -1, css::uno::Any(), css::uno::Any())); - } - } - for (PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.begin()); - i != propertiesChangeListeners_.end(); ++i) - { - broadcaster->addPropertiesChangeNotification( - *i, - css::uno::Sequence< css::beans::PropertyChangeEvent >()/*TODO*/); - } - //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)); + rtl::Reference< ChildAccess > child(getChild(i->first)); if (child.is()) { - child->initGlobalBroadcaster(globalModifications, broadcaster); + switch (child->getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + if (Components::allLocales(getRootAccess()->getLocale())) { + break; + } + //TODO: filter child mods that are irrelevant for locale: + if (!i->second.children.empty()) { + 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())); + } + } + } + return; + case Node::KIND_LOCALIZED_VALUE: + if (Components::allLocales(getRootAccess()->getLocale())) { + return; + } + // fall through + case Node::KIND_PROPERTY: + if (i->second.children.empty()) { + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + //TODO: filter out adds/removes: + 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) + { + //TODO: filter out adds/removes: + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + } + return; + default: + break; + } + child->initGlobalBroadcaster(i->second, broadcaster); + //TODO: recurse only into children w/ listeners } } } @@ -300,61 +339,100 @@ void Access::clearListeners() throw() { } void Access::initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster) + Modifications const & modifications, Broadcaster * broadcaster) { OSL_ASSERT(broadcaster != 0); - //TODO: only for matching modifications: - for (ContainerListeners::iterator i(containerListeners_.begin()); - i != containerListeners_.end(); ++i) - { - broadcaster->addContainerNotification( - *i, - css::container::ContainerEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::Any()/*TODO*/, css::uno::Any()/*TODO*/, - css::uno::Any()/*TODO*/)); - } - for (PropertyChangeListeners::iterator i(propertyChangeListeners_.begin()); - i != propertyChangeListeners_.end(); ++i) + //TODO: handle containerListeners_, vetoableChangeListeners_, + // propertiesChangeListeners_ + for (Modifications::Children::const_iterator i( + modifications.children.begin()); + i != modifications.children.end(); ++i) { - for (PropertyChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addPropertyChangeNotification( - *j, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), getNameInternal(), - false, -1, css::uno::Any(), css::uno::Any())); - } - } - for (VetoableChangeListeners::iterator i(vetoableChangeListeners_.begin()); - i != vetoableChangeListeners_.end(); ++i) - { - for (VetoableChangeListenersElement::iterator j(i->second.begin()); - j != i->second.end(); ++j) - { - broadcaster->addVetoableChangeNotification( - *j, - css::beans::PropertyChangeEvent( - static_cast< cppu::OWeakObject * >(this), getNameInternal(), - false, -1, css::uno::Any(), css::uno::Any())); - } - } - for (PropertiesChangeListeners::iterator i( - propertiesChangeListeners_.begin()); - i != propertiesChangeListeners_.end(); ++i) - { - broadcaster->addPropertiesChangeNotification( - *i, - css::uno::Sequence< css::beans::PropertyChangeEvent >()/*TODO*/); - } - //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)); + rtl::Reference< ChildAccess > child(getChild(i->first)); if (child.is()) { - child->initLocalBroadcaster(localModifications, broadcaster); + switch (child->getNode()->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + if (Components::allLocales(getRootAccess()->getLocale())) { + break; + } + //TODO: filter child mods that are irrelevant for locale: + if (!i->second.children.empty()) { + 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())); + } + } + } + return; + case Node::KIND_LOCALIZED_VALUE: + if (Components::allLocales(getRootAccess()->getLocale())) { + return; + } + // fall through + case Node::KIND_PROPERTY: + if (i->second.children.empty()) { + PropertyChangeListeners::iterator j( + propertyChangeListeners_.find(i->first)); + if (j != propertyChangeListeners_.end()) { + for (PropertyChangeListenersElement::iterator k( + j->second.begin()); + k != j->second.end(); ++k) + { + //TODO: filter out adds/removes: + 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) + { + //TODO: filter out adds/removes: + broadcaster->addPropertyChangeNotification( + *k, + css::beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >(this), + i->first, false, -1, css::uno::Any(), + css::uno::Any())); + } + } + } + return; + default: + break; + } + child->initLocalBroadcaster(i->second, broadcaster); + //TODO: recurse only into children w/ listeners } } } @@ -1143,6 +1221,7 @@ void Access::addPropertyChangeListener( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), static_cast< cppu::OWeakObject * >(this)); } + checkKnownProperty(aPropertyName); if (!disposed_) { propertyChangeListeners_[aPropertyName].insert(xListener); return; @@ -1164,6 +1243,7 @@ void Access::removePropertyChangeListener( { OSL_ASSERT(thisIs(IS_GROUP)); osl::MutexGuard g(lock); + checkKnownProperty(aPropertyName); PropertyChangeListeners::iterator i( propertyChangeListeners_.find(aPropertyName)); if (i != propertyChangeListeners_.end()) { @@ -1193,6 +1273,7 @@ void Access::addVetoableChangeListener( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("null listener")), static_cast< cppu::OWeakObject * >(this)); } + checkKnownProperty(PropertyName); if (!disposed_) { vetoableChangeListeners_[PropertyName].insert(aListener); return; @@ -1214,6 +1295,7 @@ void Access::removeVetoableChangeListener( { OSL_ASSERT(thisIs(IS_GROUP)); osl::MutexGuard g(lock); + checkKnownProperty(PropertyName); VetoableChangeListeners::iterator i( vetoableChangeListeners_.find(PropertyName)); if (i != vetoableChangeListeners_.end()) { @@ -1792,6 +1874,33 @@ void Access::checkFinalized() { } } +void Access::checkKnownProperty(rtl::OUString const & descriptor) { + if (descriptor.getLength() == 0) { + return; + } + rtl::Reference< ChildAccess > child(getChild(descriptor)); + if (child.is()) { + switch (child->getNode()->kind()) { + case Node::KIND_PROPERTY: + return; + case Node::KIND_LOCALIZED_PROPERTY: + if (!Components::allLocales(getRootAccess()->getLocale())) { + return; + } + break; + case Node::KIND_LOCALIZED_VALUE: + if (Components::allLocales(getRootAccess()->getLocale())) { + return; + } + break; + default: + break; + } + } + throw css::beans::UnknownPropertyException( + descriptor, static_cast< cppu::OWeakObject * >(this)); +} + rtl::Reference< ChildAccess > Access::getFreeSetMember( css::uno::Any const & value) { diff --git a/configmgr2/source/access.hxx b/configmgr2/source/access.hxx index 06e26ff1c7bf..02a93a3d6edb 100644 --- a/configmgr2/source/access.hxx +++ b/configmgr2/source/access.hxx @@ -143,7 +143,7 @@ public: virtual bool isFinalized() = 0; virtual void initGlobalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster); + Modifications const & modifications, Broadcaster * broadcaster); using OWeakObject::acquire; using OWeakObject::release; @@ -167,7 +167,7 @@ protected: virtual void clearListeners() throw (); virtual void initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster); + Modifications const & modifications, Broadcaster * broadcaster); virtual com::sun::star::uno::Any SAL_CALL queryInterface( com::sun::star::uno::Type const & aType) @@ -506,6 +506,8 @@ private: void checkFinalized(); + void checkKnownProperty(rtl::OUString const & descriptor); + rtl::Reference< ChildAccess > getFreeSetMember( com::sun::star::uno::Any const & value); diff --git a/configmgr2/source/components.cxx b/configmgr2/source/components.cxx index 691d64ff535d..94db1ee70f43 100644 --- a/configmgr2/source/components.cxx +++ b/configmgr2/source/components.cxx @@ -48,6 +48,7 @@ #include "components.hxx" #include "data.hxx" +#include "modifications.hxx" #include "node.hxx" #include "parsemanager.hxx" #include "rootaccess.hxx" @@ -136,9 +137,10 @@ void Components::removeRootAccess(RootAccess * access) { } void Components::initGlobalBroadcaster( - Modifications const & globalModifications, + Modifications const & modifications, rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster) { + //TODO: Iterate only over roots w/ listeners: for (WeakRootSet::iterator i(roots_.begin()); i != roots_.end(); ++i) { rtl::Reference< RootAccess > root; if ((*i)->acquireCounting() > 1) { @@ -147,7 +149,23 @@ void Components::initGlobalBroadcaster( (*i)->releaseNondeleting(); if (root.is()) { if (root != exclude) { - root->initGlobalBroadcaster(globalModifications, broadcaster); + Path path(root->getAbsolutePath()); + Modifications const * mods = &modifications; + for (Path::iterator j(path.begin()); j != path.end(); ++j) { + Modifications::Children::const_iterator k( + mods->children.find(*j)); + if (k == mods->children.end()) { + mods = 0; + break; + } + mods = &k->second; + } + //TODO: If the complete tree of which root is a part is deleted, + // or replaced, mods will be null, but some of the listeners + // from within root should probably fire nonetheless: + if (mods != 0) { + root->initGlobalBroadcaster(*mods, broadcaster); + } } } } diff --git a/configmgr2/source/components.hxx b/configmgr2/source/components.hxx index 98082fb842a0..807acf827ba6 100644 --- a/configmgr2/source/components.hxx +++ b/configmgr2/source/components.hxx @@ -70,7 +70,7 @@ public: void removeRootAccess(RootAccess * access); void initGlobalBroadcaster( - Modifications const & globalModifications, + Modifications const & modifications, rtl::Reference< RootAccess > const & exclude, Broadcaster * broadcaster); diff --git a/configmgr2/source/modifications.cxx b/configmgr2/source/modifications.cxx index a2ea42211b2c..4b7acd1901c9 100644 --- a/configmgr2/source/modifications.cxx +++ b/configmgr2/source/modifications.cxx @@ -37,37 +37,24 @@ namespace configmgr { -namespace { - -bool isPrefix(Path const & prefix, Path const & path) { - if (prefix.size() > path.size()) { - return false; - } - Path::const_iterator i1(prefix.begin()); - Path::const_iterator i2(path.begin()); - while (i1 != prefix.end()) { - if (*i1++ != *i2++) { - return false; - } - } - return true; -} - -} - void Modifications::add(Path const & path) { - //TODO: performance - for (List::iterator i(list.begin()); i != list.end();) { - if (isPrefix(*i, path)) { - return; - } - if (isPrefix(path, *i)) { - list.erase(i++); + Modifications * mod = this; + bool wasPresent = false; + for (Path::const_iterator i(path.begin()); i != path.end(); ++i) { + Children::iterator j(mod->children.find(*i)); + if (j == mod->children.end()) { + if (wasPresent && mod->children.empty()) { + return; + } + j = mod->children.insert(Children::value_type(*i, Modifications())). + first; + wasPresent = false; } else { - ++i; + wasPresent = true; } + mod = &j->second; } - list.push_back(path); + mod->children.clear(); } } diff --git a/configmgr2/source/modifications.hxx b/configmgr2/source/modifications.hxx index 5a2b28e5a8be..7f7d14dba132 100644 --- a/configmgr2/source/modifications.hxx +++ b/configmgr2/source/modifications.hxx @@ -32,19 +32,18 @@ #include "sal/config.h" -#include <list> - -#include "boost/noncopyable.hpp" +#include <map> #include "path.hxx" +namespace rtl { class OUString; } + namespace configmgr { -struct Modifications: private boost::noncopyable { -public: - typedef std::list< Path > List; +struct Modifications { + typedef std::map< rtl::OUString, Modifications > Children; - List list; + Children children; void add(Path const & path); }; diff --git a/configmgr2/source/rootaccess.cxx b/configmgr2/source/rootaccess.cxx index 554fcf0f4f70..4dee4109d342 100644 --- a/configmgr2/source/rootaccess.cxx +++ b/configmgr2/source/rootaccess.cxx @@ -75,26 +75,16 @@ RootAccess::RootAccess( pathRepresentation_(pathRepresentation), locale_(locale), update_(update) {} +Path RootAccess::getAbsolutePath() { + getNode(); + return path_; +} + void RootAccess::initGlobalBroadcaster( - Modifications const & globalModifications, Broadcaster * broadcaster) + Modifications const & modifications, Broadcaster * broadcaster) { - OSL_ASSERT(broadcaster != 0); - //TODO: only for matching modifications: - for (ChangesListeners::iterator i(changesListeners_.begin()); - i != changesListeners_.end(); ++i) - { - broadcaster->addChangesNotification( - *i, - css::util::ChangesEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny( - css::uno::Reference< css::uno::XInterface >( - static_cast< cppu::OWeakObject * >(this))), - //TODO: XInterface or something else? - css::uno::Sequence< css::util::ElementChange >()/*TODO*/)); - - } - Access::initGlobalBroadcaster(globalModifications, broadcaster); + Access::initGlobalBroadcaster(modifications, broadcaster); + //TODO: handle changesListeners_ } void RootAccess::acquire() throw () { @@ -118,11 +108,6 @@ RootAccess::~RootAccess() { Components::singleton().removeRootAccess(this); } -Path RootAccess::getAbsolutePath() { - getNode(); - return path_; -} - Path RootAccess::getRelativePath() { return Path(); } @@ -201,25 +186,10 @@ void RootAccess::clearListeners() throw() { } void RootAccess::initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster) + Modifications const & modifications, Broadcaster * broadcaster) { - OSL_ASSERT(broadcaster != 0); - //TODO: only for matching modifications: - for (ChangesListeners::iterator i(changesListeners_.begin()); - i != changesListeners_.end(); ++i) - { - broadcaster->addChangesNotification( - *i, - css::util::ChangesEvent( - static_cast< cppu::OWeakObject * >(this), - css::uno::makeAny( - css::uno::Reference< css::uno::XInterface >( - static_cast< cppu::OWeakObject * >(this))), - //TODO: XInterface or something else? - css::uno::Sequence< css::util::ElementChange >()/*TODO*/)); - - } - Access::initLocalBroadcaster(localModifications, broadcaster); + Access::initLocalBroadcaster(modifications, broadcaster); + //TODO: handle changesListeners_ } css::uno::Any RootAccess::queryInterface(css::uno::Type const & aType) diff --git a/configmgr2/source/rootaccess.hxx b/configmgr2/source/rootaccess.hxx index 250a8f194d0c..9ea568bcf104 100644 --- a/configmgr2/source/rootaccess.hxx +++ b/configmgr2/source/rootaccess.hxx @@ -69,8 +69,10 @@ public: rtl::OUString const & pathRepresenation, rtl::OUString const & locale, bool update); + virtual Path getAbsolutePath(); + virtual void initGlobalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster); + Modifications const & modifications, Broadcaster * broadcaster); virtual void SAL_CALL acquire() throw (); @@ -83,8 +85,6 @@ public: private: virtual ~RootAccess(); - virtual Path getAbsolutePath(); - virtual Path getRelativePath(); virtual rtl::OUString getRelativePathRepresentation(); @@ -107,7 +107,7 @@ private: virtual void clearListeners() throw (); virtual void initLocalBroadcaster( - Modifications const & localModifications, Broadcaster * broadcaster); + Modifications const & modifications, Broadcaster * broadcaster); virtual com::sun::star::uno::Any SAL_CALL queryInterface( com::sun::star::uno::Type const & aType) diff --git a/configmgr2/source/writemodfile.cxx b/configmgr2/source/writemodfile.cxx index ccfee9b6f891..15b9e3e5eb6a 100644 --- a/configmgr2/source/writemodfile.cxx +++ b/configmgr2/source/writemodfile.cxx @@ -437,6 +437,105 @@ void writeNode( } } +void writeModifications( + oslFileHandle handle, rtl::OUString const & grandparentPathRepresentation, + rtl::OUString const & parentName, rtl::Reference< Node > const & parent, + rtl::OUString const & nodeName, rtl::Reference< Node > const & node, + Modifications const & modifications) +{ + if (modifications.children.empty()) { + OSL_ASSERT(parent.is()); + // components themselves have no parent but must have children + if (node.is()) { + writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); + writeAttributeValue( + handle, + (grandparentPathRepresentation + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + + Data::createSegment(parent->getTemplateName(), parentName))); + writeData(handle, RTL_CONSTASCII_STRINGPARAM("\">")); + writeNode(handle, parent, nodeName, node); + writeData(handle, RTL_CONSTASCII_STRINGPARAM("</item>")); + // It is never necessary to write the oor:mandatory attribute, as it + // cannot be set via the UNO API. + } else { + writeData(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); + switch (parent->kind()) { + case Node::KIND_LOCALIZED_PROPERTY: + writeAttributeValue(handle, grandparentPathRepresentation); + writeData( + handle, RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); + writeAttributeValue(handle, parentName); + writeData( + handle, + RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\"><value")); + if (nodeName.getLength() != 0) { + writeData( + handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\"")); + writeAttributeValue(handle, nodeName); + writeData(handle, RTL_CONSTASCII_STRINGPARAM("\"")); + } + writeData( + handle, + RTL_CONSTASCII_STRINGPARAM( + " oor:op=\"remove\"/></prop></item>")); + break; + case Node::KIND_GROUP: + OSL_ASSERT( + dynamic_cast< GroupNode * >(parent.get())->isExtensible()); + writeAttributeValue( + handle, + (grandparentPathRepresentation + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + + Data::createSegment( + parent->getTemplateName(), parentName))); + writeData( + handle, RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); + writeAttributeValue(handle, nodeName); + writeData( + handle, + RTL_CONSTASCII_STRINGPARAM( + "\" oor:op=\"remove\"/></item>")); + break; + case Node::KIND_SET: + writeAttributeValue( + handle, + (grandparentPathRepresentation + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + + Data::createSegment( + parent->getTemplateName(), parentName))); + writeData( + handle, RTL_CONSTASCII_STRINGPARAM("\"><node oor:name=\"")); + writeAttributeValue(handle, nodeName); + writeData( + handle, + RTL_CONSTASCII_STRINGPARAM( + "\" oor:op=\"remove\"/></item>")); + break; + default: + OSL_ASSERT(false); // this cannot happen + break; + } + } + } else { + rtl::OUString parentPathRep; + if (parent.is()) { // components themselves have no parent + parentPathRep = grandparentPathRepresentation + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + + Data::createSegment(parent->getTemplateName(), parentName); + } + OSL_ASSERT(node.is()); + for (Modifications::Children::const_iterator i( + modifications.children.begin()); + i != modifications.children.end(); ++i) + { + writeModifications( + handle, parentPathRep, nodeName, node, i->first, + node->getMember(i->first), i->second); + } + } +} + } void writeModFile(rtl::OUString const & url, Data const & data) { @@ -475,102 +574,15 @@ void writeModFile(rtl::OUString const & url, Data const & data) { //TODO: Do not write back information about those removed items that did not // come from the .xcs/.xcu files, anyway (but had been added dynamically // instead): - for (Modifications::List::const_iterator j(data.modifications.list.begin()); - j != data.modifications.list.end(); ++j) + for (Modifications::Children::const_iterator j( + data.modifications.children.begin()); + j != data.modifications.children.end(); ++j) { - Path::const_iterator k(j->begin()); - OSL_ASSERT(k != j->end()); - rtl::OUString parentName(*k++); - rtl::Reference< Node > parent( - Data::findNode(Data::NO_LAYER, data.components, parentName)); - OSL_ASSERT(parent.is() && k != j->end()); - rtl::OUString nodeName; - rtl::Reference< Node > node; - rtl::OUStringBuffer pathRep; // up to grandparent segment - for (;;) { - nodeName = *k++; - node = parent->getMember(nodeName); - if (k == j->end()) { - break; - } - OSL_ASSERT(node.is()); - pathRep.append(sal_Unicode('/')); - pathRep.append( - Data::createSegment(parent->getTemplateName(), parentName)); - parent = node; - parentName = nodeName; - } - if (node.is()) { - writeData( - tmp.handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); - pathRep.append(sal_Unicode('/')); - pathRep.append( - Data::createSegment(parent->getTemplateName(), parentName)); - writeAttributeValue(tmp.handle, pathRep.makeStringAndClear()); - writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("\">")); - writeNode(tmp.handle, parent, nodeName, node); - writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</item>")); - // It is never necessary to write the oor:mandatory attribute, as it - // cannot be set via the UNO API. - } else { - writeData( - tmp.handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\"")); - switch (parent->kind()) { - case Node::KIND_LOCALIZED_PROPERTY: - writeAttributeValue(tmp.handle, pathRep.makeStringAndClear()); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); - writeAttributeValue(tmp.handle, parentName); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\"><value")); - if (nodeName.getLength() != 0) { - writeData( - tmp.handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\"")); - writeAttributeValue(tmp.handle, nodeName); - writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("\"")); - } - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM( - " oor:op=\"remove\"/></prop></item>")); - break; - case Node::KIND_GROUP: - OSL_ASSERT( - dynamic_cast< GroupNode * >(parent.get())->isExtensible()); - pathRep.append(sal_Unicode('/')); - pathRep.append( - Data::createSegment(parent->getTemplateName(), parentName)); - writeAttributeValue(tmp.handle, pathRep.makeStringAndClear()); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM("\"><prop oor:name=\"")); - writeAttributeValue(tmp.handle, nodeName); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM( - "\" oor:op=\"remove\"/></item>")); - break; - case Node::KIND_SET: - pathRep.append(sal_Unicode('/')); - pathRep.append( - Data::createSegment(parent->getTemplateName(), parentName)); - writeAttributeValue(tmp.handle, pathRep.makeStringAndClear()); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM("\"><node oor:name=\"")); - writeAttributeValue(tmp.handle, nodeName); - writeData( - tmp.handle, - RTL_CONSTASCII_STRINGPARAM( - "\" oor:op=\"remove\"/></item>")); - break; - default: - OSL_ASSERT(false); // this cannot happen - break; - } - } + writeModifications( + tmp.handle, rtl::OUString(), rtl::OUString(), + rtl::Reference< Node >(), j->first, + Data::findNode(Data::NO_LAYER, data.components, j->first), + j->second); } writeData(tmp.handle, RTL_CONSTASCII_STRINGPARAM("</oor:items>")); oslFileError e = osl_closeFile(tmp.handle); |