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