From: <mk...@us...> - 2003-09-06 07:06:34
|
Update of /cvsroot/csp/APPLICATIONS/SimData/Include/SimData In directory sc8-pr-cvs1:/tmp/cvs-serv25534 Modified Files: Tag: b0_4_0 Composite.h Log Message: Index: Composite.h =================================================================== RCS file: /cvsroot/csp/APPLICATIONS/SimData/Include/SimData/Attic/Composite.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** Composite.h 6 Sep 2003 01:37:07 -0000 1.1.2.1 --- Composite.h 6 Sep 2003 07:06:30 -0000 1.1.2.2 *************** *** 47,56 **** class Visitable; ! #define SIMDATA_VISITOR(visitor) \ ! typedef SIMDATA(Ref)<visitor> Ref; \ ! using SIMDATA(Visitor)<visitor>::apply; ! #define SIMDATA_VISITABLE(visitor) \ ! virtual SIMDATA(Ref)<visitor> accept(SIMDATA(Ref)<visitor> v) { \ v->apply(*this); \ return v; \ --- 47,56 ---- class Visitable; ! #define SIMDATA_VISITOR(__visitor) \ ! typedef SIMDATA(Ref)<__visitor> Ref; \ ! using SIMDATA(Visitor)<__visitor>::apply; ! #define SIMDATA_VISITABLE(__visitor) \ ! virtual SIMDATA(Ref)<__visitor> accept(SIMDATA(Ref)<__visitor> v) { \ v->apply(*this); \ return v; \ *************** *** 77,94 **** class VisitorCore: public VisitorBase { public: typedef enum { ! TRAVERSE_NONE, ! TRAVERSE_CHILDREN, ! TRAVERSE_PARENTS, } TraversalMode; TraversalMode getTraversalMode() const { return _traversal_mode; } typedef CompositeBase<N> Node; virtual void apply(Node &node) { traverse(node); } ! VisitorCore(): _traversal_mode(TRAVERSE_CHILDREN) {} protected: void traverse(Node &node) { if (_traversal_mode == TRAVERSE_CHILDREN) { --- 77,120 ---- class VisitorCore: public VisitorBase { public: + /// Composite traversal modes. typedef enum { ! TRAVERSE_NONE, //< Act on only the current node. ! TRAVERSE_CHILDREN, //< Act on the current node and all children ! TRAVERSE_PARENTS, //< Act on the current node and all parents } TraversalMode; + /** Get the mode for traversing the composite graph. + */ TraversalMode getTraversalMode() const { return _traversal_mode; } + + /// Base class type for nodes in the graph. typedef CompositeBase<N> Node; + /** Visit a node and propagate. + * + * This method is overloaded in the actual visitor classes + * to apply distinct operations to each type of node. Apply + * methods should generally conclude with a call to + * traverse(node) to continue progagation of the visitor + * through the graph. + */ virtual void apply(Node &node) { traverse(node); } ! /** Constructor. ! * ! * @param mode The initial traversal mode. The default is ! * TRAVERSE_CHILDREN. ! */ ! VisitorCore(TraversalMode mode = TRAVERSE_CHILDREN): ! _traversal_mode(mode) {} protected: + /** Propagate from a given node based on the current traversal + * mode. + * + * TRAVERSE_CHILDREN will visit the subgraph of the node + * (depth first), while TRAVERSE_PARENTS will visit all + * parents until the root of the graph is reached. + */ void traverse(Node &node) { if (_traversal_mode == TRAVERSE_CHILDREN) { *************** *** 100,106 **** --- 126,148 ---- } + /** Change the traversal mode. + * + * The initial traversal mode can be set as a contructor parameter. + * This method allows the traversal mode to be changed on the fly, + * for example to abort traversal of a graph once a condition is + * met (such as finding a matching node during a search). + */ + void setTraversalMode(TraversalMode mode) { _traversal_mode = mode; } + private: + /// The current traversal mode. TraversalMode _traversal_mode; + + /** Visit all parents of a node. + */ inline void ascend(Node &node); + + /** Visit all children of a node. + */ inline void descend(Node &node); *************** *** 116,120 **** --- 158,167 ---- friend class VisitorCore<N>; protected: + /** Propagate a visitor to all child nodes. + */ virtual void descend(VisitorBase *v) = 0; + + /** Propagate a visitor to all parent nodes. + */ virtual void ascend(VisitorBase *v) = 0; }; *************** *** 169,177 **** --- 216,240 ---- typedef Ref<V> VisitorRef; + /// A list of child node references. typedef std::vector< NodeRef > ChildList; + + /// A list of parent node pointers (which avoids circular references). typedef std::vector< Node* > ParentList; + /** Accept a visitor. + * + * This method must be implemented in each subclasses to + * ensure proper dispatch of the visitor's apply methods. + * See the Composite class documentation for details. + */ virtual VisitorRef accept(VisitorRef v)=0; + /** Add a child to this node. + * + * Extend this method to inforce constraints on the graph structure, + * such as preventing nodes from having multiple parents. + * + * @returns True if the child was added, false if it already exists. + */ virtual bool addChild(Node *node) { if (containsNode(node)) return false; *************** *** 181,188 **** --- 244,262 ---- } + /** Remove a child from this node. + * + * @returns True if the child was removed, false if it was not found. + */ virtual bool removeChild(Node *node) { return removeChild(getChildIndex(node)); } + /** Remove one or more children. + * + * @param pos The index of the first child to remove. + * @param count The number of children to remove (default 1). + * @returns True if one or more children were removed, false + * otherwise. + */ virtual bool removeChild(int pos, int count=1) { if (pos >= _children.size() || count <= 0) return false; *************** *** 199,204 **** --- 273,287 ---- } + /** Get the number of immediate children of this node. + */ inline unsigned int getNumChildren() const { return _children.size(); } + /** Replace an existing child node with a new one. + * + * The original node will be destroyed if it is not already + * referenced elsewhere. + * + * @returns True if the child was replaced, false otherwise. + */ virtual bool setChild(unsigned int i, Node* node) { if (i >= _children.size() || !node) return false; *************** *** 210,219 **** } ! inline Node* getChild(unsigned int i) { return _children[i].get(); } ! inline const Node* getChild(unsigned int i) const { return _children[i].get(); } inline ChildList const &getChildren() const { return _children; } inline bool containsNode(Node const *node) const { if (!node) return false; --- 293,322 ---- } ! /** Get a child by index number. ! * ! * @returns 0 if the index is out of range. ! */ ! inline Node* getChild(unsigned int i) { ! if (i >= _children.size()) return 0; ! return _children[i].get(); ! } ! /** Get a child by index number. ! * ! * @returns 0 if the index is out of range. ! */ ! inline const Node* getChild(unsigned int i) const { ! if (i >= _children.size()) return 0; ! return _children[i].get(); ! } + /** Get a list of immediate children of this node. + */ inline ChildList const &getChildren() const { return _children; } + /** Test if this node contains a given node. + * + * @returns True if the node is an immediate child, false otherwise. + */ inline bool containsNode(Node const *node) const { if (!node) return false; *************** *** 221,224 **** --- 324,331 ---- } + /** Get the index of a child node. + * + * @returns The index if found, otherwise the number of children. + */ inline unsigned int getChildIndex(Node const *node) const { for (int idx = 0; idx < _children.size(); ++idx) { *************** *** 228,242 **** } inline const ParentList &getParents() const { return _parents; } ! inline Node* getParent(unsigned int i) { return _parents[i]; } ! inline const Node* getParent(unsigned int i) const { return _parents[i]; } inline unsigned int getNumParents() const { return _parents.size(); } protected: inline ParentList getParents() { return _parents; } class AcceptOp { typename Composite::VisitorRef _visitor; --- 335,371 ---- } + /** Get a list of immediate parents of this node. + */ inline const ParentList &getParents() const { return _parents; } ! /** Get a parent by index number. ! * ! * @returns 0 if the index is out of range. ! */ ! inline Node* getParent(unsigned int i) { ! if (i >= _parents.size()) return 0; ! return _parents[i]; ! } ! /** Get a parent by index number. ! * ! * @returns 0 if the index is out of range. ! */ ! inline const Node* getParent(unsigned int i) const { ! if (i >= _parents.size()) return 0; ! return _parents[i]; ! } + /** Get the number of immediate parents of this node. + */ inline unsigned int getNumParents() const { return _parents.size(); } protected: + /** Get a copy of this node's parent list. + */ inline ParentList getParents() { return _parents; } + /** A function adapter for visiting child or parent nodes. + */ class AcceptOp { typename Composite::VisitorRef _visitor; *************** *** 246,253 **** --- 375,386 ---- }; + /** Propagate a visitor through all immediate children. + */ void descend(VisitorBase *visitor) { std::for_each(_children.begin(), _children.end(), AcceptOp(visitor)); } + /** Propagate a visitor through all immediate parents. + */ void ascend(VisitorBase *visitor) { std::for_each(_parents.begin(), _parents.end(), AcceptOp(visitor)); *************** *** 255,262 **** --- 388,399 ---- private: + /** Add a new parent to this node. + */ void addParent(Node *node) { _parents.push_back(node); } + /** Remove a parent from this node. + */ void removeParent(Node *node) { typename ParentList::iterator iter; *************** *** 265,269 **** --- 402,409 ---- } + /// The immediate children of this node. ChildList _children; + + /// The immediate parents of this node. ParentList _parents; }; *************** *** 324,327 **** --- 464,544 ---- class Visitor: public VisitorCore< Visitable<V> > {}; + + /** A visitor class for searching a node graph. + * + * The visitor traverses the graph until the match() + * method returns true. Implement this method in a + * derived class to specify the search condition. + * Traversal stops as soon as a match is found. After + * traversal the getNode() method can be used + * to retrieve the matching node (if any). + */ + template <class N, class V> + class FindVisitor: public V { + public: + /** The search condition. + * + * Implement this condition in derived classes to + * deterimine which node is found. + */ + virtual bool match(N &node) = 0; + + /** Search for a matching node. + * + * Don't call this directly; use node->accept(visitor); + */ + void apply(N &node) { + if (_node.valid()) return; + if (match(node)) { + _node = &node; + setTraversalMode(TRAVERSE_NONE); + } else { + traverse(node); + } + } + + /** Get the node that match the search condition, if any. + */ + Ref<N> getNode() const { return _node; } + private: + /// The matching node. + Ref<N> _node; + }; + + + /** A visitor class for searching a node graph. + * + * This visitor is similar to FindVisitor, but retrieves + * all nodes that match the condition. + */ + template <class N, class V> + class FindAllVisitor: public V { + public: + typedef std::vector< Ref<N> > NodeList; + + /** The search condition. + * + * Implement this condition in derived classes to + * deterimine which nodes are found. + */ + virtual bool match(N &node) = 0; + + /** Search for and accumulate matching nodes. + * + * Don't call this directly; use node->accept(visitor); + */ + void apply(N &node) { + if (match(node)) { + _nodes.push_back(&node); + } + traverse(node); + } + /** Get all nodes that match the search condition. + */ + NodeList getNodes() const { return _nodes; } + private: + /// The matching nodes. + NodeList _nodes; + }; |