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