481a4dde2777712797cc42500575dbd449f6e55d
[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::ChildrenRange children() const;
63         DirectoryNode & doc(std::string const & doc);
64
65         ///\}
66
67     protected:
68         ScopedDirectoryBase();
69         ~ScopedDirectoryBase();
70
71     private:
72         DirectoryNode::ptr node_;
73     };
74
75     /** \brief DirectoryNode member proxy
76
77         ScopedDirectory is used whenever a class wants to manage it's own directory. The class
78         allows to declare the directory as a public member object. This allows the user of the class
79         to register the directory in the command tree. By using the proxy, the node is automatically
80         detached from the tree (and thereby destroyed) when the object (and thereby the proxy) is
81         destroyed.
82
83         \code
84         class MyClass
85         {
86         public:
87             ScopedDirectory<MyClass> configDir;
88
89             MyClass() : configDir(this) 
90             {
91                 configDIr.add(...);
92             }
93         };
94         \endcode
95
96         The ScopedDirectory proxy implements 'add()' to add new children to the proxied
97         DirectoryNode. All add() variants supported by DirectoryNode are supported by
98         ScopedDirectory.
99
100         \idea This proxy could be made obsolete by allowing to allocate node objects
101             statically. This could be achieved by moving back to an intrusive_ptr implementation for
102             normal pointing needs with an added twist: Give each node a smart_ptr member pointing to
103             itself with a null deleter. This allows to create weak_ptr's to the nodes which will
104             automatically expire when the node is deleted (either statically or by the
105             intrusive_ptr).
106
107         \ingroup node_tree
108       */
109     template <class Owner>
110     class ScopedDirectory : public ScopedDirectoryBase
111     {
112     public:
113         ///////////////////////////////////////////////////////////////////////////
114         // Types
115         
116         typedef Owner owner;
117
118         ///////////////////////////////////////////////////////////////////////////
119         ///\name Structors and default members
120         ///@{
121
122         explicit ScopedDirectory(Owner * owner);
123
124         ///@}
125         ///////////////////////////////////////////////////////////////////////////
126
127         template <class NodeType>
128         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
129         template <class NodeType>
130         NodeType & add(std::string const & name, NodeType & node,
131                        typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
132         template <class Factory>
133         typename Factory::result_type add(std::string const & name, Factory const & factory,
134                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
135         template <class Factory>
136         typename Factory::result_type add(std::string const & name, Factory const & factory,
137                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0,
138                                           typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
139
140     protected:
141
142     private:
143         Owner * owner_;
144     };
145
146 #ifndef DOXYGEN
147
148     template <>
149     class ScopedDirectory<void> : public ScopedDirectoryBase
150     {
151     public:
152         template <class NodeType>
153         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
154         template <class NodeType>
155         NodeType & add(std::string const & name, NodeType & node,
156                        typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
157         template <class Factory>
158         typename Factory::result_type add(std::string const & name, Factory const & factory,
159                                           typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0);
160     };
161
162 #endif
163
164 }}
165
166 ///////////////////////////////hh.e////////////////////////////////////////
167 #include "ScopedDirectory.cci"
168 //#include "ScopedDirectory.ct"
169 #include "ScopedDirectory.cti"
170 #endif
171
172 \f
173 // Local Variables:
174 // mode: c++
175 // fill-column: 100
176 // comment-column: 40
177 // c-file-style: "senf"
178 // indent-tabs-mode: nil
179 // ispell-local-dictionary: "american"
180 // compile-command: "scons -u test"
181 // End: