switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / Variables.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 Variables public header */
30
31 #ifndef HH_SENF_Scheduler_Console_Variables_
32 #define HH_SENF_Scheduler_Console_Variables_ 1
33
34 // Custom includes
35 #include <boost/utility.hpp>
36 #include <boost/type_traits/is_convertible.hpp>
37 #include <boost/ref.hpp>
38 #include "Node.hh"
39
40 #include "Variables.ih"
41 //#include "Variables.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43
44 namespace senf {
45 namespace console {
46
47     class ScopedDirectoryBase;
48     template <class Variable> class VariableAttributor;
49
50 namespace factory {
51
52 #ifndef DOXYGEN
53
54     template <class Variable>
55     class ConstVariableFactory
56         : public detail::NodeFactory
57     {
58     public:
59         typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
60         typedef typename QueryOverload::Formatter Formatter;
61         typedef OverloadedCommandNode node_type;
62         typedef OverloadedCommandNode & result_type;
63
64         ConstVariableFactory doc(std::string const & doc);
65         ConstVariableFactory shortdoc(std::string const & doc);
66         ConstVariableFactory formatter(Formatter formatter);
67
68         OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
69
70         explicit ConstVariableFactory(Variable const & var);
71
72     private:
73         typename QueryOverload::ptr queryOverload_;
74         boost::optional<std::string> doc_;
75         boost::optional<std::string> shortdoc_;
76     };
77
78 #endif
79
80     /** \brief Variable node factory
81
82         Variable commands allow to register any arbitrary variable as a command node. The variable
83         will be registered as two command overloads: One which takes a single argument of the
84         variables type to set the variable and another one taking no arguments and just querying the
85         current variable value.
86         \code
87             int var;
88             ScopedDirectory<> dir;
89
90         dir.add("var", fty::Variable(var));
91         \endcode
92
93         Variables should be registered only with a ScopedDirectory declared in the same scope
94         (e.g. as a class member for member variables). This ensures, that the variable node is
95         removed from the tree when the scope is destroyed.
96
97         Since a variable command is added as a combination of two ordinary overloads, it is possible
98         to register additional overloads with the same name before or after registering the
99         variable.
100
101         It is also possible, to register a variable read-only. To achieve this, just wrap it with \c
102         boost::cref(). Such a variable only queried. Therefore, it does not have the parser() and
103         typeName() attributes.
104         \code
105             dir.add("const_var", fty::Variable(boost::cref(var)));
106         \endcode
107
108         \note Even though the interface is documented as a class, in reality it is implemented using
109             factory functions returning instances of an internal factory class.
110
111         \see \ref console_variables
112      */
113 #ifdef DOXYGEN
114     class Variable
115 #else
116     template <class Variable>
117     class VariableFactory
118         : public ConstVariableFactory<Variable>
119 #endif
120     {
121     public:
122         typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
123         typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
124         typedef typename detail::SetVariable<Variable>::OnChangeHandler OnChangeHandler;
125
126         typedef typename ConstVariableFactory<Variable>::Formatter Formatter;
127         typedef typename ConstVariableFactory<Variable>::QueryOverload QueryOverload;
128
129         VariableFactory doc(std::string const & doc); ///< Set documentation of the variable
130         VariableFactory shortdoc(std::string const & doc); ///< Set short documentation
131         VariableFactory formatter(Formatter formatter); ///< Set formatter
132                                         /**< The \a formatter must be a callable with a signature
133                                              compatible with
134                                              \code
135                                                  void formatter(Variable const & value, std::ostream & os);
136                                              \endcode
137                                                  The \a formatter takes the return value of the call \a
138                                                  value and writes it properly formated to \a os. */
139         VariableFactory parser(Parser parser); ///< Set argument parser
140                                         /**< The parser is an arbitrary callable object with
141                                              the signature
142                                              \code
143                                                  void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
144                                              \endcode
145
146                                              where \c value_type is the type of the overload
147                                              parameter. The parser must read and parse the complete
148                                              \a tokens range and return the parsed value in \a
149                                              out. If the parser fails, it must raise a
150                                              senf::console::SyntaxErrorException. */
151         VariableFactory typeName(std::string const & name); ///< Set name of the variable type
152         VariableFactory onChange(OnChangeHandler handler); ///< Set change callback
153                                         /**< The \a handler callback is called, whenever the value
154                                              of the variable is changed. The new value has already
155                                              been set, when the callback is called, the old value is
156                                              passed to the callback. The callback must have a
157                                              signature compatible to
158                                              \code
159                                                  void handler(Variable const & oldValue);
160                                              \endcode */
161
162         explicit VariableFactory(Variable & var); ///< Create Variable node
163
164     protected:
165
166     private:
167         OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
168
169         typename SetOverload::ptr setOverload_;
170         Variable & var_;
171
172         friend class senf::console::DirectoryNode;
173     };
174
175 #ifndef DOXYGEN
176
177     template <class Var>
178     VariableFactory<Var> Variable(Var & var);
179
180     template <class Var>
181     VariableFactory<Var> Variable(boost::reference_wrapper<Var> var);
182
183     template <class Var>
184     ConstVariableFactory<Var> Variable(Var const & var);
185
186     template <class Var>
187     ConstVariableFactory<Var> Variable(boost::reference_wrapper<Var const> var);
188
189 #endif
190
191 }}}
192
193 //-/////////////////////////////////////////////////////////////////////////////////////////////////
194 //#include "Variables.cci"
195 //#include "Variables.ct"
196 #include "Variables.cti"
197 #endif
198
199 \f
200 // Local Variables:
201 // mode: c++
202 // fill-column: 100
203 // comment-column: 40
204 // c-file-style: "senf"
205 // indent-tabs-mode: nil
206 // ispell-local-dictionary: "american"
207 // compile-command: "scons -u test"
208 // End: