Fawkes API  Fawkes Development Version
config-rest-api.cpp
1 
2 /***************************************************************************
3  * config-rest-api.cpp - Configuration REST API
4  *
5  * Created: Thu Apr 12 19:00:59 2018
6  * Copyright 2006-2018 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #include "config-rest-api.h"
23 
24 #include <config/config.h>
25 #include <rapidjson/document.h>
26 #include <rapidjson/pointer.h>
27 #include <webview/rest_api_manager.h>
28 
29 #include <memory>
30 
31 using namespace fawkes;
32 
33 /** @class ConfigurationRestApi "skiller-rest-api.h"
34  * REST API backend for plugins.
35  * @author Tim Niemueller
36  */
37 
38 /** Constructor. */
40 : Thread("ConfigurationRestApi", Thread::OPMODE_WAITFORWAKEUP)
41 {
42 }
43 
44 /** Destructor. */
46 {
47 }
48 
49 void
51 {
52  rest_api_ = new WebviewRestApi("config", logger);
53  rest_api_->add_handler<ConfigTree>(WebRequest::METHOD_GET,
54  "/?",
55  std::bind(&ConfigurationRestApi::cb_get_config,
56  this,
57  std::placeholders::_1));
59 }
60 
61 void
63 {
65  delete rest_api_;
66 }
67 
68 void
70 {
71 }
72 
73 static rapidjson::Value
74 create_value(std::unique_ptr<fawkes::Configuration::ValueIterator> &i,
75  rapidjson::Document::AllocatorType & a)
76 {
77  rapidjson::Value v;
78  if (i->is_list()) {
79  v.SetArray();
80  v.Reserve(i->get_list_size(), a);
81  if (i->is_float()) {
82  std::vector<float> ivs = i->get_floats();
83  for (const auto &ivsv : ivs) {
84  v.PushBack(rapidjson::Value(ivsv).Move(), a);
85  }
86  } else if (i->is_uint()) {
87  std::vector<unsigned int> ivs = i->get_uints();
88  for (const auto &ivsv : ivs) {
89  v.PushBack(rapidjson::Value(ivsv).Move(), a);
90  }
91  } else if (i->is_int()) {
92  std::vector<int> ivs = i->get_ints();
93  for (const auto &ivsv : ivs) {
94  v.PushBack(rapidjson::Value(ivsv).Move(), a);
95  }
96  } else if (i->is_bool()) {
97  std::vector<bool> ivs = i->get_bools();
98  for (const auto &ivsv : ivs) {
99  v.PushBack(rapidjson::Value(ivsv).Move(), a);
100  }
101  } else if (i->is_string()) {
102  std::vector<std::string> ivs = i->get_strings();
103  for (const auto &ivsv : ivs) {
104  v.PushBack(rapidjson::Value(ivsv, a).Move(), a);
105  }
106  }
107  } else {
108  if (i->is_float()) {
109  v.SetFloat(i->get_float());
110  } else if (i->is_uint()) {
111  v.SetUint(i->get_uint());
112  } else if (i->is_int()) {
113  v.SetInt(i->get_int());
114  } else if (i->is_bool()) {
115  v.SetBool(i->get_bool());
116  } else if (i->is_string()) {
117  v.SetString(i->get_string(), a);
118  }
119  }
120  return v;
121 }
122 
124 ConfigurationRestApi::cb_get_config(WebviewRestParams &params)
125 {
126  std::string query{params.query_arg("query")};
127 
128  ConfigTree response;
129  response.set_kind("ConfigTree");
131 
132  std::shared_ptr<rapidjson::Document> d = std::make_shared<rapidjson::Document>();
133  rapidjson::Document::AllocatorType & a = d->GetAllocator();
134  d->SetObject();
135 
136  //rapidjson::Value &v{*d};
137  std::unique_ptr<fawkes::Configuration::ValueIterator> i{config->search(query.c_str())};
138  while (i->next()) {
139  std::vector<std::string> path_elements{str_split(i->path(), '/')};
140  rapidjson::Value::MemberIterator parent = d->MemberEnd();
141  ;
142  rapidjson::Value::MemberIterator m = d->MemberBegin();
143  rapidjson::Value::MemberIterator m_end = d->MemberEnd();
144 
145  if (path_elements.size() > 1) {
146  for (size_t p = 0; p < path_elements.size() - 1; ++p) {
147  m = std::find_if(m, m_end, [&path_elements, &p](const auto &v) {
148  return path_elements[p] == v.name.GetString();
149  });
150  if (m != m_end) {
151  parent = m;
152  } else {
153  if (parent != d->MemberEnd()) {
154  parent->value.AddMember(rapidjson::Value(path_elements[p], a).Move(),
155  rapidjson::Value(rapidjson::kObjectType).Move(),
156  a);
157  parent = parent->value.FindMember(path_elements[p].c_str());
158  } else {
159  d->AddMember(rapidjson::Value(path_elements[p], a).Move(),
160  rapidjson::Value(rapidjson::kObjectType).Move(),
161  a);
162  parent = d->FindMember(path_elements[p].c_str());
163  }
164  }
165  m = parent->value.MemberBegin();
166  m_end = parent->value.MemberEnd();
167  }
168 
169  if (parent == d->MemberEnd()) {
170  d->AddMember(rapidjson::Value(path_elements.back(), a).Move(),
171  create_value(i, a).Move(),
172  a);
173  } else {
174  parent->value.AddMember(rapidjson::Value(path_elements.back(), a).Move(),
175  create_value(i, a).Move(),
176  a);
177  }
178  }
179  }
180  response.set_config(d);
181 
182  return response;
183 }
virtual void init()
Initialize the thread.
Webview REST API component.
Definition: rest_api.h:220
virtual std::vector< bool > get_bools() const =0
Get list of values from configuration which is of type bool.
virtual std::vector< std::string > get_strings() const =0
Get list of values from configuration which is of type string.
virtual std::vector< float > get_floats() const =0
Get list of values from configuration which is of type float.
virtual bool is_bool() const =0
Check if current value is a bool.
Fawkes library namespace.
std::string query_arg(const std::string &what)
Get a query argument.
Definition: rest_api.h:158
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
virtual bool next()=0
Check if there is another element and advance to this if possible.
virtual std::vector< int > get_ints() const =0
Get list of values from configuration which is of type int.
virtual float get_float() const =0
Get float value.
virtual unsigned int get_uint() const =0
Get unsigned int value.
static std::string api_version()
Get version of implemented API.
Definition: ConfigTree.h:45
Thread class encapsulation of pthreads.
Definition: thread.h:45
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
Definition: ConfigTree.h:115
virtual size_t get_list_size() const =0
Get number of elements in list value.
void unregister_api(WebviewRestApi *api)
Remove a request processor.
virtual bool is_float() const =0
Check if current value is a float.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
virtual bool is_int() const =0
Check if current value is a int.
void register_api(WebviewRestApi *api)
Add a REST API.
virtual bool get_bool() const =0
Get bool value.
void set_config(const std::shared_ptr< rapidjson::Document > &config)
Set config value.
Definition: ConfigTree.h:132
virtual int get_int() const =0
Get int value.
ConfigTree representation for JSON transfer.
Definition: ConfigTree.h:26
void add_handler(WebRequest::Method method, std::string path, Handler handler)
Add handler function.
Definition: rest_api.cpp:85
virtual bool is_string() const =0
Check if current value is a string.
virtual std::vector< unsigned int > get_uints() const =0
Get list of values from configuration which is of type unsigned int.
REST parameters to pass to handlers.
Definition: rest_api.h:124
virtual bool is_uint() const =0
Check if current value is a unsigned int.
virtual bool is_list() const =0
Check if a value is a list.
virtual std::string get_string() const =0
Get string value.
virtual void finalize()
Finalize the thread.
virtual const char * path() const =0
Path of value.
ConfigurationRestApi()
Constructor.
WebviewRestApiManager * webview_rest_api_manager
Webview REST API manager.
Definition: webview.h:55
virtual void loop()
Code to execute in the thread.
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:41
~ConfigurationRestApi()
Destructor.
void set_kind(const std::string &kind)
Set kind value.
Definition: ConfigTree.h:98