Skip to content
Snippets Groups Projects

F consolidation

Merged Timm Fitschen requested to merge f-consolidation into dev
3 files
+ 35
12
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 158
110
@@ -29,10 +29,12 @@
#ifndef CAOSDB_ENTITY_H
#define CAOSDB_ENTITY_H
#include "caosdb/data_type.h" // for DataType
#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField
#include "caosdb/logging.h" // for CAOSDB_LOG_WARN
#include "caosdb/message_code.h" // for get_message_code
#include "caosdb/status_code.h" // for StatusCode
#include "caosdb/value.h" // for Value
#include <boost/filesystem/operations.hpp> // for exists, is_di...
#include <boost/filesystem/path.hpp> // for path
#include <boost/log/core/record.hpp> // for record
@@ -40,14 +42,16 @@
#include <boost/log/sources/record_ostream.hpp> // for basic_record_...
#include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_...
#include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_...
#include <cstdint> // for int64_t
#include <google/protobuf/message.h> // for RepeatedPtrField
#include <google/protobuf/util/json_util.h> // for MessageToJson...
#include <iosfwd> // for streamsize
#include <iterator> // for iterator, output_iterato...
#include <map> // for map
#include <random> // for mt19937, rand...
#include <stdexcept> // for out_of_range
#include <string> // for string, basic...
#include <iterator> // for iterator, output_iterato...
#include <map> // for map
#include <random> // for mt19937, rand...
#include <stdexcept> // for out_of_range
#include <string> // for string, basic...
#include <vector> // for vector
namespace caosdb::entity {
using boost::filesystem::exists;
@@ -58,6 +62,8 @@ using ProtoProperty = caosdb::entity::v1alpha1::Property;
using ProtoEntity = caosdb::entity::v1alpha1::Entity;
using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor;
using ProtoMessage = caosdb::entity::v1alpha1::Message;
using caosdb::entity::v1alpha1::EntityRole;
using ProtoImportance = caosdb::entity::v1alpha1::Importance;
using caosdb::StatusCode;
using caosdb::entity::v1alpha1::EntityResponse;
using caosdb::entity::v1alpha1::FileTransmissionId;
@@ -66,6 +72,39 @@ using google::protobuf::RepeatedPtrField;
static const std::string logger_name = "caosdb::entity";
/**
* The property importance.
*/
enum class Importance {
UNSPECIFIED = ProtoImportance::IMPORTANCE_UNSPECIFIED, ///< Unset/None
OBLIGATORY = ProtoImportance::IMPORTANCE_OBLIGATORY, ///< Obligatory importance.
RECOMMENDED = ProtoImportance::IMPORTANCE_RECOMMENDED, ///< Recommended importance.
SUGGESTED = ProtoImportance::IMPORTANCE_SUGGESTED, ///< Suggested importance.
FIX = ProtoImportance::IMPORTANCE_FIX, ///< Fix importance.
};
const std::map<Importance, std::string> importance_names = {
{Importance::UNSPECIFIED, "UNSPECIFIED"},
{Importance::OBLIGATORY, "OBLIGATORY"},
{Importance::RECOMMENDED, "RECOMMENDED"},
{Importance::SUGGESTED, "SUGGESTED"},
{Importance::FIX, "FIX"}};
/**
* The entity role.
*/
enum class Role {
UNSPECIFIED = EntityRole::ENTITY_ROLE_UNSPECIFIED, ///< Unset/None
RECORD_TYPE = EntityRole::ENTITY_ROLE_RECORD_TYPE, ///< RecordType
RECORD = EntityRole::ENTITY_ROLE_RECORD, ///< Record
PROPERTY = EntityRole::ENTITY_ROLE_PROPERTY, ///< Property
FILE = EntityRole::ENTITY_ROLE_FILE, ///< File
};
const std::map<Role, std::string> role_names = {{Role::UNSPECIFIED, "UNSPECIFIED"},
{Role::RECORD_TYPE, "RECORD_TYPE"},
{Role::RECORD, "RECORD"},
{Role::PROPERTY, "PROPERTY"},
{Role::FILE, "FILE"}};
struct FileDescriptor {
FileTransmissionId *file_transmission_id;
ProtoFileDescriptor *wrapped;
@@ -88,9 +127,7 @@ public:
/**
* Return a const reference to the element at the given index.
*/
[[nodiscard]] inline auto at(int index) const -> const T & {
return *mutable_at(index);
}
[[nodiscard]] inline auto at(int index) const -> const T & { return *mutable_at(index); }
/**
* Return a mutable pointer to the element at the given index.
@@ -127,8 +164,7 @@ public:
protected:
RepeatedPtrFieldWrapper(){};
explicit inline RepeatedPtrFieldWrapper(
::google::protobuf::RepeatedPtrField<P> *wrapped)
explicit inline RepeatedPtrFieldWrapper(::google::protobuf::RepeatedPtrField<P> *wrapped)
: wrapped(wrapped){};
/**
@@ -149,7 +185,7 @@ protected:
/**
* Remove the element at the given index.
*/
inline auto remove(int index) -> void {
inline auto Remove(int index) -> void {
this->wrapped->DeleteSubrange(index, 1);
if (cache.count(index) > 0) {
cache.erase(index);
@@ -172,8 +208,8 @@ protected:
private:
class iterator : public std::iterator<std::output_iterator_tag, T> {
public:
explicit iterator(const RepeatedPtrFieldWrapper<T, P> *instance,
int index = 0);
explicit iterator(const RepeatedPtrFieldWrapper<T, P> *instance, int index = 0);
// TODO(henrik) add unit tests
auto operator*() const -> T &;
auto operator++() -> iterator &;
auto operator++(int) -> iterator;
@@ -186,8 +222,8 @@ private:
};
template <class T, class P>
RepeatedPtrFieldWrapper<T, P>::iterator::iterator(
const RepeatedPtrFieldWrapper<T, P> *instance, int index)
RepeatedPtrFieldWrapper<T, P>::iterator::iterator(const RepeatedPtrFieldWrapper<T, P> *instance,
int index)
: current_index(index), instance(instance) {}
template <typename T, typename P>
@@ -211,32 +247,27 @@ auto RepeatedPtrFieldWrapper<T, P>::iterator::operator++(int)
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator!=(
const iterator &rhs) const -> bool {
auto RepeatedPtrFieldWrapper<T, P>::iterator::operator!=(const iterator &rhs) const -> bool {
return this->current_index != rhs.current_index;
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::begin()
-> RepeatedPtrFieldWrapper<T, P>::iterator {
auto RepeatedPtrFieldWrapper<T, P>::begin() -> RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, 0);
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::end()
-> RepeatedPtrFieldWrapper<T, P>::iterator {
auto RepeatedPtrFieldWrapper<T, P>::end() -> RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, size());
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::begin() const
-> const RepeatedPtrFieldWrapper<T, P>::iterator {
auto RepeatedPtrFieldWrapper<T, P>::begin() const -> const RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, 0);
}
template <typename T, typename P>
auto RepeatedPtrFieldWrapper<T, P>::end() const
-> const RepeatedPtrFieldWrapper<T, P>::iterator {
auto RepeatedPtrFieldWrapper<T, P>::end() const -> const RepeatedPtrFieldWrapper<T, P>::iterator {
return RepeatedPtrFieldWrapper<T, P>::iterator(this, size());
}
@@ -264,9 +295,7 @@ public:
*
* The description is intended for a human reader.
*/
[[nodiscard]] inline auto GetDescription() const -> std::string {
return wrapped->description();
}
[[nodiscard]] inline auto GetDescription() const -> std::string { return wrapped->description(); }
friend class Entity;
// TODO(fspreck) Re-enable once we have decided how messages are
@@ -340,8 +369,7 @@ public:
inline auto ToString() const -> const std::string {
google::protobuf::util::JsonOptions options;
std::string out;
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out,
options);
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out, options);
return out;
}
@@ -411,8 +439,7 @@ public:
private:
inline Parents() : RepeatedPtrFieldWrapper(){};
explicit inline Parents(
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent>
*wrapped)
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent> *wrapped)
: RepeatedPtrFieldWrapper(wrapped){};
};
@@ -424,7 +451,9 @@ private:
*/
class Property {
public:
explicit inline Property(ProtoProperty *wrapped) : wrapped(wrapped){};
explicit inline Property(ProtoProperty *other)
: value(Value(other->mutable_value())), data_type(DataType(other->mutable_data_type())),
wrapped(other){};
Property();
/**
@@ -442,11 +471,11 @@ public:
/**
* Return the importance of this property
*/
[[nodiscard]] auto GetImportance() const -> const std::string &;
[[nodiscard]] auto GetImportance() const -> Importance;
/**
* Return the value of this property
*/
[[nodiscard]] auto GetValue() const -> const std::string &;
[[nodiscard]] auto GetValue() const -> const Value &;
/**
* Return the unit of this property
*/
@@ -454,7 +483,7 @@ public:
/**
* Return the datatype of this property
*/
[[nodiscard]] auto GetDatatype() const -> const std::string &;
[[nodiscard]] auto GetDataType() const -> const DataType &;
// TODO(fspreck) Implement these when we have decided how to attach
// messages to properties.
// [[nodiscard]] auto GetErrors() const -> const Messages &;
@@ -476,11 +505,22 @@ public:
/**
* Set the importance of this property.
*/
auto SetImportance(const std::string &importance) -> void;
auto SetImportance(Importance importance) -> void;
/**
* Set the value of this property.
*/
auto SetValue(const std::string &value) -> void;
auto SetValue(const Value &value) -> StatusCode;
auto SetValue(const std::string &value) -> StatusCode;
auto SetValue(const char *value) -> StatusCode;
auto SetValue(const double value) -> StatusCode;
auto SetValue(const std::vector<std::string> &values) -> StatusCode;
auto SetValue(const std::vector<char *> &values) -> StatusCode;
auto SetValue(const std::vector<int64_t> &values) -> StatusCode;
auto SetValue(const std::vector<double> &values) -> StatusCode;
auto SetValue(const std::vector<bool> &values) -> StatusCode;
auto SetValue(const int64_t value) -> StatusCode;
auto SetValue(const bool value) -> StatusCode;
/**
* Set the unit of this property.
*/
@@ -488,7 +528,9 @@ public:
/**
* Set the datatype of this property.
*/
auto SetDatatype(const std::string &datatype) -> void;
auto SetDataType(const DataType &new_data_type) -> StatusCode;
auto SetDataType(const AtomicDataType new_data_type, bool list_type = false) -> StatusCode;
auto SetDataType(const std::string &new_data_type, bool list_type = false) -> StatusCode;
/**
* Return a json string representing this property.
@@ -498,8 +540,7 @@ public:
inline auto ToString() const -> const std::string {
google::protobuf::util::JsonOptions options;
std::string out;
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out,
options);
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out, options);
return out;
}
@@ -510,6 +551,8 @@ public:
private:
static auto CreateProtoProperty() -> ProtoProperty *;
Value value;
DataType data_type;
mutable ProtoProperty *wrapped;
};
@@ -518,10 +561,18 @@ private:
* Container for Properties of Entities.
*
* Should only be instantiated and write-accessed by the owning entity.
*
* Note that iterating over the Property contents only works via references,
* since the Property copy constructor is deliberately disabled:
*
* \code
* // Accessing single properties as reference
* auto &property = my_properties.at(0);
* // Iterating via reference
* for (auto &property : my_properties) {...}
* \endcode
*/
class Properties
: public RepeatedPtrFieldWrapper<Property,
caosdb::entity::v1alpha1::Property> {
class Properties : public RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property> {
public:
~Properties() = default;
friend class Entity;
@@ -529,10 +580,8 @@ public:
private:
inline Properties(){};
explicit inline Properties(
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property>
*wrapped)
: RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property>(
wrapped){};
::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property> *wrapped)
: RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property>(wrapped){};
};
/**
@@ -541,65 +590,59 @@ private:
class Entity {
public:
Entity();
inline Entity(const Entity &original) : Entity(CreateProtoEntity()) {
inline Entity(const Entity &original)
: wrapped(original.wrapped), value(Value(original.wrapped->mutable_value())),
data_type(DataType(original.wrapped->mutable_data_type())) {
this->wrapped->CopyFrom(*original.wrapped);
data_type.wrapped = this->wrapped->mutable_data_type();
value.wrapped = this->wrapped->mutable_value();
properties.wrapped = this->wrapped->mutable_properties();
parents.wrapped = this->wrapped->mutable_parents();
errors.wrapped = CreateMessagesField();
warnings.wrapped = CreateMessagesField();
infos.wrapped = CreateMessagesField();
};
explicit Entity(IdResponse *idResponse);
explicit Entity(ProtoEntity *wrapped) : wrapped(wrapped) {
explicit Entity(IdResponse *id_response);
explicit Entity(ProtoEntity *other)
: wrapped(other), value(Value(other->mutable_value())),
data_type(DataType(other->mutable_data_type())) {
data_type.wrapped = this->wrapped->mutable_data_type();
value.wrapped = this->wrapped->mutable_value();
properties.wrapped = this->wrapped->mutable_properties();
parents.wrapped = this->wrapped->mutable_parents();
errors.wrapped = CreateMessagesField();
warnings.wrapped = CreateMessagesField();
infos.wrapped = CreateMessagesField();
};
explicit inline Entity(EntityResponse *response)
: Entity(response->release_entity()) {
explicit inline Entity(EntityResponse *response) : Entity(response->release_entity()) {
errors.wrapped->Swap(response->mutable_errors());
warnings.wrapped->Swap(response->mutable_warnings());
infos.wrapped->Swap(response->mutable_infos());
};
[[nodiscard]] inline auto GetId() const noexcept -> const std::string & {
return wrapped->id();
};
[[nodiscard]] inline auto HasId() const noexcept -> bool {
return !wrapped->id().empty();
}
[[nodiscard]] inline auto GetId() const noexcept -> const std::string & { return wrapped->id(); };
[[nodiscard]] inline auto HasId() const noexcept -> bool { return !wrapped->id().empty(); }
[[nodiscard]] inline auto GetVersionId() const -> const std::string & {
return wrapped->version().id();
};
[[nodiscard]] inline auto GetRole() const -> const std::string & {
return wrapped->role();
};
[[nodiscard]] inline auto GetName() const -> const std::string & {
return wrapped->name();
};
[[nodiscard]] inline auto GetRole() const -> Role { return static_cast<Role>(wrapped->role()); };
[[nodiscard]] inline auto GetName() const -> const std::string & { return wrapped->name(); };
[[nodiscard]] inline auto GetDescription() const -> const std::string & {
return wrapped->description();
};
[[nodiscard]] inline auto GetDatatype() const -> const std::string & {
return wrapped->datatype();
};
[[nodiscard]] inline auto GetUnit() const -> const std::string & {
return wrapped->unit();
};
[[nodiscard]] inline auto GetValue() const -> const std::string & {
return wrapped->value();
};
[[nodiscard]] inline auto GetDataType() const -> const DataType & { return this->data_type; };
[[nodiscard]] inline auto GetUnit() const -> const std::string & { return wrapped->unit(); };
[[nodiscard]] inline auto GetValue() const -> const Value & { return this->value; };
[[nodiscard]] auto GetParents() const -> const Parents &;
// TODO(henrik) const prevents properties from being changed
// what about an interface that operates on the list directly?
[[nodiscard]] auto GetProperties() const -> const Properties &;
[[nodiscard]] inline auto GetErrors() const -> const Messages & {
return errors;
}
[[nodiscard]] inline auto HasErrors() const -> bool {
return this->errors.wrapped->size() > 0;
}
[[nodiscard]] auto GetWarnings() const -> const Messages & {
return warnings;
}
[[nodiscard]] inline auto GetErrors() const -> const Messages & { return errors; }
[[nodiscard]] inline auto HasErrors() const -> bool { return this->errors.wrapped->size() > 0; }
[[nodiscard]] auto GetWarnings() const -> const Messages & { return warnings; }
[[nodiscard]] inline auto HasWarnings() const -> bool {
return this->warnings.wrapped->size() > 0;
}
@@ -608,22 +651,34 @@ public:
inline auto ToString() const -> const std::string {
google::protobuf::util::JsonOptions options;
std::string out;
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out,
options);
google::protobuf::util::MessageToJsonString(*(this->wrapped), &out, options);
return out;
}
auto SetRole(const std::string &role) -> void;
auto SetRole(Role role) -> void;
auto SetName(const std::string &name) -> void;
/**
* Set the description of this entity.
*/
auto SetDescription(const std::string &description) -> void;
auto SetValue(const std::string &value) -> void;
auto SetValue(const Value &value) -> StatusCode;
auto SetValue(const std::string &value) -> StatusCode;
auto SetValue(const char *value) -> StatusCode;
auto SetValue(const double value) -> StatusCode;
auto SetValue(const std::vector<std::string> &values) -> StatusCode;
auto SetValue(const std::vector<char *> &values) -> StatusCode;
auto SetValue(const std::vector<int64_t> &values) -> StatusCode;
auto SetValue(const std::vector<double> &values) -> StatusCode;
auto SetValue(const std::vector<bool> &values) -> StatusCode;
auto SetValue(const int64_t value) -> StatusCode;
auto SetValue(const bool value) -> StatusCode;
auto SetUnit(const std::string &unit) -> void;
// Currently no references or lists.
auto SetDatatype(const std::string &datatype) -> void;
auto SetDataType(const DataType &new_data_type) -> StatusCode;
auto SetDataType(const AtomicDataType new_data_type, bool list_type = false) -> StatusCode;
auto SetDataType(const std::string &new_data_type, bool list_type = false) -> StatusCode;
auto AppendProperty(const Property &property) -> void;
auto RemoveProperty(int index) -> void;
@@ -636,47 +691,36 @@ public:
auto CopyTo(ProtoEntity *target) -> void;
auto SetFilePath(const std::string &path) -> void;
inline auto HasFile() const -> bool {
return !this->file_descriptor.local_path.empty();
}
auto SetFileTransmissionRegistrationId(const std::string &registration_id)
-> void;
inline auto SetFileTransmissionId(FileTransmissionId *file_transmission_id)
-> void {
inline auto HasFile() const -> bool { return !this->file_descriptor.local_path.empty(); }
auto SetFileTransmissionRegistrationId(const std::string &registration_id) -> void;
inline auto SetFileTransmissionId(FileTransmissionId *file_transmission_id) -> void {
file_transmission_id->set_file_id(GetNextFileId());
file_descriptor.file_transmission_id = file_transmission_id;
}
inline auto GetFileDescriptor() -> FileDescriptor & {
return this->file_descriptor;
}
inline auto GetFileDescriptor() -> FileDescriptor & { return this->file_descriptor; }
inline auto GetLocalPath() const noexcept -> const boost::filesystem::path & {
return this->file_descriptor.local_path;
}
inline auto SetLocalPath(const boost::filesystem::path &local_path) noexcept
-> StatusCode {
if (GetRole() != "File") {
CAOSDB_LOG_WARN(logger_name)
<< "Entity::SetLocalPath failed. This is not a file entity.";
inline auto SetLocalPath(const boost::filesystem::path &local_path) noexcept -> StatusCode {
if (GetRole() != Role::FILE) {
CAOSDB_LOG_WARN(logger_name) << "Entity::SetLocalPath failed. This is not a file entity.";
return StatusCode::NOT_A_FILE_ENTITY;
}
if (!exists(local_path)) {
CAOSDB_LOG_WARN(logger_name)
<< "Entity::SetLocalPath failed. This file does not exists: "
<< local_path.string();
<< "Entity::SetLocalPath failed. This file does not exists: " << local_path.string();
return StatusCode::FILE_DOES_NOT_EXIST_LOCALLY;
}
if (is_directory(local_path)) {
CAOSDB_LOG_WARN(logger_name)
<< "Entity::SetLocalPath failed. This file is a directory: "
<< local_path.string();
<< "Entity::SetLocalPath failed. This file is a directory: " << local_path.string();
return StatusCode::PATH_IS_A_DIRECTORY;
}
CAOSDB_LOG_TRACE(logger_name)
<< "Entity::SetLocalPath(" << local_path.string() << ");";
CAOSDB_LOG_TRACE(logger_name) << "Entity::SetLocalPath(" << local_path.string() << ");";
this->file_descriptor.local_path = local_path;
return StatusCode::SUCCESS;
}
@@ -697,6 +741,8 @@ private:
static auto CreateMessagesField() -> RepeatedPtrField<ProtoMessage> *;
auto SetId(const std::string &id) -> void;
auto SetVersionId(const std::string &id) -> void;
private:
FileDescriptor file_descriptor;
ProtoEntity *wrapped;
Properties properties;
@@ -704,6 +750,8 @@ private:
Messages errors;
Messages warnings;
Messages infos;
Value value;
DataType data_type;
};
} // namespace caosdb::entity
Loading