.
This commit is contained in:
@@ -55,7 +55,7 @@ bundle(hos_cosgi_sitemap
|
||||
${PROJECT_SOURCE_DIR}/src/BundleActivator
|
||||
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/SitemapServiceImpl
|
||||
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/webresource/SitemapHandler
|
||||
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate
|
||||
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl
|
||||
)
|
||||
|
||||
target_link_libraries(hos_cosgi_sitemap
|
||||
|
||||
+11
@@ -4,6 +4,8 @@
|
||||
#include <hos/cosgi/service/Interface.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
@@ -20,6 +22,7 @@ namespace devicerepository { class DeviceRepositoryService; }
|
||||
// service namespace
|
||||
namespace sitemap {
|
||||
|
||||
namespace sitemaptemplate { class SitemapTemplate; }
|
||||
|
||||
/**
|
||||
* Public COSGI interface of the sitemap service.
|
||||
@@ -48,6 +51,14 @@ public:
|
||||
*/
|
||||
virtual devicerepository::DeviceRepositoryService* getDeviceRepository() noexcept = 0;
|
||||
|
||||
|
||||
virtual size_t sitemapCount() noexcept = 0;
|
||||
|
||||
virtual std::weak_ptr<sitemaptemplate::SitemapTemplate> getSitemap(std::string name) noexcept = 0;
|
||||
|
||||
virtual std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> getSitemaps() noexcept = 0;
|
||||
virtual std::vector<std::string> getSitemapNames() noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <hos/cosgi/service/Interface.h>
|
||||
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
|
||||
#include <Variant/Variant.h>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
|
||||
class SitemapService;
|
||||
|
||||
namespace sitemaptemplate {
|
||||
|
||||
|
||||
class Page;
|
||||
class Element;
|
||||
class AtomicElement;
|
||||
class CompositeElement;
|
||||
class Device;
|
||||
|
||||
|
||||
|
||||
class SitemapTemplate
|
||||
: public virtual interface::Object {
|
||||
public:
|
||||
virtual SitemapService* getParent() noexcept = 0;
|
||||
virtual std::weak_ptr<Page> getRootPage() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Page
|
||||
: public virtual interface::Object {
|
||||
public:
|
||||
virtual SitemapTemplate* getSiteMap() noexcept = 0;
|
||||
virtual Page* getParent() noexcept = 0;
|
||||
|
||||
virtual size_t elementCount() noexcept = 0;
|
||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept = 0;
|
||||
virtual std::vector<std::weak_ptr<Element>> getElements() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
enum class ElementType {
|
||||
// composite elements
|
||||
Frame,
|
||||
|
||||
// atomic elements
|
||||
Text,
|
||||
Switch,
|
||||
Slider
|
||||
};
|
||||
|
||||
class Element
|
||||
: public virtual interface::Object {
|
||||
public:
|
||||
virtual uint64_t getID() noexcept = 0;
|
||||
virtual const std::string& getLabel() noexcept = 0;
|
||||
virtual const std::string& getIcon() noexcept = 0;
|
||||
|
||||
virtual Page* getPage() noexcept = 0;
|
||||
virtual CompositeElement* getParent() noexcept = 0;
|
||||
|
||||
virtual bool isComposite() noexcept = 0;
|
||||
virtual ElementType getType() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CompositeElement
|
||||
: public virtual Element {
|
||||
public:
|
||||
virtual size_t elementCount() noexcept = 0;
|
||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept = 0;
|
||||
virtual std::vector<std::weak_ptr<Element>> getElements() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AtomicElement
|
||||
: public virtual Element {
|
||||
public:
|
||||
virtual const std::string& getFormat() noexcept = 0;
|
||||
virtual std::weak_ptr<Device> getDevice() noexcept = 0;
|
||||
virtual const libvariant::Variant& getAdditionalParams() noexcept = 0;
|
||||
virtual std::weak_ptr<Page> getLinkedToPage() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Device
|
||||
: public virtual interface::Object {
|
||||
public:
|
||||
virtual const std::string& getDeviceID() noexcept = 0;
|
||||
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept = 0;
|
||||
virtual const std::string& getPointer() noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace sitemaptemplate
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -108,6 +108,9 @@
|
||||
},
|
||||
"icon": {
|
||||
"type": "string"
|
||||
},
|
||||
"page": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include "SitemapServiceImpl.h"
|
||||
#include "sitemap_template/SitemapTemplateImpl.h"
|
||||
// std
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
@@ -106,7 +107,7 @@ void SitemapServiceImpl::addSitemap(const std::string& name, XmlRpc::XmlRpcValue
|
||||
if (!rootpage.IsMap()) {
|
||||
throw std::runtime_error("rootpage is not a map.");
|
||||
}
|
||||
std::shared_ptr<sitemaptemplate::SitemapTemplate> st = std::make_shared<sitemaptemplate::SitemapTemplate>(title);
|
||||
std::shared_ptr<sitemaptemplate::SitemapTemplateImpl> st = std::make_shared<sitemaptemplate::SitemapTemplateImpl>(*this, title);
|
||||
st->createPage(rootpage);
|
||||
sitemapTemplates.insert({name, st});
|
||||
} else {
|
||||
@@ -117,6 +118,34 @@ void SitemapServiceImpl::addSitemap(const std::string& name, XmlRpc::XmlRpcValue
|
||||
}
|
||||
|
||||
|
||||
std::weak_ptr<sitemaptemplate::SitemapTemplate> SitemapServiceImpl::getSitemap(std::string name) noexcept {
|
||||
auto i = sitemapTemplates.find(name);
|
||||
if (i != sitemapTemplates.end()) {
|
||||
return std::static_pointer_cast<sitemaptemplate::SitemapTemplate>(i->second);
|
||||
} else {
|
||||
return std::weak_ptr<sitemaptemplate::SitemapTemplate>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> SitemapServiceImpl::getSitemaps() noexcept {
|
||||
std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> retval;
|
||||
for (auto i : sitemapTemplates) {
|
||||
retval.insert({i.first, std::static_pointer_cast<sitemaptemplate::SitemapTemplate>(i.second)});
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> SitemapServiceImpl::getSitemapNames() noexcept {
|
||||
std::vector<std::string> retval;
|
||||
for (auto i : sitemapTemplates) {
|
||||
retval.push_back(i.first);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace sitemap */
|
||||
} /* namespace service */
|
||||
} /* namespace cosgi */
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <hos/cosgi/service/core/CoreService.h>
|
||||
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
|
||||
#include <hos/cosgi/service/Implementation.h>
|
||||
#include "sitemap_template/SitemapTemplate.h"
|
||||
#include <ros/ros.h>
|
||||
// std includes
|
||||
#include <mutex>
|
||||
@@ -14,12 +13,15 @@
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
//#include "sitemap_template/SitemapTemplateImpl.h"
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
|
||||
namespace sitemaptemplate { class SitemapTemplateImpl; }
|
||||
|
||||
class SitemapServiceImpl
|
||||
: public virtual SitemapService,
|
||||
public implementation::Service<SitemapServiceImpl> {
|
||||
@@ -35,7 +37,7 @@ private:
|
||||
std::string hosStatusTopic = "/hos/status/updates";
|
||||
bool initialized = false;
|
||||
|
||||
std::map<std::string, std::shared_ptr<sitemaptemplate::SitemapTemplate>> sitemapTemplates;
|
||||
std::map<std::string, std::shared_ptr<sitemaptemplate::SitemapTemplateImpl>> sitemapTemplates;
|
||||
|
||||
void init() noexcept;
|
||||
void addSitemap(const std::string& name, XmlRpc::XmlRpcValue& rawValue);
|
||||
@@ -60,6 +62,17 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual size_t sitemapCount() noexcept override {
|
||||
return sitemapTemplates.size();
|
||||
}
|
||||
|
||||
virtual std::weak_ptr<sitemaptemplate::SitemapTemplate> getSitemap(std::string name) noexcept override;
|
||||
|
||||
virtual std::map<std::string, std::weak_ptr<sitemaptemplate::SitemapTemplate>> getSitemaps() noexcept override;
|
||||
|
||||
virtual std::vector<std::string> getSitemapNames() noexcept override;
|
||||
|
||||
|
||||
/* Internal */
|
||||
|
||||
bool isInitialized() noexcept { return initialized; }
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
|
||||
#include "../sitemap_template/SitemapTemplate.h"
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
namespace sitemaptemplate {
|
||||
|
||||
|
||||
std::shared_ptr<Page> SitemapTemplate::createPage(const libvariant::Variant& param, std::weak_ptr<Page> parent) {
|
||||
std::shared_ptr<Page> newPage;
|
||||
if (parent.expired() && rootPage) {
|
||||
throw std::runtime_error("There is already a root page.");
|
||||
}
|
||||
auto titleRaw = param["title"];
|
||||
if (!titleRaw.IsString()) {
|
||||
throw std::runtime_error("title is not a string.");
|
||||
}
|
||||
std::string title = titleRaw.AsString();
|
||||
auto elements = param["elements"];
|
||||
if (!elements.IsList()) {
|
||||
throw std::runtime_error("elements is not a list.");
|
||||
}
|
||||
newPage = std::make_shared<Page>(*this, title, parent);
|
||||
for ( auto e : elements.AsList()) {
|
||||
newPage->createElement(e);
|
||||
}
|
||||
if (parent.expired()) {
|
||||
rootPage = newPage;
|
||||
}
|
||||
return newPage;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Element> Page::createElement(const libvariant::Variant& param) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Element> CompositeElement::createElement(const libvariant::Variant& param) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Page> AtomicElement::createLinkedToPage(const libvariant::Variant& param) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Device> AtomicElement::createDevice(const libvariant::Variant& param) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace sitemaptemplate
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// hos includes
|
||||
#include <hos/utils/SchemaLoader.h>
|
||||
// libvariant
|
||||
#include <Variant/Schema.h>
|
||||
// std includes
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
namespace sitemaptemplate {
|
||||
|
||||
|
||||
class Page;
|
||||
class Element;
|
||||
class AtomicElement;
|
||||
class CompositeElement;
|
||||
class Device;
|
||||
|
||||
|
||||
|
||||
class SitemapTemplate {
|
||||
private:
|
||||
std::string title;
|
||||
std::shared_ptr<Page> rootPage;
|
||||
|
||||
public:
|
||||
SitemapTemplate(const std::string& title) : title(title) {}
|
||||
|
||||
std::shared_ptr<Page> createPage(const libvariant::Variant& param, std::weak_ptr<Page> parent = std::weak_ptr<Page>());
|
||||
|
||||
std::shared_ptr<Page> getRootPage() noexcept { return rootPage; };
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Page {
|
||||
private:
|
||||
SitemapTemplate& sitemap;
|
||||
std::weak_ptr<Page> parent;
|
||||
std::string title;
|
||||
std::vector<std::shared_ptr<Element>> elements;
|
||||
|
||||
public:
|
||||
Page(SitemapTemplate& sitemap, const std::string& title, std::weak_ptr<Page> parent = std::weak_ptr<Page>())
|
||||
: sitemap(sitemap), title(title) {}
|
||||
|
||||
SitemapTemplate& getSiteMap() noexcept { return sitemap; }
|
||||
std::shared_ptr<Page> getParent() noexcept { return parent.lock(); }
|
||||
|
||||
std::shared_ptr<Element> createElement(const libvariant::Variant& param);
|
||||
const std::vector<std::shared_ptr<Element>>& getElements() noexcept { return elements; }
|
||||
};
|
||||
|
||||
|
||||
enum class ElementType {
|
||||
// composite elements
|
||||
Frame,
|
||||
|
||||
// atomic elements
|
||||
Text,
|
||||
Switch,
|
||||
Slider
|
||||
};
|
||||
|
||||
class Element {
|
||||
private:
|
||||
static std::atomic<uint64_t> nextID;
|
||||
|
||||
uint64_t id;
|
||||
bool compositeFlag;
|
||||
ElementType type;
|
||||
Page& page;
|
||||
std::weak_ptr<CompositeElement> parent;
|
||||
|
||||
std::string label;
|
||||
std::string icon;
|
||||
|
||||
public:
|
||||
Element( Page& page,
|
||||
bool isComposite,
|
||||
ElementType type,
|
||||
std::weak_ptr<CompositeElement> parent,
|
||||
const std::string& label,
|
||||
const std::string& icon )
|
||||
: id(nextID.fetch_add(1)), compositeFlag(isComposite), type(type), page(page), parent(parent), label(label), icon(icon) {}
|
||||
virtual ~Element() {}
|
||||
|
||||
uint64_t getID() noexcept { return id; }
|
||||
const std::string& getLabel() noexcept { return label; }
|
||||
const std::string& getIcon() noexcept { return icon; }
|
||||
|
||||
Page& getPage() noexcept { return page; }
|
||||
std::shared_ptr<CompositeElement> getParent() noexcept { return parent.lock(); }
|
||||
|
||||
bool isComposite() noexcept { return compositeFlag; };
|
||||
ElementType getType() noexcept { return type; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CompositeElement : public Element {
|
||||
private:
|
||||
std::vector<std::shared_ptr<Element>> elements;
|
||||
|
||||
public:
|
||||
CompositeElement(Page& page, ElementType etype, const std::string& label, const std::string& icon,
|
||||
std::weak_ptr<CompositeElement> parent = std::weak_ptr<CompositeElement>())
|
||||
: Element(page, true, etype, parent, label, icon) {}
|
||||
|
||||
std::shared_ptr<Element> createElement(const libvariant::Variant& param);
|
||||
const std::vector<std::shared_ptr<Element>>& getElements() noexcept { return elements; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AtomicElement : public Element {
|
||||
private:
|
||||
std::string format;
|
||||
std::shared_ptr<Device> device;
|
||||
libvariant::Variant additionalParams;
|
||||
std::shared_ptr<Page> linkedToPage;
|
||||
|
||||
public:
|
||||
AtomicElement(Page& page, ElementType etype, const std::string& label, const std::string& icon,
|
||||
const std::string& format, std::shared_ptr<Device> device, libvariant::Variant additionalParams,
|
||||
std::weak_ptr<CompositeElement> parent = std::weak_ptr<CompositeElement>())
|
||||
: Element(page, false, etype, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {}
|
||||
|
||||
const std::string& getFormat() { return format; }
|
||||
std::shared_ptr<Device> createDevice(const libvariant::Variant& param);
|
||||
std::shared_ptr<Device> getDevice() { return device; }
|
||||
const libvariant::Variant& getAdditionalParams() { return additionalParams; }
|
||||
|
||||
std::shared_ptr<Page> createLinkedToPage(const libvariant::Variant& param);
|
||||
std::shared_ptr<Page> getLinkedToPage() { return linkedToPage; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Device {
|
||||
private:
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace sitemaptemplate
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
|
||||
#include "SitemapTemplateImpl.h"
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
namespace sitemaptemplate {
|
||||
|
||||
|
||||
|
||||
std::atomic<uint64_t> ElementImpl::nextID;
|
||||
|
||||
std::shared_ptr<PageImpl> SitemapTemplateImpl::createPage(const libvariant::Variant& param, PageImpl* parent) {
|
||||
std::shared_ptr<PageImpl> newPage;
|
||||
if (!parent && rootPage) {
|
||||
throw std::runtime_error("There is already a root page.");
|
||||
}
|
||||
auto titleRaw = param["title"];
|
||||
if (!titleRaw.IsString()) {
|
||||
throw std::runtime_error("title is not a string.");
|
||||
}
|
||||
std::string title = titleRaw.AsString();
|
||||
auto elements = param["elements"];
|
||||
if (!elements.IsList()) {
|
||||
throw std::runtime_error("elements is not a list.");
|
||||
}
|
||||
newPage = std::make_shared<PageImpl>(*this, title, parent);
|
||||
for ( auto e : elements.AsList()) {
|
||||
newPage->createElement(e);
|
||||
}
|
||||
if (!parent) {
|
||||
rootPage = newPage;
|
||||
}
|
||||
return newPage;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<DeviceImpl> SitemapTemplateImpl::createDevice(const libvariant::Variant& param) {
|
||||
auto idRaw = param["id"];
|
||||
if (!idRaw.IsString()) {
|
||||
throw std::runtime_error("id is not a string.");
|
||||
}
|
||||
std::string id = idRaw.AsString();
|
||||
std::string pointer;
|
||||
auto pointerRaw = param["pointer"];
|
||||
if (!pointerRaw.IsString()) {
|
||||
throw std::runtime_error("pointer is not a string.");
|
||||
} else if (pointerRaw.IsString()) {
|
||||
pointer = pointerRaw.AsString();
|
||||
}
|
||||
auto devRepo = parent.getDeviceRepository();
|
||||
auto device = devRepo->getDevice(id);
|
||||
std::shared_ptr<DeviceImpl> newDevice = std::make_shared<DeviceImpl>(id, device, pointer);
|
||||
return newDevice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct _elementTypeInfo {
|
||||
std::string typeName;
|
||||
ElementType type;
|
||||
bool isComposite;
|
||||
};
|
||||
|
||||
_elementTypeInfo elementTypeInfo[] = {
|
||||
{ "sitemap/sitemap_template#/definitions/frame_element", ElementType::Frame, true },
|
||||
{ "sitemap/sitemap_template#/definitions/text_element", ElementType::Text, false },
|
||||
{ "sitemap/sitemap_template#/definitions/slider_element", ElementType::Slider, false },
|
||||
{ "sitemap/sitemap_template#/definitions/switch_element", ElementType::Switch, false }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::weak_ptr<Element>> PageImpl::getElements() noexcept {
|
||||
std::vector<std::weak_ptr<Element>> retval;
|
||||
for (auto i : elements) {
|
||||
retval.push_back(std::static_pointer_cast<Element>(i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<std::weak_ptr<Element>> CompositeElementImpl::getElements() noexcept {
|
||||
std::vector<std::weak_ptr<Element>> retval;
|
||||
for (auto i : elements) {
|
||||
retval.push_back(std::static_pointer_cast<Element>(i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<ElementImpl> PageImpl::createElement(const libvariant::Variant& param, CompositeElementImpl* parent) {
|
||||
std::shared_ptr<ElementImpl> newElement;
|
||||
libvariant::Variant addParams = param.Copy();
|
||||
auto typeRaw = param["type"];
|
||||
if (!typeRaw.IsString()) {
|
||||
throw std::runtime_error("type is not a string.");
|
||||
}
|
||||
std::string typeStr = typeRaw.AsString();
|
||||
addParams.Erase("type");
|
||||
_elementTypeInfo* info = nullptr;
|
||||
for (auto& e : elementTypeInfo) {
|
||||
if (typeStr.compare(e.typeName)) {
|
||||
info = &e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!info) {
|
||||
std::stringstream ss;
|
||||
ss << "Unknown element type " << typeStr << ".";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
std::string label;
|
||||
auto labelRaw = param["label"];
|
||||
if (!labelRaw.IsNull() && !labelRaw.IsString()) {
|
||||
throw std::runtime_error("label is not a string.");
|
||||
} else if (labelRaw.IsString()) {
|
||||
label = labelRaw.AsString();
|
||||
addParams.Erase("label");
|
||||
}
|
||||
std::string icon;
|
||||
if (param.Contains("icon")) {
|
||||
auto iconRaw = param["icon"];
|
||||
if (!iconRaw.IsNull() && !iconRaw.IsString()) {
|
||||
throw std::runtime_error("icon is not a string.");
|
||||
} else if (iconRaw.IsString()) {
|
||||
icon = iconRaw.AsString();
|
||||
addParams.Erase("icon");
|
||||
}
|
||||
}
|
||||
|
||||
if (info->isComposite) {
|
||||
newElement = std::make_shared<CompositeElementImpl>(*this, info->type, label, icon, parent);
|
||||
} else {
|
||||
std::string format;
|
||||
auto formatRaw = param["format"];
|
||||
if (!formatRaw.IsNull() && !formatRaw.IsString()) {
|
||||
throw std::runtime_error("format is not a string.");
|
||||
} else if (formatRaw.IsString()) {
|
||||
format = formatRaw.AsString();
|
||||
addParams.Erase("format");
|
||||
}
|
||||
std::shared_ptr<DeviceImpl> device;
|
||||
auto deviceRaw = param["device"];
|
||||
if (!deviceRaw.IsNull() && !deviceRaw.IsMap()) {
|
||||
throw std::runtime_error("device is not a map.");
|
||||
} else if (deviceRaw.IsMap()) {
|
||||
device = sitemap.createDevice(deviceRaw);
|
||||
addParams.Erase("device");
|
||||
}
|
||||
auto pageRaw = param["page"];
|
||||
if (!pageRaw.IsNull() && !pageRaw.IsMap()) {
|
||||
throw std::runtime_error("page is not a map.");
|
||||
} else if (pageRaw.IsMap()) {
|
||||
addParams.Erase("page");
|
||||
}
|
||||
std::shared_ptr<AtomicElementImpl> newAElement = std::make_shared<AtomicElementImpl>(*this, info->type, label, icon, format, device, addParams, parent);
|
||||
if (pageRaw.IsMap()) {
|
||||
newAElement->createLinkedToPage(pageRaw);
|
||||
}
|
||||
newElement = newAElement;
|
||||
}
|
||||
if (!parent) {
|
||||
elements.push_back(newElement);
|
||||
}
|
||||
return newElement;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<ElementImpl> CompositeElementImpl::createElement(const libvariant::Variant& param) {
|
||||
std::shared_ptr<ElementImpl> newElement = page.createElement(param, this);
|
||||
elements.push_back(newElement);
|
||||
return newElement;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<PageImpl> AtomicElementImpl::createLinkedToPage(const libvariant::Variant& param) {
|
||||
if (linkedToPage) {
|
||||
throw std::runtime_error("There is already a linked page.");
|
||||
}
|
||||
linkedToPage = page.sitemap.createPage(param, &page);
|
||||
return linkedToPage;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sitemaptemplate
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// hos includes
|
||||
#include <hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h>
|
||||
#include "../SitemapServiceImpl.h"
|
||||
#include <hos/utils/SchemaLoader.h>
|
||||
// libvariant
|
||||
#include <Variant/Schema.h>
|
||||
// std includes
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace sitemap {
|
||||
|
||||
class SitemapServiceImpl;
|
||||
|
||||
namespace sitemaptemplate {
|
||||
|
||||
|
||||
class PageImpl;
|
||||
class ElementImpl;
|
||||
class AtomicElementImpl;
|
||||
class CompositeElementImpl;
|
||||
class DeviceImpl;
|
||||
|
||||
|
||||
|
||||
class SitemapTemplateImpl
|
||||
: public virtual SitemapTemplate,
|
||||
public implementation::Object {
|
||||
private:
|
||||
SitemapServiceImpl& parent;
|
||||
std::string title;
|
||||
std::shared_ptr<PageImpl> rootPage;
|
||||
|
||||
public:
|
||||
SitemapTemplateImpl(SitemapServiceImpl& parent, const std::string& title) : parent(parent), title(title) {}
|
||||
|
||||
std::shared_ptr<PageImpl> createPage(const libvariant::Variant& param, PageImpl* parent = nullptr);
|
||||
std::shared_ptr<DeviceImpl> createDevice(const libvariant::Variant& param);
|
||||
|
||||
virtual SitemapService* getParent() noexcept override { return dynamic_cast<SitemapService*>(&parent); }
|
||||
virtual std::weak_ptr<Page> getRootPage() noexcept override { return std::static_pointer_cast<Page>(rootPage); };
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PageImpl
|
||||
: public virtual Page,
|
||||
public implementation::Object {
|
||||
friend class AtomicElementImpl;
|
||||
private:
|
||||
SitemapTemplateImpl& sitemap;
|
||||
PageImpl* parent;
|
||||
std::string title;
|
||||
std::vector<std::shared_ptr<ElementImpl>> elements;
|
||||
|
||||
public:
|
||||
PageImpl(SitemapTemplateImpl& sitemap, const std::string& title, PageImpl* parent = nullptr)
|
||||
: sitemap(sitemap), parent(parent), title(title) {}
|
||||
|
||||
virtual SitemapTemplate* getSiteMap() noexcept override { return static_cast<SitemapTemplate*>(&sitemap); }
|
||||
virtual Page* getParent() noexcept override { return static_cast<Page*>(parent); }
|
||||
|
||||
std::shared_ptr<ElementImpl> createElement(const libvariant::Variant& param, CompositeElementImpl* parent = nullptr);
|
||||
|
||||
virtual size_t elementCount() noexcept override { return elements.size(); }
|
||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override
|
||||
{ return std::static_pointer_cast<Element>(elements.at(index)); };
|
||||
virtual std::vector<std::weak_ptr<Element>> getElements() noexcept override;
|
||||
};
|
||||
|
||||
|
||||
class ElementImpl
|
||||
: public virtual Element,
|
||||
public implementation::Object {
|
||||
protected:
|
||||
static std::atomic<uint64_t> nextID;
|
||||
|
||||
uint64_t id;
|
||||
bool compositeFlag;
|
||||
ElementType type;
|
||||
PageImpl& page;
|
||||
CompositeElementImpl* parent;
|
||||
|
||||
std::string label;
|
||||
std::string icon;
|
||||
|
||||
public:
|
||||
ElementImpl( PageImpl& page,
|
||||
bool isComposite,
|
||||
ElementType type,
|
||||
CompositeElementImpl* parent,
|
||||
const std::string& label,
|
||||
const std::string& icon )
|
||||
: id(nextID.fetch_add(1)), compositeFlag(isComposite), type(type), page(page), parent(parent), label(label), icon(icon) {}
|
||||
|
||||
virtual uint64_t getID() noexcept override { return id; }
|
||||
virtual const std::string& getLabel() noexcept override { return label; }
|
||||
virtual const std::string& getIcon() noexcept override { return icon; }
|
||||
|
||||
virtual Page* getPage() noexcept override { return static_cast<Page*>(&page); }
|
||||
virtual CompositeElement* getParent() noexcept override;
|
||||
|
||||
virtual bool isComposite() noexcept override { return compositeFlag; };
|
||||
virtual ElementType getType() noexcept override { return type; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CompositeElementImpl
|
||||
: public virtual CompositeElement,
|
||||
public ElementImpl {
|
||||
private:
|
||||
std::vector<std::shared_ptr<ElementImpl>> elements;
|
||||
|
||||
public:
|
||||
CompositeElementImpl(PageImpl& page, ElementType etype, const std::string& label, const std::string& icon,
|
||||
CompositeElementImpl* parent = nullptr)
|
||||
: ElementImpl(page, true, etype, parent, label, icon) {}
|
||||
|
||||
std::shared_ptr<ElementImpl> createElement(const libvariant::Variant& param);
|
||||
|
||||
virtual size_t elementCount() noexcept override { return elements.size(); }
|
||||
virtual std::weak_ptr<Element> getElement(size_t index) noexcept override { return std::static_pointer_cast<Element>(elements.at(index)); }
|
||||
virtual std::vector<std::weak_ptr<Element>> getElements() noexcept override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class AtomicElementImpl
|
||||
: public virtual AtomicElement,
|
||||
public ElementImpl {
|
||||
private:
|
||||
std::string format;
|
||||
std::shared_ptr<DeviceImpl> device;
|
||||
libvariant::Variant additionalParams;
|
||||
std::shared_ptr<PageImpl> linkedToPage;
|
||||
|
||||
public:
|
||||
AtomicElementImpl(PageImpl& page, ElementType etype, const std::string& label, const std::string& icon,
|
||||
const std::string& format, std::shared_ptr<DeviceImpl> device, libvariant::Variant additionalParams,
|
||||
CompositeElementImpl* parent = nullptr)
|
||||
: ElementImpl(page, false, etype, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {}
|
||||
|
||||
std::shared_ptr<PageImpl> createLinkedToPage(const libvariant::Variant& param);
|
||||
|
||||
virtual const std::string& getFormat() noexcept override { return format; }
|
||||
virtual std::weak_ptr<Device> getDevice() noexcept override;
|
||||
virtual const libvariant::Variant& getAdditionalParams() noexcept override { return additionalParams; }
|
||||
|
||||
virtual std::weak_ptr<Page> getLinkedToPage() noexcept override { return linkedToPage; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceImpl
|
||||
: public virtual Device,
|
||||
public implementation::Object {
|
||||
private:
|
||||
std::string deviceID;
|
||||
std::weak_ptr<devicerepository::Device> device;
|
||||
std::string pointer;
|
||||
|
||||
public:
|
||||
DeviceImpl(const std::string& deviceID, std::weak_ptr<devicerepository::Device> device, const std::string& pointer)
|
||||
: deviceID(deviceID), device(device), pointer(pointer) {}
|
||||
|
||||
virtual const std::string& getDeviceID() noexcept override { return deviceID; }
|
||||
virtual std::weak_ptr<devicerepository::Device> getDevice() noexcept override { return device; }
|
||||
virtual const std::string& getPointer() noexcept override { return pointer; }
|
||||
};
|
||||
|
||||
|
||||
inline CompositeElement* ElementImpl::getParent() noexcept { return static_cast<CompositeElement*>(parent); }
|
||||
|
||||
inline std::weak_ptr<Device> AtomicElementImpl::getDevice() noexcept { return std::static_pointer_cast<Device>(device); }
|
||||
|
||||
|
||||
} // namespace sitemaptemplate
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
+109
-4
@@ -43,14 +43,24 @@ Net::HTTPRequestHandler* SitemapHandlerFactory::createRequestHandler( Poco::URI
|
||||
|
||||
void SitemapHandler::_handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form) {
|
||||
if(req.find("Upgrade") != req.end() && Poco::icompare(req["Upgrade"], "websocket") == 0) {
|
||||
//__handleEvent(req, resp, true);
|
||||
throw webserver::webresource::WebResourceHandlerException("ToDo",
|
||||
Net::HTTPResponse::HTTP_NOT_IMPLEMENTED);
|
||||
__handleEvent(req, resp, form, true);
|
||||
} else {
|
||||
if (req.getMethod() == Net::HTTPRequest::HTTP_PUT || req.getMethod() == Net::HTTPRequest::HTTP_GET || req.getMethod() == Net::HTTPRequest::HTTP_POST) {
|
||||
if (req.getMethod() == Net::HTTPRequest::HTTP_PUT) {
|
||||
// Put Command
|
||||
throw webserver::webresource::WebResourceHandlerException("Still a ToDo.",
|
||||
Net::HTTPResponse::HTTP_NOT_IMPLEMENTED);
|
||||
} else if (req.getMethod() == Net::HTTPRequest::HTTP_GET || req.getMethod() == Net::HTTPRequest::HTTP_POST) {
|
||||
SitemapAPIMethod method = getSitemapAPIMethod(req, form);
|
||||
if (method == SitemapAPIMethod::GET) {
|
||||
__handleInfo(req, resp, form);
|
||||
} else if (method == SitemapAPIMethod::COMMAND) {
|
||||
__handleCommand(req, resp, method, form);
|
||||
} else if (method == SitemapAPIMethod::EVENT) {
|
||||
__handleEvent(req, resp, form, false);
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException("Could not understood request",
|
||||
Net::HTTPResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException("Could not understood request",
|
||||
Net::HTTPResponse::HTTP_BAD_REQUEST);
|
||||
@@ -59,6 +69,101 @@ void SitemapHandler::_handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net
|
||||
}
|
||||
|
||||
|
||||
void SitemapHandler::__handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form) {
|
||||
std::vector<std::string> pathPieces, matchPieces;
|
||||
matchUri.getPathSegments(matchPieces);
|
||||
Poco::URI uri(req.getURI());
|
||||
uri.getPathSegments(pathPieces);
|
||||
|
||||
// No sitemap given, query mode (there is no real query functionality implemented yet though)
|
||||
if (pathPieces.size() <= matchPieces.size()) {
|
||||
auto sitemaps = service->getSitemapNames();
|
||||
|
||||
// Iterate over sitemaps
|
||||
Variant result = Variant::List();
|
||||
for (auto s : sitemaps) {
|
||||
result.Append(s);
|
||||
}
|
||||
|
||||
handleResponse(req, resp, form, result);
|
||||
|
||||
// Single sitemap mode
|
||||
} else {
|
||||
// Get sitemap
|
||||
std::string sitemapName = pathPieces[matchPieces.size()];
|
||||
auto sitemap = service->getSitemap(sitemapName);
|
||||
if (!sitemap.expired()) {
|
||||
// Get info category
|
||||
std::string category;
|
||||
if (pathPieces.size() > matchPieces.size() + 1) {
|
||||
category = pathPieces[matchPieces.size() + 1];
|
||||
}
|
||||
// Get path from url and append pointer parameter
|
||||
std::stringstream path;
|
||||
for (int i = matchPieces.size() + 2; i < pathPieces.size(); i++) {
|
||||
path << "/" << pathPieces[i];
|
||||
}
|
||||
std::string pointer;
|
||||
if (getPointerParameter(pointer, form)) {
|
||||
if (pointer.size() > 0 && pointer[0] != '/') {
|
||||
path << "/";
|
||||
}
|
||||
path << pointer;
|
||||
}
|
||||
// Get device info
|
||||
Variant result = libvariant::Variant("ToDo: Do something");
|
||||
// Return device info
|
||||
handleResponse(req, resp, form, result);
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException((boost::format("Could not find sitemap \"%1%\"") % sitemapName).str(),
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SitemapHandler::__handleCommand(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, SitemapAPIMethod method, Net::HTMLForm& form) {
|
||||
throw webserver::webresource::WebResourceHandlerException("ToDo. Implement that shit.",
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
void SitemapHandler::__handleEvent(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Net::HTMLForm& form, bool websocket) {
|
||||
throw webserver::webresource::WebResourceHandlerException("ToDo. Implement that shit.",
|
||||
Poco::Net::HTTPResponse::HTTPStatus::HTTP_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
SitemapAPIMethod SitemapHandler::getSitemapAPIMethod(Net::HTTPServerRequest &req, Net::HTMLForm& form) noexcept {
|
||||
SitemapAPIMethod retval = SitemapAPIMethod::GET; // default
|
||||
std::string methodRaw;
|
||||
if (form.has("method")) {
|
||||
methodRaw = form.get("method");
|
||||
} else if (req.has("API-Method")) {
|
||||
methodRaw = req.get("API-Method");
|
||||
} else if (req.has("X-API-Method")) {
|
||||
methodRaw = req.get("X-API-Method");
|
||||
}
|
||||
if (!methodRaw.empty()) {
|
||||
if (methodRaw == "get") {
|
||||
retval = SitemapAPIMethod::GET;
|
||||
} else if (methodRaw == "command") {
|
||||
retval = SitemapAPIMethod::COMMAND;
|
||||
} else if (methodRaw == "event") {
|
||||
retval = SitemapAPIMethod::EVENT;
|
||||
} else {
|
||||
throw webserver::webresource::WebResourceHandlerException(
|
||||
(boost::format("Unknown sitemap api method \"%1%\"") % methodRaw).str(),
|
||||
Net::HTTPResponse::HTTPStatus::HTTP_BAD_REQUEST );
|
||||
}
|
||||
} else if (form.has("onevent") || req.has("On-Event") || req.has("X-On-Event")) {
|
||||
retval = SitemapAPIMethod::EVENT;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace webresource
|
||||
} // namespace sitemap
|
||||
} // namespace service
|
||||
|
||||
@@ -32,6 +32,14 @@ class SitemapHandlerFactory;
|
||||
class SitemapHandler;
|
||||
|
||||
|
||||
enum class SitemapAPIMethod {
|
||||
GET,
|
||||
COMMAND,
|
||||
EVENT,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
class SitemapHandlerFactory
|
||||
: public webserver::webresource::WebResourceHandlerFactoryImpl<SitemapHandlerFactory, false> {
|
||||
private:
|
||||
@@ -63,6 +71,14 @@ public:
|
||||
|
||||
virtual void _handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form) override;
|
||||
|
||||
void __handleInfo(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form);
|
||||
|
||||
void __handleCommand(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, SitemapAPIMethod method, Poco::Net::HTMLForm& form);
|
||||
|
||||
void __handleEvent(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp, Poco::Net::HTMLForm& form, bool websocket);
|
||||
|
||||
static SitemapAPIMethod getSitemapAPIMethod(Poco::Net::HTTPServerRequest &req, Poco::Net::HTMLForm& form) noexcept;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user