fddf01a01fab2736f2f09c8f4c9f0efbff431f70
[senf.git] / Scheduler / Console / Node.cc
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 Node non-inline non-template implementation */
25
26 #include "Node.hh"
27 #include "Node.ih"
28
29 // Custom includes
30
31 //#include "Node.mpp"
32 #define prefix_
33 ///////////////////////////////cc.p////////////////////////////////////////
34
35 prefix_ senf::console::DirectoryNode & senf::console::root()
36 {
37     static DirectoryNode::ptr rootNode(new DirectoryNode());
38     return *rootNode;
39 }
40
41 ///////////////////////////////////////////////////////////////////////////
42 // senf::console::GenericNode
43
44 prefix_ std::string senf::console::GenericNode::path()
45     const
46 {
47     std::string path (name());
48     ptr node (parent());
49     while (node) {
50         path = node->name() + "/" + path;
51         node = node->parent();
52     }
53     return path.empty() ? "/" : path;
54 }
55
56 prefix_ std::string senf::console::GenericNode::path(DirectoryNode const & root)
57     const
58 {
59     std::string path;
60     cptr node (thisptr());
61     while (node && node != root.thisptr()) {
62         if (! path.empty())
63             path = node->name() + "/" + path;
64         else
65             path = node->name();
66         node = node->parent();
67     }
68     if (path.empty() || path[0] != '/')
69         path = "/" + path;
70     return path;
71 }
72
73 prefix_ bool senf::console::GenericNode::active()
74     const
75 {
76     cptr node (thisptr());
77     while (node->parent())
78         node = node->parent();
79     return node == root().thisptr();
80 }
81
82 prefix_ bool senf::console::GenericNode::isChildOf(DirectoryNode & parent)
83     const
84 {
85     cptr node (thisptr());
86     while (node && node != parent.thisptr())
87         node = node->parent();
88     return node;
89 }
90
91 ///////////////////////////////////////////////////////////////////////////
92 // senf::console::LinkNode
93
94 prefix_ void senf::console::LinkNode::v_help(std::ostream & os)
95     const
96 {
97     os << "link to ";
98     follow().help(os);
99 }
100
101 ///////////////////////////////////////////////////////////////////////////
102 //senf::console::DirectoryNode
103
104 prefix_ senf::console::GenericNode::ptr
105 senf::console::DirectoryNode::remove(std::string const & name)
106 {
107     ChildMap::iterator i (children_.find(name));
108     if (i == children_.end()) 
109         throw UnknownNodeNameException() << ": '" << name << "'";
110     GenericNode::ptr node (i->second);
111     children_.erase(i);
112     node->parent_ = 0;
113     node->name_.clear();
114     return node;
115 }
116
117 prefix_ void senf::console::DirectoryNode::add(GenericNode::ptr node)
118 {
119     BOOST_ASSERT( ! node->parent() );
120     if (node->name().empty()) {
121         node->name("unnamed");
122         SENF_LOG((senf::log::MESSAGE)("Adding 'unnamed' node"));
123     }
124     if (children_.find(node->name()) != children_.end()) {
125         unsigned suffix (0);
126         std::string newName;
127         do {
128             ++suffix;
129             newName = node->name() + "-" + boost::lexical_cast<std::string>(suffix);
130         } while (children_.find(newName) != children_.end());
131         SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '" 
132                                       << newName << "'"));
133         node->name(newName);
134     }
135     children_.insert(std::make_pair(node->name(),node));
136     node->parent_ = this;
137 }
138
139 prefix_ senf::console::GenericNode &
140 senf::console::DirectoryNode::getLink(std::string const & name)
141     const
142 {
143     ChildMap::const_iterator i (children_.find(name));
144     if (i == children_.end())
145         throw UnknownNodeNameException() << ": '" << name << "'";
146     return *(i->second);
147 }
148
149 prefix_ void senf::console::DirectoryNode::v_help(std::ostream & output)
150     const
151 {
152     output << doc_ << "\n";
153 }
154
155 ///////////////////////////////////////////////////////////////////////////
156 // senf::console::detail::NodeTraverser
157
158 prefix_ void senf::console::detail::NodeTraverser::operator()(std::string const & name)
159 {
160     if (! init_) {
161         init_ = true;
162         if (name == std::string("")) {
163             dir_ = root_.thisptr();
164             return;
165         }
166     }
167     if (! elt_.empty()) {
168         if (elt_ == "..") {
169             dir_ = dir_->parent();
170             if (! dir_ || ! dir_->isChildOf(root_))
171                 dir_ = root_.thisptr();
172         }
173         else if (elt_ != "" && elt_ != ".") {
174             if (! dir_->hasChild(elt_) && autocomplete_) {
175                 DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
176                 if (completions.size() == 1)
177                     elt_ = completions.begin()->first;
178             }
179             // Why does g++ give an error on this line ???? :
180             // dir = dynamic_cast<DirectoryNode&>( dir->get(name) ).thisptr();
181             DirectoryNode & d (dynamic_cast<DirectoryNode&>( dir_->get(elt_) ));
182             dir_ = d.thisptr();
183         }
184     }
185     elt_ = name;
186 }
187
188 prefix_ senf::console::GenericNode & senf::console::detail::NodeTraverser::node()
189 {
190     if (elt_ != "" && elt_ != ".") {
191         if (! dir_->hasChild(elt_) && autocomplete_) {
192             DirectoryNode::ChildrenRange completions (dir_->completions(elt_));
193             if (completions.size() == 1)
194                 elt_ = completions.begin()->first;
195         }
196         return dir_->get(elt_);
197     }
198     else
199         return * dir_;
200 }
201
202 ///////////////////////////////////////////////////////////////////////////
203 // senf::console::SimpleCommandNode
204
205 prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output)
206     const
207 {
208     output << doc_ << "\n";
209 }
210
211 prefix_ void senf::console::SimpleCommandNode::v_execute(std::ostream & output,
212                                                          ParseCommandInfo const & command)
213     const
214 {
215     fn_(output, command);
216 }
217
218 ///////////////////////////////cc.e////////////////////////////////////////
219 #undef prefix_
220 //#include "Node.mpp"
221
222 \f
223 // Local Variables:
224 // mode: c++
225 // fill-column: 100
226 // comment-column: 40
227 // c-file-style: "senf"
228 // indent-tabs-mode: nil
229 // ispell-local-dictionary: "american"
230 // compile-command: "scons -u test"
231 // End: