⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nt_service_profile_heirarchy.hpp

📁 j2me is based on j2mepolish, client & server for mobile application.
💻 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 + -