Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Composite.h

Go to the documentation of this file.
00001 /* SimData: Data Infrastructure for Simulations
00002  * Copyright (C) 2002, 2003 Mark Rose <tm2@stm.lbl.gov>
00003  * 
00004  * This file is part of SimData.
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  */
00020 
00021 
00030 #ifndef __SIMDATA_COMPOSITE_H__
00031 #define __SIMDATA_COMPOSITE_H__
00032 
00033 #include <iostream>
00034 #include <cstdio>
00035 #include <vector>
00036 #include <SimData/Ref.h>
00037 #include <SimData/Log.h>
00038 
00039 
00040 NAMESPACE_SIMDATA
00041 
00042 
00047 template<class V>
00048 class Visitable;
00049 
00050 #define SIMDATA_VISITOR(__visitor) \
00051         typedef SIMDATA(Ref)<__visitor> Ref; \
00052         using SIMDATA(Visitor)<__visitor>::apply
00053 
00054 #define SIMDATA_VISITABLE(__visitor) \
00055         virtual SIMDATA(Ref)<__visitor> accept(SIMDATA(Ref)<__visitor> v) { \
00056                 v->apply(*this); \
00057                 return v; \
00058         }
00059 
00064 template<class N>
00065 class CompositeBase;
00066 
00067 
00070 class VisitorBase: public virtual Referenced { };
00071 
00072 
00077 template <class N>
00078 class VisitorCore: public VisitorBase {
00079 public:
00081         typedef enum { 
00082                 TRAVERSE_NONE,     //< Act on only the current node.
00083                 TRAVERSE_CHILDREN, //< Act on the current node and all children
00084                 TRAVERSE_PARENTS   //< Act on the current node and all parents
00085         } TraversalMode;
00086 
00089         TraversalMode getTraversalMode() const { return _traversal_mode; }
00090 
00092         typedef CompositeBase<N> Node;
00093 
00102         virtual void apply(Node &node) { traverse(node); }
00103 
00109         VisitorCore(TraversalMode mode = TRAVERSE_CHILDREN): 
00110                 _traversal_mode(mode) {}
00111 
00112 protected:
00120         void traverse(Node &node) {
00121                 if (_traversal_mode == TRAVERSE_CHILDREN) {
00122                         descend(node);
00123                 } else
00124                 if (_traversal_mode == TRAVERSE_PARENTS) {
00125                         ascend(node);
00126                 }
00127         }
00128 
00136         void setTraversalMode(TraversalMode mode) { _traversal_mode = mode; }
00137 
00138 private:
00140         TraversalMode _traversal_mode;
00141 
00144         inline void ascend(Node &node);
00145 
00148         inline void descend(Node &node);
00149 
00150 };
00151 
00152 
00157 template <class N>
00158 class CompositeBase: public virtual Referenced {
00159         friend class VisitorCore<N>;
00160 protected:
00163         virtual void descend(VisitorBase *v) = 0;
00164 
00167         virtual void ascend(VisitorBase *v) = 0;
00168 };
00169 
00170 
00212 template <class V> 
00213 class Composite: public Visitable<V>, public CompositeBase< Visitable<V> > {
00214 public:
00215         typedef Composite Node;
00216         typedef Ref<Node> NodeRef;
00217         typedef Ref<V> VisitorRef;
00218 
00220         typedef std::vector< NodeRef > ChildList;
00221         
00223         typedef std::vector< Node* > ParentList;
00224 
00231         virtual VisitorRef accept(VisitorRef v)=0;
00232 
00240         virtual bool addChild(Node *node) {
00241                 if (!isContainer()) {
00242                         SIMDATA_LOG(LOG_ALL, LOG_WARNING, "simdata::Composite<>::addChild() to non-container.");
00243                         return false;
00244                 }
00245                 if (!node) {
00246                         SIMDATA_LOG(LOG_ALL, LOG_WARNING, "simdata::Composite<>::addChild() null node.");
00247                         return false;
00248                 }
00249                 if (!node->canBeAdded()) {
00250                         SIMDATA_LOG(LOG_ALL, LOG_WARNING, "simdata::Composite<>::addChild() cannot be added.");
00251                         return false;
00252                 }
00253                 if (containsNode(node)) {
00254                         SIMDATA_LOG(LOG_ALL, LOG_WARNING, "simdata::Composite<>::addChild() duplicate node.");
00255                         return false;
00256                 }
00257                 _children.push_back(node);
00258                 node->addParent(this);
00259                 return true;
00260         }
00261 
00266         virtual bool removeChild(Node *node) {
00267                 return removeChild(getChildIndex(node));
00268         }
00269 
00277         virtual bool removeChild(unsigned int pos, unsigned int count=1) {
00278                 if (pos >= _children.size() || count == 0) return false;
00279                 unsigned int end = pos + count;
00280                 if (end > _children.size()) {
00281                         SIMDATA_LOG(LOG_ALL, LOG_WARNING, "simdata::Composite<>::removeChild() index range truncated.");
00282                         end = _children.size();
00283                 }
00284                 for (unsigned int i = pos; i < end; ++i) {
00285                         _children[i]->removeParent(this);
00286                 }
00287                 _children.erase(_children.begin()+pos,_children.begin()+end);
00288                 return true;
00289         }
00290 
00293         inline unsigned int getNumChildren() const { return _children.size(); }
00294 
00302         virtual bool setChild(unsigned int i, Node* node) { 
00303                 if (i >= _children.size() || !node) return false; 
00304                 NodeRef original = _children[i];
00305                 original->removeParent(this);
00306                 _children[i] = node;
00307                 node->addParent(this);
00308                 return true;
00309         }
00310 
00315         inline Node* getChild(unsigned int i) { 
00316                 if (i >= _children.size()) return 0;
00317                 return _children[i].get(); 
00318         }
00319 
00324         inline const Node* getChild(unsigned int i) const { 
00325                 if (i >= _children.size()) return 0;
00326                 return _children[i].get(); 
00327         }
00328 
00331         inline ChildList const &getChildren() const { return _children; }
00332 
00337         inline bool containsNode(Node const *node) const {
00338                 if (!node) return false;
00339                 return std::find(_children.begin(), _children.end(), node) != _children.end();
00340         }
00341 
00346         inline unsigned int getChildIndex(Node const *node) const { 
00347                 for (unsigned int idx = 0; idx < _children.size(); ++idx) {
00348                         if (_children[idx] == node) return idx;
00349                 }
00350                 return _children.size(); // not found
00351         }
00352 
00355         inline const ParentList &getParents() const { return _parents; }
00356 
00361         inline Node* getParent(unsigned int i)  { 
00362                 if (i >= _parents.size()) return 0;
00363                 return _parents[i]; 
00364         }
00365 
00370         inline const Node* getParent(unsigned int i) const  { 
00371                 if (i >= _parents.size()) return 0;
00372                 return _parents[i]; 
00373         }
00374 
00377         inline unsigned int getNumParents() const { return _parents.size(); }
00378 
00379         virtual bool isContainer() const { return true; }
00380         virtual bool canBeAdded() const { return true; }
00381 
00382 protected:
00385         inline ParentList getParents() { return _parents; }
00386 
00389         class AcceptOp {
00390                 typename Composite::VisitorRef _visitor;
00391         public:
00392                 AcceptOp(VisitorBase *visitor) { _visitor = visitor; }
00393                 void operator()(NodeRef node) { node->accept(_visitor); }
00394         };
00395 
00398         void descend(VisitorBase *visitor) {
00399                 std::for_each(_children.begin(), _children.end(), AcceptOp(visitor));
00400         }
00401 
00404         void ascend(VisitorBase *visitor) {
00405                 std::for_each(_parents.begin(), _parents.end(), AcceptOp(visitor));
00406         }
00407 
00408 private:
00411         void addParent(Node *node) {
00412                 _parents.push_back(node);
00413         }
00414 
00417         void removeParent(Node *node) {
00418                 typename ParentList::iterator iter;
00419                 iter = std::find(_parents.begin(), _parents.end(), node);
00420                 if (iter != _parents.end()) _parents.erase(iter);
00421         }
00422 
00424         ChildList _children;
00425 
00427         ParentList _parents;
00428 };
00429 
00430 
00431 template <class N>
00432 void VisitorCore<N>::descend(CompositeBase<N> &node) {
00433         node.descend(this);
00434 };
00435 
00436 
00437 template <class N>
00438 void VisitorCore<N>::ascend(CompositeBase<N> &node) {
00439         node.ascend(this);
00440 };
00441 
00442 
00445 template <class V>
00446 class Visitable: public virtual Referenced {
00447 public:
00448         virtual Ref<V> accept(Ref<V> v)=0;
00449 };
00450 
00451 
00484 template <class V>
00485 class Visitor: public VisitorCore< Visitable<V> > {};
00486 
00487 
00497 template <class N, class V>
00498 class FindVisitor: public V {
00499 public:
00505         virtual bool match(N &node) = 0;
00506 
00511         void apply(N &node) {
00512                 if (_node.valid()) return;
00513                 if (match(node)) {
00514                         _node = &node;
00515                         setTraversalMode(TRAVERSE_NONE);
00516                 } else {
00517                         traverse(node);
00518                 }
00519         }
00520 
00523         simdata::Ref<N> getNode() const { return _node; }
00524 private:
00526         simdata::Ref<N> _node;
00527 };
00528 
00529 
00535 template <class N, class V>
00536 class FindAllVisitor: public V {
00537 public:
00538         typedef std::vector< simdata::Ref<N> > NodeList;
00539 
00545         virtual bool match(N &node) = 0;
00546 
00551         void apply(N &node) {
00552                 if (match(node)) {
00553                         _nodes.push_back(&node);
00554                 } 
00555                 traverse(node);
00556         }
00559         NodeList getNodes() const { return _nodes; }
00560 private:
00562         NodeList _nodes;
00563 };
00564 
00565 
00566 NAMESPACE_SIMDATA_END
00567 
00568 #endif // __SIMDATA_COMPOSITE_H__
00569 

SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage.

Generated on Tue Oct 14 12:06:38 2003, using Doxygen 1.2.18.

[SF.net]