Socket/Protocols/INet: Fix INet6Address in6_addr constructor
[senf.git] / Console / Node.hh
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Node public header */
25
26 /** \defgroup node_tree The console/config file-system node tree
27     
28     The console/config node tree is the central data-structure of the library. Into this tree, all
29     commands and parameters are entered. The tree is then exposed using a file-system like
30     interface.
31     
32     \autotoc
33
34     \section console_tree The tree
35
36     We will start by giving a more complete example. This example contains most of the stuff needed
37     for using the console/config library.
38
39     \code
40     // Define callback function.
41     void mycommand(std::ostream & os, senf::console::Arguments const & args)
42     {
43         // ...
44         os << "!! Important message ...\n";
45     }
46
47     class SomeClass
48     {
49     public:
50         // Declare a directory node (proxy) for use by this class. This must be public so we can add
51         // it to the node tree later.
52         senf::console::ObjectDirectory<SomeClass> dir;
53
54         SomeClass() : dir(this) 
55         {
56             // You may document the directory here or later when adding it to the tree
57             dir.doc("Manager for something");
58
59             // Add a member function (the pointer-to-member is automatically bound to this instance)
60             dir.add("member", &SomeClass::member)
61                 .doc("Do the member operation");
62         }
63
64         void member(std::ostream & os, senf::console::Arguments const & args)
65         {
66             // ...
67         }
68     };
69
70     int main(int, char**)
71     {
72         // Provide global documentation
73         senf::console::root()
74             .doc("This is someServer server");
75
76         // Add a new directory to the root and document it. All the mutators return the node object
77         // itself so operations can be chained.
78         senf::console::DirectoryNode & mydir (
79                 .mkdir("myserver")
80                 .doc("My server specific directory"));
81
82         // Add a command to that directory
83         mydir.add("mycommand", &mycommand)
84             .doc("mycommand <foo> [<bar>]\n\n"
85                  "If <bar> is given, flurgle the <foo>, otherwise burgle it");
86
87         // Create a SomeClass instance and add it's directory.
88         SomeClass someClass;
89         mydir.add("someClass", someClass.dir);
90
91         // Start the interactive console server
92         senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
93             .name("someServer");
94     }
95     \endcode
96
97     \subsection console_nodes Node types
98
99     The console/config library tree consists of two basic node types:
100     
101     \li senf::console::DirectoryNode provides internal nodes with an arbitrary number of children
102     \li senf::console::CommandNode describes a command entry in the tree
103
104     senf::console::CommandNode is the base-class of all command nodes of which there are several,
105     depending on the type of command.
106
107     There is a single root node, the senf::console::DirectoryNode called senf::console::root(). From
108     this node, the tree is traversed.
109
110     All nodes are allocated on the heap and are managed using a smart pointer.
111     
112     \subsection console_manipulate Manipulating the node tree
113
114     There are several ways to add nodes to the tree:
115
116     \li A senf::console::DirectoryNode can be added using senf::console::DirectoryNode::mkdir().
117     \li An arbitrary node can be created and then (possibly later) added to the tree using the
118         corresponding senf::console::DirectoryNode::add() overload.
119     \li A senf::console::CommandNode is normally added to the tree by directly adding a callback
120         using one of the overloaded senf::console::DirectoryNode::add() members.
121
122     When directly adding a node callback, the type of node added depends on the type of
123     callback. The callback types which can be added are listed at \ref console_callbacks.
124     
125     \code
126     void callback(std::ostream & os, senf::console::Arguments const & args) { ... }
127     // ...
128     myDirectory.add("foo",&callback);
129     \endcode
130
131     Every node is identified among it's siblings by it's name. The name of the node is set when
132     adding the node to the tree. If the name is empty or non-unique, a unique name will be
133     automatically provided.
134
135     To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink()
136     member. This call removes the node from it's parent and returns a (smart) node pointer.
137
138     \li If you ignore the return value, the node (and it's children) will be deleted.
139     \li Alternatively, you may store away the node and re-attach it later.
140     \li An node (or subtree) can be moved to a different place by unlinking the node at it's old
141         place and re-adding it at it's new location.
142     \li To rename a node, unlink and re-add it with a different name.
143
144     \code
145     myDirectory.add("bar", myDirectory("foo").unlink());
146     \endcode
147
148     \subsection console_node_param Assigning additional node parameters
149
150     Depending on the node type added, additional node parameters may be set. For example, every node
151     has a documentation parameter which is used by the online-help system. To assign these
152     parameters, the node exposes corresponding member functions. Since
153     senf::console::DirectoryNode::add() returns the newly added node by reference, additional
154     parameters may just be added to the end of the add command:
155     \code
156     myDirectory.add("foo",&fooCallback).doc("The foo method");
157     \endcode
158     Since the parameter setters all return the node reference, additional parameters may just be
159     added to the end of the command.
160     
161     \subsection console_tree_traverse Traversing the tree
162
163     The simplest way to access tree elements is to save the return value of the
164     senf::console::DirectoryNode::add() members. However, saving the reference will not ensure, that
165     the node is not removed. If the node might be removed from the tree, you should use a smart
166     pointer (either <tt>ptr</tt> or <tt>weak_ptr</tt>) to hold the node.
167
168     Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
169     '()' have been overloaded in senf::console::DirectoryNode.
170     \code
171     senf::console::root()["myDirectory"]("foo")
172     \endcode
173     The '[]' operator will return a senf::console::DirectoryNode whereas '()' will return a
174     senf::console::CommandNode. If the node is not found or is not of the correct type, an exception
175     will be raised.
176
177     \section console_object_dir Assigning a directory to an object instance
178
179     Most objects will register several commands. So it makes sense for these objects to manage their
180     own directory. Since directories are however allocated on the heap, they cannot be directly
181     added to a class. To facilitate this usage, the senf::console::ObjectDirectory is used. This
182     class provides a senf::console::DirectoryNode facade. Internally, it automatically creates a
183     senf::console::DirectoryNode to which all calls are forwarded.
184
185     The senf::console::ObjectDirectory member should be declared public. This allows the user of the
186     class to add the node to the tree.
187  */
188
189 #ifndef HH_Node_
190 #define HH_Node_ 1
191
192 // Custom includes
193 #include <map>
194 #include <boost/shared_ptr.hpp>
195 #include <boost/weak_ptr.hpp>
196 #include <boost/enable_shared_from_this.hpp>
197 #include <boost/utility.hpp>
198 #include <boost/range/iterator_range.hpp>
199 #include <boost/typeof/typeof.hpp>
200 #include <boost/type_traits/remove_reference.hpp>
201 #include "../Utils/Exception.hh"
202 #include "../Utils/mpl.hh"
203 #include "../Utils/Logger/SenfLog.hh"
204 #include "Parse.hh"
205
206 //#include "Node.mpp"
207 ///////////////////////////////hh.p////////////////////////////////////////
208
209 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
210
211 namespace senf {
212 namespace console {
213
214     class DirectoryNode;
215     class CommandNode;
216
217     /** \brief Config/console node tree base-class
218
219         GenericNode is the base class of all node objects. There are two basic node types derived
220         from GenericNode:  DirectoryNode and CommandNode.
221
222         All nodes are dynamically allocated and automatically managed using reference counting.
223
224         All nodes are normally linked into a single tree which root node is
225         senf::console::root(). Nodes may however be orphaned (not linked to the tree) either
226         directly (the node has no parent) or indirectly (the node has a parent but is part of an
227         orphaned subtree which is not linked to the root node).
228
229         Every active (non-orphaned) node (except the root() node) has a non-empty node name. This
230         name is assigned to the node when adding the node to the tree.
231
232         \ingroup node_tree
233       */
234     class GenericNode 
235         : public boost::enable_shared_from_this<GenericNode>
236     {
237         SENF_LOG_CLASS_AREA();
238     public:
239         ///////////////////////////////////////////////////////////////////////////
240         // Types
241
242         typedef boost::shared_ptr<GenericNode> ptr;
243         typedef boost::shared_ptr<GenericNode const> cptr;
244         typedef boost::weak_ptr<GenericNode> weak_ptr;
245
246         ///////////////////////////////////////////////////////////////////////////
247
248         virtual ~GenericNode();
249
250         std::string const & name() const; ///< Node name
251         boost::shared_ptr<DirectoryNode> parent() const; ///< Parent node
252                                         /**< May be null, if the node is the root node or if it is
253                                              not linked to the tree */
254
255         std::string path() const;       ///< Node path
256                                         /**< The node path is built by joining the names of all
257                                              parent nodes with '/' chars. */
258
259         ptr unlink();                   ///< Remove node from it's parent directory
260                                         /**< You may either discard the return value and thereby
261                                              dispose the node or may re-attach the node at some
262                                              other place using DirectoryNode::add(). */
263
264         bool active() const;            ///< \c true, if node is attached to the root() node
265
266         void help(std::ostream & output) const; /// Write help info to \a output
267
268         ptr thisptr();                  ///< Get smart pointer to node
269         cptr thisptr() const;           ///< Get smart pointer to node (const)
270
271     protected:
272         GenericNode();
273
274         void name(std::string const & name);
275
276 #ifndef DOXYGEN
277     private:
278 #else
279     public:
280 #endif
281         virtual void v_help(std::ostream & output) const = 0;
282                                         ///< Provide help information
283                                         /**< This member must be implemented in derived classes
284                                              to provide node specific help information. */
285
286     private:
287         std::string name_;
288         DirectoryNode * parent_;
289
290         friend class DirectoryNode;
291     };
292
293     class SimpleCommandNode;
294
295     /** \brief Internal: Node creation helper traits
296         
297         This class is used internally to find out the type of node to create for a specific argument
298         type. 
299      */
300     template <class Object>
301     struct NodeCreateTraits
302     {
303         typedef BOOST_TYPEOF_TPL( senf_console_add_node( 
304                                       * static_cast<DirectoryNode *>(0),
305                                       * static_cast<std::string const *>(0),
306                                       * static_cast<Object const *>(0),
307                                       0) ) result_type;
308
309         typedef typename boost::remove_reference<result_type>::type NodeType;
310
311         /// Internal
312         struct Creator {
313             static NodeType & create(DirectoryNode & node, std::string const & name, 
314                                      Object const & ob);
315         };
316     };
317
318     /** \brief Config/console tree directory node
319
320         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
321         children and supports directory traversal.
322         
323         Nodes are normally not instantiated manually but are created by the DirectoryNode via
324         mkdir() or add(). Special add() members however allow externally allocated node objects.
325
326         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
327         managed dynamically, there is a special ObjectDirectory proxy template which provides a
328         DirectoryNode facade. ObjectDirectory is used if a class wants to manage it's own directory
329         as a data member.
330
331         Every node is assigned a (new) name when it is added to a directory. If the directory
332         already has an entry of that name, the name is made unique by appending a suffix of the form
333         '-n' where n is a number starting at 1. If the name is empty, int is set to 'unnamed' and
334         then uniquified as above. Automatically providing unique names simplifies adding
335         configuration/console support to generic components.
336
337         \ingroup node_tree
338       */
339     class DirectoryNode : public GenericNode
340     {
341         SENF_LOG_CLASS_AREA();
342         typedef std::map<std::string, GenericNode::ptr> ChildMap;
343     public:
344         ///////////////////////////////////////////////////////////////////////////
345         // Types
346
347         typedef boost::shared_ptr<DirectoryNode> ptr;
348         typedef boost::shared_ptr<DirectoryNode const> cptr;
349         typedef boost::weak_ptr<DirectoryNode> weak_ptr;
350
351         typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
352         typedef ChildMap::const_iterator child_iterator;
353
354         ///////////////////////////////////////////////////////////////////////////
355         ///\name Structors and default members
356         ///\{
357
358         static ptr create();            ///< Create node object.
359                                         /**< You should normally use either mkdir() or
360                                              ObjectDirectory instead of create() */
361
362         ///\}
363         ///////////////////////////////////////////////////////////////////////////
364         ///\name Children
365         ///\{
366
367         template <class NodeType>
368         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
369                                         ///< Add node to tree
370                                         /**< Adds the \a node to the tree as a child of \a this
371                                              node. The node is given the name \a name. If a node of
372                                              that name already exists, a numeric suffix of the form
373                                              '-n' is added to the name until the name is unique. If
374                                              \a name is empty, it is set to 'unnamed'. */
375
376         template <class Object>
377         typename NodeCreateTraits<Object>::NodeType & add (std::string const & name, 
378                                                            Object const & ob);
379                                         ///< Generic child node factory
380                                         /**< This member is used to create a new child node of the
381                                              current directory. The type of node created depends on
382                                              the type of argument passed.
383
384                                              The node type is selected by the NodeCreateTraits
385                                              class. To allow adding a specific node type, you need
386                                              to provide an overload for
387                                              <tt>senf_console_add_node</tt> which must be visible at
388                                              when you register the new node.
389                                              \code
390                                              MyNodeType & senf_console_add_node(
391                                                  DirectoryNode & dir,
392                                                  std::string const & name,
393                                                  MySpecialObject const & ob,
394                                                  int)
395                                              {
396                                                  return dir.add(name, MyNodeType::create(ob));
397                                              }
398                                              \endcode
399                                              (Do not forget the last unnamed 'int' parameter which
400                                              is not used but serves to disambiguate the
401                                              overloads). */
402
403         GenericNode::ptr remove(std::string const & name);
404                                         ///< Remove node \a name from the tree
405                                         /**< The returned pointer may either be discarded, which
406                                              will automatically dispose the removed node, or it may
407                                              be saved and/or re-attached at some other place in the
408                                              tree. */
409
410         DirectoryNode & operator[](std::string const & name) const;
411                                         ///< Get directory child node
412                                         /**< \throws UnknownNodeNameException if a child \a name
413                                                  does not exist. 
414                                              \throws std::bad_cast if the child \a name is not a
415                                                  directory node. */
416
417         CommandNode & operator()(std::string const & name) const;
418                                         ///< Get command child node
419                                         /**< \throws UnknownNodeNameException if a child \a name
420                                                  does not exist
421                                              \throws std::bad_cast if the child \a name is not a
422                                                  command node. */
423
424         GenericNode & get(std::string const & name) const;
425                                         ///< Get child node
426                                         /**< \throws UnknownNodeNameException if a child \a name
427                                                  does not exist */
428
429         DirectoryNode & mkdir(std::string const & name);
430                                         ///< Create sub-directory node
431         
432         ChildrenRange children() const;
433                                         ///< Return iterator range over all children.
434                                         /**< The returned range is sorted by child name. */
435
436         ///\}
437         ///////////////////////////////////////////////////////////////////////////
438
439         template <class ForwardRange>
440         GenericNode & traverse(ForwardRange const & range);
441                                         ///< Traverse node path starting at this node
442                                         /**< The <tt>FordwareRange::value_type</tt> must be
443                                              (convertible to) std::string. Each range element
444                                              constitutes a step along the node traversal.
445
446                                              If the range starts with an empty element, the
447                                              traversal is started at the root() node, otherwise it
448                                              is started at \a this node. The traversal supports '.',
449                                              '..' and ignores further empty elements. */
450
451         DirectoryNode & doc(std::string const & doc);
452                                         ///< Set node documentation
453
454         ptr thisptr();
455         cptr thisptr() const;
456
457     protected:
458         DirectoryNode();
459
460     private:
461         void add(GenericNode::ptr node);
462         virtual void v_help(std::ostream & output) const;
463
464         ChildMap children_;
465         std::string doc_;
466
467         friend DirectoryNode & root();
468     };
469
470     BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode);
471
472     /// Exception: Unknown node name
473     struct UnknownNodeNameException : public senf::Exception
474     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
475
476 #ifndef DOXYGEN
477     template <class Type>
478     struct NodeCreateTraits< boost::shared_ptr<Type> >
479     {};
480 #endif
481
482     /** \brief Config/console tree command node
483
484         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
485         implementations are derived from this class.
486
487         To execute a command, CommandNode::operator()() is called. This abstract virtual function
488         must be implemented in a derived class.
489
490         \ingroup node_tree
491       */
492     class CommandNode : public GenericNode
493     {
494         SENF_LOG_CLASS_AREA();
495     public:
496         ///////////////////////////////////////////////////////////////////////////
497         // Types
498
499         typedef boost::shared_ptr<CommandNode> ptr;
500         typedef boost::shared_ptr<CommandNode const> cptr;
501         typedef boost::weak_ptr<CommandNode> weak_ptr;
502
503         typedef ParseCommandInfo::ArgumentsRange Arguments;
504
505         ///////////////////////////////////////////////////////////////////////////
506
507         virtual void operator()(std::ostream & output, Arguments const & arguments) = 0;
508                                         ///< Called to execute the command
509                                         /**< \param[in] output stream where result messages may be
510                                                  written to
511                                              \param[in] arguments command arguments. This is a
512                                                  range of ranges of ArgumentToken instances. */
513
514         ptr thisptr();
515         cptr thisptr() const;
516
517     protected:
518         CommandNode();
519
520     private:
521     };
522
523     typedef CommandNode::Arguments Arguments;
524
525     /** \brief Most simple CommandNode implementation
526
527         This CommandNode implementation simply forwards the \a output and \a arguments arguments to
528         an arbitrary callback.
529  
530         \ingroup node_tree
531      */
532     class SimpleCommandNode : public CommandNode
533     {
534         SENF_LOG_CLASS_AREA();
535     public:
536         ///////////////////////////////////////////////////////////////////////////
537         // Types
538
539         typedef boost::shared_ptr<SimpleCommandNode> ptr;
540         typedef boost::shared_ptr<SimpleCommandNode const> cptr;
541         typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
542
543         typedef boost::function<void (std::ostream &, Arguments const &)> Function;
544
545         ///////////////////////////////////////////////////////////////////////////
546         ///\name Structors and default members
547         ///\{
548
549         static ptr create(Function const & fn);
550
551         ///\}
552         ///////////////////////////////////////////////////////////////////////////
553
554         virtual void operator()(std::ostream & output, Arguments const & arguments);
555
556         ptr thisptr();
557         cptr thisptr() const;
558
559         SimpleCommandNode & doc(std::string const & doc);
560
561     protected:
562         SimpleCommandNode(Function const & fn);
563
564     private:
565         virtual void v_help(std::ostream & output) const;
566
567         Function fn_;
568         std::string doc_;
569     };
570
571 #ifndef DOXYGEN
572     template <class Function>
573     SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name, 
574                                               Function const & fn, ...);
575 #endif
576
577     BOOST_TYPEOF_REGISTER_TYPE(SimpleCommandNode);
578
579     DirectoryNode & root();
580
581 }}
582
583 ///////////////////////////////hh.e////////////////////////////////////////
584 #include "Node.cci"
585 #include "Node.ct"
586 #include "Node.cti"
587 #endif
588
589 \f
590 // Local Variables:
591 // mode: c++
592 // fill-column: 100
593 // comment-column: 40
594 // c-file-style: "senf"
595 // indent-tabs-mode: nil
596 // ispell-local-dictionary: "american"
597 // compile-command: "scons -u test"
598 // End: