diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index e6b92d53d6ddb1aa8360af55f6438d23eafff7ae..d11f2efd4a1619929ed3a9a602e403d4d642c240 100644 --- a/include/caosdb/data_type.h +++ b/include/caosdb/data_type.h @@ -40,6 +40,7 @@ using ProtoReferenceDataType = caosdb::entity::v1alpha1::ReferenceDataType; using DataTypeCase = caosdb::entity::v1alpha1::DataType::DataTypeCase; using ListDataTypeCase = caosdb::entity::v1alpha1::ListDataType::ListDataTypeCase; using caosdb::utility::ProtoMessageWrapper; +using caosdb::utility::ScalarFieldWrapper; class Entity; class Property; @@ -68,7 +69,7 @@ const std::map<AtomicDataType, std::string> atomicdatatype_names = { class DataType; class ListDataType; -class ReferenceDataType : public ProtoMessageWrapper<ProtoDataType> { +class ReferenceDataType : public ScalarFieldWrapper<ProtoDataType> { public: [[nodiscard]] inline auto GetName() const noexcept -> const std::string & { // is list of reference? @@ -91,11 +92,11 @@ protected: inline static auto Create(ProtoDataType *wrapped) -> std::unique_ptr<ReferenceDataType> { return std::unique_ptr<ReferenceDataType>(new ReferenceDataType(wrapped)); } - ReferenceDataType() : ProtoMessageWrapper<ProtoDataType>() {} - ReferenceDataType(ProtoDataType *wrapped) : ProtoMessageWrapper<ProtoDataType>(wrapped) {} + ReferenceDataType() : ScalarFieldWrapper<ProtoDataType>() {} + ReferenceDataType(ProtoDataType *wrapped) : ScalarFieldWrapper<ProtoDataType>(wrapped) {} }; -class ListDataType : public ProtoMessageWrapper<ProtoDataType> { +class ListDataType : public ScalarFieldWrapper<ProtoDataType> { public: [[nodiscard]] inline auto IsListOfReference() const noexcept -> bool { return this->wrapped->list_data_type().list_data_type_case() == @@ -130,17 +131,17 @@ protected: inline static auto Create(ProtoDataType *wrapped) -> std::unique_ptr<ListDataType> { return std::unique_ptr<ListDataType>(new ListDataType(wrapped)); } - ListDataType() : ProtoMessageWrapper<ProtoDataType>() {} + ListDataType() : ScalarFieldWrapper<ProtoDataType>() {} - ListDataType(ProtoDataType *wrapped) : ProtoMessageWrapper<ProtoDataType>(wrapped) {} + ListDataType(ProtoDataType *wrapped) : ScalarFieldWrapper<ProtoDataType>(wrapped) {} mutable std::unique_ptr<ReferenceDataType> reference_data_type; }; -class DataType : public ProtoMessageWrapper<ProtoDataType> { +class DataType : public ScalarFieldWrapper<ProtoDataType> { public: - DataType(ProtoDataType *wrapped) : ProtoMessageWrapper<ProtoDataType>(wrapped) {} - DataType() : ProtoMessageWrapper<ProtoDataType>() {} + DataType(ProtoDataType *wrapped) : ScalarFieldWrapper<ProtoDataType>(wrapped) {} + DataType() : ScalarFieldWrapper<ProtoDataType>() {} /** * Create an AtomicDataType typed DataType. For references, use the std::string constructor. */ diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h index de6d4928771af83edca68d748d73b58f690a35f7..c066c7e2624afa5b033c9c3795b289238fd8b5f3 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -53,6 +53,7 @@ #include <stdexcept> // for out_of_range #include <string> // for string, basic... #include <vector> // for vector +#include <utility> // for move namespace caosdb::entity { using boost::filesystem::exists; @@ -69,6 +70,7 @@ using caosdb::StatusCode; using caosdb::entity::v1alpha1::EntityResponse; using caosdb::entity::v1alpha1::FileTransmissionId; using caosdb::utility::get_arena; +using caosdb::utility::ProtoMessageWrapper; using ::google::protobuf::RepeatedPtrField; using google::protobuf::RepeatedPtrField; @@ -118,14 +120,15 @@ struct FileDescriptor { * * This is a list-like class. */ -template <typename T, typename P> class RepeatedPtrFieldWrapper { +template <typename T, typename P> +class RepeatedPtrFieldWrapper : public ProtoMessageWrapper<RepeatedPtrField<P>> { class iterator; public: /** * Return the current size of the container. */ - [[nodiscard]] inline auto size() const -> int { return wrapped->size(); } + [[nodiscard]] inline auto size() const -> int { return this->wrapped->size(); } /** * Return a const reference to the element at the given index. */ @@ -139,10 +142,11 @@ public: throw std::out_of_range("Container has size " + std::to_string(size())); } if (cache.count(index) == 0) { - cache.emplace(index, T(&(wrapped->at(index)))); + cache.emplace(std::move(index), std::move(T(this->wrapped->Mutable(index)))); } return &(cache.at(index)); } + /** * Return iterator positioned at the beginning of the list. */ @@ -164,10 +168,26 @@ public: virtual ~RepeatedPtrFieldWrapper(){}; + inline auto ToString() const noexcept -> const std::string override { + if (this->size() == 0) { + return "[]"; + } + std::string result("["); + for (int i = 0; i < this->size(); i++) { + CAOSDB_DEBUG_MESSAGE_STRING(this->wrapped->at(i), next); + result += next; + if (i < this->size() - 1) { + result += ","; + } + } + + return result.append(std::string("]")); + } + protected: - RepeatedPtrFieldWrapper(){}; - explicit inline RepeatedPtrFieldWrapper(::google::protobuf::RepeatedPtrField<P> *wrapped) - : wrapped(wrapped){}; + RepeatedPtrFieldWrapper() : ProtoMessageWrapper<RepeatedPtrField<P>>(){}; + explicit inline RepeatedPtrFieldWrapper(RepeatedPtrField<P> *wrapped) + : ProtoMessageWrapper<RepeatedPtrField<P>>(wrapped) {} /** * Append an element. This adds the element to the end of the wrapped list @@ -175,13 +195,7 @@ protected: */ inline auto Append(const T &element) -> void { auto *destination = this->wrapped->Add(); - destination->Swap(element.wrapped); - - // Clear the originally wrapped object and return it to the Arena - element.wrapped->Clear(); - - // set the pointer to the new object which is owned by the RepeatedPtrField - element.wrapped = destination; + destination->CopyFrom(*element.wrapped); } /** @@ -189,24 +203,24 @@ protected: */ inline auto Remove(int index) -> void { this->wrapped->DeleteSubrange(index, 1); - if (cache.count(index) > 0) { - cache.erase(index); - } - - // shift all indices in the cache above index (such that the values do not - // get deleted/copied because this could destroy pointers (c-interface). - for (int i = index + 1; i < size(); i++) { - if (cache.count(i) > 0) { - auto handle = cache.extract(i); - handle.key()--; - cache.insert(std::move(handle)); - } - } + cache.clear(); + // if (cache.count(index) > 0) { + // cache.erase(index); + //} + + //// shift all indices in the cache above index (such that the values do not + //// get deleted/copied because this could destroy pointers (c-interface). + // for (int i = index + 1; i < size(); i++) { + // if (cache.count(i) > 0) { + // auto handle = cache.extract(i); + // handle.key()--; + // cache.insert(std::move(handle)); + //} + //} } inline auto Clear() noexcept -> void { this->wrapped->Clear(); } - ::google::protobuf::RepeatedPtrField<P> *wrapped; mutable std::map<int, T> cache; private: @@ -282,8 +296,9 @@ auto RepeatedPtrFieldWrapper<T, P>::end() const -> const RepeatedPtrFieldWrapper * A Message object can be thought of as kinf of a generalized error object in * other frameworks. Please have a look at MessageCodes for more details. */ -class Message { +class Message : public ScalarFieldWrapper<ProtoMessage> { public: + // inline Message() {}; /** * Get the code of this message. * @@ -310,9 +325,7 @@ public: friend class RepeatedPtrFieldWrapper<Message, ProtoMessage>; private: - explicit inline Message(ProtoMessage *wrapped) : wrapped(wrapped){}; - - ProtoMessage *wrapped; + explicit inline Message(ProtoMessage *wrapped) : ScalarFieldWrapper<ProtoMessage>(wrapped){}; }; /** @@ -338,10 +351,10 @@ private: * words, this class wraps a protobuf message and provides getter and setter * methods. */ -class Parent { +class Parent : public ScalarFieldWrapper<ProtoParent> { public: - explicit inline Parent(ProtoParent *wrapped) : wrapped(wrapped){}; - Parent(); + explicit inline Parent(ProtoParent *wrapped) : ScalarFieldWrapper<ProtoParent>(wrapped){}; + Parent() : ScalarFieldWrapper<ProtoParent>(){}; /** * Return the id of the parent entity. @@ -365,19 +378,6 @@ public: */ auto SetName(const std::string &name) -> void; - /** - * Return a json string representing this parent. - * - * This is intended for debugging. - */ - inline auto ToString() const -> const std::string { - google::protobuf::util::JsonPrintOptions options; - options.add_whitespace = true; - std::string out; - google::protobuf::util::MessageToJsonString(*(this->wrapped), &out, options); - return out; - } - // TODO(fspreck) Finish the following implementations once we have // decided how to attach messages to parents. // /** @@ -410,22 +410,6 @@ public: friend class RepeatedPtrFieldWrapper<Parent, ProtoParent>; private: - /** - * Return an empty protobuf message pointer. - * - * This function is called by the default constructor of the - * caosdb::entity::Parent class and the protobuf message is used as the - * storage-backend for the new Parent instance. - * - * An 'Arena' takes care of the the memory management. Don't try to delete - * this. - */ - static auto CreateProtoParent() -> ProtoParent *; - - /** - * Message which serves as storage backend. - */ - mutable ProtoParent *wrapped; // Messages errors; // Messages warnings; // Messages infos; @@ -454,12 +438,37 @@ private: * This is a property which belongs to another entity. Don't confuse it with * an Entity with the "Property" role. */ -class Property { +class Property : public ScalarFieldWrapper<ProtoProperty> { public: + /** + * Copy constructor. + */ + inline Property(const Property &other) + : Property(ProtoMessageWrapper<ProtoProperty>::CopyProtoMessage(other.wrapped)) { + CAOSDB_LOG_TRACE(logger_name) << "Property::Property(const Property &) " + << "- Copy constructor"; + }; + + /** + * Move constructor. + */ + inline Property(Property &&other) : Property() { + CAOSDB_LOG_TRACE(logger_name) << "Property::Property(Property &&) " + << "- Move constructor"; + this->wrapped = std::move(other.wrapped); + this->value.wrapped = this->wrapped->mutable_value(); + this->data_type.wrapped = this->wrapped->mutable_data_type(); + + other.data_type.wrapped = nullptr; + other.value.wrapped = nullptr; + } + explicit inline Property(ProtoProperty *other) - : value(Value(other->mutable_value())), data_type(DataType(other->mutable_data_type())), - wrapped(other){}; - Property(); + : ScalarFieldWrapper<ProtoProperty>(other), value(this->wrapped->mutable_value()), + data_type(this->wrapped->mutable_data_type()){}; + inline Property() + : ScalarFieldWrapper<ProtoProperty>(), value(this->wrapped->mutable_value()), + data_type(this->wrapped->mutable_data_type()){}; /** * Return the id of this property @@ -541,16 +550,27 @@ public: auto SetDataType(const std::string &new_data_type, bool list_type = false) -> StatusCode; /** - * Return a json string representing this property. - * - * This is intended for debugging + * Copy assignment operator. */ - inline auto ToString() const -> const std::string { - google::protobuf::util::JsonPrintOptions options; - options.add_whitespace = true; - std::string out; - google::protobuf::util::MessageToJsonString(*(this->wrapped), &out, options); - return out; + auto operator=(const Property &other) -> Property & { + CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(const Property &) " + << "- Copy assignment operator"; + this->wrapped->CopyFrom(*other.wrapped); + this->value = Value(this->wrapped->mutable_value()); + this->data_type = DataType(this->wrapped->mutable_data_type()); + return *this; + } + + /** + * Move assignment operator. + */ + auto operator=(Property &&other) -> Property & { + CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(Property &&) " + << "- Move assignment operator"; + this->wrapped = std::move(other.wrapped); + this->value = std::move(other.value); + this->data_type = std::move(other.data_type); + return *this; } friend class Entity; @@ -558,11 +578,8 @@ public: friend class RepeatedPtrFieldWrapper<Property, ProtoProperty>; private: - static auto CreateProtoProperty() -> ProtoProperty *; Value value; DataType data_type; - - mutable ProtoProperty *wrapped; }; /** @@ -580,16 +597,15 @@ private: * for (auto &property : my_properties) {...} * \endcode */ -class Properties : public RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property> { +class Properties : public RepeatedPtrFieldWrapper<Property, ProtoProperty> { public: ~Properties() = default; friend class Entity; private: inline Properties(){}; - explicit inline Properties( - ::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Property> *wrapped) - : RepeatedPtrFieldWrapper<Property, caosdb::entity::v1alpha1::Property>(wrapped){}; + explicit inline Properties(RepeatedPtrField<ProtoProperty> *wrapped) + : RepeatedPtrFieldWrapper<Property, ProtoProperty>(wrapped){}; }; /** diff --git a/include/caosdb/protobuf_helper.h b/include/caosdb/protobuf_helper.h index 9a73c0d726b25a792232530d0e01852d9c0b2e99..4e0114ab4f71e64f14c0693704351487deec8dca 100644 --- a/include/caosdb/protobuf_helper.h +++ b/include/caosdb/protobuf_helper.h @@ -22,16 +22,17 @@ #ifndef CAOSDB_PROTOBUF_HELPER_H #define CAOSDB_PROTOBUF_HELPER_H -#include "caosdb/status_code.h" // for StatusCode, SUCCESS -#include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/extension_set.h> // for Arena -#include <google/protobuf/util/json_util.h> // for JsonOptions, MessageToJs... -#include <string> // for string +#include "caosdb/status_code.h" // for StatusCode, SUCCESS +#include <google/protobuf/arena.h> // for Arena +#include <google/protobuf/generated_message_util.h> // for Arena +#include <google/protobuf/util/json_util.h> // for JsonOptions, MessageToJs... +#include <string> // for string #define CAOSDB_DEBUG_MESSAGE_STRING(message, out) \ std::string out; \ { \ google::protobuf::util::JsonOptions options; \ + options.add_whitespace = true; \ google::protobuf::util::MessageToJsonString(message, &out, options); \ } @@ -43,8 +44,8 @@ auto get_arena() -> Arena *; template <typename P> class ProtoMessageWrapper { public: - ProtoMessageWrapper(const ProtoMessageWrapper &other) = default; - inline auto CopyFrom(const ProtoMessageWrapper &other) noexcept -> StatusCode { + ProtoMessageWrapper(const ProtoMessageWrapper<P> &other) = default; + inline auto CopyFrom(const ProtoMessageWrapper<P> &other) noexcept -> StatusCode { this->wrapped->CopyFrom(*other.wrapped); return StatusCode::SUCCESS; } @@ -52,16 +53,51 @@ public: /** * Return a json representation of this object. */ - inline auto ToString() const noexcept -> const std::string { - CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out) - return out; + virtual inline auto ToString() const noexcept -> const std::string = 0; + //{ + // CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out) + // return out; + //} + + /** + * Return true if the underlying Protobuf messages have the same + * serialization. + */ + inline auto operator==(const ProtoMessageWrapper<P> &other) const noexcept -> bool { + return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString(); + } + + /** + * Return true if the underlying Protobuf messages have a different + * serialization. + */ + inline auto operator!=(const ProtoMessageWrapper<P> &other) const noexcept -> bool { + return this->wrapped->SerializeAsString() != other.wrapped->SerializeAsString(); } protected: + inline static auto CopyProtoMessage(P *wrapped) -> P * { + P *copy = Arena::CreateMessage<P>(get_arena()); + copy->CopyFrom(*wrapped); + return copy; + } ProtoMessageWrapper() : ProtoMessageWrapper(Arena::CreateMessage<P>(get_arena())) {} ProtoMessageWrapper(P *wrapped) : wrapped(wrapped) {} P *wrapped; }; +template <typename P> class ScalarFieldWrapper : public ProtoMessageWrapper<P> { +public: + inline ScalarFieldWrapper() = default; + inline ScalarFieldWrapper(P *wrapped) : ProtoMessageWrapper<P>(wrapped) {} + /** + * Return a json representation of this object. + */ + inline auto ToString() const noexcept -> const std::string override { + CAOSDB_DEBUG_MESSAGE_STRING(*this->wrapped, out) + return out; + } +}; + } // namespace caosdb::utility #endif diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h index 0699e14b28ae6e4b44ff495695c843ffa2e8d01f..68040dc663a378e58840281acfd3f8a659881bc8 100644 --- a/include/caosdb/transaction.h +++ b/include/caosdb/transaction.h @@ -35,7 +35,6 @@ #include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_E... #include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_S... #include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/generated_message_util.h> // for CreateMessage... #include <google/protobuf/util/json_util.h> // for MessageToJsonS... #include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue #include <algorithm> // for max diff --git a/include/caosdb/value.h b/include/caosdb/value.h index fd70c4f837dccaeedca0c9801c2518eb111af398..f4f8f3b91851070818a85d6272eb0c16f5748a8a 100644 --- a/include/caosdb/value.h +++ b/include/caosdb/value.h @@ -31,7 +31,7 @@ #include <vector> // for vector #define LIST_VALUE_CONSTRUCTOR(TYPE, SETTER) \ - explicit inline Value(const std::vector<TYPE> &values) : ProtoMessageWrapper<ProtoValue>() { \ + explicit inline Value(const std::vector<TYPE> &values) : ScalarFieldWrapper<ProtoValue>() { \ for (const auto &value : values) { \ this->wrapped->mutable_list_values()->add_values()->SETTER(value); \ } \ @@ -40,6 +40,7 @@ namespace caosdb::entity { using caosdb::utility::get_arena; using caosdb::utility::ProtoMessageWrapper; +using caosdb::utility::ScalarFieldWrapper; using google::protobuf::Arena; using ProtoSpecialValue = caosdb::entity::v1alpha1::SpecialValue; using ProtoValue = caosdb::entity::v1alpha1::Value; @@ -167,7 +168,7 @@ protected: inline AbstractValue::~AbstractValue() {} -class ScalarValue : public AbstractValue, public ProtoMessageWrapper<ProtoScalarValue> { +class ScalarValue : public AbstractValue, public ScalarFieldWrapper<ProtoScalarValue> { public: /** * Destructor. @@ -203,7 +204,7 @@ public: } inline ScalarValue(ProtoScalarValue *wrapped) - : ProtoMessageWrapper<ProtoScalarValue>(wrapped), proto_value(nullptr) {} + : ScalarFieldWrapper<ProtoScalarValue>(wrapped), proto_value(nullptr) {} [[nodiscard]] inline auto IsNull() const noexcept -> bool { return (this->wrapped->scalar_value_case() == ScalarValueCase::kSpecialValue && @@ -248,7 +249,7 @@ public: return empty_collection; } [[nodiscard]] inline auto ToString() const noexcept -> const std::string { - return ProtoMessageWrapper::ToString(); + return ScalarFieldWrapper::ToString(); } friend class Value; @@ -261,13 +262,13 @@ protected: } return this->proto_value; }; - inline ScalarValue() : ProtoMessageWrapper<ProtoScalarValue>(), proto_value(nullptr) {} + inline ScalarValue() : ScalarFieldWrapper<ProtoScalarValue>(), proto_value(nullptr) {} private: mutable ProtoValue *proto_value; }; -class Value : public AbstractValue, public ProtoMessageWrapper<ProtoValue> { +class Value : public AbstractValue, public ScalarFieldWrapper<ProtoValue> { public: /** * Copy constructor. @@ -281,7 +282,7 @@ public: * Destructor. */ inline ~Value() {} - inline Value() : ProtoMessageWrapper<ProtoValue>() { + inline Value() : ScalarFieldWrapper<ProtoValue>() { // has NULL_VALUE now } explicit inline Value(const ScalarValue &value) : Value() { @@ -290,21 +291,21 @@ public: explicit inline Value(const AbstractValue &value) : Value() { this->wrapped->CopyFrom(*value.GetProtoValue()); } - explicit inline Value(ProtoValue *wrapped) : ProtoMessageWrapper<ProtoValue>(wrapped) {} - explicit inline Value(const std::string &value) : ProtoMessageWrapper<ProtoValue>() { + explicit inline Value(ProtoValue *wrapped) : ScalarFieldWrapper<ProtoValue>(wrapped) {} + explicit inline Value(const std::string &value) : ScalarFieldWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_string_value(value); } - explicit inline Value(const char *value) : ProtoMessageWrapper<ProtoValue>() { + explicit inline Value(const char *value) : ScalarFieldWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_string_value(std::string(value)); } - explicit inline Value(double value) : ProtoMessageWrapper<ProtoValue>() { + explicit inline Value(double value) : ScalarFieldWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_double_value(value); } - explicit inline Value(int64_t value) : ProtoMessageWrapper<ProtoValue>() { + explicit inline Value(int64_t value) : ScalarFieldWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_integer_value(value); } explicit inline Value(int value) : Value(static_cast<int64_t>(value)) {} - explicit inline Value(bool value) : ProtoMessageWrapper<ProtoValue>() { + explicit inline Value(bool value) : ScalarFieldWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_boolean_value(value); } @@ -387,14 +388,6 @@ public: return *(this->collection_values); } - /** - * Return true if the underlying Protobuf messages have the same - * serialization. - */ - inline auto operator==(const Value &other) const noexcept -> bool { - return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString(); - } - /** * Copy assignment operator. */ @@ -416,7 +409,7 @@ public: } [[nodiscard]] inline auto ToString() const noexcept -> const std::string { - return ProtoMessageWrapper::ToString(); + return ScalarFieldWrapper::ToString(); } friend class Entity; diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp index c409a46e8ad37aee93b67b2a36109b1fe8f8c640..37d7b3ce6ebdb11d8e0ce7cf8f2a03c1c090c3f6 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -42,18 +42,6 @@ Messages::~Messages() = default; // Parent ///////////////////////////////////////////////////////////////////// -Parent::Parent() : wrapped(Parent::CreateProtoParent()) { - // TODO(fspreck) Re-enable once we have decided how to attach - // messages to parents. - // errors.wrapped = this->wrapped->mutable_errors(); - // warnings.wrapped = this->wrapped->mutable_warnings(); - // infos.wrapped = this->wrapped->mutable_infos(); -} - -auto Parent::CreateProtoParent() -> ProtoParent * { - return Arena::CreateMessage<ProtoParent>(get_arena()); -} - auto Parent::SetName(const std::string &name) -> void { this->wrapped->set_name(name); } auto Parent::SetId(const std::string &id) -> void { this->wrapped->set_id(id); } @@ -66,11 +54,7 @@ auto Parent::SetId(const std::string &id) -> void { this->wrapped->set_id(id); } return this->wrapped->description(); } -Property::Property() : Property(Property::CreateProtoProperty()) {} - -auto Property::CreateProtoProperty() -> ProtoProperty * { - return Arena::CreateMessage<ProtoProperty>(get_arena()); -} +// Property /////////////////////////////////////////////////////////////////// [[nodiscard]] auto Property::GetId() const -> const std::string & { return this->wrapped->id(); } diff --git a/src/caosdb/file_transmission/download_request_handler.cpp b/src/caosdb/file_transmission/download_request_handler.cpp index a157754b337e798fc4c144cb44abea153053ed79..cbe79e93eb89261d1d85484cf39f4ad5deecba18 100644 --- a/src/caosdb/file_transmission/download_request_handler.cpp +++ b/src/caosdb/file_transmission/download_request_handler.cpp @@ -59,17 +59,16 @@ #include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_... #include <exception> // IWYU pragma: keep // IWYU pragma: no_include <bits/exception.h> -#include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/generated_message_util.h> // for Arena -#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncRe... -#include <grpcpp/impl/codegen/client_context.h> // for ClientContext -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <grpcpp/impl/codegen/status.h> // for Status -#include <grpcpp/impl/codegen/status_code_enum.h> // for OK, UNAUTHENT... -#include <iostream> // for char_traits -#include <stdexcept> // for runtime_error -#include <string> // for string, opera... -#include <utility> // for move +#include <google/protobuf/arena.h> // for Arena +#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncRe... +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue +#include <grpcpp/impl/codegen/status.h> // for Status +#include <grpcpp/impl/codegen/status_code_enum.h> // for OK, UNAUTHENT... +#include <iostream> // for char_traits +#include <stdexcept> // for runtime_error +#include <string> // for string, opera... +#include <utility> // for move namespace caosdb::transaction { using caosdb::StatusCode; diff --git a/src/caosdb/file_transmission/upload_request_handler.cpp b/src/caosdb/file_transmission/upload_request_handler.cpp index cc8170249b932fb8bfa572fd345746bbbacc16af..bc74391753a0c7c3dce01f80d8fa67acc9e782cd 100644 --- a/src/caosdb/file_transmission/upload_request_handler.cpp +++ b/src/caosdb/file_transmission/upload_request_handler.cpp @@ -61,17 +61,16 @@ #include <cstdint> // for uint64_t #include <exception> // IWYU pragma: keep // IWYU pragma: no_include <bits/exception.h> -#include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/generated_message_util.h> // for CreateMessage... -#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncWr... -#include <grpcpp/impl/codegen/call_op_set.h> // for WriteOptions -#include <grpcpp/impl/codegen/client_context.h> // for ClientContext -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <grpcpp/impl/codegen/status.h> // for Status -#include <grpcpp/impl/codegen/status_code_enum.h> // for OK, UNAUTHENT... -#include <iostream> // for endl, streamsize -#include <string> // for basic_string -#include <utility> // for move +#include <google/protobuf/arena.h> // for Arena +#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncWr... +#include <grpcpp/impl/codegen/call_op_set.h> // for WriteOptions +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue +#include <grpcpp/impl/codegen/status.h> // for Status +#include <grpcpp/impl/codegen/status_code_enum.h> // for OK, UNAUTHENT... +#include <iostream> // for endl, streamsize +#include <string> // for basic_string +#include <utility> // for move namespace caosdb::transaction { using caosdb::StatusCode; diff --git a/src/caosdb/protobuf_helper.cpp b/src/caosdb/protobuf_helper.cpp index e8bbd07834ead9b561c7e8769ed834527337f7a6..418d14b9c847bc204582f6165fae81bf6adcc156 100644 --- a/src/caosdb/protobuf_helper.cpp +++ b/src/caosdb/protobuf_helper.cpp @@ -19,8 +19,7 @@ * */ #include "caosdb/protobuf_helper.h" -#include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/extension_set.h> // for Arena +#include <google/protobuf/arena.h> // for Arena namespace caosdb::utility { diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 551d90560498a2aee4b3ce169d416079e8cc80c0..6380dcdde6f845ae4507328d5ccb073d82942b06 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -35,15 +35,14 @@ #include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_... #include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_... // IWYU pragma: no_include <bits/exception.h> -#include <exception> // IWYU pragma: keep -#include <google/protobuf/arena.h> // for Arena -#include <google/protobuf/generated_message_util.h> // for CreateMessage... -#include <grpc/impl/codegen/gpr_types.h> // for gpr_timespec -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <iosfwd> // for streamsize -#include <map> // for map, operator!= -#include <memory> // for unique_ptr -#include <utility> // for move, pair +#include <exception> // IWYU pragma: keep +#include <google/protobuf/arena.h> // for Arena +#include <grpc/impl/codegen/gpr_types.h> // for gpr_timespec +#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue +#include <iosfwd> // for streamsize +#include <map> // for map, operator!= +#include <memory> // for unique_ptr +#include <utility> // for move, pair namespace caosdb::transaction { using caosdb::entity::v1alpha1::EntityTransactionService; diff --git a/test/test_entity.cpp b/test/test_entity.cpp index 75adc7e7a051cc1e2a154d6b3723e44123e28130..d4b67705bf88e5f425f270692f160e5a6cb84ac0 100644 --- a/test/test_entity.cpp +++ b/test/test_entity.cpp @@ -38,6 +38,7 @@ #include <memory> // for allocator, shared_ptr #include <stdexcept> // for out_of_range #include <string> // for operator+, to_string +#include <utility> // for move namespace caosdb::entity { using caosdb::entity::v1alpha1::IdResponse; @@ -132,11 +133,88 @@ TEST(test_entity, test_append_property) { EXPECT_EQ(prop.GetName(), same_prop.GetName()); EXPECT_EQ(prop.GetId(), same_prop.GetId()); EXPECT_EQ(prop.GetImportance(), same_prop.GetImportance()); - EXPECT_EQ(prop.GetValue(), same_prop.GetValue()); + EXPECT_EQ(prop.GetValue().ToString(), same_prop.GetValue().ToString()); EXPECT_EQ(prop.GetUnit(), same_prop.GetUnit()); EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType()); } +TEST(test_entity, test_property_copy_constructor) { + Property prop; + prop.SetName("prop_name"); + prop.SetId("prop_id"); + prop.SetImportance(Importance::RECOMMENDED); + prop.SetValue("prop_value"); + prop.SetUnit("prop_unit"); + prop.SetDataType("prop_dtype"); + + Property other_prop(prop); + + EXPECT_EQ(prop, other_prop); + EXPECT_EQ(prop.GetName(), other_prop.GetName()); + EXPECT_EQ(prop.GetId(), other_prop.GetId()); + EXPECT_EQ(prop.GetImportance(), other_prop.GetImportance()); + EXPECT_EQ(prop.GetValue().ToString(), other_prop.GetValue().ToString()); + EXPECT_EQ(prop.GetUnit(), other_prop.GetUnit()); + EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType()); +} + +TEST(test_entity, test_property_copy_assignment) { + Property prop; + prop.SetName("prop_name"); + prop.SetId("prop_id"); + prop.SetImportance(Importance::RECOMMENDED); + prop.SetValue("prop_value"); + prop.SetUnit("prop_unit"); + prop.SetDataType("prop_dtype"); + + auto other_prop = prop; + EXPECT_EQ(prop, other_prop); + EXPECT_EQ(prop.GetName(), other_prop.GetName()); + EXPECT_EQ(prop.GetId(), other_prop.GetId()); + EXPECT_EQ(prop.GetImportance(), other_prop.GetImportance()); + EXPECT_EQ(prop.GetValue().ToString(), other_prop.GetValue().ToString()); + EXPECT_EQ(prop.GetUnit(), other_prop.GetUnit()); + EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType()); + + other_prop.SetName("other_prop_name"); + EXPECT_NE(prop, other_prop); + EXPECT_NE(prop.GetName(), other_prop.GetName()); + EXPECT_EQ(prop.GetName(), "prop_name"); + EXPECT_EQ(other_prop.GetName(), "other_prop_name"); +} + +TEST(test_entity, test_property_move_assignment) { + Property prop; + prop.SetName("prop_name"); + prop.SetId("prop_id"); + prop.SetImportance(Importance::RECOMMENDED); + prop.SetValue("prop_value"); + prop.SetUnit("prop_unit"); + prop.SetDataType("prop_dtype"); + + // we compare the moved one with this one + const Property copy_prop(prop); + + Property other_prop = std::move(prop); + // EXPECT_NE(prop, copy_prop); NOLINT + // EXPECT_NE(prop, other_prop); NOLINT + // EXPECT_EQ(prop.ToString(), "{}"); NOLINT + + EXPECT_EQ(copy_prop, other_prop); + EXPECT_EQ(copy_prop.GetName(), other_prop.GetName()); + EXPECT_EQ(copy_prop.GetId(), other_prop.GetId()); + EXPECT_EQ(copy_prop.GetImportance(), other_prop.GetImportance()); + EXPECT_EQ(copy_prop.GetValue().ToString(), other_prop.GetValue().ToString()); + EXPECT_EQ(copy_prop.GetUnit(), other_prop.GetUnit()); + EXPECT_EQ(copy_prop.GetDataType(), other_prop.GetDataType()); + + other_prop.SetName("other_prop_name"); + EXPECT_NE(copy_prop, other_prop); + EXPECT_NE(copy_prop.GetName(), other_prop.GetName()); + EXPECT_EQ(copy_prop.GetName(), "prop_name"); + EXPECT_EQ(other_prop.GetName(), "other_prop_name"); +} + TEST(test_entity, test_copy_to) { auto entity = Entity(); entity.SetRole(Role::RECORD); @@ -361,7 +439,22 @@ TEST(test_entity, test_remove_property) { // P0,P1,P2,P3,P4,P5,P6,P7,P8,P9 // ^ // P0,P1,P2, P4,P5,P6,P7,P8,P9 + CAOSDB_LOG_WARN(logger_name) << "REMOVE(3)!!!!!!!!!!!!!!!!!!!!!"; + CAOSDB_LOG_WARN(logger_name) << entity.GetProperties().ToString(); entity.RemoveProperty(3); + CAOSDB_LOG_WARN(logger_name) << entity.GetProperties().ToString(); + + ASSERT_EQ(entity.GetProperties().size(), 9); + for (int i = 0; i < 3; i++) { + auto name = "PROPERTY-" + std::to_string(i); + const auto &property = entity.GetProperties().at(i); + EXPECT_EQ(property.GetName(), name); + } + for (int i = 3; i < 9; i++) { + auto name = "PROPERTY-" + std::to_string(i + 1); + const auto &property = entity.GetProperties().at(i); + EXPECT_EQ(property.GetName(), name); + } // Remove at index 6 // P0,P1,P2, P4,P5,P6,P7,P8,P9 @@ -369,6 +462,21 @@ TEST(test_entity, test_remove_property) { // P0,P1,P2, P4,P5,P6, P8,P9 entity.RemoveProperty(6); ASSERT_EQ(entity.GetProperties().size(), 8); + for (int i = 0; i < 3; i++) { + auto name = "PROPERTY-" + std::to_string(i); + const auto &property = entity.GetProperties().at(i); + EXPECT_EQ(property.GetName(), name); + } + for (int i = 3; i < 6; i++) { + auto name = "PROPERTY-" + std::to_string(i + 1); + const auto &property = entity.GetProperties().at(i); + EXPECT_EQ(property.GetName(), name); + } + for (int i = 6; i < 8; i++) { + auto name = "PROPERTY-" + std::to_string(i + 2); + const auto &property = entity.GetProperties().at(i); + EXPECT_EQ(property.GetName(), name); + } // AppendProperty another property // P0,P1,P2, P4,P5,P6, P8,P9 diff --git a/test/test_value.cpp b/test/test_value.cpp index 25f8a12909e52fee4e3ed3a6b688b1871a41a32f..4e24d9258b287ed9a84538ca04c553e130c73409 100644 --- a/test/test_value.cpp +++ b/test/test_value.cpp @@ -22,6 +22,7 @@ #include "caosdb/value.h" // for Value #include "caosdb/entity/v1alpha1/main.pb.h" // for AtomicDataType, DataType +#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper #include <algorithm> // for max #include <cmath> // for isnan #include <gtest/gtest-message.h> // for Message