diff --git a/src/hos_cosgi_sitemap/CMakeLists.txt b/src/hos_cosgi_sitemap/CMakeLists.txt index 99b3722d..e3f932e7 100644 --- a/src/hos_cosgi_sitemap/CMakeLists.txt +++ b/src/hos_cosgi_sitemap/CMakeLists.txt @@ -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 diff --git a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h index f5f46514..4c196642 100644 --- a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h +++ b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/SitemapService.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -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 getSitemap(std::string name) noexcept = 0; + + virtual std::map> getSitemaps() noexcept = 0; + virtual std::vector getSitemapNames() noexcept = 0; + }; diff --git a/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h new file mode 100644 index 00000000..aa1a7db5 --- /dev/null +++ b/src/hos_cosgi_sitemap/include/hos_cosgi_sitemap/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h @@ -0,0 +1,115 @@ + +#pragma once + + +#include +#include +#include +#include +#include +#include +#include + + +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 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 getElement(size_t index) noexcept = 0; + virtual std::vector> 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 getElement(size_t index) noexcept = 0; + virtual std::vector> getElements() noexcept = 0; +}; + + + +class AtomicElement + : public virtual Element { +public: + virtual const std::string& getFormat() noexcept = 0; + virtual std::weak_ptr getDevice() noexcept = 0; + virtual const libvariant::Variant& getAdditionalParams() noexcept = 0; + virtual std::weak_ptr getLinkedToPage() noexcept = 0; +}; + + + +class Device + : public virtual interface::Object { +public: + virtual const std::string& getDeviceID() noexcept = 0; + virtual std::weak_ptr getDevice() noexcept = 0; + virtual const std::string& getPointer() noexcept = 0; +}; + + + +} // namespace sitemaptemplate +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos + diff --git a/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json b/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json index cd93e2f0..e875d8cd 100644 --- a/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json +++ b/src/hos_cosgi_sitemap/schema/sitemap/sitemap_template.json @@ -108,6 +108,9 @@ }, "icon": { "type": "string" + }, + "page": { + "type": "string" } } }, diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp index 31eb0fda..60cf2275 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.cpp @@ -1,5 +1,6 @@ #include "SitemapServiceImpl.h" +#include "sitemap_template/SitemapTemplateImpl.h" // std #include #include @@ -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 st = std::make_shared(title); + std::shared_ptr st = std::make_shared(*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 SitemapServiceImpl::getSitemap(std::string name) noexcept { + auto i = sitemapTemplates.find(name); + if (i != sitemapTemplates.end()) { + return std::static_pointer_cast(i->second); + } else { + return std::weak_ptr(); + } +} + + +std::map> SitemapServiceImpl::getSitemaps() noexcept { + std::map> retval; + for (auto i : sitemapTemplates) { + retval.insert({i.first, std::static_pointer_cast(i.second)}); + } + return retval; +} + + +std::vector SitemapServiceImpl::getSitemapNames() noexcept { + std::vector retval; + for (auto i : sitemapTemplates) { + retval.push_back(i.first); + } + return retval; +} + + } /* namespace sitemap */ } /* namespace service */ } /* namespace cosgi */ diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h index 1be10418..0ba91520 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/SitemapServiceImpl.h @@ -6,7 +6,6 @@ #include #include #include -#include "sitemap_template/SitemapTemplate.h" #include // std includes #include @@ -14,12 +13,15 @@ #include #include #include +//#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 { @@ -35,7 +37,7 @@ private: std::string hosStatusTopic = "/hos/status/updates"; bool initialized = false; - std::map> sitemapTemplates; + std::map> 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 getSitemap(std::string name) noexcept override; + + virtual std::map> getSitemaps() noexcept override; + + virtual std::vector getSitemapNames() noexcept override; + + /* Internal */ bool isInitialized() noexcept { return initialized; } diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.cpp deleted file mode 100644 index f868608d..00000000 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include "../sitemap_template/SitemapTemplate.h" - -namespace hos { -namespace cosgi { -namespace service { -namespace sitemap { -namespace sitemaptemplate { - - -std::shared_ptr SitemapTemplate::createPage(const libvariant::Variant& param, std::weak_ptr parent) { - std::shared_ptr 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(*this, title, parent); - for ( auto e : elements.AsList()) { - newPage->createElement(e); - } - if (parent.expired()) { - rootPage = newPage; - } - return newPage; -} - - -std::shared_ptr Page::createElement(const libvariant::Variant& param) { - -} - - -std::shared_ptr CompositeElement::createElement(const libvariant::Variant& param) { - -} - - -std::shared_ptr AtomicElement::createLinkedToPage(const libvariant::Variant& param) { - -} - - -std::shared_ptr AtomicElement::createDevice(const libvariant::Variant& param) { - -} - - -} // namespace sitemaptemplate -} // namespace sitemap -} // namespace service -} // namespace cosgi -} // namespace hos diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h deleted file mode 100644 index 1e502cb7..00000000 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplate.h +++ /dev/null @@ -1,164 +0,0 @@ - -#pragma once - -// hos includes -#include -// libvariant -#include -// std includes -#include -#include -#include -#include -#include - - -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 rootPage; - -public: - SitemapTemplate(const std::string& title) : title(title) {} - - std::shared_ptr createPage(const libvariant::Variant& param, std::weak_ptr parent = std::weak_ptr()); - - std::shared_ptr getRootPage() noexcept { return rootPage; }; -}; - - - -class Page { -private: - SitemapTemplate& sitemap; - std::weak_ptr parent; - std::string title; - std::vector> elements; - -public: - Page(SitemapTemplate& sitemap, const std::string& title, std::weak_ptr parent = std::weak_ptr()) - : sitemap(sitemap), title(title) {} - - SitemapTemplate& getSiteMap() noexcept { return sitemap; } - std::shared_ptr getParent() noexcept { return parent.lock(); } - - std::shared_ptr createElement(const libvariant::Variant& param); - const std::vector>& getElements() noexcept { return elements; } -}; - - -enum class ElementType { - // composite elements - Frame, - - // atomic elements - Text, - Switch, - Slider -}; - -class Element { -private: - static std::atomic nextID; - - uint64_t id; - bool compositeFlag; - ElementType type; - Page& page; - std::weak_ptr parent; - - std::string label; - std::string icon; - -public: - Element( Page& page, - bool isComposite, - ElementType type, - std::weak_ptr 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 getParent() noexcept { return parent.lock(); } - - bool isComposite() noexcept { return compositeFlag; }; - ElementType getType() noexcept { return type; } -}; - - - -class CompositeElement : public Element { -private: - std::vector> elements; - -public: - CompositeElement(Page& page, ElementType etype, const std::string& label, const std::string& icon, - std::weak_ptr parent = std::weak_ptr()) - : Element(page, true, etype, parent, label, icon) {} - - std::shared_ptr createElement(const libvariant::Variant& param); - const std::vector>& getElements() noexcept { return elements; } -}; - - - -class AtomicElement : public Element { -private: - std::string format; - std::shared_ptr device; - libvariant::Variant additionalParams; - std::shared_ptr linkedToPage; - -public: - AtomicElement(Page& page, ElementType etype, const std::string& label, const std::string& icon, - const std::string& format, std::shared_ptr device, libvariant::Variant additionalParams, - std::weak_ptr parent = std::weak_ptr()) - : Element(page, false, etype, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {} - - const std::string& getFormat() { return format; } - std::shared_ptr createDevice(const libvariant::Variant& param); - std::shared_ptr getDevice() { return device; } - const libvariant::Variant& getAdditionalParams() { return additionalParams; } - - std::shared_ptr createLinkedToPage(const libvariant::Variant& param); - std::shared_ptr getLinkedToPage() { return linkedToPage; } -}; - - - -class Device { -private: - -public: - -}; - - - -} // namespace sitemaptemplate -} // namespace sitemap -} // namespace service -} // namespace cosgi -} // namespace hos - diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp new file mode 100644 index 00000000..2a02b927 --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.cpp @@ -0,0 +1,195 @@ + +#include "SitemapTemplateImpl.h" + +namespace hos { +namespace cosgi { +namespace service { +namespace sitemap { +namespace sitemaptemplate { + + + +std::atomic ElementImpl::nextID; + +std::shared_ptr SitemapTemplateImpl::createPage(const libvariant::Variant& param, PageImpl* parent) { + std::shared_ptr 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(*this, title, parent); + for ( auto e : elements.AsList()) { + newPage->createElement(e); + } + if (!parent) { + rootPage = newPage; + } + return newPage; +} + + +std::shared_ptr 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 newDevice = std::make_shared(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> PageImpl::getElements() noexcept { + std::vector> retval; + for (auto i : elements) { + retval.push_back(std::static_pointer_cast(i)); + } + return retval; +} + +std::vector> CompositeElementImpl::getElements() noexcept { + std::vector> retval; + for (auto i : elements) { + retval.push_back(std::static_pointer_cast(i)); + } + return retval; +} + + +std::shared_ptr PageImpl::createElement(const libvariant::Variant& param, CompositeElementImpl* parent) { + std::shared_ptr 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(*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 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 newAElement = std::make_shared(*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 CompositeElementImpl::createElement(const libvariant::Variant& param) { + std::shared_ptr newElement = page.createElement(param, this); + elements.push_back(newElement); + return newElement; +} + + +std::shared_ptr 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 diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h new file mode 100644 index 00000000..19018958 --- /dev/null +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/sitemap_template/SitemapTemplateImpl.h @@ -0,0 +1,193 @@ + +#pragma once + +// hos includes +#include +#include "../SitemapServiceImpl.h" +#include +// libvariant +#include +// std includes +#include +#include +#include +#include +#include + + +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 rootPage; + +public: + SitemapTemplateImpl(SitemapServiceImpl& parent, const std::string& title) : parent(parent), title(title) {} + + std::shared_ptr createPage(const libvariant::Variant& param, PageImpl* parent = nullptr); + std::shared_ptr createDevice(const libvariant::Variant& param); + + virtual SitemapService* getParent() noexcept override { return dynamic_cast(&parent); } + virtual std::weak_ptr getRootPage() noexcept override { return std::static_pointer_cast(rootPage); }; +}; + + + +class PageImpl + : public virtual Page, + public implementation::Object { +friend class AtomicElementImpl; +private: + SitemapTemplateImpl& sitemap; + PageImpl* parent; + std::string title; + std::vector> 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(&sitemap); } + virtual Page* getParent() noexcept override { return static_cast(parent); } + + std::shared_ptr createElement(const libvariant::Variant& param, CompositeElementImpl* parent = nullptr); + + virtual size_t elementCount() noexcept override { return elements.size(); } + virtual std::weak_ptr getElement(size_t index) noexcept override + { return std::static_pointer_cast(elements.at(index)); }; + virtual std::vector> getElements() noexcept override; +}; + + +class ElementImpl + : public virtual Element, + public implementation::Object { +protected: + static std::atomic 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); } + 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> 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 createElement(const libvariant::Variant& param); + + virtual size_t elementCount() noexcept override { return elements.size(); } + virtual std::weak_ptr getElement(size_t index) noexcept override { return std::static_pointer_cast(elements.at(index)); } + virtual std::vector> getElements() noexcept override; +}; + + + +class AtomicElementImpl + : public virtual AtomicElement, + public ElementImpl { +private: + std::string format; + std::shared_ptr device; + libvariant::Variant additionalParams; + std::shared_ptr linkedToPage; + +public: + AtomicElementImpl(PageImpl& page, ElementType etype, const std::string& label, const std::string& icon, + const std::string& format, std::shared_ptr device, libvariant::Variant additionalParams, + CompositeElementImpl* parent = nullptr) + : ElementImpl(page, false, etype, parent, label, icon), format(format), device(device), additionalParams(additionalParams) {} + + std::shared_ptr createLinkedToPage(const libvariant::Variant& param); + + virtual const std::string& getFormat() noexcept override { return format; } + virtual std::weak_ptr getDevice() noexcept override; + virtual const libvariant::Variant& getAdditionalParams() noexcept override { return additionalParams; } + + virtual std::weak_ptr getLinkedToPage() noexcept override { return linkedToPage; } +}; + + + +class DeviceImpl + : public virtual Device, + public implementation::Object { +private: + std::string deviceID; + std::weak_ptr device; + std::string pointer; + +public: + DeviceImpl(const std::string& deviceID, std::weak_ptr device, const std::string& pointer) + : deviceID(deviceID), device(device), pointer(pointer) {} + + virtual const std::string& getDeviceID() noexcept override { return deviceID; } + virtual std::weak_ptr getDevice() noexcept override { return device; } + virtual const std::string& getPointer() noexcept override { return pointer; } +}; + + +inline CompositeElement* ElementImpl::getParent() noexcept { return static_cast(parent); } + +inline std::weak_ptr AtomicElementImpl::getDevice() noexcept { return std::static_pointer_cast(device); } + + +} // namespace sitemaptemplate +} // namespace sitemap +} // namespace service +} // namespace cosgi +} // namespace hos + diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp index aa927103..c8d5d629 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.cpp @@ -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 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 diff --git a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h index 4952ce1f..69e7c799 100644 --- a/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h +++ b/src/hos_cosgi_sitemap/src/hos/cosgi/service/sitemap/webresource/SitemapHandler.h @@ -32,6 +32,14 @@ class SitemapHandlerFactory; class SitemapHandler; +enum class SitemapAPIMethod { + GET, + COMMAND, + EVENT, + UNKNOWN +}; + + class SitemapHandlerFactory : public webserver::webresource::WebResourceHandlerFactoryImpl { 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; + };