diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 2d01b5d71..27f3ee009 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -125,6 +125,8 @@ void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const */ DynamicObject::Ptr ConfigItem::Commit(void) { + Logger::Write(LogDebug, "base", "Commit called for ConfigItem Type=" + GetType() + ", Name=" + GetName()); + DynamicObject::Ptr dobj = m_DynamicObject.lock(); Dictionary::Ptr properties = boost::make_shared(); @@ -168,10 +170,35 @@ DynamicObject::Ptr ConfigItem::Commit(void) else dobj->Register(); - /* TODO: Figure out whether there are any child objects which inherit - * from this config item and Commit() them as well */ + pair ikey = make_pair(GetType(), GetName()); + ItemMap::iterator it = m_Items.find(ikey); - m_Items[make_pair(GetType(), GetName())] = GetSelf(); + /* unregister the old item from its parents */ + if (it != m_Items.end()) { + ConfigItem::Ptr oldItem = it->second; + oldItem->UnregisterFromParents(); + + /* steal the old item's children */ + m_ChildObjects = oldItem->m_ChildObjects; + } + + /* register this item with its parents */ + BOOST_FOREACH(const String& parentName, m_Parents) { + ConfigItem::Ptr parent = GetObject(GetType(), parentName); + parent->RegisterChild(GetSelf()); + } + + /* notify our children of the update */ + BOOST_FOREACH(const ConfigItem::WeakPtr wchild, m_ChildObjects) { + const ConfigItem::Ptr& child = wchild.lock(); + + if (!child) + continue; + + child->OnParentCommitted(); + } + + m_Items[ikey] = GetSelf(); OnCommitted(GetSelf()); @@ -194,9 +221,38 @@ void ConfigItem::Unregister(void) if (it != m_Items.end()) m_Items.erase(it); + UnregisterFromParents(); + OnRemoved(GetSelf()); } +void ConfigItem::RegisterChild(const ConfigItem::Ptr& child) +{ + m_ChildObjects.insert(child); +} + +void ConfigItem::UnregisterChild(const ConfigItem::Ptr& child) +{ + m_ChildObjects.erase(child); +} + +void ConfigItem::UnregisterFromParents(void) +{ + BOOST_FOREACH(const String& parentName, m_Parents) { + ConfigItem::Ptr parent = GetObject(GetType(), parentName); + parent->UnregisterChild(GetSelf()); + } +} + +/* + * Notifies an item that one of its parents has been committed. + */ +void ConfigItem::OnParentCommitted(void) +{ + if (GetObject(GetType(), GetName()) == static_cast(GetSelf())) + Commit(); +} + /** * Retrieves the DynamicObject that belongs to the configuration item. * diff --git a/lib/config/configitem.h b/lib/config/configitem.h index e68c8583b..2cc73c919 100644 --- a/lib/config/configitem.h +++ b/lib/config/configitem.h @@ -63,6 +63,12 @@ public: private: void CalculateProperties(const Dictionary::Ptr& dictionary) const; + void RegisterChild(const ConfigItem::Ptr& child); + void UnregisterChild(const ConfigItem::Ptr& child); + void UnregisterFromParents(void); + + void OnParentCommitted(void); + String m_Type; /**< The object type. */ String m_Name; /**< The name. */ @@ -72,8 +78,10 @@ private: DebugInfo m_DebugInfo; /**< Debug information. */ DynamicObject::WeakPtr m_DynamicObject; /**< The instantiated version - of this configuration - item */ + * of this configuration + * item */ + set m_ChildObjects; /**< Instantiated items + * that inherit from this item */ typedef map, ConfigItem::Ptr> ItemMap; static ItemMap m_Items; /**< All registered configuration items. */