RSC  0.16.0
LoggerTreeNode.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of the RSC project.
4  *
5  * Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "LoggerTreeNode.h"
28 
29 #include <boost/format.hpp>
30 #include <boost/algorithm/string.hpp>
31 
33 
34 using namespace std;
35 
36 namespace rsc {
37 namespace logging {
38 
39 LoggerTreeNode::LoggerTreeNode(const string& name, LoggerTreeNodeWeakPtr parent) :
40  name(name), parent(parent) {
41 }
42 
45  name(name), loggerProxy(loggerProxy), parent(parent) {
46 }
47 
49  return parent.lock();
50 }
51 
52 string LoggerTreeNode::getName() const {
53  return name;
54 }
55 
57  return loggerProxy;
58 }
59 
61  this->loggerProxy = loggerProxy;
62 }
63 
65  // we rely on the fact that map only inserts if not present
66  return children.insert(make_pair(child->getName(), child)).second;
67 }
68 
70  CreateFunction createFn, const NamePath &processedPath) {
71 
72  if (path.size() == 0) {
73  throw invalid_argument("Empty path given");
74  }
75 
76  const string directChildName = path.front();
77  NamePath subPath = path;
78  subPath.erase(subPath.begin());
79  NamePath childPath = processedPath;
80  childPath.push_back(directChildName);
81 
82  if (!children.count(path.front())) {
83  children[path.front()] = LoggerTreeNodePtr(
84  new LoggerTreeNode(path.front(), shared_from_this()));
85  children[path.front()]->setLoggerProxy(
86  createFn(childPath, children[directChildName]));
87  }
88 
89  if (path.size() > 1) {
90  return children[directChildName]->addChildren(subPath, createFn,
91  childPath);
92  } else {
93  return children[directChildName];
94  }
95 
96 }
97 
99 }
100 
101 void LoggerTreeNode::visit(VisitorPtr visitor, const NamePath& thisPath) {
102 
103  for (map<string, LoggerTreeNodePtr>::const_iterator it = children.begin();
104  it != children.end(); ++it) {
105 
106  NamePath childPath = thisPath;
107  childPath.push_back(it->first);
108 
109  bool descend = visitor->visit(childPath, it->second,
110  loggerProxy->getLogger()->getLevel());
111  if (descend) {
112  it->second->visit(visitor, childPath);
113  }
114 
115  }
116 
117 }
118 
119 bool LoggerTreeNode::hasChild(const string& name) const {
120  return children.count(name) == 1;
121 }
122 
123 bool LoggerTreeNode::hasChild(const NamePath& path) const {
124  if (path.size() == 0) {
125  throw invalid_argument("Empty name path given");
126  }
127  map<string, LoggerTreeNodePtr>::const_iterator childIt = children.find(
128  path.front());
129  if (childIt == children.end()) {
130  return false;
131  }
132  NamePath subPath = path;
133  subPath.erase(subPath.begin());
134  return childIt->second->hasChild(subPath);
135 }
136 
138  map<string, LoggerTreeNodePtr>::const_iterator it = children.find(name);
139  if (it == children.end()) {
140  throw invalid_argument(
141  boost::str(
142  boost::format("No direct child with name %1 exists.")
143  % name));
144  }
145  return it->second;
146 }
147 
149  if (path.size() == 0) {
150  throw invalid_argument("Empty name path given");
151  }
152  map<string, LoggerTreeNodePtr>::const_iterator childIt = children.find(
153  path.front());
154  if (childIt == children.end()) {
155  throw invalid_argument(
156  boost::str(
157  boost::format("No direct child with name %1 exists.")
158  % name));
159  }
160  NamePath subPath = path;
161  subPath.erase(subPath.begin());
162  return childIt->second->getChild(subPath);
163 }
164 
166  children.clear();
167 }
168 
170  if (name.empty()) {
171  return NamePath();
172  }
173 
174  // TODO add checks which can be detected easiest in the string representation
175 
176  NamePath path;
177  string lowerName = name;
178  boost::algorithm::to_lower(lowerName);
179  boost::algorithm::split(path, lowerName, boost::algorithm::is_any_of("."));
180 
181  // Some consistency checks
182  assert(path.size() > 0);
183 
184  // avoid reserved keywords at the end
185  // TODO how to avoid string duplication with OptionBasedConfigurator?
186  // The configurator would be the place to store the two string constants in
187  // but I do not want to have a dependency from this class to the
188  // configurator.
189  if (path.back() == "level" || path.back() == "system") {
190  throw invalid_argument(
191  "Logger names must not end with system or level (case-insensitive), but I received: '"
192  + name + "'");
193  }
194 
195  return path;
196 }
197 
199  stringstream s;
200  for (NamePath::const_iterator it = path.begin(); it != path.end(); ++it) {
201  s << *it;
202  if (it != --path.end()) {
203  s << ".";
204  }
205  }
206  return s.str();
207 }
208 
209 boost::shared_ptr<Logger::Level> LoggerTreeNode::getAssignedLevel() const {
210  return assignedLevel;
211 }
212 
213 void LoggerTreeNode::setAssignedLevel(boost::shared_ptr<Logger::Level> level) {
214  this->assignedLevel = level;
215 }
216 
218  assignedLevel.reset(new Logger::Level(level));
219 }
220 
222  return assignedLevel.get() != NULL;
223 }
224 
225 }
226 }
boost::shared_ptr< LoggerProxy > LoggerProxyPtr
Definition: LoggerProxy.h:112
LoggerTreeNodePtr getParent() const
void setAssignedLevel(boost::shared_ptr< Logger::Level > level)
LoggerTreeNodePtr getChild(const std::string &name) const
LoggerTreeNodeWeakPtr parent
STL namespace.
pair< _T1, _T2 > make_pair(_T1 __x, _T2 __y)
A convenience wrapper for creating a pair from two objects.
void setLoggerProxy(LoggerProxyPtr loggerProxy)
std::vector< std::string > NamePath
A unique representation of a name.
Level
Possible logging levels.
Definition: Logger.h:63
LoggerProxyPtr getLoggerProxy() const
std::string name
New name part of this node.
LoggerTreeNode(const std::string &name, LoggerTreeNodeWeakPtr parent)
Creates a new node without an assigned LoggerProxy.
bool hasChild(const std::string &name) const
boost::shared_ptr< Logger::Level > getAssignedLevel() const
boost::shared_ptr< LoggerTreeNode > LoggerTreeNodePtr
boost::shared_ptr< Visitor > VisitorPtr
boost::shared_ptr< Logger::Level > assignedLevel
std::string getName() const
std::map< std::string, LoggerTreeNodePtr > children
void visit(VisitorPtr visitor, const NamePath &thisPath=NamePath())
Visits every sub-node excluding this node.
boost::function< LoggerProxyPtr(const NamePath &name, LoggerTreeNodePtr node)> CreateFunction
boost::weak_ptr< LoggerTreeNode > LoggerTreeNodeWeakPtr
static std::string pathToName(const NamePath &path)
static NamePath nameToPath(const std::string &name)
Converts a string name of the form a.test.string to a hierarchical logger path representation.
LoggerTreeNodePtr addChildren(const NamePath &path, CreateFunction createFn, const NamePath &processedPath=NamePath())
Retrieves an (indirect) child and creates required ancestors of this child using a custom callback me...
bool addChild(LoggerTreeNodePtr child)
Adds a child if it does not exist so far.