Utils/Console: Fix DirectoryNode::add(...) API
[senf.git] / senf / Utils / Console / ScopedDirectory.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 ScopedDirectory public header */
25
26 #ifndef HH_SENF_Scheduler_Console_ScopedDirectory_
27 #define HH_SENF_Scheduler_Console_ScopedDirectory_ 1
28
29 // Custom includes
30 #include <boost/utility.hpp>
31 #include <boost/type_traits/is_convertible.hpp>
32 #include "Node.hh"
33 #include "LazyDirectory.hh" // For ScopedDirectory template default arg
34
35 //#include "ScopedDirectory.mpp"
36 ///////////////////////////////hh.p////////////////////////////////////////
37
38 namespace senf {
39 namespace console {
40
41     namespace detail { struct OwnedNodeFactory {}; }
42
43     /** \brief Internal: Marker base class for all ScopedDirectory proxies
44      */
45     class ScopedDirectoryBase
46     {
47     public:
48         DirectoryNode & node() const;   ///< Access the proxied DirectoryNode
49         operator DirectoryNode & () const; ///< Access the proxied DirectoryNode
50
51         ///////////////////////////////////////////////////////////////////////////
52         ///\name Proxied members (see DirectoryNode)
53         ///\{
54
55         GenericNode::ptr remove(std::string const & name);
56         bool hasChild(std::string const & name) const;
57         DirectoryNode & getDirectory(std::string const & name) const;
58         DirectoryNode & operator[](std::string const & name) const;
59         CommandNode & getCommand(std::string const & name) const;
60         CommandNode & operator()(std::string const & name) const;
61         GenericNode & get(std::string const & name) const;
62         DirectoryNode & mkdir(std::string const & name);
63         void link(std::string const & name, GenericNode & node);
64         DirectoryNode::ChildrenRange children() const;
65         DirectoryNode & doc(std::string const & doc);
66
67         ///\}
68
69     protected:
70         ScopedDirectoryBase();
71         ~ScopedDirectoryBase();
72
73     private:
74         DirectoryNode::ptr node_;
75     };
76
77     /** \brief DirectoryNode member proxy
78
79         ScopedDirectory is used whenever a class wants to manage it's own directory. The class
80         allows to declare the directory as a public member object. This allows the user of the class
81         to register the directory in the command tree. By using the proxy, the node is automatically
82         detached from the tree (and thereby destroyed) when the object (and thereby the proxy) is
83         destroyed.
84
85         \code
86         class MyClass
87         {
88         public:
89             ScopedDirectory<MyClass> configDir;
90
91             MyClass() : configDir(this) 
92             {
93                 configDIr.add(...);
94             }
95         };
96         \endcode
97
98         The ScopedDirectory proxy implements 'add()' to add new children to the proxied
99         DirectoryNode. All add() variants supported by DirectoryNode are supported by
100         ScopedDirectory.
101
102         \idea This proxy could be made obsolete by allowing to allocate node objects
103             statically. This could be achieved by moving back to an intrusive_ptr implementation for
104             normal pointing needs with an added twist: Give each node a smart_ptr member pointing to
105             itself with a null deleter. This allows to create weak_ptr's to the nodes which will
106             automatically expire when the node is deleted (either statically or by the
107             intrusive_ptr).
108
109         \ingroup node_tree
110       */
111     template <class Owner>
112     class ScopedDirectory : public ScopedDirectoryBase
113     {
114     public:
115         ///////////////////////////////////////////////////////////////////////////
116         // Types
117         
118         typedef Owner owner;
119
120         ///////////////////////////////////////////////////////////////////////////
121         ///\name Structors and default members
122         ///@{
123
124         explicit ScopedDirectory(Owner * owner);
125
126         ///@}
127         ///////////////////////////////////////////////////////////////////////////
128
129         template <class NodeType>
130         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
131         template <class NodeType>
132         NodeType & add(std::string const & name, NodeType & node,
133                        typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
134         template <class Factory>
135         typename Factory::result_type add(std::string const & name, Factory const & factory,
136                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
137         template <class Factory>
138         typename Factory::result_type add(std::string const & name, Factory const & factory,
139                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0,
140                                           typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
141
142     protected:
143
144     private:
145         Owner * owner_;
146     };
147
148 #ifndef DOXYGEN
149
150     template <>
151     class ScopedDirectory<void> : public ScopedDirectoryBase
152     {
153     public:
154         template <class NodeType>
155         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
156         template <class NodeType>
157         NodeType & add(std::string const & name, NodeType & node,
158                        typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
159         template <class Factory>
160         typename Factory::result_type add(std::string const & name, Factory const & factory,
161                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0);
162     };
163
164 #endif
165
166 }}
167
168 ///////////////////////////////hh.e////////////////////////////////////////
169 #include "ScopedDirectory.cci"
170 //#include "ScopedDirectory.ct"
171 #include "ScopedDirectory.cti"
172 #endif
173
174 \f
175 // Local Variables:
176 // mode: c++
177 // fill-column: 100
178 // comment-column: 40
179 // c-file-style: "senf"
180 // indent-tabs-mode: nil
181 // ispell-local-dictionary: "american"
182 // compile-command: "scons -u test"
183 // End: