OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
osvr_print_tree.cpp
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 // Internal Includes
26 #include <osvr/ClientKit/Context.h>
31 #include <osvr/Common/PathNode.h>
37 
38 // Library/third-party includes
39 #include <boost/noncopyable.hpp>
40 #include <boost/program_options.hpp>
41 #include <boost/variant.hpp>
42 
43 // Standard includes
44 #include <chrono>
45 #include <iomanip>
46 #include <iostream>
47 #include <string>
48 #include <thread>
49 #include <unordered_set>
50 #include <vector>
51 
52 struct Options {
53  bool showAliasSource;
54  bool showAliasPriority;
55  bool showDeviceDetails;
56  bool showDeviceDescriptor;
57  bool showSensors;
58  bool showStringData;
59 };
60 
63 
70 class TreeNodePrinter : public boost::static_visitor<>, boost::noncopyable {
71  public:
73  TreeNodePrinter(Options opts, std::vector<std::string> const &badAliases)
74  : boost::static_visitor<>(), m_opts(opts),
75  m_maxTypeLen(elements::getMaxTypeNameLength()), m_os(std::cout),
76  m_indentStream(m_maxTypeLen + 2 + 1 + 2, m_os),
77  m_badAliases(begin(badAliases), end(badAliases)) {
78  // Computation for initializing the indent stream above:
79  // Indents type name size, +2 for the brackets, +1 for the space, and +2
80  // so it doesn't line up with the path.
81 
82  // Some initial space to set the output off.
83  m_os << "\n\n";
84  }
85 
87  void operator()(PathNode const &, elements::NullElement const &) {}
88 
90  void operator()(PathNode const &node, elements::SensorElement const &elt) {
91  if (m_opts.showSensors) {
92  outputBasics(node, elt) << "\n";
93  }
94  }
95 
97  void operator()(PathNode const &node, elements::AliasElement const &elt) {
98  outputBasics(node, elt) << std::endl;
99 
101  auto fullPath = osvr::common::getFullPath(node);
102  if (m_badAliases.find(fullPath) != m_badAliases.end()) {
103  m_indentStream << "WARNING: this alias does not fully resolve to a "
104  "device/sensor!\n";
105  }
106 
107  if (m_opts.showAliasSource) {
108  m_indentStream << "-> " << elt.getSource() << std::endl;
109  }
110  if (m_opts.showAliasPriority) {
111  m_indentStream << "Priority: "
113  << std::endl;
114  }
115  }
117  void operator()(PathNode const &node, elements::DeviceElement const &elt) {
118  outputBasics(node, elt) << std::endl;
119  if (m_opts.showDeviceDetails) {
120  m_indentStream << "- corresponds to " << elt.getFullDeviceName()
121  << std::endl;
122  }
123  if (m_opts.showDeviceDescriptor) {
124  m_indentStream << "- Descriptor: "
125  << elt.getDescriptor().toStyledString() << std::endl;
126  }
127  }
128 
130  void operator()(PathNode const &node, elements::StringElement const &elt) {
131  outputBasics(node, elt) << std::endl;
132  if (m_opts.showStringData) {
133  m_indentStream << "- Contained value: " << elt.getString()
134  << std::endl;
135  }
136  }
137 
139  template <typename T> void operator()(PathNode const &node, T const &elt) {
140  outputBasics(node, elt) << "\n";
141  }
142 
143  private:
146  template <typename T>
147  std::ostream &outputBasics(PathNode const &node, T const &elt) {
148  m_os << "[" << std::setw(m_maxTypeLen) << osvr::common::getTypeName(elt)
149  << "] " << osvr::common::getFullPath(node);
150  return m_os;
151  }
152  Options m_opts;
153  size_t m_maxTypeLen;
154  std::ostream &m_os;
155  osvr::util::IndentingStream m_indentStream;
156 
158  std::unordered_set<std::string> m_badAliases;
159 };
160 
161 int main(int argc, char *argv[]) {
162  Options opts;
163  namespace po = boost::program_options;
164  // clang-format off
165  po::options_description desc("Options");
166  desc.add_options()
167  ("help,h", "produce help message")
168  ("alias-source", po::value<bool>(&opts.showAliasSource)->default_value(true), "Whether or not to show the source associated with each alias")
169  ("alias-priority", po::value<bool>(&opts.showAliasPriority)->default_value(false), "Whether or not to show the priority associated with each alias")
170  ("device-details", po::value<bool>(&opts.showDeviceDetails)->default_value(true), "Whether or not to show the basic details associated with each device")
171  ("device-descriptors", po::value<bool>(&opts.showDeviceDescriptor)->default_value(false), "Whether or not to show the JSON descriptors associated with each device")
172  ("sensors", po::value<bool>(&opts.showSensors)->default_value(true), "Whether or not to show the 'sensor' nodes")
173  ("string-data", po::value<bool>(&opts.showStringData)->default_value(true), "Whether or not to show the data in 'string' nodes")
174  ;
175  // clang-format on
176  po::variables_map vm;
177  bool usage = false;
178  try {
179  po::store(po::command_line_parser(argc, argv)
180  .options(desc)
181  .extra_parser(
183  .run(),
184  vm);
185  po::notify(vm);
186  } catch (std::exception &e) {
187  std::cerr << "\nError parsing command line: " << e.what() << "\n\n";
188  usage = true;
189  }
190  if (usage || vm.count("help")) {
191  std::cerr << "\nTraverses the path tree and outputs it as text for "
192  "human consumption. See\nPathTreeExport for structured "
193  "output for graphical display.\n";
194  std::cerr << "Usage: " << argv[0] << " [options]\n\n";
195  std::cerr << "All options are shown as being --option 1/0 (true/false) "
196  "but may be expressed\nas --show-option or --hide-option "
197  "instead (e.g. --show-alias-priority)\n\n";
198  std::cerr << desc << "\n";
199  return 1;
200  }
201 
202  osvr::common::PathTree pathTree;
203  std::vector<std::string> badAliases;
204 
205  {
208  osvr::clientkit::ClientContext context("org.osvr.tools.printtree");
209 
210  if (!context.checkStatus()) {
211  context.log(OSVR_LOGLEVEL_NOTICE,
212  "Client context has not yet started up - waiting. "
213  "Make sure the server is running.");
214  do {
215  std::this_thread::sleep_for(std::chrono::milliseconds(1));
216  context.update();
217  } while (!context.checkStatus());
218  context.log(OSVR_LOGLEVEL_NOTICE,
219  "OK, client context ready. Proceeding.");
220  }
222  osvr::common::clonePathTree(context.get()->getPathTree(), pathTree);
225  badAliases = osvr::common::resolveFullTree(pathTree);
226  }
227 
230  osvr::util::log::flush();
231 
232  TreeNodePrinter printer{opts, badAliases};
238  pathTree.getRoot(), [&printer](PathNode const &node) {
239  osvr::common::applyPathNodeVisitor(printer, node);
240  });
241 
242  return 0;
243 }
detail::AliasPriorityWrapper outputPriority(AliasPriority priority)
Helper method to output a priority in a formatted way to a stream.
void operator()(PathNode const &node, elements::StringElement const &elt)
We might print something for a sensor element.
size_t getMaxTypeNameLength()
Gets the length of the longest type name.
void operator()(PathNode const &node, T const &elt)
Catch-all for other element types.
The element type corresponding to a path alias, with a priority level for sorting out whether automat...
Client context object: Create and keep one in your application. Handles lifetime management and provi...
Definition: Context_decl.h:57
A tree representation, with path/url syntax, of the known OSVR system.
Definition: PathTree.h:43
::osvr::util::TreeNode< PathElement > PathNode
The specific tree node type that contains a path element.
Definition: PathNode_fwd.h:42
void log(OSVR_LogLevel severity, const char *message)
Log a message to the plugin-specific channel.
Definition: Context.h:115
bool checkStatus() const
Checks to see if the client context is properly and fully started up.
Definition: Context.h:111
AliasPriority & priority()
Get/set whether this alias was automatically set (and thus subject to being override by explicit rout...
Header including PathTree.h and all additional headers needed to define related types.
TreeNodePrinter(Options opts, std::vector< std::string > const &badAliases)
Constructor.
std::string & getSource()
Get the source of data for this alias.
STL namespace.
The element type corresponding to a particular sensor of an interface.
Header.
void operator()(PathNode const &node, elements::SensorElement const &elt)
We might print something for a sensor element.
int main(int argc, char *argv[])
void operator()(PathNode const &, elements::NullElement const &)
print nothing for a null element.
The element type corresponding to a device, which implements 0 or more interfaces.
std::string getFullPath(PathNode const &node)
Gets the absolute path for the given node.
Definition: PathNode.cpp:42
void traverseWith(T &node, F &&functor)
A method to handle visiting every node in a tree with a lambda or other by-value function object...
Namespace for the various element types that may constitute a node in the path tree.
The element type corresponding to a string value such as a JSON string.
osvr::common::PathTree const & getPathTree() const
Accessor for the path tree.
OSVR_ClientContext get()
Gets the bare OSVR_ClientContext.
Definition: Context.h:109
void operator()(PathNode const &node, elements::AliasElement const &elt)
Print aliases.
Visitor::result_type applyPathNodeVisitor(Visitor &v, PathNode &node)
Visit a node's element's contained type, similar to boost::apply_visitor, but passing both the PathNo...
const char * getTypeName(PathNode const &node)
Gets an identifying string for the node value type.
Definition: PathNode.cpp:39
std::vector< std::string > resolveFullTree(PathTree &tree)
Traverse the given path tree, resolving all aliases found to fully populate any generated sensor targ...
A boost::iostreams::filtering_ostream with a constructor that automatically sets it up to indent the ...
void update()
Updates the state of the context - call regularly in your mainloop.
Definition: Context.h:54
std::string & getString()
Get/set (if non const) the stored string.
void operator()(PathNode const &node, elements::DeviceElement const &elt)
Print Devices.
std::pair< std::string, std::string > convertProgramOptionShowHideIntoTrueFalse(std::string s)
An "additional parser" for Boost.Program_options that will turn any –hide-xyz into –xyz false and â€...
The element type created when requesting a path that isn't yet in the tree.
Header.