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. |