📄 nt_service_profile_heirarchy.hpp
字号:
// Copyright E骾n O'Callaghan 2008 - 2008.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef NT_SERVICE_PROFILE_HPP_INCLUDED
#define NT_SERVICE_PROFILE_HPP_INCLUDED
#include "StdAfx.hpp"
#include <boost/variant.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/serialization/optional.hpp>
#include <boost/serialization/set.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/list_of.hpp>
#define BOOST_GUID_ENABLE_SERIALIZATION
#include "boost/guid.hpp"
#include "auxiliary/txml_ini_adapter.hpp"
#include "auxiliary/txml_oarchive.hpp"
#include "auxiliary/txml_iarchive.hpp"
#include "nt_service.hpp"
#include "event_logger.hpp"
class nt_service_profile;
typedef boost::shared_ptr<nt_service_profile> nt_service_profile_ptr;
typedef boost::bimap<boost::bimaps::set_of<size_t>, boost::bimaps::set_of<boost::guid> > guid_bimap;
class nt_service_profile : public boost::enable_shared_from_this<nt_service_profile>
{
public:
nt_service_profile() :
guid_(boost::guid::create()),
saved_(false),
readonly_(false)
{}
nt_service_profile(std::wstring name, bool readonly=false) :
guid_(boost::guid::create()),
name_(name),
saved_(false),
readonly_(readonly)
{}
nt_service_profile(std::wstring name, nt_service_profile_ptr parent, bool readonly=false) :
guid_(boost::guid::create()),
name_(name),
saved_(false),
parent_(parent->guid()),
readonly_(readonly)
{
parent->children_.insert(guid_);
}
const boost::guid guid() const { return guid_; }
bool readonly() const { return readonly_; }
std::vector<nt_service::service_settings>& settings()
{
return settings_;
}
const boost::optional<boost::guid> parent() const { return parent_; }
void set_parent(boost::optional<boost::guid> p) { parent_ = p; }
void reset_parent() { parent_.reset(); }
std::set<boost::guid>& children() { return children_; }
const boost::filesystem::wpath filename() const
{
if (!filename_)
{
filename_ = (aux::app.non_roaming_directory() /
(guid().to_wstring() + L".spxml"));
}
return *filename_;
}
const std::wstring name() const { return name_; }
void set_name(const std::wstring& name)
{
name_ = name;
}
bool saved() const { return saved_; }
void set_saved(bool saved)
{
saved_ = saved;
}
bool operator==(const nt_service_profile& nt_p) const
{
return (guid_ == nt_p.guid_);
}
bool operator!=(const nt_service_profile& nt_p) const
{
return !(*this == nt_p);
}
bool operator<(const nt_service_profile& nt_p) const
{
return (guid_ < nt_p.guid_);
}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
using boost::serialization::make_nvp;
ar & make_nvp("guid", guid_);
ar & make_nvp("name", name_);
ar & make_nvp("parent", parent_);
ar & make_nvp("children", children_);
ar & make_nvp("readonly", readonly_);
ar & make_nvp("settings", settings_);
}
private:
boost::guid guid_;
std::wstring name_;
bool readonly_;
mutable boost::optional<boost::filesystem::wpath> filename_;
bool saved_;
boost::optional<boost::guid> parent_;
std::set<boost::guid> children_;
std::vector<nt_service::service_settings> settings_;
};
class nt_service_profile_heirarchy
{
typedef boost::function<void (const std::wstring&, size_t, size_t)> profile_loaded_fn;
public:
nt_service_profile_heirarchy(profile_loaded_fn pa) :
profile_loaded_(pa)
{}
size_t new_profile(std::wstring name, int parent=-1, bool readonly=false)
{
nt_service_profile_ptr p;
if (parent == -1)
p.reset(new nt_service_profile(name, readonly));
else
if(nt_service_profile_ptr par = get_profile(parent))
p.reset(new nt_service_profile(name, par, readonly));
profiles_[p->guid()] = p;
size_t uid_internal = guids_.size()+1;
guids_.insert(guid_bimap::value_type(uid_internal, p->guid()));
return uid_internal;
}
void set_profile_name(size_t i, std::wstring name)
{
get_profile(i)->set_name(name);
}
nt_service_profile_ptr get_profile(size_t i)
{
std::map<boost::guid, nt_service_profile_ptr>::iterator
p = profiles_.find(guids_.left.find(i)->second);
if (p != profiles_.end())
{
return (*p).second;
}
throw std::runtime_error("Invalid profile id");
}
nt_service_profile_ptr get_profile(boost::guid gi)
{
std::map<boost::guid, nt_service_profile_ptr>::iterator
p = profiles_.find(gi);
if (p != profiles_.end())
{
return (*p).second;
}
throw std::runtime_error("Invalid profile guid");
}
void load_profile(boost::filesystem::wpath file, bool use_guid_filename=false)
{
aux::txml_ini profile_ini(file);
aux::txml_ini_adapter adapter("profiles", profile_ini);
profile_ini.load_data();
std::set<nt_service_profile_ptr> profiles;
std::stringstream xml_data;
try
{
if(adapter.load_stream_data(xml_data))
{
aux::xml::txml_iarchive ixml(xml_data);
ixml >> boost::serialization::make_nvp("profiles", profiles);
}
size_t old_uids = guids_.size();
foreach(nt_service_profile_ptr new_profile, profiles)
{
new_profile->set_saved(true);
// Check if already present.
std::map<boost::guid, nt_service_profile_ptr>::iterator
p = profiles_.find(new_profile->guid());
if (p == profiles_.end())
{
// If NOT a duplicate.
profiles_[new_profile->guid()] = new_profile;
guids_.insert(guid_bimap::value_type(guids_.size()+1, new_profile->guid()));
}
}
if (guids_.size() > old_uids)
{
// At least 1 valid profile loaded.
std::set<boost::guid> associated_root_guids;
for (size_t i=old_uids+1, e=guids_.size(); i<=e; ++i)
associated_root_guids.insert(
find_branch_root(get_profile(i))->guid());
foreach(boost::guid g, associated_root_guids)
{
nt_service_profile_ptr p = get_profile(g);
validate_all_children(p);
save_profile(p);
traverse_and_build_profile_branch(p);
}
}
}
catch(const std::exception& e)
{
aux::wlog() << boost::wformat(L" !! std::exception: %1%") % e.what();
}
}
bool save_profile(const nt_service_profile_ptr p_ptr)
{
nt_service_profile_ptr ptr_parent = find_branch_root(p_ptr);
aux::txml_ini profile_ini(ptr_parent->filename());
aux::txml_ini_adapter adapter("profiles", profile_ini);
std::set<nt_service_profile_ptr> profiles;
traverse_and_insert(ptr_parent, profiles);
std::stringstream xml_data;
{
aux::xml::txml_oarchive oxml(xml_data);
oxml << boost::serialization::make_nvp("profiles", profiles);
}
adapter.save_stream_data(xml_data);
p_ptr->set_saved(true);
return profile_ini.save_data();
}
bool delete_profile(size_t index)
{
return delete_profile(get_profile(index));
}
bool delete_profile(nt_service_profile_ptr p_ptr)
{
if (p_ptr == find_branch_root(p_ptr))
{
aux::wlog() << L"! It's the big daddy";
boost::filesystem::remove(p_ptr->filename());
}
if (p_ptr->parent())
{
get_profile(*(p_ptr->parent()))->children().erase(p_ptr->guid());
}
profiles_.erase(p_ptr->guid());
traverse_and_delete(p_ptr);
return true;
}
bool export_profile_set(boost::filesystem::wpath filename, std::set<size_t> data_set)
{
aux::txml_ini profile_ini(filename);
aux::txml_ini_adapter adapter("profiles", profile_ini);
std::set<nt_service_profile_ptr> profiles;
foreach(size_t data, data_set)
profiles.insert(get_profile(data));
logger.post(new event_type(event_logger::info,
boost::wformat(L"Exporting %1% profiles.") % profiles.size()));
std::stringstream xml_data;
{
aux::xml::txml_oarchive oxml(xml_data);
oxml << boost::serialization::make_nvp("profiles", profiles);
}
adapter.save_stream_data(xml_data);
profile_ini.save_data();
return true;
}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
using boost::serialization::make_nvp;
ar & make_nvp("profiles", profiles_);
}
private:
nt_service_profile_ptr find_branch_root(nt_service_profile_ptr p_ptr)
{
while (p_ptr && p_ptr->parent())
{
p_ptr = get_profile(*(p_ptr->parent()));
}
return p_ptr;
}
void traverse_and_build_profile_branch(nt_service_profile_ptr p_ptr, size_t parent_code=0)
{
size_t tree_code = guids_.right.find(p_ptr->guid())->second;
profile_loaded_(p_ptr->name(), tree_code, parent_code);
foreach(boost::guid gi, p_ptr->children())
{
traverse_and_build_profile_branch(get_profile(gi), tree_code);
}
}
void traverse_and_insert(nt_service_profile_ptr p_ptr, std::set<nt_service_profile_ptr>& pros)
{
pros.insert(p_ptr);
foreach(boost::guid gi, p_ptr->children())
{
traverse_and_insert(get_profile(gi), pros);
}
}
void traverse_and_delete(nt_service_profile_ptr p_ptr)
{
foreach(boost::guid gi, p_ptr->children())
{
traverse_and_delete(get_profile(gi));
}
profiles_.erase(p_ptr->guid());
p_ptr.reset();
}
void validate_all_children(nt_service_profile_ptr p_ptr)
{
for (std::set<boost::guid>::iterator i=p_ptr->children().begin(), e=p_ptr->children().end();
i != e; /* nothing here */)
{
std::map<boost::guid, nt_service_profile_ptr>::iterator
p = profiles_.find(*i);
if (p != profiles_.end())
{
validate_all_children((*p).second);
++i;
}
else
{
aux::wlog() << L"! invalid child profile !";
p_ptr->children().erase(i++);
}
}
}
profile_loaded_fn profile_loaded_;
std::map<boost::guid, nt_service_profile_ptr> profiles_;
guid_bimap guids_;
};
BOOST_CLASS_VERSION(nt_service_profile_ptr, 2)
#endif // NT_SERVICE_PROFILE_HPP_INCLUDED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -