15 #ifndef _OCRA_COMPOSITE_H_ 16 #define _OCRA_COMPOSITE_H_ 24 #include <boost/noncopyable.hpp> 25 #include <boost/static_assert.hpp> 26 #include <boost/type_traits/is_base_of.hpp> 27 #include <boost/type_traits/is_convertible.hpp> 28 #include <boost/type_traits/has_nothrow_constructor.hpp> 37 template<
class ComponentDerived,
class CompositeDerived,
class ParenthoodInfo>
class Component;
38 template<
class ComponentDerived,
class CompositeDerived,
class ParenthoodInfo>
class Composite;
93 template<
class ComponentDerived,
class CompositeDerived,
class ParenthoodInfo = NoInfo>
105 friend class Composite<ComponentDerived, CompositeDerived, ParenthoodInfo>;
121 Parenthood(parent_t& parent, component_t& child)
122 : parent_(parent), child_(child)
123 , rankOfParent_(child.parents_.size()), rankOfChild_(parent.children_.size())
127 ocra_assert(!parent.isAncestorOf(child) &&
"Parent is already an ancestor of child!");
128 ocra_assert(!child.isAncestorOf(parent) &&
"Parent is already a descendant of child!");
129 ocra_assert(&child != &parent &&
"Cannot attach a node to itself!");
131 parent_.children_.push_back(
this);
132 child_.parents_.push_back(
this);
135 child_.onAttachedParentI(*
this);
136 parent_.onAttachedChildI(*
this);
139 ocra_assert(&parent.getChildhood(getRankOfChild()) == &child.getParenthood(getRankOfParent()) &&
140 &parent.getChildhood(getRankOfChild()) ==
this &&
141 "The same bond is supposed to be registered in both the parent and the child");
142 ocra_assert(parent_.isAncestorOf(child_) &&
"Parent-child relationship not acknowledged");
143 ocra_assert(!child_.isAncestorOf(parent_) &&
"Reversed parent-child relationship");
177 typename std::vector<parenthood_t*>::iterator itChild = parent_.children_.begin() + rankOfChild_;
178 typename std::vector<parenthood_t*>::iterator itParent = child_.parents_.begin() + rankOfParent_;
181 ocra_assert(
this == *itChild &&
this == *itParent &&
"Class invariant broken: the bond is not properly registered in the parent and the child.");
182 ocra_assert(parent_.isAncestorOf_impl(child_) &&
"Class invariant broken");
184 ocra_assert(!childIsAncestorOfParent_forDestructor() &&
"Class invariant broken");
187 child_.onDetachedParentI(*
this);
188 parent_.onDetachedChildI(*
this);
190 parent_.children_.erase(parent_.children_.begin() + rankOfChild_);
191 child_.parents_.erase(child_.parents_.begin() + rankOfParent_);
194 for(itChild = parent_.children_.begin() + rankOfChild_; itChild != parent_.children_.end(); ++itChild)
196 ocra_assert((*itChild)->rankOfChild_ &&
"rankOfChild_ is not supposed to be decreased when already 0");
197 --(*itChild)->rankOfChild_;
201 for(itParent = child_.parents_.begin() + rankOfParent_; itParent != child_.parents_.end(); ++itParent)
203 ocra_assert((*itParent)->rankOfParent_ &&
"rankOfParent_ is not supposed to be decreased when already 0");
204 --(*itParent)->rankOfParent_;
208 int childIsAncestorOfParent_forDestructor()
210 parent_t* child_or_null =
dynamic_cast<parent_t*
>(&child_);
213 return child_or_null->isAncestorOf_impl(parent_);
220 CompositeDerived& getParent()
const {
return static_cast<CompositeDerived&
>(parent_); }
224 ComponentDerived&
getChild()
const {
return static_cast<ComponentDerived&
>(child_); }
227 ParenthoodInfo&
getInfo()
const {
return info_; }
237 ocra_assert(rankOfParent_ < child_.parents_.size() &&
"rankOfParent_ >= child_->parents_.size() should never happen");
238 ocra_assert(*(child_.parents_.begin() + rankOfParent_) ==
this &&
"Class invariant broken: parenthood not in the expected place in child's parents");
242 return child_.parents_[rankOfParent_ - 1];
247 ocra_assert(rankOfParent_ < child_.parents_.size() &&
"rankOfParent_ >= child_->parents_.size() should never happen");
248 ocra_assert(*(child_.parents_.begin() + rankOfParent_) ==
this &&
"Class invariant broken: parenthood not in the expected place in child's parents");
250 size_t rankOfNextParent = rankOfParent_ + 1;
251 if(rankOfNextParent >= child_.parents_.size())
253 return child_.parents_[rankOfNextParent];
258 Parenthood* getPreviousChild()
const 261 ocra_assert(rankOfChild_ < parent_.children_.size() &&
"rankOfChild_ >= parent_->children_.size() should never happen");
262 ocra_assert(*(parent_.children_.begin() + rankOfChild_) ==
this &&
"Class invariant broken: parenthood not in the expected place in parent's children");
266 return parent_.children_[rankOfChild_ - 1];
271 ocra_assert(rankOfChild_ < parent_.children_.size() &&
"rankOfChild_ >= parent_->children_.size() should never happen");
272 ocra_assert(*(parent_.children_.begin() + rankOfChild_) ==
this &&
"Class invariant broken: parenthood not in the expected place in parent's children");
274 size_t rankOfNextChild = rankOfChild_ + 1;
275 if(rankOfNextChild >= parent_.children_.size())
277 return parent_.children_[rankOfNextChild];
303 parentIs(
const parent_t* parent): parent_(parent) {}
310 childIs(
const component_t* child): child_(child) {}
325 size_t rankOfParent_;
327 mutable ParenthoodInfo info_;
330 typedef boost::is_base_of<ComponentDerived, CompositeDerived>
331 ComponentDerived_must_be_base_of_CompositeDerived;
333 typedef boost::is_convertible<CompositeDerived*, ComponentDerived*>
334 CompositeDerived_must_publicly_derive_ComponentDerived;
336 typedef boost::has_nothrow_default_constructor<ParenthoodInfo>
337 ParenthoodInfo_must_have_default_nothrow_constructor;
341 typedef boost::is_base_of<component_base_t_, ComponentDerived>
342 component_base_t_must_be_base_of_ComponentDerived;
344 typedef boost::is_convertible<ComponentDerived*, component_base_t_*>
345 ComponentDerived_must_publicly_derive_component_base_t_;
349 typedef boost::is_base_of<composite_base_t_, CompositeDerived>
350 composite_base_t_must_be_base_of_CompositeDerived;
352 typedef boost::is_convertible<CompositeDerived*, composite_base_t_*>
353 CompositeDerived_must_publicly_derive_composite_base_t_;
355 BOOST_STATIC_ASSERT( ComponentDerived_must_be_base_of_CompositeDerived ::value );
356 BOOST_STATIC_ASSERT( CompositeDerived_must_publicly_derive_ComponentDerived ::value );
358 BOOST_STATIC_ASSERT( component_base_t_must_be_base_of_ComponentDerived ::value );
359 BOOST_STATIC_ASSERT( ComponentDerived_must_publicly_derive_component_base_t_ ::value );
360 BOOST_STATIC_ASSERT( composite_base_t_must_be_base_of_CompositeDerived ::value );
361 BOOST_STATIC_ASSERT( CompositeDerived_must_publicly_derive_composite_base_t_ ::value );
450 template<
class ComponentDerived,
class CompositeDerived,
class ParenthoodInfo = NoInfo>
455 typedef ComponentDerived component_t;
460 typedef typename std::vector<parenthood_t*>::iterator
iterator;
465 size_t getNumParenthoods()
const {
return parents_.size(); }
471 const_iterator parents_begin()
const {
return parents_.begin(); }
486 int isDescendantOf(
const ComponentDerived& node)
const {
return node.isAncestorOf(*static_cast<const ComponentDerived*>(
this)); }
491 for(const_iterator it = parents_begin(); it != parents_end(); ++it)
492 if(&(*it)->getParent() == &node)
497 void printTree(std::ostream& os) { printSubTree(0, os); }
512 virtual int isAncestorOf(
const ComponentDerived& node)
const = 0;
519 virtual void printSubTree(
int depth, std::ostream& os)
const = 0;
527 virtual void printNode(
int depth, std::ostream& os)
const = 0;
553 componentBeingDestroyed_ =
true;
554 while(parents_.size())
555 parents_.back()->getParent().Composite<ComponentDerived, CompositeDerived, ParenthoodInfo>::remove(*static_cast<ComponentDerived*>(
this));
567 int isDescendantOf(
const CompositeDerived& node,
int level)
const 571 for(
size_t i = 0; !result && (i < parents_.size()); ++i)
573 const parent_t& parent = parents_[i]->getParent();
584 void onAttachedParentI(
const parenthood_t& parent)
587 if(!componentBeingDestroyed_)
588 onAttachedParent(parent);
591 void onDetachedParentI(
const parenthood_t& parent)
593 if(!componentBeingDestroyed_)
594 onDetachedParent(parent);
599 std::vector<parenthood_t*> parents_;
600 bool componentBeingDestroyed_;
604 friend class Parenthood<ComponentDerived, CompositeDerived, ParenthoodInfo>;
636 template<
class ComponentDerived,
class CompositeDerived,
class ParenthoodInfo = NoInfo>
643 typedef typename std::vector<parenthood_t_*>::const_iterator const_iterator_;
644 typedef typename std::vector<parenthood_t_*>::iterator iterator_;
649 for(const_iterator_ it = children_begin(); it != children_end(); ++it)
650 if(&(*it)->getChild() == &node)
656 size_t getNumChildhoods()
const {
return children_.size(); }
658 const parenthood_t_&
getChildhood(
size_t i)
const {
return *children_[i]; }
662 const_iterator_ children_begin()
const {
return children_.begin(); }
677 virtual CompositeDerived&
add(ComponentDerived& child) { attach(child);
return *
static_cast<CompositeDerived*
>(
this); }
678 virtual CompositeDerived&
remove(ComponentDerived& child) { detach(child);
return *
static_cast<CompositeDerived*
>(
this); }
699 compositeBeingDestroyed_ =
true;
700 while(children_.size())
701 detach(children_.back()->getChild());
708 new parenthood_t_(*static_cast<CompositeDerived*>(
this), child);
714 typename std::vector<parenthood_t_*>::iterator itParent =
715 std::find_if(child.parents_begin(), child.parents_end(),
typename parenthood_t_::parentIs(static_cast<CompositeDerived*>(
this)));
717 if(itParent == child.parents_end())
718 throw std::runtime_error(
"[ocra::Composite::detach]: parent not found in child's parents... Are the nodes really bound together?");
723 int isAncestorOf_impl(
const ComponentDerived& node)
const {
return node.isDescendantOf(*static_cast<const CompositeDerived*>(
this)); }
727 static_cast<const CompositeDerived*
>(
this)->printNode(depth, os);
728 for(
size_t i = 0; i < children_.size(); ++i)
729 static_cast<ComponentDerived*>(&children_[i]->getChild())->printSubTree(depth + 1, os);
734 void onAttachedChildI(
const parenthood_t_& child)
737 if(!compositeBeingDestroyed_)
738 onAttachedChild(child);
741 void onDetachedChildI(
const parenthood_t_& child)
743 if(!compositeBeingDestroyed_)
744 onDetachedChild(child);
749 std::vector<parenthood_t_*> children_;
750 bool compositeBeingDestroyed_;
753 friend class Parenthood<ComponentDerived, CompositeDerived, ParenthoodInfo>;
773 template<
class LeafDerived>
785 typedef boost::is_base_of<leaf_base_t_, LeafDerived>
786 leaf_base_t_must_be_base_of_LeafDerived;
788 typedef boost::is_convertible<LeafDerived*, leaf_base_t_*>
789 LeafDerived_must_publicly_derive_leaf_base_t_;
791 BOOST_STATIC_ASSERT( leaf_base_t_must_be_base_of_LeafDerived ::value );
792 BOOST_STATIC_ASSERT( LeafDerived_must_publicly_derive_leaf_base_t_ ::value );
799 static_cast<const LeafDerived*
>(
this)->printNode(depth, os);
804 #endif // _OCRA_COMPOSITE_H_ childIs(const component_t *child)
Parenthood< ComponentDerived, CompositeDerived, ParenthoodInfo > parenthood_t
int isDescendantOf(const CompositeDerived &node) const
Returns the number of levels that separates the component from a potential parent.
virtual void onDetachedParent(const parenthood_t &parent)
void detach(ComponentDerived &child)
Erases a Parenthood bond between a Composite and a Component.
std::vector< parenthood_t * >::const_iterator const_iterator
Parenthood * getNextParent() const
int isAncestorOf_impl(const ComponentDerived &node) const
CompositeDerived parent_t
iterator_ children_begin()
Empty information block to attach to a parenthood relationship between a Composite and a Component...
bool operator()(const parenthood_t *p) const
const_iterator parents_end() const
void printTree_impl(int depth, std::ostream &os) const
CompositeDerived & getParent() const
Access to parenthood info, parent, child and their ranks, see constructor postconditions and class de...
ComponentDerived component_t
size_t getRankOfChild() const
virtual void onDetachedChild(const parenthood_t_ &child)
Parenthood * getPreviousParent() const
These methods return the parent of this->getChild() at position this->getRankOfParent()-1 (+1 respect...
const parenthood_t_ & getChildhood(size_t i) const
bool operator()(const parenthood_t *p) const
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
virtual void onAttachedParent(const parenthood_t &parent)
Default implementation of the callbacks, to overload in class ComponentDerived.
void attach(ComponentDerived &child)
Attaches a Component to a Composite by simply creating a Parenthood bond between them.
bool isParentOf(const ComponentDerived &node)
Base class for the Composite class of the Composite pattern.
Parenthood< ComponentDerived, CompositeDerived, ParenthoodInfo > parenthood_t
virtual void onAttachedChild(const parenthood_t_ &child)
Default implementation of the callbacks, to overload in the private part of class CompositeDerived...
ComponentDerived component_t
Inherited typedefs.
size_t getRankOfParent() const
Stores information about a Parent/Child relationship in the Composite design pattern.
CompositeDerived parent_t
int isDescendantOf(const ComponentDerived &node) const
const parenthood_t & getParenthood(size_t i) const
Parenthood * getNextChild() const
Base class for the Component class of the Composite pattern.
ParenthoodInfo & getInfo() const
Base class for the Leaf class of the Composite pattern.
std::vector< parenthood_t * >::iterator iterator
parentIs(const parent_t *parent)
void printTree(std::ostream &os)
ComponentDerived & getChild() const
bool isChildOf(const CompositeDerived &node)
#define ocra_assert(ocra_expression)
const_iterator_ children_end() const
virtual CompositeDerived & add(ComponentDerived &child)
Append and detach a child.
const component_t * child_
void printTree_impl(int depth, std::ostream &os) const
Functors to locate a parent or a child.