4665716aabafd7c2bfd140d4f0c790547fedc3f9
[senf.git] / senf / Utils / 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 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::ParseCommandInfo const & command)
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::ScopedDirectory<SomeClass> dir;
53
54         SomeClass() : dir(this)
55         {
56             namespace fty = senf::console::factory;
57             // You may document the directory here or later when adding it to the tree
58             dir.doc("Manager for something");
59
60             // Add a member function (the pointer-to-member is automatically bound to this instance)
61             dir.add("member", fty::Command(&SomeClass::member, this)
62                 .doc("Do the member operation"));
63         }
64
65         void member(std::ostream & os, senf::console::ParseCommandInfo const & command)
66         {
67             // ...
68         }
69     };
70
71     int main(int, char**)
72     {
73         namespace fty = senf::console::factory;
74
75         // Provide global documentation
76         senf::console::root()
77             .doc("This is someServer server");
78
79         // Add a new directory to the root and document it. All the mutators return the node object
80         // itself so operations can be chained.
81         senf::console::DirectoryNode & mydir ( senf::console::root()
82                 .add("myserver", fty::Directory()
83                      .doc("My server specific directory")));
84
85         // Add a command to that directory
86         mydir.add("mycommand", fty::Command(&mycommand)
87             .doc("mycommand <foo> [<bar>]\n\n"
88                  "If <bar> is given, flurgle the <foo>, otherwise burgle it"));
89
90         // Create a SomeClass instance and add it's directory.
91         SomeClass someClass;
92         mydir.add("someClass", someClass.dir);
93
94         // Start the interactive console server
95         senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
96             .name("someServer");
97     }
98     \endcode
99
100     \subsection console_nodes Node types
101
102     The console/config library tree consists of two basic node types:
103
104     \li senf::console::DirectoryNode provides internal nodes with an arbitrary number of children
105     \li senf::console::CommandNode describes a command entry in the tree
106     \li senf::console::LinkNode is a link to another node. It works much like a symlink on POSIX
107         systems.
108
109     senf::console::CommandNode is the base-class of all command nodes of which there are several,
110     depending on the type of command.
111
112     There is a single root node, the senf::console::DirectoryNode called senf::console::root(). From
113     this node, the tree is traversed.
114
115     All nodes are allocated on the heap and are managed using a smart pointer.
116
117     \subsection console_manipulate Manipulating the node tree
118
119     There are several ways to add nodes to the tree:
120
121     \li A senf::console::DirectoryNode can be added using senf::console::DirectoryNode::mkdir().
122     \li An arbitrary node can be created and then (possibly later) added to the tree using the
123         corresponding senf::console::DirectoryNode::add() overload.
124     \li A senf::console::CommandNode is normally added to the tree by directly adding a callback
125         using one of the overloaded senf::console::DirectoryNode::add() members. See \ref
126         console_commands.
127     \li A senf::console::LinkNode is created by senf::console::DirectoryNode::link()
128
129     When directly adding a node callback, the type of node added depends on the type of
130     callback. The callback types which can be added are listed at \ref console_callbacks.
131
132     \code
133     void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
134     // ...
135     myDirectory.add("foo",fty::Command(&callback));
136     \endcode
137
138     Every node is identified among it's siblings by it's name. The name of the node is set when
139     adding the node to the tree. If the name is empty or non-unique, a unique name will be
140     automatically provided.
141
142     To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink() or the
143     parents senf::console::DirectoryNode::remove() member. This call removes the node from it's
144     parent and returns a (smart) node pointer.
145
146     \li If you ignore the return value, the node (and it's children) will be deleted.
147     \li Alternatively, you may store away the node and re-attach it later.
148     \li An node (or subtree) can be moved to a different place by unlinking the node at it's old
149         place and re-adding it at it's new location.
150     \li To rename a node, unlink and re-add it with a different name.
151
152     \code
153     myDirectory.add("bar", myDirectory.remove("foo"));
154     \endcode
155
156     \subsection console_node_param Assigning additional node parameters
157
158     Depending on the node type added, additional node parameters may be set. For example, every node
159     has a documentation parameter which is used by the online-help system. To assign these
160     parameters, the node exposes corresponding member functions. Since
161     senf::console::DirectoryNode::add() returns the newly added node by reference. Additional
162     parameters may be added after the factory call:
163     \code
164     myDirectory.add("foo", fty::Command(&fooCallback).doc("The foo method") );
165     \endcode
166     Since the parameter setters all return the node reference, additional parameters may just be
167     added to the end of the command.
168
169     \subsection console_tree_traverse Traversing the tree
170
171     The simplest way to access tree elements is to save the return value of the
172     senf::console::DirectoryNode::add() members. However, saving the reference will not ensure, that
173     the node is not removed. If the node might be removed from the tree, you should use a smart
174     pointer (either <tt>ptr</tt> or <tt>weak_ptr</tt>) to hold the node.
175
176     Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
177     '()' have been overloaded in senf::console::DirectoryNode.
178     \code
179     senf::console::root().getDirectory("myDirectory").getCommand("foo")
180     \\ or more concise but otherwise completely identical
181     senf::console::root()["myDirectory"]("foo")
182     \endcode
183
184     getDirectory and the '[]' operator will return a senf::console::DirectoryNode whereas getCommand
185     and the '()' operator will return a senf::console::CommandNode. If the node is not found or is
186     not of the correct type, an exception will be raised.
187
188     \section console_object_dir Assigning a directory to an object instance
189
190     Most objects will register several commands. So it makes sense for these objects to manage their
191     own directory. Since directories are however allocated on the heap, they cannot be directly
192     added to a class. To facilitate this usage, the senf::console::ScopedDirectory is used. This
193     class provides a senf::console::DirectoryNode facade. Internally, it automatically creates a
194     senf::console::DirectoryNode to which all calls are forwarded.
195
196     The senf::console::ScopedDirectory member should be declared public. This allows the user of the
197     class to add the node to the tree.
198  */
199
200 #ifndef HH_SENF_Scheduler_Console_Node_
201 #define HH_SENF_Scheduler_Console_Node_ 1
202
203 // Custom includes
204 #include <map>
205 #include <boost/shared_ptr.hpp>
206 #include <boost/weak_ptr.hpp>
207 #include <boost/enable_shared_from_this.hpp>
208 #include <boost/utility.hpp>
209 #include <boost/range/iterator_range.hpp>
210 #include <boost/any.hpp>
211 #include <senf/Utils/Exception.hh>
212 #include <senf/Utils/Logger/SenfLog.hh>
213
214 //#include "Node.mpp"
215 //-/////////////////////////////////////////////////////////////////////////////////////////////////
216
217 namespace senf {
218 namespace console {
219
220     class LinkNode;
221     class DirectoryNode;
222     class CommandNode;
223
224     namespace detail { struct NodeFactory {}; }
225
226     /** \brief Get console root node */
227     DirectoryNode & root();
228
229     /** \brief Dump console directory structure
230
231         Recursively dumps the console directory structure starting at \a dir. By default, dumps the
232         complete tree beginning at the root node.
233
234         In contrast to the console 'lr' command, links are dumped by showing the \e absolute path
235         to the target node.
236      */
237     void dump(std::ostream & os, DirectoryNode & dir=root());
238
239     /** \brief Config/console node tree base-class
240
241         GenericNode is the base class of all node objects. There are two basic node types derived
242         from GenericNode:  DirectoryNode and CommandNode.
243
244         All nodes are dynamically allocated and automatically managed using reference counting.
245
246         All nodes are normally linked into a single tree which root node is
247         senf::console::root(). Nodes may however be orphaned (not linked to the tree) either
248         directly (the node has no parent) or indirectly (the node has a parent but is part of an
249         orphaned subtree which is not linked to the root node).
250
251         Every active (non-orphaned) node (except the root() node) has a non-empty node name. This
252         name is assigned to the node when adding the node to the tree.
253
254         \ingroup node_tree
255       */
256     class GenericNode
257         : public boost::enable_shared_from_this<GenericNode>
258     {
259         SENF_LOG_CLASS_AREA();
260     public:
261         //-////////////////////////////////////////////////////////////////////////
262         // Types
263
264         typedef boost::shared_ptr<GenericNode> ptr;
265         typedef boost::shared_ptr<GenericNode const> cptr;
266         typedef boost::weak_ptr<GenericNode> weak_ptr;
267
268         //-////////////////////////////////////////////////////////////////////////
269
270         virtual ~GenericNode();
271
272         std::string const & name() const; ///< Node name
273         boost::shared_ptr<DirectoryNode> parent() const; ///< Parent node
274                                         /**< May be null, if the node is the root node or if it is
275                                              not linked to the tree */
276
277         std::string path() const;       ///< Node path
278                                         /**< The node path is built by joining the names of all
279                                              parent nodes with '/' chars. */
280         std::string path(DirectoryNode const & root) const;
281                                         ///< Node path up to \a root
282                                         /**< The node path is built by joining the names of all
283                                              parent nodes up to \a root with '/' chars. */
284
285         ptr unlink();                   ///< Remove node from it's parent directory
286                                         /**< You may either discard the return value and thereby
287                                              dispose the node or may re-attach the node at some
288                                              other place using DirectoryNode::add(). */
289
290         bool active() const;            ///< \c true, if node is attached to the root() node
291
292         void help(std::ostream & output) const; ///< Write help info to \a output
293         std::string shorthelp() const;  ///< Get short (one-line) documentation
294
295         ptr thisptr();                  ///< Get smart pointer to node
296         cptr thisptr() const;           ///< Get smart pointer to node (const)
297
298         bool isChildOf(DirectoryNode & parent) const;
299                                         ///< \c true, if node is a child of \a parent
300                                         /**< Will also return \c true, if \a parent is the current
301                                              node. */
302
303         bool operator== (GenericNode & other) const;
304                                         ///< \c true, if this and \a other are the same node
305         bool operator!= (GenericNode & other) const;
306                                         ///< \c true, if this and \a other are different nodes
307
308         bool isDirectory() const;       ///< \c true, if this is a directory node
309         bool isLink() const;            ///< \c true, if this is a link node
310         bool isCommand() const;         ///< \c true, if this is a command node
311
312         GenericNode const & followLink() const; ///< Follow link if \c this node is a link node
313         GenericNode & followLink();     ///< Follow link if \c this node is a link node
314
315     protected:
316         GenericNode();
317
318         void name(std::string const & name);
319
320 #ifndef DOXYGEN
321     private:
322 #else
323     public:
324 #endif
325         virtual void v_help(std::ostream & output) const = 0;
326                                         ///< Provide help information
327                                         /**< This member must be implemented in derived classes to
328                                              provide node specific help information. */
329         virtual std::string v_shorthelp() const = 0;
330                                         ///< Provide short documentation
331                                         /**< This member must be implemented in derived classes to
332                                              provide node specific documentation. */
333
334     private:
335         std::string name_;
336         DirectoryNode * parent_;
337
338         friend class DirectoryNode;
339     };
340
341     /** \brief Config/console tree link node
342
343         A LinkNode references another node and provides an additional alias name for that node. A
344         LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a
345         UNIX symlink but references another node directly (not via it's path) like a UNIX
346         hardlink. Therefore, a LinkNode works across chroot().
347       */
348     class LinkNode
349         : public GenericNode
350     {
351     public:
352         //-////////////////////////////////////////////////////////////////////////
353         // Types
354
355         typedef boost::shared_ptr<LinkNode> ptr;
356         typedef boost::shared_ptr<LinkNode const> cptr;
357         typedef boost::weak_ptr<LinkNode> weak_ptr;
358
359         //-////////////////////////////////////////////////////////////////////////
360         ///\name Structors and default members
361         //\{
362
363         static ptr create(GenericNode & node); ///< Create new link node.
364                                         /**< You should normally use DirectoryNode::link() to
365                                              create a link node. */
366
367         //\}
368         //-////////////////////////////////////////////////////////////////////////
369
370         GenericNode & follow() const;   ///< Access the referenced node
371
372     protected:
373
374     private:
375         explicit LinkNode(GenericNode & node);
376
377         virtual void v_help(std::ostream &) const;
378         virtual std::string v_shorthelp() const;
379
380         GenericNode::ptr node_;
381     };
382
383     class SimpleCommandNode;
384
385     /** \brief Config/console tree directory node
386
387         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
388         children and supports directory traversal.
389
390         Nodes are normally not instantiated manually but are created using factory calls. Special
391         add() members however allow externally allocated node objects.
392
393         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
394         managed dynamically, there is a special ScopedDirectory proxy template which provides a
395         DirectoryNode facade. ScopedDirectory is used if a class wants to manage it's own directory
396         as a data member.
397
398         Every node is assigned a (new) name when it is added to a directory. If the directory
399         already has an entry of that name, the name is made unique by appending a suffix of the form
400         '-n' where n is a number starting at 1. If the name is empty, int is set to 'unnamed' and
401         then uniquified as above. Automatically providing unique names simplifies adding
402         configuration/console support to generic components.
403
404         \ingroup node_tree
405       */
406     class DirectoryNode : public GenericNode
407     {
408         SENF_LOG_CLASS_AREA();
409         typedef std::map<std::string, GenericNode::ptr> ChildMap;
410     public:
411         //-////////////////////////////////////////////////////////////////////////
412         // Types
413
414         typedef boost::shared_ptr<DirectoryNode> ptr;
415         typedef boost::shared_ptr<DirectoryNode const> cptr;
416         typedef boost::weak_ptr<DirectoryNode> weak_ptr;
417
418         typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
419         typedef ChildMap::const_iterator child_iterator;
420
421         typedef DirectoryNode node_type;
422         typedef DirectoryNode & return_type;
423
424         //-////////////////////////////////////////////////////////////////////////
425         ///\name Structors and default members
426         //\{
427
428         static ptr create();            ///< Create node object.
429                                         /**< You should normally use either mkdir() or
430                                              ScopedDirectory instead of create() */
431         ~DirectoryNode();
432
433         //\}
434         //-////////////////////////////////////////////////////////////////////////
435         ///\name Children
436         //\{
437
438         template <class NodeType>
439         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
440                                         ///< Add node to tree
441                                         /**< Adds the \a node to the tree as a child of \a this
442                                              node. The node is given the name \a name. If a node of
443                                              that name already exists, a numeric suffix of the form
444                                              '-n' is added to the name until the name is unique. If
445                                              \a name is empty, it is set to 'unnamed'. */
446
447         template <class NodeType>
448         NodeType & add(std::string const & name, NodeType & node,
449                        typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
450
451         template <class Factory>
452         typename Factory::result_type add(std::string const & name, Factory const & factory,
453                                           typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type * = 0);
454                                         ///< Generic child node factory
455                                         /**< This member is used to create a new child node of the
456                                              current directory. The type of node created depends on
457                                              the type of argument passed. */
458
459         GenericNode::ptr remove(std::string const & name);
460                                         ///< Remove node \a name from the tree
461                                         /**< The returned pointer may either be discarded, which
462                                              will automatically dispose the removed node, or it may
463                                              be saved and/or re-attached at some other place in the
464                                              tree. */
465
466         bool hasChild(std::string const & name) const;
467                                         ///< \c true, if there is a child with name \a name
468
469         GenericNode & get(std::string const & name) const;
470                                         ///< Get child node automatically dereferencing links
471                                         /**< \throws UnknownNodeNameException if a child \a name
472                                                  does not exist */
473         GenericNode & getLink(std::string const & name) const;
474                                         ///< Get child node without dereferencing links
475                                         /**< \throws UnknownNodeNameException if a child \a name
476                                                  does not exist */
477
478         DirectoryNode & getDirectory(std::string const & name) const;
479                                         ///< Get directory child node (dereferencing links)
480                                         /**< Same as operator[]
481                                              \throws UnknownNodeNameException if a child \a name
482                                                  does not exist.
483                                              \throws std::bad_cast if the child \a name is not a
484                                                  directory node. */
485
486         DirectoryNode & operator[](std::string const & name) const;
487                                         ///< Get directory child node (dereferencing links)
488                                         /**< Same as getDirectory
489                                              \throws UnknownNodeNameException if a child \a name
490                                                  does not exist.
491                                              \throws std::bad_cast if the child \a name is not a
492                                                  directory node. */
493
494         CommandNode & getCommand(std::string const & name) const;
495                                         ///< Get command child node (dereferencing links)
496                                         /**< Same as operator()
497                                              \throws UnknownNodeNameException if a child \a name
498                                                  does not exist
499                                              \throws std::bad_cast if the child \a name is not a
500                                                  command node. */
501
502         CommandNode & operator()(std::string const & name) const;
503                                         ///< Get command child node (dereferencing links)
504                                         /**< Same as getCommand()
505                                              \throws UnknownNodeNameException if a child \a name
506                                                  does not exist
507                                              \throws std::bad_cast if the child \a name is not a
508                                                  command node. */
509
510         ChildrenRange children() const; ///< Return iterator range over all children.
511                                         /**< The returned range is sorted by child name. */
512
513         ChildrenRange completions(std::string const & s) const;
514                                         ///< Return iterator range of completions for \a s
515                                         /**< The returned range is sorted by child name. */
516
517         //\}
518         //-////////////////////////////////////////////////////////////////////////
519
520         DirectoryNode & doc(std::string const & doc); ///< Set node documentation
521         DirectoryNode & shortdoc(std::string const & doc); ///< Set node short documentation
522
523         ptr thisptr();
524         cptr thisptr() const;
525
526     protected:
527         DirectoryNode();
528
529     private:
530         void add(GenericNode::ptr node);
531         virtual void v_help(std::ostream & output) const;
532         virtual std::string v_shorthelp() const;
533
534         ChildMap children_;
535         std::string doc_;
536         std::string shortdoc_;
537
538         friend DirectoryNode & root();
539     };
540
541     /// Exception: Unknown node name
542     struct UnknownNodeNameException : public senf::Exception
543     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
544
545     /** \brief Config/console tree command node
546
547         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
548         implementations are derived from this class.
549
550         To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
551
552         Subclass instances of this node type are automatically created when adding commands to the
553         tree. See \ref console_commands.
554
555         \ingroup node_tree
556       */
557     class CommandNode : public GenericNode
558     {
559         SENF_LOG_CLASS_AREA();
560     public:
561         //-////////////////////////////////////////////////////////////////////////
562         // Types
563
564         typedef boost::shared_ptr<CommandNode> ptr;
565         typedef boost::shared_ptr<CommandNode const> cptr;
566         typedef boost::weak_ptr<CommandNode> weak_ptr;
567
568         //-////////////////////////////////////////////////////////////////////////
569
570         void execute(std::ostream & output, ParseCommandInfo const & command) const;
571                                         ///< Execute the command
572                                         /**< \param[in] output stream where result messages may be
573                                                  written to
574                                              \param[in] command command arguments. This is a
575                                                  range of ranges of Token instances. */
576
577         void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
578             const;
579                                         ///< Execute the command
580                                         /**< \param[out] rv command return value
581                                              \param[in] output stream where result messages may be
582                                                  written to
583                                              \param[in] command command arguments. This is a
584                                                  range of ranges of Token instances. */
585
586         void operator()(std::ostream & output, ParseCommandInfo const & command) const;
587                                         ///< Execute the command
588                                         /**< Same as execute()
589                                              \param[in] output stream where result messages may be
590                                                  written to
591                                              \param[in] command command arguments. This is a
592                                                  range of ranges of Token instances. */
593         void operator()(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
594             const;
595
596         ptr thisptr();
597         cptr thisptr() const;
598
599     protected:
600         CommandNode();
601
602 #ifndef DOXYGEN
603     private:
604 #endif
605         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
606             const = 0;
607                                         ///< Called to execute the command
608                                         /**< \param[out] rv return value holder
609                                               \param[in] os stream where result messages may be
610                                                  written to
611                                              \param[in] command command arguments. This is a
612                                                  range of ranges of Token instances. */
613
614     private:
615     };
616
617     /** \brief Most simple CommandNode implementation
618
619         This CommandNode implementation simply forwards the \a output and \a arguments arguments to
620         an arbitrary callback. Thus, it allows to add callbacks with the signature
621         \code
622         void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
623         { ... }
624         \endcode
625         to the tree.
626
627         \ingroup console_commands
628      */
629     class SimpleCommandNode : public CommandNode
630     {
631         SENF_LOG_CLASS_AREA();
632     public:
633         //-////////////////////////////////////////////////////////////////////////
634         // Types
635
636         typedef boost::shared_ptr<SimpleCommandNode> ptr;
637         typedef boost::shared_ptr<SimpleCommandNode const> cptr;
638         typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
639
640         typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
641
642         typedef SimpleCommandNode node_type;
643         typedef SimpleCommandNode & return_type;
644
645         //-////////////////////////////////////////////////////////////////////////
646         ///\name Structors and default members
647         //\{
648
649         static ptr create(Function const & fn);
650
651         //\}
652         //-////////////////////////////////////////////////////////////////////////
653
654         ptr thisptr();
655         cptr thisptr() const;
656
657         SimpleCommandNode & doc(std::string const & doc);
658         SimpleCommandNode & shortdoc(std::string const & doc);
659
660     protected:
661         SimpleCommandNode(Function const & fn);
662
663     private:
664         virtual void v_help(std::ostream & output) const;
665         virtual std::string v_shorthelp() const;
666         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
667             const;
668
669
670         Function fn_;
671         std::string doc_;
672         std::string shortdoc_;
673     };
674
675     DirectoryNode & provideDirectory(DirectoryNode & dir, std::string const & name);
676
677 /** \brief Console node factories
678
679     The senf::console::factory namespace (customarily aliased to \c fty in user code) contains
680     factories used to create new node types:
681     \code
682     namespace fty = senf::console::factory;
683
684     senf::console::DirectoryNode & dir (node.add("dirname", fty::Directory()));
685
686     dir.add("name", fty::Command<void(bool)>(&fn)
687                 .arg("flag")
688                 .doc("documentation"));
689     \endcode
690
691     The node is added by passing the factory instance to senf::console::DirectoryNode::add().
692
693     To further customize the node, you may call attributor members on the temporary factory class
694     instance. Since the attributor members always return a self-reference to the factory class
695     instance, attributor calls may be chained arbitrarily.
696
697     \see
698         \ref console_commands for details on the command nodes \n
699         \ref node_tree for details on the structural nodes (directory, link)
700
701     \note All factories are documented here as classes when in fact some are functions returning
702         internal classes.
703
704     \implementation It is not true, that all attributor members return a self reference. Some
705         attributor members will return a new object of slightly different type. However, the
706         behavior is as documented above.
707
708     \ingroup console_commands
709  */
710 namespace factory {
711
712     /** \brief SimpleCommandNode factory
713
714         This factory will create a SimpleCommandNode calling the given callback. A SimpleCommandNode
715         does not support overloading or automatic argument parsing.
716
717         \attention This class is of interest mostly for testing and as a simple CommandNode
718         example. Use senf::console::factory::Command instead.
719      */
720     class SimpleCommand
721         : public detail::NodeFactory
722     {
723     public:
724         typedef SimpleCommandNode node_type;
725         typedef SimpleCommandNode & result_type;
726
727         explicit SimpleCommand(SimpleCommandNode::Function fn);
728
729         SimpleCommand const & doc(std::string const & doc) const;
730                                         ///< Set simple command documentation
731         SimpleCommand const & shortdoc(std::string const & doc) const;
732                                         ///< Set simple command short documentation
733
734     private:
735         SimpleCommandNode & create(DirectoryNode & dir, std::string const & name) const;
736
737         SimpleCommandNode::ptr node_;
738
739         friend class senf::console::DirectoryNode;
740     };
741
742     /** \brief DirectoryNode factory
743
744         This factory will create new directory nodes. Use
745
746         \code
747         namespace fty = senf::console::factory;
748         node.add("mydir", fty::Directory())
749         \endcode
750
751         To add a directory \a mydir to \a node.
752
753         \see \ref node_tree
754      */
755     class Directory
756         : public detail::NodeFactory
757     {
758     public:
759         typedef DirectoryNode node_type;
760         typedef DirectoryNode & result_type;
761
762         Directory();
763
764         Directory const & doc(std::string const & doc) const;
765                                         ///< Set directory documentation
766         Directory const & shortdoc(std::string const & doc) const;
767                                         ///< Set directory short documentation
768
769     private:
770         DirectoryNode & create(DirectoryNode & dir, std::string const & name) const;
771
772         DirectoryNode::ptr node_;
773
774         friend class senf::console::DirectoryNode;
775     };
776
777     /** \brief LinkNode factory
778
779         This factory will create new link nodes. Use
780
781         \code
782         namespace fty = senf::console::factory;
783         node.add("mylink", fty::Link(targetNode))
784         \endcode
785
786         To add a link \a mylink to \a node pointing to \a targetNode
787
788         \see \ref node_tree
789      */
790     class Link
791         : public detail::NodeFactory
792     {
793     public:
794         typedef LinkNode node_type;
795         typedef LinkNode & result_type;
796
797         explicit Link(GenericNode & target);
798
799     private:
800         LinkNode & create(DirectoryNode & dir, std::string const & name) const;
801
802         LinkNode::ptr node_;
803
804         friend class senf::console::DirectoryNode;
805     };
806
807 }
808
809 }}
810
811 //-/////////////////////////////////////////////////////////////////////////////////////////////////
812 #include "Node.cci"
813 //#include "Node.ct"
814 #include "Node.cti"
815 #endif
816
817 \f
818 // Local Variables:
819 // mode: c++
820 // fill-column: 100
821 // comment-column: 40
822 // c-file-style: "senf"
823 // indent-tabs-mode: nil
824 // ispell-local-dictionary: "american"
825 // compile-command: "scons -u test"
826 // End: