diff --git a/README_SETUP.md b/README_SETUP.md deleted file mode 100644 index f73190cad3386518361a9d76dac2f1825d5f3f28..0000000000000000000000000000000000000000 --- a/README_SETUP.md +++ /dev/null @@ -1,142 +0,0 @@ -# How to Develop and Use Libcaosdb - -## Dependencies - -* See [DEPENDENCIES.md](Dependencies.md) - -## Build - -We use [cmake](https://cmake.org) as build tool. - -0. clone/update the subrepo `git submodule update --init proto` -1. `mkdir build && cd build` -2. `conan install .. -s "compiler.libcxx=libstdc++11"` -3. `cmake -B . ..` -4. `cmake --build .` - -You may also want to install libcaosdb system-wide to -`CMAKE_INSTALL_PREFIX/lib` by - -5. `cmake --install .` - -The default install prefix is `~/.local`. It can be set by adding -`-DCMAKE_INSTALL_PREFIX=/path/to/install/prefix` to the first cmake -command (3.). - -### How to build on MacOS - -Instead of the above conan command (2.) use - -2. `conan install .. -s "cppstd=11"` - -and continue as you would when building on a Linux system. You may -have to add `build/lib/` (or, alternatively after installation, -`CMAKE_INSTALL_PREFIX/lib`) to your `DYLD_LIBRARY_PATH` environmental -variable. - -### How to build on Windows - -We use [Visual Studio 2019](https://visualstudio.microsoft.com/de/vs/features/cplusplus/) -as compiler. We use [cmake](https://cmake.org/download/) as build tool. - -0. clone/update the subrepo `git submodule update --init proto` -1. `mkdir build` -2. `cd build` -3. `conan install .. -g visual_studio -s arch=x86_64 -s build_type=Release -s compiler.toolset=v142 -s compiler.version=16 -s compiler.runtime=MD --build=missing --update` -4. `cmake -B . ..` -5. open ` libcaosdb.sln` with Visual Studio, change the buildtype to `Release` - and build the project. (You can open Tools/Command Line/Developer Command - Prompt and execute `msbuild libcaosdb.sln /property:Configuration=Release`) - -### Creating a Local Conan Package ## - -Building and installing libcaosdb with Conan is just a single command: `make conan-install` - -For MacOS, you probably should adjust the option as mentioned above. - -### Troubleshooting - -#### `conan install` Fails Due to Missing Prebuilts - -When `conan install` fails during the installation of the dependencies because -a precompiled package is not available for your specific settings, try adding -the `--build=missing` option: `conan install .. [ other options -] --build=missing`. This should download and compile the sources of the -dependencies. - -#### cmake fails when using the Debug flag -Depending on the clang version it might be necessary to use additionally the following flag: -`-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"` - -## Unit Tests - -### Build - -For the tests there is a slightly different setup required (with option `-D CMAKE_BUILD_TYPE=Debug`) - -1. `mkdir build && cd build/` -2. `conan install .. -s "compiler.libcxx=libstdc++11"` -3. `cmake -B . -D CMAKE_BUILD_TYPE=Debug ..` - * If your clang-format version is too old, formatting, linting etc. can be skipped: - `cmake -B . -D CMAKE_BUILD_TYPE=Debug -D SKIP_LINTING=ON ..` -4. `cmake --build .` - -### Run - -In the build directory, run `ctest` - -### Framework - -We use [GoogleTest](https://google.github.io/googletest/) for unit testing. - -### Coverage - -We use [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) and -[lcov](https://github.com/linux-test-project/lcov) for generating test coverage -reports. - -In the build directory, generate the coverage report by running -`cmake --build . --target unit_test_coverage`. - -Note that this special target will run the tests again. Thus it is not -necessary to run `ctest` prior to this target. - -The coverage report can be viewed in a browser by opening -`<build_directory>/unit_test_coverage/index.html`. - -## Code Formatting - -* install clang-format on your system. -* `clang-format -i --verbose $(find test/ src/ include/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in")` - -## Naming Convention - -Please adhere to [Google's C++ naming conventions](https://google.github.io/styleguide/cppguide.html#Naming). - -## Client Configuration - -You can use a json file for the configuration of the client. See -`test/test_data/test_caosdb_client.json` for an example. You may use -`caosdb-client-configuration-schema.json` to validate your schema. -Typically, you will need to provide the path to your SSL certificate. - -The client will load the configuration file from the first existing -file in the following locations (precedence from highest to lowest): - -1. A file specified by the environment variable - `$CAOSDB_CLIENT_CONFIGURATION`. -2. `$PWD/caosdb_client.json` -3. `$PWD/caosdb-client.json` -4. `$PWD/.caosdb_client.json` -5. `$PWD/.caosdb-client.json` -6. `$HOME/caosdb_client.json` -7. `$HOME/caosdb-client.json` -8. `$HOME/.caosdb_client.json` -9. `$HOME/.caosdb-client.json` - -## Documentation - -In the build directory, run - -* `cmake --build . --target doc-doxygen` (generate Doxygen) -* `cmake --build . --target doc-sphinx` (generate Sphinx) diff --git a/README_SETUP.md b/README_SETUP.md new file mode 120000 index 0000000000000000000000000000000000000000..c5c7270fb583274df037848bfb735cdb48829d28 --- /dev/null +++ b/README_SETUP.md @@ -0,0 +1 @@ +doc/README_SETUP.md \ No newline at end of file diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 76d7dad56583120795d49f1828998315597e803c..e2b585d02150ddd2411dbf208d3358c73d4bf17f 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -81,10 +81,19 @@ if (DOXYGEN_FOUND) -c ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} sphinx_out - DEPENDS doc-doxygen + DEPENDS doc-doxygen + Examples.rst + README_SETUP.md WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Sphinx" - VERBATIM ) + VERBATIM + ) + # Copying files is necessary: https://stackoverflow.com/a/45808534/232888 + FILE(COPY + Examples.rst + README_SETUP.md + # Tutorial.rst + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") else () message("Sphinx need to be installed to generate the sphinx documentation") endif () diff --git a/doc/Examples.rst b/doc/Examples.rst new file mode 100644 index 0000000000000000000000000000000000000000..ea65e02cd421b880d5d748c6774798ac115d0d9a --- /dev/null +++ b/doc/Examples.rst @@ -0,0 +1,237 @@ +Examples +======== + + +Connect to a CaosDB server +-------------------------- + +See also the hints on how to :doc:`get started<README_SETUP>`, and set-up of +libcaosdb. In order to connect to a CaosDB server with libcaosdb you first have to configure the +connection via a configuration file as explained in the :ref:`configuration section <Client Configuration>`. Once the configuration is set up, connecting to the server is +as easy as + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + +You can print the full version of the server that you are connected to (and +therby test the connection) via: + +.. code:: cpp + // get version info of the server + connection.RetrieveVersionInfo() + const auto &v_info = connection->GetVersionInfo(); + std::cout << "Server Version: " << v_info->GetMajor() << "." + << v_info->GetMinor() << "." << v_info->GetPatch() << "-" + << v_info->GetPreRelease() << "-" << v_info->GetBuild() + << std::endl; + + +Retrieve a Record +----------------- + +With libcaosdb you can create a transaction +object, fill it with sub-requests, execute it, and retrieve the +result(s) . This +is handy when you want to have several requests in the same transaction. +However, most of the time, e.g., when retrieving one or multiple +Records, this is not necessary. libcaosdb provides helper functions so +you don’t have to worry about transactions and their executions. Assume +you want to retrieve an Entity with id=123. This is done via + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + auto transaction(connection->CreateTransaction()); + + const auto *id = "1231"; + transaction->RetrieveById(id); + auto status = transaction->Execute(); + + const auto &result_set = transaction->GetResultSet(); + + const auto &entity = result_set.at(0) + + +You can then use the getter methods like :cpp:any:`GetId<caosdb::entity::Entity::GetId>`, +:cpp:any:`GetParents<caosdb::entity::Entity::GetParents>`, or :cpp:any:`GetProperties`<caosdb::entity::Entity::GetProperties>` to get the +name, the parents, or the properties of the retrieved entity. + +Retrieving multiple entities works in the same way. Type + +.. code:: cpp + + const std::vector<std::string> ids = {"1220", "1221", "1222"}; + transaction->RetrieveById(ids.begin(), ids.end()); + +to retrieve the entities with ids 1220, 1221 and 1222. They can then be +accessed using ``result_set.at(1)`` etc. + +The same (and more) can be achieved by building and executing the +transaction manually. This is done by + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + auto transaction(connection->CreateTransaction()); + + transaction->RetrieveById("1231"); + transaction->RetrieveById("1233"); + auto status = transaction->Execute(); + +A result set can be obtained +via :cpp:any:`GetResultSet`<caosdb::transaction::Transaction::GetResultSet>` which contains the resulting entities +and can, e.g., be checked for length. + +Execute queries +--------------- + +Executing queries works very similar to the retrieval of entities via +ids. + +FIND and SELECT queries +~~~~~~~~~~~~~~~~~~~~~~~ + +In general, entities can be found using CaosDB’s query language like + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + auto query_transaction(connection->CreateTransaction()); + query_transaction->Query("FIND ENTITY WITH id = 1222"); + query_transaction->Execute(); + auto result_set = query_transaction->GetResultSet(); + std::cout << "Found " << result_set.size() + << "entity with id=" + << result_set.at(0).GetId() << std::endl; + +``result_set`` is a (possibly empty) list of entities that can be +inspected as above. + +:: + + SELECT queries haven't been implemented in the C++ client yet and + thus cannot be executed from libcaosdb right now. SELECT queries + will be added in a future release. + +COUNT queries +~~~~~~~~~~~~~ + +COUNT queries are different from FIND or SELECT queries in two ways. +Firstly, they do not return entities but a single number which is why, +secondly, they do not have a result set that could be returned. +The result of the count is +obtained using the :cpp:any:`GetCountResult<caosdb::transaction::Transaction::GetCountResult>` function: + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + auto query_transaction(connection->CreateTransaction()); + query_transaction->Query("COUNT RECORD person WITH NAME LIKE '*Baggins'"); + query_transaction->Execute(); + std::cout << "Found " << query_transaction->GetCountResult() + << "entities."<< std::endl; + +Insert, update, and delete entities +----------------------------------- + +Insert, update and delete operations function the same way. The respective +task is added to a transaction and the transaction is executed. + +.. code:: cpp + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + + // ######## INSERT ######## + // create the entity + Entity entity; + entity.SetRole(Role::RECORD_TYPE); + entity.SetName("RT1"); + + // create the transaction, add the task and execute the transaction + auto insert_transaction(connection->CreateTransaction()); + insert_transaction->InsertEntity(&entity); + auto insert_status = insert_transaction->Execute(); + + const auto &insert_result_set = insert_transaction->GetResultSet(); + // the result is an entity with the new id + const auto &new_entity = insert_result_set.at(0); + std::cout << "The newly inserted entity has the id " + << new_entity.GetId() << std::endl; + + + // get the inserted entity + // RETRIEVE + auto retrieve_transaction(connection->CreateTransaction()); + retrieve_transaction->RetrieveById(new_entity.GetId()); + retrieve_transaction->Execute(); + // save the entity from the result set in a new variable + auto update_entity(retrieve_transaction->GetResultSet().at(0)); + + // ######## UPDATE ######## + // and change it + update_entity.SetName("RT1-Update"); + + // create update transaction + auto update_transaction(connection->CreateTransaction()); + update_transaction->UpdateEntity(&update_entity); + auto update_status = update_transaction->Execute(); + // same as with insert transaction, the update transaction returns an entity + // with the id + const auto &updated_entity = update_transaction->GetResultSet().at(0); + std::cout << "The entity with the id " + << update_entity.GetId() << "was updated." << std::endl; + + // ######## DELETE ######## + auto delete_transaction(connection->CreateTransaction()); + delete_transaction->DeleteById(updated_entity .GetId()); + auto delete_status = delete_transaction->Execute(); + + // again, the delete transaction returns a result set with entities + // with the ids that where deleted + const auto &delete_result_set = delete_transaction->GetResultSet(); + + +Up- and Download a file +--------------- + +.. code:: cpp + + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + Entity file; + file.SetRole(Role::FILE); + file.SetFilePath("test.txt"); + file.SetLocalPath(test_upload_file_1); + + // in order to upload a file, the corresponding entity simply has to be + // inserted + auto insert_transaction(connection->CreateTransaction()); + insert_transaction->InsertEntity(&file); + insert_transaction->Execute(); + + // entity in the result set contains the new id + const auto &insert_results = insert_transaction->GetResultSet(); + const auto &inserted_file = insert_results.at(0); + + // for the download you need to use the RetrieveAndDownloadFilesById task and + // supply the path where the file shall be stored + test_download_file = fs::path("test_download_file_delete_me.dat"); + auto download_transaction(connection->CreateTransaction()); + download_transaction->RetrieveAndDownloadFilesById( + inserted_file.GetId(), test_download_file.string()); + download_transaction->ExecuteAsynchronously(); + download_transaction->WaitForIt().GetCode() + + const auto &download_results = download_transaction->GetResultSet(); + const auto &downloaded_file = download_results.at(0); diff --git a/doc/README_SETUP.md b/doc/README_SETUP.md new file mode 100644 index 0000000000000000000000000000000000000000..f73190cad3386518361a9d76dac2f1825d5f3f28 --- /dev/null +++ b/doc/README_SETUP.md @@ -0,0 +1,142 @@ +# How to Develop and Use Libcaosdb + +## Dependencies + +* See [DEPENDENCIES.md](Dependencies.md) + +## Build + +We use [cmake](https://cmake.org) as build tool. + +0. clone/update the subrepo `git submodule update --init proto` +1. `mkdir build && cd build` +2. `conan install .. -s "compiler.libcxx=libstdc++11"` +3. `cmake -B . ..` +4. `cmake --build .` + +You may also want to install libcaosdb system-wide to +`CMAKE_INSTALL_PREFIX/lib` by + +5. `cmake --install .` + +The default install prefix is `~/.local`. It can be set by adding +`-DCMAKE_INSTALL_PREFIX=/path/to/install/prefix` to the first cmake +command (3.). + +### How to build on MacOS + +Instead of the above conan command (2.) use + +2. `conan install .. -s "cppstd=11"` + +and continue as you would when building on a Linux system. You may +have to add `build/lib/` (or, alternatively after installation, +`CMAKE_INSTALL_PREFIX/lib`) to your `DYLD_LIBRARY_PATH` environmental +variable. + +### How to build on Windows + +We use [Visual Studio 2019](https://visualstudio.microsoft.com/de/vs/features/cplusplus/) +as compiler. We use [cmake](https://cmake.org/download/) as build tool. + +0. clone/update the subrepo `git submodule update --init proto` +1. `mkdir build` +2. `cd build` +3. `conan install .. -g visual_studio -s arch=x86_64 -s build_type=Release -s compiler.toolset=v142 -s compiler.version=16 -s compiler.runtime=MD --build=missing --update` +4. `cmake -B . ..` +5. open ` libcaosdb.sln` with Visual Studio, change the buildtype to `Release` + and build the project. (You can open Tools/Command Line/Developer Command + Prompt and execute `msbuild libcaosdb.sln /property:Configuration=Release`) + +### Creating a Local Conan Package ## + +Building and installing libcaosdb with Conan is just a single command: `make conan-install` + +For MacOS, you probably should adjust the option as mentioned above. + +### Troubleshooting + +#### `conan install` Fails Due to Missing Prebuilts + +When `conan install` fails during the installation of the dependencies because +a precompiled package is not available for your specific settings, try adding +the `--build=missing` option: `conan install .. [ other options +] --build=missing`. This should download and compile the sources of the +dependencies. + +#### cmake fails when using the Debug flag +Depending on the clang version it might be necessary to use additionally the following flag: +`-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"` + +## Unit Tests + +### Build + +For the tests there is a slightly different setup required (with option `-D CMAKE_BUILD_TYPE=Debug`) + +1. `mkdir build && cd build/` +2. `conan install .. -s "compiler.libcxx=libstdc++11"` +3. `cmake -B . -D CMAKE_BUILD_TYPE=Debug ..` + * If your clang-format version is too old, formatting, linting etc. can be skipped: + `cmake -B . -D CMAKE_BUILD_TYPE=Debug -D SKIP_LINTING=ON ..` +4. `cmake --build .` + +### Run + +In the build directory, run `ctest` + +### Framework + +We use [GoogleTest](https://google.github.io/googletest/) for unit testing. + +### Coverage + +We use [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) and +[lcov](https://github.com/linux-test-project/lcov) for generating test coverage +reports. + +In the build directory, generate the coverage report by running +`cmake --build . --target unit_test_coverage`. + +Note that this special target will run the tests again. Thus it is not +necessary to run `ctest` prior to this target. + +The coverage report can be viewed in a browser by opening +`<build_directory>/unit_test_coverage/index.html`. + +## Code Formatting + +* install clang-format on your system. +* `clang-format -i --verbose $(find test/ src/ include/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in")` + +## Naming Convention + +Please adhere to [Google's C++ naming conventions](https://google.github.io/styleguide/cppguide.html#Naming). + +## Client Configuration + +You can use a json file for the configuration of the client. See +`test/test_data/test_caosdb_client.json` for an example. You may use +`caosdb-client-configuration-schema.json` to validate your schema. +Typically, you will need to provide the path to your SSL certificate. + +The client will load the configuration file from the first existing +file in the following locations (precedence from highest to lowest): + +1. A file specified by the environment variable + `$CAOSDB_CLIENT_CONFIGURATION`. +2. `$PWD/caosdb_client.json` +3. `$PWD/caosdb-client.json` +4. `$PWD/.caosdb_client.json` +5. `$PWD/.caosdb-client.json` +6. `$HOME/caosdb_client.json` +7. `$HOME/caosdb-client.json` +8. `$HOME/.caosdb_client.json` +9. `$HOME/.caosdb-client.json` + +## Documentation + +In the build directory, run + +* `cmake --build . --target doc-doxygen` (generate Doxygen) +* `cmake --build . --target doc-sphinx` (generate Sphinx) diff --git a/doc/conf.py.in b/doc/conf.py.in index f04a7a83ac79d555d819528d3ae6d92ed63580ee..c359c11e4d785a840761e50e93c2787d86312a43 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -45,7 +45,8 @@ extensions = [ 'sphinx.ext.viewcode', 'sphinx_sitemap', 'sphinx.ext.inheritance_diagram', - 'breathe' + 'breathe', + "recommonmark" # For markdown files. ] # Add any paths that contain templates here, relative to this directory. diff --git a/doc/index.rst.in b/doc/index.rst.in index e3fac2458d21571721f412adb3c120264f14dee6..47b16c95efa3da4aee32a1c6f2b559e5295377e3 100644 --- a/doc/index.rst.in +++ b/doc/index.rst.in @@ -25,13 +25,13 @@ Welcome to |PROJECT_NAME|'s documentation! ========================================== -This is work in progress. - .. toctree:: :maxdepth: 4 :caption: Contents: Welcome <self> + Getting Started <README_SETUP> + Examples.rst cppapi/index capi/index diff --git a/doc/requirements.txt b/doc/requirements.txt index 491959d5a9d70de347b8640872f9bf190af02261..1a306c69d3e8c80b51e0a0824da0d66ca378ad11 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -2,6 +2,7 @@ alabaster==0.7.12 Babel==2.9.1 breathe==4.30.0 certifi==2020.12.5 +recommonmark chardet==4.0.0 docutils==0.16 idna==2.10 diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index 645e9c5bde4f5e559dc0975f4c899634c7223691..71a8707e22d960befcb139b8d58f6d59fb47a008 100644 --- a/include/caosdb/data_type.h +++ b/include/caosdb/data_type.h @@ -176,6 +176,22 @@ public: this->wrapped->mutable_reference_data_type()->set_name(data_type); } } + + inline static auto ListOf(const AtomicDataType &atomic_data_type) + -> DataType { + DataType result; + result.wrapped->mutable_list_data_type()->set_atomic_data_type( + static_cast<ProtoAtomicDataType>(atomic_data_type)); + return result; + } + inline static auto ListOf(const std::string reference_data_type) -> DataType { + DataType result; + result.wrapped->mutable_list_data_type() + ->mutable_reference_data_type() + ->set_name(reference_data_type); + return result; + } + [[nodiscard]] inline auto IsAtomic() const noexcept -> bool { return this->wrapped->data_type_case() == DataTypeCase::kAtomicDataType; } diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h index e861e9fafafa955be636a1d6fdec131d45a7473c..c26c7b284bdbc3f0ec15ed4ae6c13cfa9820c066 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -42,6 +42,7 @@ #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 @@ -50,6 +51,7 @@ #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; @@ -530,9 +532,16 @@ public: */ 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 int64_t value) -> StatusCode; - // auto SetValue(const bool 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. */ @@ -704,10 +713,15 @@ public: 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; - // TODO(tf) - // auto SetValue(const int64_t value) -> StatusCode; - // auto SetValue(const bool 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; diff --git a/include/caosdb/value.h b/include/caosdb/value.h index 9cde6c61fe427bbd13743933c2b0112041ca2dec..30a2bec91de6dcec15d6f1f0cf2f78b77a500300 100644 --- a/include/caosdb/value.h +++ b/include/caosdb/value.h @@ -111,7 +111,9 @@ public: : ProtoMessageWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_string_value(value); } - explicit inline Value(const char value[]) : Value(std::string(value)) {} + explicit inline Value(const char *value) : ProtoMessageWrapper<ProtoValue>() { + this->wrapped->mutable_scalar_value()->set_string_value(std::string(value)); + } explicit inline Value(double value) : ProtoMessageWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_double_value(value); } @@ -123,15 +125,12 @@ public: this->wrapped->mutable_scalar_value()->set_boolean_value(value); } - explicit inline Value(const std::vector<std::string> &values) - : ProtoMessageWrapper<ProtoValue>() { - for (const auto &value : values) { - this->wrapped->mutable_list_values()->add_values()->set_string_value( - value); - } - } - + LIST_VALUE_CONSTRUCTOR(int, set_integer_value) LIST_VALUE_CONSTRUCTOR(int64_t, set_integer_value) + LIST_VALUE_CONSTRUCTOR(double, set_double_value) + LIST_VALUE_CONSTRUCTOR(std::string, set_string_value) + LIST_VALUE_CONSTRUCTOR(char *, set_string_value) + LIST_VALUE_CONSTRUCTOR(bool, set_boolean_value) [[nodiscard]] inline auto IsNull() -> bool { return this->wrapped->value_case() == ValueCase::VALUE_NOT_SET; diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp index 3ec6da0f92a01922aee2c1e1901197a4fb4aa2ee..ebd22660cbb48b9b2262ccc83153b578eb9686b2 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -130,10 +130,42 @@ auto Property::SetValue(const std::string &value) -> StatusCode { return SetValue(Value(value)); } +auto Property::SetValue(const char *value) -> StatusCode { + return SetValue(Value(value)); +} + auto Property::SetValue(double value) -> StatusCode { return SetValue(Value(value)); } +auto Property::SetValue(const std::vector<std::string> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Property::SetValue(const std::vector<char *> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Property::SetValue(const std::vector<int64_t> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Property::SetValue(const std::vector<double> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Property::SetValue(const std::vector<bool> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Property::SetValue(const int64_t value) -> StatusCode { + return SetValue(Value(value)); +} + +auto Property::SetValue(const bool value) -> StatusCode { + return SetValue(Value(value)); +} + auto Property::SetUnit(const std::string &unit) -> void { this->wrapped->set_unit(unit); } @@ -223,10 +255,42 @@ auto Entity::SetValue(const std::string &value) -> StatusCode { return SetValue(Value(value)); } +auto Entity::SetValue(const char *value) -> StatusCode { + return SetValue(Value(value)); +} + auto Entity::SetValue(double value) -> StatusCode { return SetValue(Value(value)); } +auto Entity::SetValue(const std::vector<std::string> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Entity::SetValue(const std::vector<char *> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Entity::SetValue(const std::vector<int64_t> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Entity::SetValue(const std::vector<double> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Entity::SetValue(const std::vector<bool> &values) -> StatusCode { + return SetValue(Value(values)); +} + +auto Entity::SetValue(const int64_t value) -> StatusCode { + return SetValue(Value(value)); +} + +auto Entity::SetValue(const bool value) -> StatusCode { + return SetValue(Value(value)); +} + auto Entity::SetUnit(const std::string &unit) -> void { this->wrapped->set_unit(unit); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4399f657769a8574eeb2b9c2ea2200f8ba3855c6..6edff54857aca64b64c99a47ea8344ebf9eee265 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,6 +26,7 @@ set(test_cases test_entity test_file_transmission test_info + test_list_properties test_protobuf test_transaction test_utility diff --git a/test/test_list_properties.cpp b/test/test_list_properties.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34895dfa15eabc207c2a485f4a22fcb33428a791 --- /dev/null +++ b/test/test_list_properties.cpp @@ -0,0 +1,64 @@ +/* + * + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "caosdb/data_type.h" // for DataType, AtomicDataType +#include "caosdb/entity.h" // for Entity +#include "caosdb/entity/v1alpha1/main.pb.h" // for AtomicDataType, DataType +#include "caosdb/value.h" // for Value +#include <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApi... +#include <gtest/gtest_pred_impl.h> // for AssertionResult, Test +#include <memory> // for allocator_traits<>::valu... +#include <string> // for string +#include <vector> // for vector + +namespace caosdb::entity { +using ProtoEntity = caosdb::entity::v1alpha1::Entity; +using ProtoParent = caosdb::entity::v1alpha1::Parent; +using ProtoDataType = caosdb::entity::v1alpha1::DataType; +using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType; + +TEST(test_list_property, test_list_of_text) { + Property list_property; + list_property.SetDataType(DataType::ListOf(AtomicDataType::TEXT)); + std::vector<std::string> in_value{"item1", "item2", "item3"}; + list_property.SetValue(in_value); + + Entity entity; + entity.SetRole(Role::RECORD_TYPE); + entity.SetName("TestRT"); + entity.AppendProperty(list_property); + + const auto &data_type = entity.GetProperties().at(0).GetDataType(); + const auto &value = entity.GetProperties().at(0).GetValue(); + + EXPECT_TRUE(data_type.IsList()); + EXPECT_TRUE(data_type.AsList().IsListOfAtomic()); + EXPECT_EQ(data_type.AsList().GetAtomicDataType(), AtomicDataType::TEXT); + + EXPECT_TRUE(value.IsList()); + EXPECT_EQ(value.AsList().size(), 3); + EXPECT_TRUE(value.AsList().at(1).IsString()); + EXPECT_EQ(value.AsList().at(1).AsString(), "item2"); +} + +} // namespace caosdb::entity diff --git a/test/test_value.cpp b/test/test_value.cpp index 39a6ac4a0b7f5eadb292dbcf7b3447061892b579..0bbc645397ede57fcbcecb9243085f42120cbebb 100644 --- a/test/test_value.cpp +++ b/test/test_value.cpp @@ -48,7 +48,7 @@ TEST(test_value, test_null) { } TEST(test_value, test_string) { - Value value("test"); + Value value(std::string("test")); EXPECT_FALSE(value.IsNull()); EXPECT_TRUE(value.IsString()); EXPECT_FALSE(value.IsDouble()); @@ -57,7 +57,7 @@ TEST(test_value, test_string) { EXPECT_EQ(value.AsString(), "test"); - Value empty_string(""); + Value empty_string(std::string("")); EXPECT_FALSE(empty_string.IsNull()); EXPECT_TRUE(empty_string.IsString()); EXPECT_FALSE(empty_string.IsDouble());