Skip to content
Snippets Groups Projects
Commit e47cf7f9 authored by Henrik tom Wörden's avatar Henrik tom Wörden
Browse files

Merge branch 'f-parse-string-values' into 'dev'

Workaround to return non-string values, according to the specified DataType.

See merge request !16
parents 0d013f35 e4bcd35d
No related branches found
No related tags found
1 merge request!16Workaround to return non-string values, according to the specified DataType.
Pipeline #12510 passed with warnings
Pipeline: caosdb-cppinttest

#12512

    ...@@ -454,7 +454,9 @@ class Property { ...@@ -454,7 +454,9 @@ class Property {
    public: public:
    explicit inline Property(ProtoProperty *other) explicit inline Property(ProtoProperty *other)
    : value(Value(other->mutable_value())), data_type(DataType(other->mutable_data_type())), : value(Value(other->mutable_value())), data_type(DataType(other->mutable_data_type())),
    wrapped(other){}; wrapped(other) {
    FixValue();
    };
    Property(); Property();
    /** /**
    ...@@ -551,6 +553,12 @@ public: ...@@ -551,6 +553,12 @@ public:
    friend class RepeatedPtrFieldWrapper<Property, ProtoProperty>; friend class RepeatedPtrFieldWrapper<Property, ProtoProperty>;
    private: private:
    /**
    * Workaround until non-string values are supported by the server.
    *
    * Only has an effect if there is a DataType.
    */
    auto FixValue() -> void;
    static auto CreateProtoProperty() -> ProtoProperty *; static auto CreateProtoProperty() -> ProtoProperty *;
    Value value; Value value;
    DataType data_type; DataType data_type;
    ...@@ -602,6 +610,7 @@ public: ...@@ -602,6 +610,7 @@ public:
    errors.wrapped = CreateMessagesField(); errors.wrapped = CreateMessagesField();
    warnings.wrapped = CreateMessagesField(); warnings.wrapped = CreateMessagesField();
    infos.wrapped = CreateMessagesField(); infos.wrapped = CreateMessagesField();
    FixValue();
    }; };
    explicit Entity(IdResponse *id_response); explicit Entity(IdResponse *id_response);
    explicit Entity(ProtoEntity *other) explicit Entity(ProtoEntity *other)
    ...@@ -614,11 +623,13 @@ public: ...@@ -614,11 +623,13 @@ public:
    errors.wrapped = CreateMessagesField(); errors.wrapped = CreateMessagesField();
    warnings.wrapped = CreateMessagesField(); warnings.wrapped = CreateMessagesField();
    infos.wrapped = CreateMessagesField(); infos.wrapped = CreateMessagesField();
    FixValue();
    }; };
    explicit inline Entity(EntityResponse *response) : Entity(response->release_entity()) { explicit inline Entity(EntityResponse *response) : Entity(response->release_entity()) {
    errors.wrapped->Swap(response->mutable_errors()); errors.wrapped->Swap(response->mutable_errors());
    warnings.wrapped->Swap(response->mutable_warnings()); warnings.wrapped->Swap(response->mutable_warnings());
    infos.wrapped->Swap(response->mutable_infos()); infos.wrapped->Swap(response->mutable_infos());
    FixValue();
    }; };
    [[nodiscard]] inline auto GetId() const noexcept -> const std::string & { return wrapped->id(); }; [[nodiscard]] inline auto GetId() const noexcept -> const std::string & { return wrapped->id(); };
    ...@@ -744,6 +755,13 @@ private: ...@@ -744,6 +755,13 @@ private:
    auto SetId(const std::string &id) -> void; auto SetId(const std::string &id) -> void;
    auto SetVersionId(const std::string &id) -> void; auto SetVersionId(const std::string &id) -> void;
    /**
    * Workaround until non-string values are supported by the server.
    *
    * Only has an effect if there is a DataType.
    */
    auto FixValue() -> void;
    private: private:
    FileDescriptor file_descriptor; FileDescriptor file_descriptor;
    ProtoEntity *wrapped; ProtoEntity *wrapped;
    ......
    ...@@ -20,10 +20,12 @@ ...@@ -20,10 +20,12 @@
    * *
    */ */
    #include "caosdb/entity.h" #include "caosdb/entity.h"
    #include "caosdb/data_type.h" // for DataType #include "caosdb/data_type.h" // for DataType
    #include "caosdb/entity/v1alpha1/main.pb.h" // for Messages #include "caosdb/entity/v1alpha1/main.pb.h" // for Messages
    #include "caosdb/protobuf_helper.h" // for get_arena #include "caosdb/exceptions.h"
    #include "caosdb/value.h" // for Value #include "caosdb/protobuf_helper.h" // for get_arena
    #include "caosdb/value.h" // for Value
    #include <boost/algorithm/string.hpp>
    #include <google/protobuf/arena.h> // for Arena #include <google/protobuf/arena.h> // for Arena
    #include <google/protobuf/generated_message_util.h> // for Arena::Create... #include <google/protobuf/generated_message_util.h> // for Arena::Create...
    #include <new> // for operator new #include <new> // for operator new
    ...@@ -42,6 +44,12 @@ using google::protobuf::Arena; ...@@ -42,6 +44,12 @@ using google::protobuf::Arena;
    Messages::~Messages() = default; Messages::~Messages() = default;
    // Forward declarations ///////////////////////////////////////////////////////
    template <typename E> auto FixValueImpl(E *ent) -> void;
    // Parent /////////////////////////////////////////////////////////////////////
    Parent::Parent() : wrapped(Parent::CreateProtoParent()) { Parent::Parent() : wrapped(Parent::CreateProtoParent()) {
    // TODO(fspreck) Re-enable once we have decided how to attach // TODO(fspreck) Re-enable once we have decided how to attach
    // messages to parents. // messages to parents.
    ...@@ -66,7 +74,7 @@ auto Parent::SetId(const std::string &id) -> void { this->wrapped->set_id(id); } ...@@ -66,7 +74,7 @@ auto Parent::SetId(const std::string &id) -> void { this->wrapped->set_id(id); }
    return this->wrapped->description(); return this->wrapped->description();
    } }
    Property::Property() : Property(Property::CreateProtoProperty()) {} Property::Property() : Property(Property::CreateProtoProperty()) { FixValue(); }
    auto Property::CreateProtoProperty() -> ProtoProperty * { auto Property::CreateProtoProperty() -> ProtoProperty * {
    return Arena::CreateMessage<ProtoProperty>(get_arena()); return Arena::CreateMessage<ProtoProperty>(get_arena());
    ...@@ -152,6 +160,9 @@ auto Property::SetDataType(const std::string &new_data_type, bool list_type) -> ...@@ -152,6 +160,9 @@ auto Property::SetDataType(const std::string &new_data_type, bool list_type) ->
    return SetDataType(DataType(new_data_type, list_type)); return SetDataType(DataType(new_data_type, list_type));
    } }
    auto Property::FixValue() -> void { FixValueImpl(this); }
    // Entity /////////////////////////////////////////////////////////////////////
    [[nodiscard]] auto Entity::GetParents() const -> const Parents & { return parents; } [[nodiscard]] auto Entity::GetParents() const -> const Parents & { return parents; }
    auto Entity::AppendParent(const Parent &parent) -> void { this->parents.Append(parent); } auto Entity::AppendParent(const Parent &parent) -> void { this->parents.Append(parent); }
    ...@@ -174,9 +185,10 @@ Entity::Entity(IdResponse *id_response) : Entity() { ...@@ -174,9 +185,10 @@ Entity::Entity(IdResponse *id_response) : Entity() {
    this->errors.wrapped->Swap(id_response->mutable_errors()); this->errors.wrapped->Swap(id_response->mutable_errors());
    this->warnings.wrapped->Swap(id_response->mutable_warnings()); this->warnings.wrapped->Swap(id_response->mutable_warnings());
    this->infos.wrapped->Swap(id_response->mutable_infos()); this->infos.wrapped->Swap(id_response->mutable_infos());
    FixValue();
    } }
    Entity::Entity() : Entity(Entity::CreateProtoEntity()) {} Entity::Entity() : Entity(Entity::CreateProtoEntity()) { FixValue(); }
    auto Entity::CreateMessagesField() -> RepeatedPtrField<ProtoMessage> * { auto Entity::CreateMessagesField() -> RepeatedPtrField<ProtoMessage> * {
    return Arena::CreateMessage<RepeatedPtrField<ProtoMessage>>(get_arena()); return Arena::CreateMessage<RepeatedPtrField<ProtoMessage>>(get_arena());
    ...@@ -256,4 +268,98 @@ auto Entity::SetFilePath(const std::string &path) -> void { ...@@ -256,4 +268,98 @@ auto Entity::SetFilePath(const std::string &path) -> void {
    this->wrapped->mutable_file_descriptor()->set_path(path); this->wrapped->mutable_file_descriptor()->set_path(path);
    } }
    auto Entity::FixValue() -> void { FixValueImpl(this); }
    // Utility functions //////////////////////////////////////////////////////////
    template <typename E> auto FixValueImpl(E *ent) -> void {
    const auto &dtype = ent->GetDataType();
    const auto &value = ent->GetValue();
    auto new_value = Value();
    if (value.IsNull() || !value.IsString()) { // Don't treat NULL and non-string values.
    return;
    }
    if (value.IsList()) { // Also don't treat empty or non-string lists.
    const auto &list = value.AsList();
    if (list.empty() || !list[0].IsString()) {
    return;
    }
    }
    auto atype = AtomicDataType::UNSPECIFIED;
    if (dtype.IsList()) { // List Datatype
    if (!value.IsList()) {
    throw caosdb::exceptions::Exception(StatusCode::OTHER_CLIENT_ERROR,
    "DataType is list, but Value is scalar.");
    }
    auto &list_type = dtype.AsList();
    atype = list_type.GetAtomicDataType();
    if (!list_type.IsListOfAtomic() // References, strings etc. need no treatment.
    || atype == AtomicDataType::UNSPECIFIED || atype == AtomicDataType::TEXT ||
    atype == AtomicDataType::DATETIME) {
    return;
    }
    if (atype == AtomicDataType::DOUBLE) {
    std::vector<double> data;
    for (auto &d : value.AsList()) {
    data.push_back(std::stod(d.AsString()));
    }
    new_value = Value(data);
    } else if (atype == AtomicDataType::INTEGER) {
    std::vector<int64_t> data;
    for (auto &d : value.AsList()) {
    data.push_back(std::stol(d.AsString()));
    }
    new_value = Value(data);
    } else if (atype == AtomicDataType::BOOLEAN) {
    std::vector<bool> data;
    for (auto &d : value.AsList()) {
    const auto &bool_value = d.AsString();
    if (boost::to_upper_copy(bool_value) == "TRUE") {
    data.push_back(true);
    } else if (boost::to_upper_copy(bool_value) == "FALSE") {
    data.push_back(false);
    } else {
    throw caosdb::exceptions::Exception(StatusCode::OTHER_CLIENT_ERROR,
    "Boolean value is neither true nor false.");
    }
    }
    new_value = Value(data);
    } else {
    std::cout << "Unhandled datatype: " << ent->ToString() << std::endl;
    throw std::logic_error("Unhandled datatype");
    }
    } else { // Scalar Datatype
    if (value.IsList()) {
    throw caosdb::exceptions::Exception(StatusCode::OTHER_CLIENT_ERROR,
    "Value is list, but DataType is scalar.");
    }
    atype = dtype.AsAtomic();
    if (!dtype.IsAtomic() // References, strings etc. need no treatment.
    || atype == AtomicDataType::UNSPECIFIED || atype == AtomicDataType::TEXT ||
    atype == AtomicDataType::DATETIME) {
    return;
    }
    if (atype == AtomicDataType::DOUBLE) {
    new_value = Value(std::stod(value.AsString()));
    } else if (atype == AtomicDataType::INTEGER) {
    new_value = Value(std::stol(value.AsString()));
    } else if (atype == AtomicDataType::BOOLEAN) {
    const auto &bool_value = value.AsString();
    if (boost::to_upper_copy(bool_value) == "TRUE") {
    new_value = Value(true);
    } else if (boost::to_upper_copy(bool_value) == "FALSE") {
    new_value = Value(false);
    } else {
    throw caosdb::exceptions::Exception(StatusCode::OTHER_CLIENT_ERROR,
    "Boolean value is neither true nor false.");
    }
    } else {
    std::cout << "Unhandled datatype: " << ent->ToString() << std::endl;
    throw std::logic_error("Unhandled datatype");
    }
    }
    ent->SetValue(new_value);
    }
    } // namespace caosdb::entity } // namespace caosdb::entity
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment