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 }
ConfigTree::set_config
void set_config(const std::shared_ptr< rapidjson::Document > &config)
Set config value.
Definition: ConfigTree.h:131
fawkes::WebviewRestApiManager::unregister_api
void unregister_api(WebviewRestApi *api)
Remove a request processor.
Definition: rest_api_manager.cpp:71
ConfigurationRestApi::loop
virtual void loop()
Code to execute in the thread.
Definition: config-rest-api.cpp:69
fawkes::WebviewRestApiManager::register_api
void register_api(WebviewRestApi *api)
Add a REST API.
Definition: rest_api_manager.cpp:58
ConfigurationRestApi::~ConfigurationRestApi
~ConfigurationRestApi()
Destructor.
Definition: config-rest-api.cpp:45
ConfigurationRestApi::init
virtual void init()
Initialize the thread.
Definition: config-rest-api.cpp:50
ConfigurationRestApi::ConfigurationRestApi
ConfigurationRestApi()
Constructor.
Definition: config-rest-api.cpp:39
ConfigTree
ConfigTree representation for JSON transfer.
Definition: ConfigTree.h:25
fawkes::Configuration::search
virtual ValueIterator * search(const char *path)=0
fawkes::LoggingAspect::logger
Logger * logger
Definition: logging.h:50
ConfigTree::set_kind
void set_kind(const std::string &kind)
Set kind value.
Definition: ConfigTree.h:97
fawkes
fawkes::WebviewAspect::webview_rest_api_manager
WebviewRestApiManager * webview_rest_api_manager
Webview REST API manager.
Definition: webview.h:59
fawkes::ConfigurableAspect::config
Configuration * config
Definition: configurable.h:50
fawkes::WebviewRestParams
REST parameters to pass to handlers.
Definition: rest_api.h:127
ConfigTree::set_apiVersion
void set_apiVersion(const std::string &apiVersion)
Set apiVersion value.
Definition: ConfigTree.h:114
fawkes::WebviewRestApi
Definition: rest_api.h:223
fawkes::Thread
Definition: thread.h:44
fawkes::WebviewRestParams::query_arg
std::string query_arg(const std::string &what)
Get a query argument.
Definition: rest_api.h:161
ConfigurationRestApi::finalize
virtual void finalize()
Finalize the thread.
Definition: config-rest-api.cpp:62
ConfigTree::api_version
static std::string api_version()
Get version of implemented API.
Definition: ConfigTree.h:44
fawkes::WebviewRestApi::add_handler
void add_handler(WebRequest::Method method, std::string path, Handler handler)
Add handler function.
Definition: rest_api.cpp:88