Loading...
Searching...
No Matches
ResourceList.h
Go to the documentation of this file.
#ifndef INCLUDE_HUEPLUSPLUS_RESOURCE_LIST_H
#define INCLUDE_HUEPLUSPLUS_RESOURCE_LIST_H
#include <functional>
#include <map>
#include <string>
#include <vector>
#include "APICache.h"
#include "HueException.h"
#include "NewDeviceList.h"
#include "Utils.h"
namespace hueplusplus
{
template <typename Resource, typename IdT>
class ResourceList
{
public:
using ResourceType = Resource;
using IdType = IdT;
static_assert(std::is_integral<IdType>::value || std::is_same<std::string, IdType>::value,
"IdType must be integral or string");
ResourceList(std::shared_ptr<APICache> baseCache, const std::string& cacheEntry,
std::chrono::steady_clock::duration refreshDuration, bool sharedState = false,
const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
= nullptr)
: stateCache(std::make_shared<APICache>(baseCache, cacheEntry, refreshDuration)),
factory(factory),
path(stateCache->getRequestPath() + '/'),
sharedState(sharedState)
{ }
ResourceList(const HueCommandAPI& commands, const std::string& path,
std::chrono::steady_clock::duration refreshDuration,
const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
= nullptr)
: stateCache(std::make_shared<APICache>(path, commands, refreshDuration, nullptr)),
factory(factory),
path(path + '/'),
sharedState(false)
{ }
ResourceList(const ResourceList&) = delete;
ResourceList& operator=(const ResourceList&) = delete;
void refresh() { stateCache->refresh(); }
void setRefreshDuration(std::chrono::steady_clock::duration refreshDuration)
{
stateCache->setRefreshDuration(refreshDuration);
}
std::vector<Resource> getAll()
{
nlohmann::json& state = stateCache->getValue();
std::vector<Resource> result;
result.reserve(state.size());
for (auto it = state.begin(); it != state.end(); ++it)
{
result.emplace_back(construct(maybeStoi(it.key()), it.value()));
}
return result;
}
Resource get(const IdType& id)
{
const nlohmann::json& state = stateCache->getValue();
std::string key = maybeToString(id);
if (!state.count(key))
{
throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Resource id is not valid");
}
return construct(id, state[key]);
}
bool exists(const IdType& id) { return stateCache->getValue().count(maybeToString(id)) != 0; }
bool exists(const IdType& id) const { return stateCache->getValue().count(maybeToString(id)) != 0; }
bool remove(const IdType& id)
{
std::string requestPath = path + maybeToString(id);
nlohmann::json result = stateCache->getCommandAPI().DELETERequest(
requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
bool success = utils::safeGetMember(result, 0, "success") == requestPath + " deleted";
return success;
}
protected:
static IdType maybeStoi(const std::string& key) { return maybeStoi(key, std::is_integral<IdType> {}); }
static std::string maybeToString(const IdType& id) { return maybeToString(id, std::is_integral<IdType> {}); }
Resource construct(const IdType& id, const nlohmann::json& state)
{
return construct(id, state,
std::is_constructible<Resource, IdType, HueCommandAPI, std::chrono::steady_clock::duration,
const nlohmann::json&> {});
}
ResourceList(ResourceList&&) = default;
ResourceList& operator=(ResourceList&&) = default;
private:
// Resource is constructible
Resource construct(const IdType& id, const nlohmann::json& state, std::true_type)
{
if (factory)
{
return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
}
else
{
if (sharedState)
{
return Resource(id, stateCache);
}
else
{
return Resource(id, stateCache->getCommandAPI(), stateCache->getRefreshDuration(), state);
}
}
}
// Resource is not constructible
Resource construct(const IdType& id, const nlohmann::json& state, std::false_type)
{
if (!factory)
{
throw HueException(FileInfo {__FILE__, __LINE__, __func__},
"Resource is not constructable with default parameters, but no factory given");
}
return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
}
private:
static IdType maybeStoi(const std::string& key, std::true_type) { return std::stoi(key); }
static IdType maybeStoi(const std::string& key, std::false_type) { return key; }
static std::string maybeToString(IdType id, std::true_type) { return std::to_string(id); }
static std::string maybeToString(const IdType& id, std::false_type) { return id; }
protected:
std::shared_ptr<APICache> stateCache;
std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory;
std::string path;
bool sharedState;
};
template <typename Resource>
class SearchableResourceList : public ResourceList<Resource, int>
{
public:
using ResourceList<Resource, int>::ResourceList;
void search(const std::vector<std::string>& deviceIds = {})
{
std::string requestPath = this->path;
// Remove trailing slash
requestPath.pop_back();
if (deviceIds.empty())
{
this->stateCache->getCommandAPI().POSTRequest(
requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
}
else
{
this->stateCache->getCommandAPI().POSTRequest(
requestPath, nlohmann::json {{"deviceid", deviceIds}}, FileInfo {__FILE__, __LINE__, __func__});
}
}
NewDeviceList getNewDevices() const
{
nlohmann::json response = this->stateCache->getCommandAPI().GETRequest(
this->path + "new", nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
return NewDeviceList::parse(response);
}
protected:
SearchableResourceList(SearchableResourceList&&) = default;
SearchableResourceList& operator=(SearchableResourceList&&) = default;
};
template <typename BaseResourceList, typename CreateType>
class CreateableResourceList : public BaseResourceList
{
public:
using BaseResourceList::BaseResourceList;
typename BaseResourceList::IdType create(const CreateType& params)
{
std::string requestPath = this->path;
// Remove slash
requestPath.pop_back();
nlohmann::json response = this->stateCache->getCommandAPI().POSTRequest(
requestPath, params.getRequest(), FileInfo {__FILE__, __LINE__, __func__});
nlohmann::json id = utils::safeGetMember(response, 0, "success", "id");
if (id.is_string())
{
std::string idStr = id.get<std::string>();
if (idStr.find(this->path) == 0)
{
idStr.erase(0, this->path.size());
}
this->stateCache->refresh();
return this->maybeStoi(idStr);
}
return typename BaseResourceList::IdType {};
}
protected:
CreateableResourceList(CreateableResourceList&&) = default;
CreateableResourceList& operator=(CreateableResourceList&&) = default;
};
template <typename Resource, typename CreateType>
class GroupResourceList : public CreateableResourceList<ResourceList<Resource, int>, CreateType>
{
using Base = CreateableResourceList<ResourceList<Resource, int>, CreateType>;
public:
using Base::Base;
Resource get(const int& id)
{
const nlohmann::json& state = this->stateCache->getValue();
std::string key = this->maybeToString(id);
if (!state.count(key) && id != 0)
{
throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Resource id is not valid");
}
return this->construct(id, id == 0 ? nlohmann::json {nullptr} : state[key]);
}
bool exists(int id) const { return id == 0 || Base::exists(id); }
protected:
GroupResourceList(GroupResourceList&&) = default;
GroupResourceList& operator=(GroupResourceList&&) = default;
};
} // namespace hueplusplus
#endif
APICache.h
HueException.h
NewDeviceList.h
Utils.h
hueplusplus::APICache
Caches API GET requests and refreshes regularly.
Definition APICache.h:38
hueplusplus::CreateableResourceList
Handles a ResourceList where Resources can be added by the user.
Definition ResourceList.h:286
hueplusplus::CreateableResourceList::create
BaseResourceList::IdType create(const CreateType &params)
Create a new resource.
Definition ResourceList.h:298
hueplusplus::CreateableResourceList::operator=
CreateableResourceList & operator=(CreateableResourceList &&)=default
Protected defaulted move assignment.
hueplusplus::CreateableResourceList::CreateableResourceList
CreateableResourceList(CreateableResourceList &&)=default
Protected defaulted move constructor.
hueplusplus::GroupResourceList
Handles a group list with the special group 0.
Definition ResourceList.h:332
hueplusplus::GroupResourceList::get
Resource get(const int &id)
Get group, specially handles group 0.
Definition ResourceList.h:339
hueplusplus::GroupResourceList::operator=
GroupResourceList & operator=(GroupResourceList &&)=default
Protected defaulted move assignment.
hueplusplus::GroupResourceList::GroupResourceList
GroupResourceList(GroupResourceList &&)=default
Protected defaulted move constructor.
hueplusplus::GroupResourceList::exists
bool exists(int id) const
Get group, specially handles group 0.
Definition ResourceList.h:351
hueplusplus::HueCommandAPI
Definition HueCommandAPI.h:38
hueplusplus::HueException
Exception class with file information. Base class of all custom exception classes.
Definition HueException.h:50
hueplusplus::NewDeviceList
List of new devices found during the last scan.
Definition NewDeviceList.h:36
hueplusplus::NewDeviceList::parse
static NewDeviceList parse(const nlohmann::json &json)
Parse from json response.
Definition NewDeviceList.cpp:45
hueplusplus::ResourceList
Handles a list of a certain API resource.
Definition ResourceList.h:47
hueplusplus::ResourceList::ResourceList
ResourceList(ResourceList &&)=default
Protected defaulted move constructor.
hueplusplus::ResourceList::ResourceList
ResourceList(const ResourceList &)=delete
Deleted copy constructor.
hueplusplus::ResourceList::ResourceType
Resource ResourceType
Definition ResourceList.h:49
hueplusplus::ResourceList::ResourceList
ResourceList(const HueCommandAPI &commands, const std::string &path, std::chrono::steady_clock::duration refreshDuration, const std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> &factory=nullptr)
Construct ResourceList with a separate cache and optional factory function.
Definition ResourceList.h:76
hueplusplus::ResourceList::refresh
void refresh()
Refreshes internal state now.
Definition ResourceList.h:92
hueplusplus::ResourceList::get
Resource get(const IdType &id)
Get resource specified by id.
Definition ResourceList.h:126
hueplusplus::ResourceList::exists
bool exists(const IdType &id) const
Checks whether resource with id exists.
Definition ResourceList.h:151
hueplusplus::ResourceList::ResourceList
ResourceList(std::shared_ptr< APICache > baseCache, const std::string &cacheEntry, std::chrono::steady_clock::duration refreshDuration, bool sharedState=false, const std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> &factory=nullptr)
Construct ResourceList using a base cache and optional factory function.
Definition ResourceList.h:61
hueplusplus::ResourceList::setRefreshDuration
void setRefreshDuration(std::chrono::steady_clock::duration refreshDuration)
Sets custom refresh interval for this list and all resources created.
Definition ResourceList.h:96
hueplusplus::ResourceList::getAll
std::vector< Resource > getAll()
Get all resources that exist.
Definition ResourceList.h:107
hueplusplus::ResourceList::operator=
ResourceList & operator=(const ResourceList &)=delete
Deleted copy assignment.
hueplusplus::ResourceList::IdType
IdT IdType
Definition ResourceList.h:50
hueplusplus::ResourceList::operator=
ResourceList & operator=(ResourceList &&)=default
Protected defaulted move assignment.
hueplusplus::ResourceList::construct
Resource construct(const IdType &id, const nlohmann::json &state)
Constructs resource using factory or constructor, if available.
Definition ResourceList.h:180
hueplusplus::ResourceList::maybeStoi
static IdType maybeStoi(const std::string &key)
Calls std::stoi if IdType is int.
Definition ResourceList.h:173
hueplusplus::ResourceList::sharedState
bool sharedState
Definition ResourceList.h:233
hueplusplus::ResourceList::stateCache
std::shared_ptr< APICache > stateCache
Definition ResourceList.h:230
hueplusplus::ResourceList::path
std::string path
Definition ResourceList.h:232
hueplusplus::ResourceList::factory
std::function< Resource(IdType, const nlohmann::json &, const std::shared_ptr< APICache > &)> factory
Definition ResourceList.h:231
hueplusplus::ResourceList::remove
bool remove(const IdType &id)
Removes the resource.
Definition ResourceList.h:162
hueplusplus::ResourceList::maybeToString
static std::string maybeToString(const IdType &id)
Calls std::to_string if IdType is int.
Definition ResourceList.h:176
hueplusplus::ResourceList::exists
bool exists(const IdType &id)
Checks whether resource with id exists.
Definition ResourceList.h:144
hueplusplus::SearchableResourceList
Handles a ResourceList of physical devices which can be searched for.
Definition ResourceList.h:240
hueplusplus::SearchableResourceList::getNewDevices
NewDeviceList getNewDevices() const
Get devices found in last search.
Definition ResourceList.h:266
hueplusplus::SearchableResourceList::search
void search(const std::vector< std::string > &deviceIds={})
Start search for new devices.
Definition ResourceList.h:248
hueplusplus::SearchableResourceList::SearchableResourceList
SearchableResourceList(SearchableResourceList &&)=default
Protected defaulted move constructor.
hueplusplus::SearchableResourceList::operator=
SearchableResourceList & operator=(SearchableResourceList &&)=default
Protected defaulted move assignment.
hueplusplus::utils::safeGetMember
nlohmann::json safeGetMember(const nlohmann::json &json, Paths &&... paths)
Returns the object/array member or null if it does not exist.
Definition Utils.h:92
hueplusplus
Namespace for the hueplusplus library.
Definition Action.h:28
hueplusplus::FileInfo
Contains information about error location, use CURRENT_FILE_INFO to create.
Definition HueException.h:35