Commit 438d8852 authored by Giorgio Azzinnaro's avatar Giorgio Azzinnaro

moved dynamic message creation to Loader

parent e4be45de
......@@ -170,6 +170,38 @@ const DescriptorPool & Loader::GetNormalizedPool() const
return this->normalizedPool;
}
const Descriptor * Loader::GetDescriptor(PoolType poolType, std::string typeName) const
{
const DescriptorPool & pool = ((poolType == SCHEMA)
? this->schemaPool
: this->normalizedPool);
BOOST_LOG_TRIVIAL(debug) << "Getting descriptor "
<< typeName
<< " from "
<< ((poolType == SCHEMA)
? "SCHEMA"
: "NORMALIZED")
<< " pool";
const Descriptor * descriptor = pool.FindMessageTypeByName(typeName);
if (descriptor == NULL)
throw std::runtime_error(typeName + " doesn't exist");
BOOST_LOG_TRIVIAL(trace) << std::endl << descriptor->DebugString();
return descriptor;
}
const Message * Loader::CreateMessage(PoolType poolType, std::string typeName)
{
BOOST_LOG_TRIVIAL(debug) << "Creating message " << typeName;
return this->messageFactory.GetPrototype(
this->GetDescriptor(poolType, typeName));
}
void Loader::BoostLogErrorCollector::AddError(
const std::string & filename,
const std::string & element_name,
......
......@@ -24,8 +24,9 @@
#include <profanedb/protobuf/storage.pb.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <boost/filesystem.hpp>
#include <boost/log/trivial.hpp>
......@@ -61,6 +62,20 @@ public:
const google::protobuf::DescriptorPool & GetSchemaPool() const;
const google::protobuf::DescriptorPool & GetNormalizedPool() const;
enum PoolType {
SCHEMA,
NORMALIZED
};
// Retrieve a Descriptor either from Schema or Normalized pool
const google::protobuf::Descriptor * GetDescriptor(
PoolType poolType,
std::string typeName) const;
// Create a prototype Message from defined pool
// (Should use `CreateMessage()->New() to get an empty Message from the prototype)
const google::protobuf::Message * CreateMessage(PoolType poolType, std::string typeName);
private:
// Given a Protobuf FileDescriptor from the pool, parse all of its messages,
......@@ -90,7 +105,6 @@ private:
google::protobuf::DescriptorPool::ErrorCollector::ErrorLocation location,
const std::string & message) override;
};
// google::protobuf::DescriptorPool::ErrorCollector & errorCollector;
BoostLogErrorCollector errorCollector;
std::unique_ptr<RootSourceTree> includeSourceTree;
......@@ -107,6 +121,9 @@ private:
// For each keyable message in schema, there is a normalized version
// which has Key in place of nested keyable messages
google::protobuf::DescriptorPool normalizedPool;
// The message factory is used to create new messages from the pools
google::protobuf::DynamicMessageFactory messageFactory;
};
}
}
......
......@@ -50,7 +50,9 @@ MessageTreeNode Marshaller::Marshal(const Message & message)
// The normalized message will be filled with data coming from input message,
// replacing references to other objects with their keys.
// It will then be serialized and set as storable message payload in messageTree;
Message * normalizedMessage = this->CreateMessage(NORMALIZED, message.GetTypeName());
Message * normalizedMessage
= this->loader->CreateMessage(Loader::NORMALIZED,
message.GetTypeName())->New();
// Only fields which are set in the message are processed
std::vector< const FieldDescriptor * > setFields;
......@@ -102,10 +104,14 @@ MessageTreeNode Marshaller::Marshal(const Message & message)
const Message & Marshaller::Unmarshal(const StorableMessage & storable)
{
// An empty normalized message is generated using the Key
Message * normalizedMessage = this->CreateMessage(NORMALIZED, storable.key().message_type());
Message * normalizedMessage
= this->loader->CreateMessage(Loader::NORMALIZED,
storable.key().message_type())->New();
// The original message is also retrieved
Message * originalMessage = this->CreateMessage(SCHEMA, storable.key().message_type());
Message * originalMessage
= this->loader->CreateMessage(Loader::SCHEMA,
storable.key().message_type())->New();
// StorableMessage payload contains the serialized normalized message,
// as previously stored into the DB
......@@ -147,28 +153,6 @@ const Message & Marshaller::Unmarshal(const StorableMessage & storable)
return *originalMessage;
}
Message * Marshaller::CreateMessage(Marshaller::MessagePool pool, std::string type)
{
BOOST_LOG_TRIVIAL(debug) << "Creating prototype message "
<< type
<< " from "
<< ((pool == SCHEMA) ? "SCHEMA" : "NORMALIZED")
<< " pool";
// DescriptorPool is either from Schema or Normalized
const DescriptorPool & descriptorPool =
(pool == SCHEMA)
? loader->GetSchemaPool()
: loader->GetNormalizedPool();
const Descriptor * descriptor = descriptorPool.FindMessageTypeByName(type);
if (descriptor == nullptr)
throw std::runtime_error(type + " doesn't exist");
return this->messageFactory.GetPrototype(descriptor)->New();
}
void Marshaller::CopyField(
const FieldDescriptor * fromField,
const Message & from,
......
......@@ -49,12 +49,6 @@ public:
virtual profanedb::protobuf::MessageTreeNode Marshal(const google::protobuf::Message & message) override;
virtual const google::protobuf::Message & Unmarshal(const profanedb::protobuf::StorableMessage & storable) override;
enum MessagePool {
SCHEMA,
NORMALIZED
};
google::protobuf::Message * CreateMessage(MessagePool pool, std::string type);
private:
// Loader contains the schemaPool and normalizedPool
const std::shared_ptr<Loader> loader;
......@@ -63,8 +57,6 @@ private:
// Storage is used to recursively retrieve them.
const std::shared_ptr<profanedb::vault::Storage> storage;
google::protobuf::DynamicMessageFactory messageFactory;
// Copy a field from a message to another.
// Differs from MergeFrom because it doesn't check whether Descriptors match.
void CopyField(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment