#ifndef TPL_ENCODER_
#define TPL_ENCODER_
#include "rdf_rule_core.h"
#include "rdf_date_time.h"
#include "rdf_graph.h"
#include <istream>
#include <sstream>
#include <fstream>
#include <utility>
#include <cstdlib>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace parser {
class tpl_encoder;
typedef std::tr1::shared_ptr<tpl_encoder> tpl_encoder_ptr_type;
class tpl_encoder_model;
typedef std::tr1::shared_ptr<tpl_encoder_model> tpl_encoder_model_ptr_type;
// map of (tpl_encoder_model::name, tpl_encoder_model)
typedef std::tr1::unordered_map<std::string, tpl_encoder_model_ptr_type> tpl_encoder_model_map_type;
namespace internal {
class tpl_encoder_helper;
typedef std::tr1::shared_ptr<tpl_encoder_helper> tpl_encoder_helper_ptr_type;
// data structure used internally between the helper and the public classes
typedef std::tr1::unordered_multimap<std::string, std::string> po_map_t;
typedef std::tr1::unordered_map<std::string, po_map_t> spo_map_t;
/////////////////////////////////////////////////////////////////////////////////////////
// struct model_version
/////////////////////////////////////////////////////////////////////////////////////////
struct model_version
{
model_version():
name("TOP_ENGINE_MODEL"),
version(0),
next_key(0)
{};
std::string name;
unsigned int version;
unsigned int next_key;
};
/////////////////////////////////////////////////////////////////////////////////////////
// class tpl_encoder_helper
//
// Class hold common resources to make encoded buffers of graph smaller.
/////////////////////////////////////////////////////////////////////////////////////////
class tpl_encoder_helper
{
public:
typedef std::tr1::unordered_map<std::string, std::string> str_pool_map_t;
typedef std::tr1::unordered_map<std::string, rdf::index_type> key_index_map_t;
typedef std::tr1::unordered_map<rdf::index_type, std::string> index_key_map_t;
tpl_encoder_helper(
tpl_encoder_model_ptr_type model_p,
rdf::rdf_graph_ptr_type & graph_p,
bool verbose):
m_model_p(model_p),
m_graph_p(graph_p),
m_next_key(0),
m_key_str_map(),
m_str_key_map(),
m_key_index_map(),
m_index_key_map(),
m_key_encoded_index_map(),
m_has_model(true),
m_verbose(verbose)
{};
tpl_encoder_helper(
rdf::rdf_graph_ptr_type & graph_p,
bool verbose):
m_model_p(),
m_graph_p(graph_p),
m_next_key(0),
m_key_str_map(),
m_str_key_map(),
m_key_index_map(),
m_index_key_map(),
m_key_encoded_index_map(),
m_has_model(false),
m_verbose(verbose)
{};
~tpl_encoder_helper()
{};
/////////////////////////////////////////////////////////////////////////////////////////
// set_next_key
/////////////////////////////////////////////////////////////////////////////////////////
void
set_next_key(unsigned int next_key)
{
m_next_key = next_key;
};
/////////////////////////////////////////////////////////////////////////////////////////
// get_next_key
/////////////////////////////////////////////////////////////////////////////////////////
unsigned int
get_last_key()const
{
return m_next_key;
};
/////////////////////////////////////////////////////////////////////////////////////////
// parse_version
/////////////////////////////////////////////////////////////////////////////////////////
std::string::size_type
parse_version(model_version & version, unsigned int & last_key, std::string const& buffer, std::string::size_type ipos)const;
/////////////////////////////////////////////////////////////////////////////////////////
// encode_version
/////////////////////////////////////////////////////////////////////////////////////////
void
encode_version(model_version const& version, std::stringstream & sbuf, unsigned int last_key)const;
/////////////////////////////////////////////////////////////////////////////////////////
// parse_string_pool
/////////////////////////////////////////////////////////////////////////////////////////
std::string::size_type
parse_string_pool(std::string const& buffer, std::string::size_type ipos);
/////////////////////////////////////////////////////////////////////////////////////////
// encode_string_pool
/////////////////////////////////////////////////////////////////////////////////////////
void
encode_string_pool(std::stringstream & sbuf);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_resource_pool
/////////////////////////////////////////////////////////////////////////////////////////
std::string::size_type
parse_resource_pool(std::string const& buffer, std::string::size_type ipos);
/////////////////////////////////////////////////////////////////////////////////////////
// encode_resource_pool
/////////////////////////////////////////////////////////////////////////////////////////
void
encode_resource_pool(std::stringstream & sbuf);
/////////////////////////////////////////////////////////////////////////////////////////
// parse_triples
/////////////////////////////////////////////////////////////////////////////////////////
std::string::size_type
parse_triples(rdf::rdf_graph_ptr_type & graph_p, std::string const& buffer, std::string::size_type ipos);
/////////////////////////////////////////////////////////////////////////////////////////
// encode_triples
/////////////////////////////////////////////////////////////////////////////////////////
void
encode_triples(std::stringstream & sbuf, spo_map_t const& spo_map);
/////////////////////////////////////////////////////////////////////////////////////////
// get_index
//
// returns NULL if key is not found
/////////////////////////////////////////////////////////////////////////////////////////
rdf::index_type
get_index(std::string const& key)const;
/////////////////////////////////////////////////////////////////////////////////////////
// get_str
//
// returns empty str if key not found
/////////////////////////////////////////////////////////////////////////////////////////
std::string
get_str(std::string const& key)const;
/////////////////////////////////////////////////////////////////////////////////////////
// get_key_for
/////////////////////////////////////////////////////////////////////////////////////////
std::string const&
get_key_for(std::string const& str);
std::string const&
get_key_for(rdf::index_type index);
/////////////////////////////////////////////////////////////////////////////////////////
// encode_resource
//
// Encode the index argument and returns the encoded key.
// Add the (key, encoded-resource) pair into m_key_encoded_index_map
/////////////////////////////////////////////////////////////////////////////////////////
std::string const&
encode_resource(rdf::index_type index);
/////////////////////////////////////////////////////////////////////////////////////////
// create_index
/////////////////////////////////////////////////////////////////////////////////////////
rdf::index_type
create_index(unsigned int rb_key, std::string const& name, std::string const& type, std::string const& content);
private:
/////////////////////////////////////////////////////////////////////////////////////////
// get_encoded_name
/////////////////////////////////////////////////////////////////////////////////////////
std::string
get_encoded_name(rdf::index_type index)
{
std::string name = "*";
if(!index->has_local_name()) {
std::string const& iname = index->get_name();
std::string::size_type ipos = iname.find('#');
if(ipos!=std::string::npos && ipos>0) {
std::string const& base_key = get_key_for(iname.substr(0, ipos));
name = base_key + iname.substr(ipos);
} else {
name = get_key_for(index->get_name());
}
}
return name;
};
tpl_encoder_model_ptr_type m_model_p;
rdf::rdf_graph_ptr_type m_graph_p;
unsigned int m_next_key;
str_pool_map_t m_key_str_map;
str_pool_map_t m_str_key_map;
key_index_map_t m_key_index_map;
index_key_map_t m_index_key_map;
str_pool_map_t m_key_encoded_index_map;
bool m_has_model; // is true if helper to tpl_encoder_model, false helper to tpl_encoder
bool m_verbose;
};
}; /* internal namespace */
/////////////////////////////////////////////////////////////////////////////////////////
// class tpl_encoder
//
// Class to encode / decode triples into a string buffer.
// This uses an encoder model (tpl_encoder_model) where common resources, such as predicate,
// classes and commonly used individuals (usually from model) are defined to reduce the
// size of the buffer.
//
// This class is a single use class to encode / decode from / to a graph to / from a string buffer
/////////////////////////////////////////////////////////////////////////////////////////
class tpl_encoder
{
public:
tpl_encoder(
tpl_encoder_model_ptr_type const& tpl_encoder_model_p,
rdf::rdf_graph_ptr_type & graph_p,
bool verbose):
m_tpl_encoder_model_p(tpl_encoder_model_p),
m_helper_p(new internal::tpl_encoder_helper(tpl_encoder_model_p, graph_p, verbose)),
m_graph_p(graph_p),
m_verbose(verbose)
{};
public:
~tpl_encoder()
{};
/////////////////////////////////////////////////////////////////////////////////////////
// get_helper
/////////////////////////////////////////////////////////////////////////////////////////
internal::tpl_encoder_helper_ptr_type
get_helper_ptr() const
{
return m_helper_p;
};
/////////////////////////////////////////////////////////////////////////////////////////
// is_verbose
/////////////////////////////////////////////////////////////////////////////////////////
bool
is_verbose()const
{
return m_verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// set_verbose
/////////////////////////////////////////////////////////////////////////////////////////
void
set_verbose(bool verbose)
{
m_verbose = verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// decode
//
// Decode all triples from input buffer and assert them into m_graph_p
/////////////////////////////////////////////////////////////////////////////////////////
void
decode(std::string const& buffer);
/////////////////////////////////////////////////////////////////////////////////////////
// encode
//
// Encode all triples in m_graph_p into a string buffer using tpl_encoder_model_name
/////////////////////////////////////////////////////////////////////////////////////////
std::string
encode();
protected:
/////////////////////////////////////////////////////////////////////////////////////////
// add_triple
/////////////////////////////////////////////////////////////////////////////////////////
void
add_triple(internal::spo_map_t & triples, std::string const& skey, std::string const& pkey, std::string const& okey)
{
internal::po_map_t & po_map = triples[skey];
po_map.insert(std::make_pair(pkey, okey));
};
private:
friend class tpl_encoder_model;
tpl_encoder_model_ptr_type m_tpl_encoder_model_p;
internal::tpl_encoder_helper_ptr_type m_helper_p;
rdf::rdf_graph_ptr_type m_graph_p;
bool m_verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// class tpl_encoder_model
//
// Class hold common resources to make encoded buffers of graph smaller - hold the encoded metadata graph
/////////////////////////////////////////////////////////////////////////////////////////
class tpl_encoder_model
{
public:
tpl_encoder_model(
rdf::rdf_graph_ptr_type & graph_p,
bool verbose):
m_helper_p(new internal::tpl_encoder_helper(graph_p, verbose)),
m_model_version(),
m_graph_p(graph_p),
m_verbose(verbose)
{};
~tpl_encoder_model()
{};
/////////////////////////////////////////////////////////////////////////////////////////
// is_verbose
/////////////////////////////////////////////////////////////////////////////////////////
bool
is_verbose()const
{
return m_verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// set_verbose
/////////////////////////////////////////////////////////////////////////////////////////
void
set_verbose(bool verbose)
{
m_verbose = verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// set_model_version
/////////////////////////////////////////////////////////////////////////////////////////
void
set_version(std::string const& name, unsigned int v)
{
m_model_version.name = name;
m_model_version.version = v;
};
/////////////////////////////////////////////////////////////////////////////////////////
// get_version
/////////////////////////////////////////////////////////////////////////////////////////
internal::model_version const&
get_version() const
{
return m_model_version;
};
/////////////////////////////////////////////////////////////////////////////////////////
// get_version_name
/////////////////////////////////////////////////////////////////////////////////////////
std::string const&
get_version_name() const
{
return m_model_version.name;
};
/////////////////////////////////////////////////////////////////////////////////////////
// get_version_number
/////////////////////////////////////////////////////////////////////////////////////////
unsigned int
get_version_number() const
{
return m_model_version.version;
};
/////////////////////////////////////////////////////////////////////////////////////////
// get_helper
/////////////////////////////////////////////////////////////////////////////////////////
internal::tpl_encoder_helper_ptr_type
get_helper_ptr() const
{
return m_helper_p;
};
/////////////////////////////////////////////////////////////////////////////////////////
// decode
//
// Decode string and resource pools from buffer and metadata graph triples
/////////////////////////////////////////////////////////////////////////////////////////
void
decode(std::string const& buffer);
/////////////////////////////////////////////////////////////////////////////////////////
// encode
//
// Encode all resources defined in m_graph and metadata triples from m_graph
// if(graph_p) then use graph_p for the triples, this will create a new version
// NOTE: graph_p must use the same resource_base_map as m_graph_p
/////////////////////////////////////////////////////////////////////////////////////////
std::string
encode(rdf::rdf_graph_ptr_type & graph_p);
std::string
encode()
{
// creating a new helper
m_helper_p = internal::tpl_encoder_helper_ptr_type(new internal::tpl_encoder_helper(m_graph_p, m_verbose));
rdf::rdf_graph_ptr_type graph_p;
return encode(graph_p);
};
protected:
/////////////////////////////////////////////////////////////////////////////////////////
// add_triple
/////////////////////////////////////////////////////////////////////////////////////////
void
add_triple(internal::spo_map_t & triples, std::string const& skey, std::string const& pkey, std::string const& okey)
{
internal::po_map_t & po_map = triples[skey];
po_map.insert(std::make_pair(pkey, okey));
};
private:
internal::tpl_encoder_helper_ptr_type m_helper_p;
internal::model_version m_model_version;
rdf::rdf_graph_ptr_type m_graph_p;
bool m_verbose;
};
/////////////////////////////////////////////////////////////////////////////////////////
// create_tpl_encoder_model
/////////////////////////////////////////////////////////////////////////////////////////
inline tpl_encoder_model_ptr_type
create_tpl_encoder_model(rdf::rdf_graph_ptr_type & graph_p, bool verbose)
{
return tpl_encoder_model_ptr_type(new tpl_encoder_model(graph_p, verbose));
};
/////////////////////////////////////////////////////////////////////////////////////////
// create_tpl_encoder
/////////////////////////////////////////////////////////////////////////////////////////
inline tpl_encoder_ptr_type
create_tpl_encoder(tpl_encoder_model_ptr_type const& encoder_model_p, rdf::rdf_graph_ptr_type & graph_p, bool verbose)
{
return tpl_encoder_ptr_type(new tpl_encoder(encoder_model_p, graph_p, verbose));
};
}; /* parser namespace */
#endif /*TPL_ENCODER_*/