diff --git a/.clang-format b/.clang-format
index 19ff63cb42294f1ce5aa49d78a74d82e6141927b..af6747eb4b062e0f6ec7d670cbb1aec40c4338bd 100644
--- a/.clang-format
+++ b/.clang-format
@@ -54,7 +54,7 @@ BreakConstructorInitializersBeforeComma: false
 BreakConstructorInitializers: BeforeColon
 BreakAfterJavaFieldAnnotations: false
 BreakStringLiterals: true
-ColumnLimit:     80
+ColumnLimit:     100
 CommentPragmas:  '^ IWYU pragma:'
 CompactNamespaces: false
 ConstructorInitializerAllOnOneLineOrOnePerLine: false
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a54a23c5ad43ef851afeea2e31351a00ec2cadcc..d81b6e4ad2475604755798318be85371cd21484a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,6 +24,7 @@ variables:
   CPPLIB_REGISTRY_IMAGE: $CI_REGISTRY/caosdb/src/caosdb-cpplib/testenv:$CI_COMMIT_REF_NAME
 
   CPPINTTEST_PIPELINE: https://gitlab.indiscale.com/api/v4/projects/111/trigger/pipeline
+  CPPINTTEST_BRANCHES: https://gitlab.indiscale.com/api/v4/projects/111/repository/branches
   GIT_SUBMODULE_STRATEGY: normal
 
   ## FOR DEBUGGING
@@ -101,8 +102,13 @@ trigger_inttest:
     # ... use an f-branch if posible...
     - F_BRANCH=dev
     - if echo "$CI_COMMIT_REF_NAME" | grep -c "^f-" ; then
-        CPPINT_REF=$CI_COMMIT_REF_NAME ;
-        F_BRANCH=$CI_COMMIT_REF_NAME ;
+        if curl -o /dev/null -s -w "%{http_code}" $CPPINTTEST_BRANCHES/$CI_COMMIT_REF_NAME | grep "404"; then
+          CPPINT_REF=dev ;
+          F_BRANCH=dev ;
+        else
+          CPPINT_REF=$CI_COMMIT_REF_NAME ;
+          F_BRANCH=$CI_COMMIT_REF_NAME ;
+        fi
       fi;
     # ... or use main if possible...
     - if [[ "$CI_COMMIT_REF_NAME" == "main" ]] ; then
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10652f17f2f515bb408d91ffc2f18564c7452f1d..03710a3d17afebc1636ed47bd870742db3be9e04 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,10 +5,12 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [Unreleased]
+## [0.0.13 - Unreleased]
 
 ### Added
 
+- New functions getEnumNameFromValue() and getEnumValueFromName().
+
 ### Changed
 
 ### Deprecated
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3c3603ca52409df19a008b0e1a73a4766d9be596..30a702752b32a068346694e8401bc10198c9268a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@
 
 cmake_minimum_required(VERSION 3.13)
 
-set(libcaosdb_VERSION 0.0.11)
+set(libcaosdb_VERSION 0.0.13)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5)
 set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0)
@@ -412,7 +412,7 @@ install(FILES ${PROJECT_SOURCE_DIR}/caosdbConfigVersion.cmake
 ### code formatting with clang-format
 #######################################################
 option(AUTOFORMATTING "call clang-format at configure time" ON)
-if(AUTOFORMATTING)
+if(AUTOFORMATTING AND NOT SKIP_LINTING)
     file(GLOB format_test_sources test/*.cpp test/*.h test/*.h.in)
     execute_process(COMMAND clang-format -i --verbose ${libcaosdb_INCL}
         ${libcaosdb_SRC} ${libcaosdb_TEST_SRC}
diff --git a/README_SETUP.md b/README_SETUP.md
deleted file mode 100644
index 147745c32ad3d1460609e91942e4b7400b243560..0000000000000000000000000000000000000000
--- a/README_SETUP.md
+++ /dev/null
@@ -1,140 +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 ..`
-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/conanfile.py b/conanfile.py
index 300f652d76620d2cd6d4c698a0d651941daed5a4..7b34a061a4502c4f303517117ac77f77d622b32b 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools
 
 class CaosdbConan(ConanFile):
     name = "caosdb"
-    version = "0.0.11"
+    version = "0.0.13"
     license = "AGPL-3.0-or-later"
     author = "Timm C. Fitschen <t.fitschen@indiscale.com>"
     url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git"
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
index 76d7dad56583120795d49f1828998315597e803c..4255ab7d0f5531187491de7586a8c7b6c61545f7 100644
--- a/doc/CMakeLists.txt
+++ b/doc/CMakeLists.txt
@@ -81,10 +81,20 @@ 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
+		# TODO fix for docs
+		#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/CMakeLists.txt b/include/CMakeLists.txt
index c0db7a2c007d13394a06bede00d1c601ad83bef2..18d9334acdac17d3b583efabb4e2eeb116cbb5a9 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -25,6 +25,7 @@ set(libcaosdb_INCL
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/configuration.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.h
     ${CMAKE_CURRENT_BINARY_DIR}/caosdb/constants.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/data_type.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/entity.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/exceptions.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/handler_interface.h
@@ -39,6 +40,7 @@ set(libcaosdb_INCL
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction_status.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/unary_rpc_handler.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utility.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/value.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_upload_handler.h
 	# TODO this  file is still missing
 	# ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_download_handler.h
diff --git a/include/caosdb/authentication.h b/include/caosdb/authentication.h
index fc2420c5dc3100682a16eefb56494a63e64e8162..070346c9366d89e7476f125b74feaea4ceb40a32 100644
--- a/include/caosdb/authentication.h
+++ b/include/caosdb/authentication.h
@@ -70,8 +70,7 @@ public:
 
   auto GetMetadata(string_ref service_url, string_ref method_name,
                    const AuthContext &channel_auth_context,
-                   std::multimap<grpc::string, grpc::string> *metadata)
-    -> Status override;
+                   std::multimap<grpc::string, grpc::string> *metadata) -> Status override;
 };
 
 class PlainPasswordAuthenticator : public Authenticator {
@@ -79,11 +78,9 @@ private:
   std::string basic;
 
 public:
-  PlainPasswordAuthenticator(const std::string &username,
-                             const std::string &password);
+  PlainPasswordAuthenticator(const std::string &username, const std::string &password);
 
-  [[nodiscard]] auto GetCallCredentials() const
-    -> std::shared_ptr<grpc::CallCredentials> override;
+  [[nodiscard]] auto GetCallCredentials() const -> std::shared_ptr<grpc::CallCredentials> override;
 };
 } // namespace authentication
 } // namespace caosdb
diff --git a/include/caosdb/configuration.h b/include/caosdb/configuration.h
index bb6a1ff598be3df57ae24b21e5844cad6a9c0e71..2c521e7b0f36c351dabd6f7341ea3bb393fd402c 100644
--- a/include/caosdb/configuration.h
+++ b/include/caosdb/configuration.h
@@ -62,8 +62,7 @@ private:
 public:
   ConnectionConfiguration(const std::string &host, int port);
   virtual ~ConnectionConfiguration() = default;
-  friend auto operator<<(std::ostream &out,
-                         const ConnectionConfiguration &configuration)
+  friend auto operator<<(std::ostream &out, const ConnectionConfiguration &configuration)
     -> std::ostream &;
 
   [[nodiscard]] auto virtual ToString() const -> std::string = 0;
@@ -79,8 +78,7 @@ private:
 
 public:
   InsecureConnectionConfiguration(const std::string &host, int port);
-  [[nodiscard]] auto GetChannelCredentials() const
-    -> std::shared_ptr<ChannelCredentials> override;
+  [[nodiscard]] auto GetChannelCredentials() const -> std::shared_ptr<ChannelCredentials> override;
   [[nodiscard]] auto ToString() const -> std::string override;
 };
 
@@ -91,15 +89,13 @@ private:
 
 public:
   TlsConnectionConfiguration(const std::string &host, int port);
-  TlsConnectionConfiguration(const std::string &host, int port,
-                             const Authenticator &authenticator);
+  TlsConnectionConfiguration(const std::string &host, int port, const Authenticator &authenticator);
   TlsConnectionConfiguration(const std::string &host, int port,
                              const CertificateProvider &certificate_provider);
   TlsConnectionConfiguration(const std::string &host, int port,
                              const CertificateProvider &certificate_provider,
                              const Authenticator &authenticator);
-  [[nodiscard]] auto GetChannelCredentials() const
-    -> std::shared_ptr<ChannelCredentials> override;
+  [[nodiscard]] auto GetChannelCredentials() const -> std::shared_ptr<ChannelCredentials> override;
   [[nodiscard]] auto ToString() const -> std::string override;
 };
 
@@ -114,17 +110,13 @@ public:
 
 private:
   auto ConvertLogLevel(const std::string &string_level) const -> int;
-  auto CreateConsoleSinkConfiguration(const object &from,
-                                      const std::string &name, int level) const
+  auto CreateConsoleSinkConfiguration(const object &from, const std::string &name, int level) const
     -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateSyslogSinkConfiguration(const object &from,
-                                     const std::string &name, int level) const
+  auto CreateSyslogSinkConfiguration(const object &from, const std::string &name, int level) const
     -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateFileSinkConfiguration(const object &from, const std::string &name,
-                                   int level) const
+  auto CreateFileSinkConfiguration(const object &from, const std::string &name, int level) const
     -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateSinkConfiguration(const object &from, const std::string &name,
-                               int default_level) const
+  auto CreateSinkConfiguration(const object &from, const std::string &name, int default_level) const
     -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
   auto CreateLoggingConfiguration(const object &from) const
     -> caosdb::logging::LoggingConfiguration;
@@ -143,23 +135,19 @@ private:
   /**
    * @param from - a single connection configuration.
    */
-  auto CreateCertificateProvider(const object &from) const
-    -> std::unique_ptr<CertificateProvider>;
+  auto CreateCertificateProvider(const object &from) const -> std::unique_ptr<CertificateProvider>;
 
   /**
    * @param from - a single connection configuration.
    */
-  auto CreateAuthenticator(const object &from) const
-    -> std::unique_ptr<Authenticator>;
+  auto CreateAuthenticator(const object &from) const -> std::unique_ptr<Authenticator>;
 
   /**
    * @param from - a single connection configuration.
    */
-  auto
-  CreateConnectionConfiguration(const bool tls, const std::string &host,
-                                const int port,
-                                const CertificateProvider *certificate_provider,
-                                const Authenticator *authenticator) const
+  auto CreateConnectionConfiguration(const bool tls, const std::string &host, const int port,
+                                     const CertificateProvider *certificate_provider,
+                                     const Authenticator *authenticator) const
     -> std::unique_ptr<ConnectionConfiguration>;
 
   /**
@@ -200,8 +188,7 @@ public:
   /**
    * See mLoadSingleJSONConfiguration.
    */
-  inline static auto LoadSingleJSONConfiguration(const path &json_file)
-    -> void {
+  inline static auto LoadSingleJSONConfiguration(const path &json_file) -> void {
     GetInstance().mLoadSingleJSONConfiguration(json_file);
   }
 
@@ -218,8 +205,7 @@ public:
    */
   inline static auto GetDefaultConnectionConfiguration()
     -> std::unique_ptr<ConnectionConfiguration> {
-    return GetInstance().mGetConnectionConfiguration(
-      GetInstance().mGetDefaultConnectionName());
+    return GetInstance().mGetConnectionConfiguration(GetInstance().mGetDefaultConnectionName());
   }
 
   /**
diff --git a/include/caosdb/connection.h b/include/caosdb/connection.h
index ef9597bb06cb5454160eb02938219a8ced564d17..d3ed0945e0022f29e6097fb4ea2d9207c3258987 100644
--- a/include/caosdb/connection.h
+++ b/include/caosdb/connection.h
@@ -85,8 +85,7 @@ public:
    * RetrieveVersionInfoNoExceptions() before the version info is locally
    * available. Otherwise a nullptr is being returned.
    */
-  [[nodiscard]] inline auto GetVersionInfo() const noexcept
-    -> const VersionInfo * {
+  [[nodiscard]] inline auto GetVersionInfo() const noexcept -> const VersionInfo * {
     return this->version_info.get();
   };
 
@@ -128,8 +127,7 @@ private:
 
   auto mHasConnection(const std::string &name) const -> bool;
 
-  auto mGetConnection(const std::string &name) const
-    -> const std::shared_ptr<Connection> &;
+  auto mGetConnection(const std::string &name) const -> const std::shared_ptr<Connection> &;
 
   auto mGetDefaultConnection() const -> const std::shared_ptr<Connection> &;
 
@@ -148,22 +146,18 @@ public:
     return ConnectionManager::GetInstance().mHasConnection(name);
   };
 
-  inline static auto GetConnection(const std::string &name)
-    -> const std::shared_ptr<Connection> & {
+  inline static auto GetConnection(const std::string &name) -> const std::shared_ptr<Connection> & {
     return ConnectionManager::GetInstance().mGetConnection(name);
   };
 
   /**
    * Get the connection marked by the "default" key in the configuration.
    */
-  inline static auto GetDefaultConnection()
-    -> const std::shared_ptr<Connection> & {
+  inline static auto GetDefaultConnection() -> const std::shared_ptr<Connection> & {
     return ConnectionManager::GetInstance().mGetDefaultConnection();
   };
 
-  inline static auto Reset() -> void {
-    return ConnectionManager::GetInstance().mReset();
-  };
+  inline static auto Reset() -> void { return ConnectionManager::GetInstance().mReset(); };
 
   ConnectionManager(ConnectionManager const &) = delete;
   void operator=(ConnectionManager const &) = delete;
diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..22358fcda808c8ebf93c140156ba7e39c5757e8d
--- /dev/null
+++ b/include/caosdb/data_type.h
@@ -0,0 +1,227 @@
+/*
+ * 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/>.
+ *
+ */
+
+/**
+ * DataTypes have 2 dimensions: They may be atomic or reference typed, and they
+ * may be scalar or list valued.  If they are atomic, they have an
+ * AtomicDataType.  If they are reference typed, the reference name can be
+ * obtained with GetName().
+ */
+
+#ifndef CAOSDB_DATA_TYPE_H
+#define CAOSDB_DATA_TYPE_H
+#include "caosdb/protobuf_helper.h"         // for ProtoMessageWrapper
+#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message
+#include <memory>                           // for unique_ptr
+#include <string>                           // for string
+namespace caosdb::entity {
+using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType;
+using ProtoDataType = caosdb::entity::v1alpha1::DataType;
+using ProtoListDataType = caosdb::entity::v1alpha1::ListDataType;
+using ProtoReferenceDataType = caosdb::entity::v1alpha1::ReferenceDataType;
+using DataTypeCase = caosdb::entity::v1alpha1::DataType::DataTypeCase;
+using ListDataTypeCase = caosdb::entity::v1alpha1::ListDataType::ListDataTypeCase;
+using caosdb::utility::ProtoMessageWrapper;
+
+class Entity;
+class Property;
+
+// Atomic data types.
+enum class AtomicDataType {
+  // The data type is unset/unknown.
+  UNSPECIFIED = ProtoAtomicDataType::ATOMIC_DATA_TYPE_UNSPECIFIED,
+  // TEXT data type.
+  TEXT = ProtoAtomicDataType::ATOMIC_DATA_TYPE_TEXT,
+  // DOUBLE data type.
+  DOUBLE = ProtoAtomicDataType::ATOMIC_DATA_TYPE_DOUBLE,
+  // DATETIME data type.
+  DATETIME = ProtoAtomicDataType::ATOMIC_DATA_TYPE_DATETIME,
+  // INTEGER data type.
+  INTEGER = ProtoAtomicDataType::ATOMIC_DATA_TYPE_INTEGER,
+  // BOOLEAN data type.
+  BOOLEAN = ProtoAtomicDataType::ATOMIC_DATA_TYPE_BOOLEAN,
+};
+
+const std::map<AtomicDataType, std::string> atomicdatatype_names = {
+  {AtomicDataType::UNSPECIFIED, "UNSPECIFIED"}, {AtomicDataType::TEXT, "TEXT"},
+  {AtomicDataType::DOUBLE, "DOUBLE"},           {AtomicDataType::DATETIME, "DATETIME"},
+  {AtomicDataType::INTEGER, "INTEGER"},         {AtomicDataType::BOOLEAN, "BOOLEAN"}};
+
+class DataType;
+class ListDataType;
+
+class ReferenceDataType : public ProtoMessageWrapper<ProtoDataType> {
+public:
+  [[nodiscard]] inline auto GetName() const noexcept -> const std::string & {
+    // is list of reference?
+    if (this->wrapped->data_type_case() == DataTypeCase::kListDataType) {
+      return this->wrapped->list_data_type().reference_data_type().name();
+    }
+    return this->wrapped->reference_data_type().name();
+  }
+
+  friend class DataType;
+  friend class ListDataType;
+
+  inline auto GetWrapped() const -> const ProtoDataType * { return wrapped; }
+
+protected:
+  static auto GetEmptyInstance() -> const ReferenceDataType & {
+    static ReferenceDataType instance;
+    return instance;
+  }
+  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) {}
+};
+
+class ListDataType : public ProtoMessageWrapper<ProtoDataType> {
+public:
+  [[nodiscard]] inline auto IsListOfReference() const noexcept -> bool {
+    return this->wrapped->list_data_type().list_data_type_case() ==
+           ListDataTypeCase::kReferenceDataType;
+  }
+  [[nodiscard]] inline auto GetReferenceDataType() const -> const ReferenceDataType & {
+    if (!IsListOfReference()) {
+      return ReferenceDataType::GetEmptyInstance();
+    }
+    if (reference_data_type == nullptr) {
+      this->reference_data_type =
+        std::unique_ptr<ReferenceDataType>(ReferenceDataType::Create(this->wrapped).release());
+    }
+    return *this->reference_data_type;
+  }
+
+  [[nodiscard]] inline auto IsListOfAtomic() const noexcept -> bool {
+    return this->wrapped->list_data_type().list_data_type_case() ==
+           ListDataTypeCase::kAtomicDataType;
+  }
+  [[nodiscard]] inline auto GetAtomicDataType() const -> AtomicDataType {
+    return static_cast<AtomicDataType>(this->wrapped->list_data_type().atomic_data_type());
+  }
+
+  friend class DataType;
+
+protected:
+  static auto GetEmptyInstance() -> const ListDataType & {
+    static auto empty_instance = ListDataType();
+    return empty_instance;
+  }
+  inline static auto Create(ProtoDataType *wrapped) -> std::unique_ptr<ListDataType> {
+    return std::unique_ptr<ListDataType>(new ListDataType(wrapped));
+  }
+  ListDataType() : ProtoMessageWrapper<ProtoDataType>() {}
+
+  ListDataType(ProtoDataType *wrapped) : ProtoMessageWrapper<ProtoDataType>(wrapped) {}
+
+  mutable std::unique_ptr<ReferenceDataType> reference_data_type;
+};
+
+class DataType : public ProtoMessageWrapper<ProtoDataType> {
+public:
+  DataType(ProtoDataType *wrapped) : ProtoMessageWrapper<ProtoDataType>(wrapped) {}
+  DataType() : ProtoMessageWrapper<ProtoDataType>() {}
+  /**
+   * Create an AtomicDataType typed DataType.  For references, use the std::string constructor.
+   */
+  DataType(AtomicDataType data_type, bool list_type = false) : DataType() {
+    if (list_type) {
+      this->wrapped->mutable_list_data_type()->set_atomic_data_type(
+        static_cast<ProtoAtomicDataType>(data_type));
+    } else {
+      this->wrapped->set_atomic_data_type(static_cast<ProtoAtomicDataType>(data_type));
+    }
+  }
+  /**
+   * Create a reference typed DataType.
+   */
+  DataType(const std::string &data_type, bool list_type = false) : DataType() {
+    if (list_type) {
+      this->wrapped->mutable_list_data_type()->mutable_reference_data_type()->set_name(data_type);
+    } else {
+      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;
+  }
+  [[nodiscard]] inline auto AsAtomic() const noexcept -> AtomicDataType {
+    return static_cast<AtomicDataType>(this->wrapped->atomic_data_type());
+  }
+
+  [[nodiscard]] inline auto IsReference() const noexcept -> bool {
+    return this->wrapped->data_type_case() == DataTypeCase::kReferenceDataType;
+  }
+  [[nodiscard]] inline auto AsReference() const noexcept -> const ReferenceDataType & {
+    if (!IsReference()) {
+      return ReferenceDataType::GetEmptyInstance();
+    } else if (reference_data_type == nullptr) {
+      reference_data_type =
+        std::unique_ptr<ReferenceDataType>(ReferenceDataType::Create(this->wrapped).release());
+    }
+    return *reference_data_type;
+  }
+
+  [[nodiscard]] inline auto IsList() const noexcept -> bool {
+    return this->wrapped->data_type_case() == DataTypeCase::kListDataType;
+  }
+
+  [[nodiscard]] inline auto AsList() const noexcept -> const ListDataType & {
+    if (!IsList()) {
+      return ListDataType::GetEmptyInstance();
+    } else if (list_data_type == nullptr) {
+      list_data_type = std::unique_ptr<ListDataType>(ListDataType::Create(this->wrapped).release());
+    }
+    return *list_data_type;
+  }
+
+  inline auto operator==(const DataType &other) const noexcept -> bool {
+    // TODO(tf) Is this safe?
+    return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString();
+  }
+
+  friend class Entity;
+  friend class Property;
+
+protected:
+  mutable std::unique_ptr<ReferenceDataType> reference_data_type;
+  mutable std::unique_ptr<ListDataType> list_data_type;
+};
+
+} // namespace caosdb::entity
+
+#endif
diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h
index 3917e934122453e71d782604903143ecf5625bd1..13834b71d8467c45df58e199f98fd3c6606d69b4 100644
--- a/include/caosdb/entity.h
+++ b/include/caosdb/entity.h
@@ -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
diff --git a/include/caosdb/exceptions.h b/include/caosdb/exceptions.h
index 9ac46d2fd2e0a24fab08c49606b21033893c14e7..304216679200329660c5068362fa9e089f089235 100644
--- a/include/caosdb/exceptions.h
+++ b/include/caosdb/exceptions.h
@@ -65,8 +65,7 @@ public:
  */
 class TransactionError : public Exception {
 protected:
-  TransactionError(StatusCode code, const std::string &what_arg)
-    : Exception(code, what_arg) {}
+  TransactionError(StatusCode code, const std::string &what_arg) : Exception(code, what_arg) {}
 
 public:
   explicit TransactionError(const std::string &what_arg)
diff --git a/include/caosdb/file_transmission/download_request_handler.h b/include/caosdb/file_transmission/download_request_handler.h
index cb2108aa3c9c091316e557c1d732297d84171db9..3af72cc5939ced7a2f6c2edf86981cc8ef62cbb0 100644
--- a/include/caosdb/file_transmission/download_request_handler.h
+++ b/include/caosdb/file_transmission/download_request_handler.h
@@ -74,8 +74,7 @@ using caosdb::transaction::HandlerTag;
 class DownloadRequestHandler final : public HandlerInterface {
 public:
   DownloadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub,
-                         grpc::CompletionQueue *cq,
-                         FileDescriptor file_descriptor);
+                         grpc::CompletionQueue *cq, FileDescriptor file_descriptor);
 
   ~DownloadRequestHandler() override = default;
 
diff --git a/include/caosdb/file_transmission/register_file_upload_handler.h b/include/caosdb/file_transmission/register_file_upload_handler.h
index 17a42c0a2a2cf1d591048abb6e4c8b329bfd008c..f4586220980b056891effb142c4d736efc809fcf 100644
--- a/include/caosdb/file_transmission/register_file_upload_handler.h
+++ b/include/caosdb/file_transmission/register_file_upload_handler.h
@@ -73,8 +73,7 @@ public:
   ~RegisterFileUploadHandler();
 
   RegisterFileUploadHandler(const RegisterFileUploadHandler &) = delete;
-  RegisterFileUploadHandler &
-  operator=(const RegisterFileUploadHandler &) = delete;
+  RegisterFileUploadHandler &operator=(const RegisterFileUploadHandler &) = delete;
   RegisterFileUploadHandler(RegisterFileUploadHandler &&) = delete;
   RegisterFileUploadHandler &operator=(RegisterFileUploadHandler &&) = delete;
 
@@ -85,8 +84,7 @@ protected:
 
   FileTransmissionService::Stub *stub_;
 
-  std::unique_ptr<grpc::ClientAsyncResponseReader<RegisterFileUploadResponse>>
-    rpc_;
+  std::unique_ptr<grpc::ClientAsyncResponseReader<RegisterFileUploadResponse>> rpc_;
 
   RegisterFileUploadRequest *request_;
   RegisterFileUploadResponse *response_;
diff --git a/include/caosdb/file_transmission/upload_request_handler.h b/include/caosdb/file_transmission/upload_request_handler.h
index 54621d12ba7d67d374037ecdb1f1259662071319..9965d54ef870c0ab0ae21b65e456859fb1ef34a3 100644
--- a/include/caosdb/file_transmission/upload_request_handler.h
+++ b/include/caosdb/file_transmission/upload_request_handler.h
@@ -72,8 +72,7 @@ using caosdb::transaction::HandlerTag;
 class UploadRequestHandler final : public HandlerInterface {
 public:
   UploadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub,
-                       grpc::CompletionQueue *cq,
-                       FileDescriptor file_descriptor);
+                       grpc::CompletionQueue *cq, FileDescriptor file_descriptor);
 
   ~UploadRequestHandler() override = default;
 
@@ -89,13 +88,7 @@ public:
   void Cancel() override;
 
 protected:
-  enum class CallState {
-    NewCall,
-    SendingHeader,
-    SendingFile,
-    ExpectingResponse,
-    CallComplete
-  };
+  enum class CallState { NewCall, SendingHeader, SendingFile, ExpectingResponse, CallComplete };
 
   void handleNewCallState();
   void handleSendingHeaderState();
diff --git a/include/caosdb/info.h b/include/caosdb/info.h
index a9e94c1077f809bd5e2e28c225773e91b13a9e98..cf2c879120becd8db211e85df39d62ac9ba1434e 100644
--- a/include/caosdb/info.h
+++ b/include/caosdb/info.h
@@ -54,21 +54,13 @@ public:
    * server behind the given connection.
    */
   explicit inline VersionInfo(ProtoVersionInfo *info) : info(info){};
-  [[nodiscard]] inline auto GetMajor() const -> int32_t {
-    return this->info->major();
-  }
-  [[nodiscard]] inline auto GetMinor() const -> int32_t {
-    return this->info->minor();
-  }
-  [[nodiscard]] inline auto GetPatch() const -> int32_t {
-    return this->info->patch();
-  }
+  [[nodiscard]] inline auto GetMajor() const -> int32_t { return this->info->major(); }
+  [[nodiscard]] inline auto GetMinor() const -> int32_t { return this->info->minor(); }
+  [[nodiscard]] inline auto GetPatch() const -> int32_t { return this->info->patch(); }
   [[nodiscard]] inline auto GetPreRelease() const -> const std::string & {
     return this->info->pre_release();
   }
-  [[nodiscard]] inline auto GetBuild() const -> const std::string & {
-    return this->info->build();
-  }
+  [[nodiscard]] inline auto GetBuild() const -> const std::string & { return this->info->build(); }
 
 private:
   /// This object is the owner of the Protobuf VersionInfo message.
diff --git a/include/caosdb/logging.h b/include/caosdb/logging.h
index 439eefd41ea0c90f263b095f1033270e3d546e7b..35c5fdfa1a72ba5f55933f3bd99aa93f313c3e33 100644
--- a/include/caosdb/logging.h
+++ b/include/caosdb/logging.h
@@ -38,8 +38,7 @@ namespace caosdb::logging {
 
 const std::string logger_name = "caosdb::logging";
 
-typedef boost::log::sources::severity_channel_logger_mt<int, std::string>
-  boost_logger_class;
+typedef boost::log::sources::severity_channel_logger_mt<int, std::string> boost_logger_class;
 
 BOOST_LOG_GLOBAL_LOGGER(logger, boost_logger_class)
 
@@ -67,8 +66,7 @@ public:
   virtual ~LoggingConfiguration() = default;
   LoggingConfiguration(int level);
   auto AddSink(const std::shared_ptr<SinkConfiguration> &sink) -> void;
-  auto GetSinks() const
-    -> const std::vector<std::shared_ptr<SinkConfiguration>> &;
+  auto GetSinks() const -> const std::vector<std::shared_ptr<SinkConfiguration>> &;
 
 private:
   std::vector<std::shared_ptr<SinkConfiguration>> sinks;
@@ -102,8 +100,7 @@ public:
   [[nodiscard]] virtual auto GetDestination() const -> const std::string & = 0;
 
   friend auto initialize_logging_defaults() -> int;
-  friend auto
-  initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
+  friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
 
 protected:
   virtual auto Configure(boost::log::settings &settings) const -> void;
@@ -118,8 +115,7 @@ public:
   ConsoleSinkConfiguration(const std::string &name, int level);
   [[nodiscard]] auto GetDestination() const -> const std::string & override;
   friend auto initialize_logging_defaults() -> int;
-  friend auto
-  initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
+  friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
 
 protected:
   typedef SinkConfiguration sink_configuration;
@@ -139,12 +135,10 @@ class FileSinkConfiguration : public SinkConfiguration {
 public:
   virtual ~FileSinkConfiguration() = default;
   FileSinkConfiguration(const std::string &name, int level);
-  [[nodiscard]] virtual auto GetDestination() const
-    -> const std::string & override;
+  [[nodiscard]] virtual auto GetDestination() const -> const std::string & override;
   auto SetDirectory(const std::string &directory) -> void;
   friend auto initialize_logging_defaults() -> int;
-  friend auto
-  initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
+  friend auto initialize_logging(const LoggingConfiguration &logging_configuration) -> void;
 
 protected:
   typedef SinkConfiguration sink_configuration;
@@ -159,8 +153,7 @@ class SyslogSinkConfiguration : public SinkConfiguration {
 public:
   virtual ~SyslogSinkConfiguration() = default;
   SyslogSinkConfiguration(const std::string &name, int level);
-  [[nodiscard]] virtual auto GetDestination() const
-    -> const std::string & override;
+  [[nodiscard]] virtual auto GetDestination() const -> const std::string & override;
 
 private:
   const std::string destination = "Syslog";
@@ -193,29 +186,22 @@ void caosdb_log_trace(const char *channel, const char *msg);
 
 } // namespace caosdb::logging
 
-#define CAOSDB_LOG_FATAL(Channel)                                              \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_FATAL)
-#define CAOSDB_LOG_ERROR(Channel)                                              \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_ERROR)
-#define CAOSDB_LOG_WARN(Channel)                                               \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_WARN)
-#define CAOSDB_LOG_INFO(Channel)                                               \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_INFO)
-#define CAOSDB_LOG_DEBUG(Channel)                                              \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_DEBUG)
-#define CAOSDB_LOG_TRACE(Channel)                                              \
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel,               \
-                        CAOSDB_LOG_LEVEL_TRACE)
-
-#define CAOSDB_LOG_ERROR_AND_RETURN_STATUS(Channel, StatusCode, Message)       \
-  CAOSDB_LOG_ERROR(Channel)                                                    \
-    << "StatusCode (" << StatusCode << ") "                                    \
-    << caosdb::get_status_description(StatusCode) << ": " << Message;          \
+#define CAOSDB_LOG_FATAL(Channel)                                                                  \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_FATAL)
+#define CAOSDB_LOG_ERROR(Channel)                                                                  \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_ERROR)
+#define CAOSDB_LOG_WARN(Channel)                                                                   \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_WARN)
+#define CAOSDB_LOG_INFO(Channel)                                                                   \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_INFO)
+#define CAOSDB_LOG_DEBUG(Channel)                                                                  \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_DEBUG)
+#define CAOSDB_LOG_TRACE(Channel)                                                                  \
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_TRACE)
+
+#define CAOSDB_LOG_ERROR_AND_RETURN_STATUS(Channel, StatusCode, Message)                           \
+  CAOSDB_LOG_ERROR(Channel) << "StatusCode (" << StatusCode << ") "                                \
+                            << caosdb::get_status_description(StatusCode) << ": " << Message;      \
   return StatusCode;
 
 #endif
diff --git a/include/caosdb/message_code.h b/include/caosdb/message_code.h
index 2cc3f516f4e3356d9dfccc9e0435bfdfe2063306..367b5e9be8c43887e85436ac5491545329de9f10 100644
--- a/include/caosdb/message_code.h
+++ b/include/caosdb/message_code.h
@@ -41,17 +41,16 @@ namespace caosdb::entity {
 enum MessageCode {
   UNSPECIFIED = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_UNSPECIFIED,
   UNKNOWN = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_UNKNOWN,
-  ENTITY_DOES_NOT_EXIST =
-    caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_DOES_NOT_EXIST,
-  ENTITY_HAS_NO_PROPERTIES = caosdb::entity::v1alpha1::MessageCode::
-    MESSAGE_CODE_ENTITY_HAS_NO_PROPERTIES,
+  ENTITY_DOES_NOT_EXIST = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_DOES_NOT_EXIST,
+  ENTITY_HAS_NO_PROPERTIES =
+    caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_HAS_NO_PROPERTIES,
 };
 
 [[nodiscard]] inline auto get_message_code(int code) noexcept -> MessageCode {
   // TODO(tf) smarter, less forgot-it-prone implementation
-  static MessageCode all_codes[] = {
-    MessageCode::UNSPECIFIED, MessageCode::UNKNOWN,
-    MessageCode::ENTITY_DOES_NOT_EXIST, MessageCode::ENTITY_HAS_NO_PROPERTIES};
+  static MessageCode all_codes[] = {MessageCode::UNSPECIFIED, MessageCode::UNKNOWN,
+                                    MessageCode::ENTITY_DOES_NOT_EXIST,
+                                    MessageCode::ENTITY_HAS_NO_PROPERTIES};
 
   for (MessageCode known_code : all_codes) {
     if (known_code == code) {
diff --git a/include/caosdb/protobuf_helper.h b/include/caosdb/protobuf_helper.h
index bd3395f4de7e8cd586a613869e84b1d5ffeb729b..3cfa3d433d540c545fd3d96789e9cec9166022ee 100644
--- a/include/caosdb/protobuf_helper.h
+++ b/include/caosdb/protobuf_helper.h
@@ -22,14 +22,15 @@
 #ifndef CAOSDB_PROTOBUF_HELPER_H
 #define CAOSDB_PROTOBUF_HELPER_H
 
+#include "caosdb/status_code.h"
 #include <google/protobuf/arena.h>         // for Arena
 #include <google/protobuf/extension_set.h> // for Arena
 
-#define CAOSDB_DEBUG_MESSAGE_STRING(message, out)                              \
-  std::string out;                                                             \
-  {                                                                            \
-    google::protobuf::util::JsonOptions options;                               \
-    google::protobuf::util::MessageToJsonString(message, &out, options);       \
+#define CAOSDB_DEBUG_MESSAGE_STRING(message, out)                                                  \
+  std::string out;                                                                                 \
+  {                                                                                                \
+    google::protobuf::util::JsonOptions options;                                                   \
+    google::protobuf::util::MessageToJsonString(message, &out, options);                           \
   }
 
 namespace caosdb::utility {
@@ -38,5 +39,19 @@ using google::protobuf::Arena;
 
 auto get_arena() -> Arena *;
 
+template <typename P> class ProtoMessageWrapper {
+public:
+  ProtoMessageWrapper(const ProtoMessageWrapper &other) = default;
+  inline auto CopyFrom(const ProtoMessageWrapper &other) noexcept -> StatusCode {
+    this->wrapped->CopyFrom(*other.wrapped);
+    return StatusCode::SUCCESS;
+  }
+
+protected:
+  ProtoMessageWrapper() : ProtoMessageWrapper(Arena::CreateMessage<P>(get_arena())) {}
+  ProtoMessageWrapper(P *wrapped) : wrapped(wrapped) {}
+  P *wrapped;
+};
+
 } // namespace caosdb::utility
 #endif
diff --git a/include/caosdb/status_code.h b/include/caosdb/status_code.h
index f996901581f10d3fdadc0137b3b0a3db74348036..573b126fa94435c4669ace37ea00cbdbbbde6545 100644
--- a/include/caosdb/status_code.h
+++ b/include/caosdb/status_code.h
@@ -54,11 +54,13 @@ enum StatusCode {
   UNSUPPORTED_FEATURE = 27,
   ORIGINAL_ENTITY_MISSING_ID = 28,
   EXTERN_C_ASSIGNMENT_ERROR = 29,
-  PATH_IS_A_DIRECTORY = 30,
-  FILE_DOES_NOT_EXIST_LOCALLY = 31,
-  FILE_UPLOAD_ERROR = 32,
-  FILE_DOWNLOAD_ERROR = 33,
-  NOT_A_FILE_ENTITY = 34,
+  ENTITY_CANNOT_HAVE_A_DATA_TYPE = 30,
+  ENTITY_CANNOT_HAVE_A_VALUE = 31,
+  NOT_A_FILE_ENTITY = 32,
+  PATH_IS_A_DIRECTORY = 33,
+  FILE_DOES_NOT_EXIST_LOCALLY = 34,
+  FILE_UPLOAD_ERROR = 35,
+  FILE_DOWNLOAD_ERROR = 36,
   OTHER_CLIENT_ERROR = 9999,
 };
 
diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h
index bda5bb355b5dc317e6727c8bcea5ac10450e582f..c994ed65131f4236d872fdf1b0af862128d6c284 100644
--- a/include/caosdb/transaction.h
+++ b/include/caosdb/transaction.h
@@ -21,20 +21,21 @@
 #ifndef CAOSDB_TRANSACTION_H
 #define CAOSDB_TRANSACTION_H
 
-#include "caosdb/entity.h"                       // for Entity, FileDe...
-#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransact...
-#include "caosdb/entity/v1alpha1/main.pb.h"      // for MultiTransacti...
-#include "caosdb/handler_interface.h"            // for HandlerInterface
-#include "caosdb/transaction_handler.h"          // for EntityTransactionHandler
-#include "caosdb/logging.h"                      // for CAOSDB_LOG_ERR...
-#include "caosdb/protobuf_helper.h"              // for get_arena
-#include "caosdb/status_code.h"                  // for StatusCode
-#include "caosdb/transaction_status.h"           // for StatusCode
-#include <boost/log/core/record.hpp>             // for record
-#include <boost/log/sources/record_ostream.hpp>  // for basic_record_o...
+#include "caosdb/entity.h"                            // for Entity, FileDe...
+#include "caosdb/entity/v1alpha1/main.grpc.pb.h"      // for EntityTransact...
+#include "caosdb/entity/v1alpha1/main.pb.h"           // for MultiTransacti...
+#include "caosdb/handler_interface.h"                 // for HandlerInterface
+#include "caosdb/transaction_handler.h"               // for EntityTransactionHandler
+#include "caosdb/logging.h"                           // for CAOSDB_LOG_ERR...
+#include "caosdb/protobuf_helper.h"                   // for get_arena
+#include "caosdb/status_code.h"                       // for StatusCode
+#include "caosdb/transaction_status.h"                // for StatusCode
+#include <boost/log/core/record.hpp>                  // for record
+#include <boost/log/sources/record_ostream.hpp>       // for basic_record_o...
 #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 <iterator>                                   // for iterator, next
@@ -49,113 +50,109 @@
  * Do all necessary checks and assure that another retrieval (by id or by
  * query) can be added as a sub-request to a transaction.
  */
-#define ASSERT_CAN_ADD_RETRIEVAL                                               \
-  if (!IsStatus(TransactionStatus::INITIAL()) &&                               \
-      !IsStatus(TransactionStatus::GO_ON())) {                                 \
-    return StatusCode::TRANSACTION_STATUS_ERROR;                               \
-  }                                                                            \
-  switch (this->transaction_type) {                                            \
-  case NONE:                                                                   \
-    this->transaction_type = TransactionType::READ_ONLY;                       \
-    break;                                                                     \
-  case READ_ONLY:                                                              \
-    break;                                                                     \
-  case MIXED_READ_AND_WRITE:                                                   \
-    break;                                                                     \
-  default:                                                                     \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                         \
-      "You cannot add a retrieval to this transaction because it has the "     \
-      "wrong TransactionType.")                                                \
+#define ASSERT_CAN_ADD_RETRIEVAL                                                                   \
+  if (!IsStatus(TransactionStatus::INITIAL()) && !IsStatus(TransactionStatus::GO_ON())) {          \
+    return StatusCode::TRANSACTION_STATUS_ERROR;                                                   \
+  }                                                                                                \
+  switch (this->transaction_type) {                                                                \
+  case NONE:                                                                                       \
+    this->transaction_type = TransactionType::READ_ONLY;                                           \
+    break;                                                                                         \
+  case READ_ONLY:                                                                                  \
+    break;                                                                                         \
+  case MIXED_READ_AND_WRITE:                                                                       \
+    break;                                                                                         \
+  default:                                                                                         \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                                             \
+      "You cannot add a retrieval to this transaction because it has the "                         \
+      "wrong TransactionType.")                                                                    \
   }
 
 /**
  * Do all necessary checks and assure that another retrieval (by id or by
  * query) can be added as a sub-request to a transaction.
  */
-#define ASSERT_CAN_ADD_QUERY                                                   \
-  ASSERT_CAN_ADD_RETRIEVAL                                                     \
-  if (this->has_query) {                                                       \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::UNSUPPORTED_FEATURE,                            \
-      "Currently the number of queries which can be processed in a single "    \
-      "transaction is limitted to one.");                                      \
+#define ASSERT_CAN_ADD_QUERY                                                                       \
+  ASSERT_CAN_ADD_RETRIEVAL                                                                         \
+  if (this->has_query) {                                                                           \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::UNSUPPORTED_FEATURE,                                                \
+      "Currently the number of queries which can be processed in a single "                        \
+      "transaction is limitted to one.");                                                          \
   }
 
 /**
  * Do all necessary checks and assure that another deletion can be added as a
  * sub-request to a transaction.
  */
-#define ASSERT_CAN_ADD_DELETION                                                \
-  if (!IsStatus(TransactionStatus::INITIAL()) &&                               \
-      !IsStatus(TransactionStatus::GO_ON())) {                                 \
-    return StatusCode::TRANSACTION_STATUS_ERROR;                               \
-  }                                                                            \
-  switch (this->transaction_type) {                                            \
-  case NONE:                                                                   \
-    this->transaction_type = TransactionType::DELETE;                          \
-  case DELETE:                                                                 \
-  case MIXED_WRITE:                                                            \
-  case MIXED_READ_AND_WRITE:                                                   \
-    break;                                                                     \
-  default:                                                                     \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                         \
-      "You cannot add a deletion to this transaction because it has the "      \
-      "wrong TransactionType.")                                                \
+#define ASSERT_CAN_ADD_DELETION                                                                    \
+  if (!IsStatus(TransactionStatus::INITIAL()) && !IsStatus(TransactionStatus::GO_ON())) {          \
+    return StatusCode::TRANSACTION_STATUS_ERROR;                                                   \
+  }                                                                                                \
+  switch (this->transaction_type) {                                                                \
+  case NONE:                                                                                       \
+    this->transaction_type = TransactionType::DELETE;                                              \
+  case DELETE:                                                                                     \
+  case MIXED_WRITE:                                                                                \
+  case MIXED_READ_AND_WRITE:                                                                       \
+    break;                                                                                         \
+  default:                                                                                         \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                                             \
+      "You cannot add a deletion to this transaction because it has the "                          \
+      "wrong TransactionType.")                                                                    \
   }
 
 /**
  * Do all necessary checks and assure that another insertion can be added as a
  * sub-request to a transaction.
  */
-#define ASSERT_CAN_ADD_INSERTION                                               \
-  if (!IsStatus(TransactionStatus::INITIAL()) &&                               \
-      !IsStatus(TransactionStatus::GO_ON())) {                                 \
-    return StatusCode::TRANSACTION_STATUS_ERROR;                               \
-  }                                                                            \
-  switch (this->transaction_type) {                                            \
-  case NONE:                                                                   \
-    this->transaction_type = TransactionType::INSERT;                          \
-  case INSERT:                                                                 \
-  case MIXED_WRITE:                                                            \
-  case MIXED_READ_AND_WRITE:                                                   \
-    break;                                                                     \
-  default:                                                                     \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                         \
-      "You cannot add an insertion to this transaction because it has the "    \
-      "wrong TransactionType.")                                                \
+#define ASSERT_CAN_ADD_INSERTION                                                                   \
+  if (!IsStatus(TransactionStatus::INITIAL()) && !IsStatus(TransactionStatus::GO_ON())) {          \
+    return StatusCode::TRANSACTION_STATUS_ERROR;                                                   \
+  }                                                                                                \
+  switch (this->transaction_type) {                                                                \
+  case NONE:                                                                                       \
+    this->transaction_type = TransactionType::INSERT;                                              \
+  case INSERT:                                                                                     \
+  case MIXED_WRITE:                                                                                \
+  case MIXED_READ_AND_WRITE:                                                                       \
+    break;                                                                                         \
+  default:                                                                                         \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                                             \
+      "You cannot add an insertion to this transaction because it has the "                        \
+      "wrong TransactionType.")                                                                    \
   }
 
 /**
  * Do all necessary checks and assure that another update can be added as a
  * sub-request to a transaction.
  */
-#define ASSERT_CAN_ADD_UPDATE                                                  \
-  if (!IsStatus(TransactionStatus::INITIAL()) &&                               \
-      !IsStatus(TransactionStatus::GO_ON())) {                                 \
-    return StatusCode::TRANSACTION_STATUS_ERROR;                               \
-  }                                                                            \
-  switch (this->transaction_type) {                                            \
-  case NONE:                                                                   \
-    this->transaction_type = TransactionType::INSERT;                          \
-  case INSERT:                                                                 \
-  case MIXED_WRITE:                                                            \
-  case MIXED_READ_AND_WRITE:                                                   \
-    break;                                                                     \
-  default:                                                                     \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                         \
-      "You cannot add an update to this transaction because it has the "       \
-      "wrong TransactionType.")                                                \
-  }                                                                            \
-  if (!entity->HasId()) {                                                      \
-    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                        \
-      logger_name, StatusCode::ORIGINAL_ENTITY_MISSING_ID,                     \
-      "You cannot update this entity without any id. Probably you did not "    \
-      "retrieve it first? Entity updates should always start with the "        \
-      "retrieval of the existing entity which may then be changed.")           \
+#define ASSERT_CAN_ADD_UPDATE                                                                      \
+  if (!IsStatus(TransactionStatus::INITIAL()) && !IsStatus(TransactionStatus::GO_ON())) {          \
+    return StatusCode::TRANSACTION_STATUS_ERROR;                                                   \
+  }                                                                                                \
+  switch (this->transaction_type) {                                                                \
+  case NONE:                                                                                       \
+    this->transaction_type = TransactionType::INSERT;                                              \
+  case INSERT:                                                                                     \
+  case MIXED_WRITE:                                                                                \
+  case MIXED_READ_AND_WRITE:                                                                       \
+    break;                                                                                         \
+  default:                                                                                         \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::TRANSACTION_TYPE_ERROR,                                             \
+      "You cannot add an update to this transaction because it has the "                           \
+      "wrong TransactionType.")                                                                    \
+  }                                                                                                \
+  if (!entity->HasId()) {                                                                          \
+    CAOSDB_LOG_ERROR_AND_RETURN_STATUS(                                                            \
+      logger_name, StatusCode::ORIGINAL_ENTITY_MISSING_ID,                                         \
+      "You cannot update this entity without any id. Probably you did not "                        \
+      "retrieve it first? Entity updates should always start with the "                            \
+      "retrieval of the existing entity which may then be changed.")                               \
   }
 
 /**
@@ -219,14 +216,10 @@ private:
 class AbstractMultiResultSet : public ResultSet {
 public:
   virtual ~AbstractMultiResultSet() = default;
-  inline explicit AbstractMultiResultSet(
-    std::vector<std::unique_ptr<Entity>> result_set)
+  inline explicit AbstractMultiResultSet(std::vector<std::unique_ptr<Entity>> result_set)
     : items(std::move(result_set)) {}
-  [[nodiscard]] inline auto size() const noexcept -> int override {
-    return this->items.size();
-  }
-  [[nodiscard]] inline auto at(const int index) const
-    -> const Entity & override {
+  [[nodiscard]] inline auto size() const noexcept -> int override { return this->items.size(); }
+  [[nodiscard]] inline auto at(const int index) const -> const Entity & override {
     return *(this->items.at(index));
   }
   [[nodiscard]] inline auto mutable_at(int index) const -> Entity * override {
@@ -286,8 +279,7 @@ public:
    * If the file cannot be downloaded due to unsufficient permissions an error
    * is appended.
    */
-  auto RetrieveAndDownloadFilesById(const std::string &id,
-                                    const std::string &local_path) noexcept
+  auto RetrieveAndDownloadFilesById(const std::string &id, const std::string &local_path) noexcept
     -> StatusCode;
 
   /**
@@ -302,8 +294,7 @@ public:
    * Add all entity ids to this transaction for retrieval.
    */
   template <class InputIterator>
-  inline auto RetrieveById(InputIterator begin, InputIterator end) noexcept
-    -> StatusCode;
+  inline auto RetrieveById(InputIterator begin, InputIterator end) noexcept -> StatusCode;
 
   /**
    * Add a query to this transaction.
@@ -369,9 +360,7 @@ public:
   /**
    * Return the current status of the transaction.
    */
-  [[nodiscard]] inline auto GetStatus() const noexcept -> TransactionStatus {
-    return this->status;
-  }
+  [[nodiscard]] inline auto GetStatus() const noexcept -> TransactionStatus { return this->status; }
 
   [[nodiscard]] inline auto GetResultSet() const noexcept -> const ResultSet & {
     return *(this->result_set.get());
@@ -384,9 +373,7 @@ public:
    * this transaction. In all other cases, the return value will be
    * -1.
    */
-  [[nodiscard]] inline auto GetCountResult() const noexcept -> long {
-    return query_count;
-  }
+  [[nodiscard]] inline auto GetCountResult() const noexcept -> long { return query_count; }
 
   /**
    * Return the number of sub-requests in this transaction.
@@ -425,9 +412,7 @@ public:
   /**
    * Return the vector which holds all the files which are to be uploaded.
    */
-  inline auto GetUploadFiles() const -> const std::vector<FileDescriptor> & {
-    return upload_files;
-  }
+  inline auto GetUploadFiles() const -> const std::vector<FileDescriptor> & { return upload_files; }
 
 protected:
   /**
@@ -463,11 +448,10 @@ private:
   std::map<std::string, FileDescriptor> download_files;
 
   // auto RegisterUploadFile(RegisterFileUploadResponse *response) -> void;
-  auto UploadFile(FileUploadResponse *response,
-                  const FileDescriptor &file_descriptor,
+  auto UploadFile(FileUploadResponse *response, const FileDescriptor &file_descriptor,
                   const std::string &registration_id) -> void;
-  auto DownloadFile(FileDownloadResponse *response,
-                    const FileTransmissionId &file_transmission_id) -> void;
+  auto DownloadFile(FileDownloadResponse *response, const FileTransmissionId &file_transmission_id)
+    -> void;
   bool has_query = false;
   TransactionType transaction_type = TransactionType::NONE;
   mutable std::unique_ptr<ResultSet> result_set;
@@ -481,8 +465,7 @@ private:
 };
 
 template <class InputIterator>
-inline auto Transaction::RetrieveById(InputIterator begin,
-                                      InputIterator end) noexcept
+inline auto Transaction::RetrieveById(InputIterator begin, InputIterator end) noexcept
   -> StatusCode {
   ASSERT_CAN_ADD_RETRIEVAL
 
diff --git a/include/caosdb/transaction_handler.h b/include/caosdb/transaction_handler.h
index 0a7154d03dfbde19284807d1e1f40998c89e1de0..18cb5fcfcaa87a924ff0f36b0c5356d10fc9f70b 100644
--- a/include/caosdb/transaction_handler.h
+++ b/include/caosdb/transaction_handler.h
@@ -17,14 +17,12 @@ class EntityTransactionHandler final : public UnaryRpcHandler {
 public:
   EntityTransactionHandler(HandlerTag tag, EntityTransactionService::Stub *stub,
                            grpc::CompletionQueue *completion_queue,
-                           MultiTransactionRequest *request,
-                           MultiTransactionResponse *response);
+                           MultiTransactionRequest *request, MultiTransactionResponse *response);
 
   ~EntityTransactionHandler() override = default;
 
   EntityTransactionHandler(const EntityTransactionHandler &) = delete;
-  EntityTransactionHandler &
-  operator=(const EntityTransactionHandler &) = delete;
+  EntityTransactionHandler &operator=(const EntityTransactionHandler &) = delete;
   EntityTransactionHandler(EntityTransactionHandler &&) = delete;
   EntityTransactionHandler &operator=(EntityTransactionHandler &&) = delete;
 
@@ -35,8 +33,7 @@ protected:
 
   EntityTransactionService::Stub *stub_;
 
-  std::unique_ptr<grpc::ClientAsyncResponseReader<MultiTransactionResponse>>
-    rpc_;
+  std::unique_ptr<grpc::ClientAsyncResponseReader<MultiTransactionResponse>> rpc_;
 
   MultiTransactionRequest *request_;
   MultiTransactionResponse *response_;
diff --git a/include/caosdb/transaction_status.h b/include/caosdb/transaction_status.h
index ca40c578bc1c3dd2555ccda97c06b4da726e9c7b..218ac8614ca73ed16d7d15d9793c698a8446c5b9 100644
--- a/include/caosdb/transaction_status.h
+++ b/include/caosdb/transaction_status.h
@@ -39,11 +39,11 @@ using caosdb::exceptions::TransactionTypeError;
 /**
  * Define static factory method in the TransactionStatus class.
  */
-#define CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(_StatusName, _StatusCode)    \
-  inline static auto _StatusName()->const TransactionStatus & {                \
-    static const TransactionStatus instance(                                   \
-      _StatusCode, caosdb::get_status_description(_StatusCode));               \
-    return instance;                                                           \
+#define CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(_StatusName, _StatusCode)                        \
+  inline static auto _StatusName()->const TransactionStatus & {                                    \
+    static const TransactionStatus instance(_StatusCode,                                           \
+                                            caosdb::get_status_description(_StatusCode));          \
+    return instance;                                                                               \
   }
 
 /**
@@ -99,25 +99,21 @@ public:
    * possibly due to misconfiguration of the client, errors in the network or
    * because the server is down.
    */
-  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(CONNECTION_ERROR,
-                                            StatusCode::CONNECTION_ERROR)
+  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(CONNECTION_ERROR, StatusCode::CONNECTION_ERROR)
   /**
    * Factory for an AUTHENTICATION_ERROR status.
    *
    * This status means that the RPC layer reported an authentication error.
    */
-  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(AUTHENTICATION_ERROR,
-                                            StatusCode::AUTHENTICATION_ERROR)
+  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(AUTHENTICATION_ERROR, StatusCode::AUTHENTICATION_ERROR)
   /**
    * Another factory for an TRANSACTION_ERROR Status with a detailed
    * description.
    */
-  inline static auto AUTHENTICATION_ERROR(const std::string &details)
-    -> const TransactionStatus {
-    return TransactionStatus(
-      StatusCode::AUTHENTICATION_ERROR,
-      caosdb::get_status_description(StatusCode::AUTHENTICATION_ERROR) +
-        " Original error: " + details);
+  inline static auto AUTHENTICATION_ERROR(const std::string &details) -> const TransactionStatus {
+    return TransactionStatus(StatusCode::AUTHENTICATION_ERROR,
+                             caosdb::get_status_description(StatusCode::AUTHENTICATION_ERROR) +
+                               " Original error: " + details);
   }
   /**
    * Factory for a FILE_UPLOAD_ERROR status.
@@ -125,49 +121,43 @@ public:
    * This status means that the transaction failed during the upload of the
    * file blobs of file entities.
    */
-  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(FILE_UPLOAD_ERROR,
-                                            StatusCode::FILE_UPLOAD_ERROR);
+  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(FILE_UPLOAD_ERROR, StatusCode::FILE_UPLOAD_ERROR);
   /**
    * Factory for a FILE_DOWN_ERROR status.
    *
    * This status means that the transaction failed during the download of the
    * file blobs of file entities.
    */
-  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(FILE_DOWNLOAD_ERROR,
-                                            StatusCode::FILE_DOWNLOAD_ERROR);
+  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(FILE_DOWNLOAD_ERROR, StatusCode::FILE_DOWNLOAD_ERROR);
   /**
    * Factory for a TRANSACTION_ERROR status.
    *
    * This status means that the transaction failed due to errors thrown by the
    * server.
    */
-  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(
-    TRANSACTION_ERROR, StatusCode::GENERIC_TRANSACTION_ERROR)
+  CAOSDB_TRANSACTION_STATUS_DEFAULT_FACTORY(TRANSACTION_ERROR,
+                                            StatusCode::GENERIC_TRANSACTION_ERROR)
   /**
    * Another factory for a TRANSACTION_ERROR status with a detailed
    * description.
    */
-  inline static auto TRANSACTION_ERROR(const std::string &details)
-    -> const TransactionStatus {
-    return TransactionStatus(
-      StatusCode::GENERIC_TRANSACTION_ERROR,
-      caosdb::get_status_description(StatusCode::GENERIC_TRANSACTION_ERROR) +
-        " Original error: " + details);
+  inline static auto TRANSACTION_ERROR(const std::string &details) -> const TransactionStatus {
+    return TransactionStatus(StatusCode::GENERIC_TRANSACTION_ERROR,
+                             caosdb::get_status_description(StatusCode::GENERIC_TRANSACTION_ERROR) +
+                               " Original error: " + details);
   }
   /**
    * Factory for a RPC_ERROR with a detailed description.
    *
    * This status is used for any error on the RPC layer.
    */
-  inline static auto RPC_ERROR(const std::string &details)
-    -> const TransactionStatus {
+  inline static auto RPC_ERROR(const std::string &details) -> const TransactionStatus {
     // We use the GENERIC_RPC_ERROR here because we might want to add further
     // RPC_ERROR states with different error codes (which stem from GRPC) here
     // in the future.
-    return TransactionStatus(
-      StatusCode::GENERIC_RPC_ERROR,
-      caosdb::get_status_description(StatusCode::GENERIC_RPC_ERROR) +
-        " Original error: " + details);
+    return TransactionStatus(StatusCode::GENERIC_RPC_ERROR,
+                             caosdb::get_status_description(StatusCode::GENERIC_RPC_ERROR) +
+                               " Original error: " + details);
   }
 
   /**
@@ -177,18 +167,16 @@ public:
    * supposedly do not have a special handling.
    */
   inline static auto GENERIC_ERROR(const std::string &details) {
-    return TransactionStatus(
-      StatusCode::GENERIC_ERROR,
-      caosdb::get_status_description(StatusCode::GENERIC_ERROR) +
-        "Original error: " + details);
+    return TransactionStatus(StatusCode::GENERIC_ERROR,
+                             caosdb::get_status_description(StatusCode::GENERIC_ERROR) +
+                               "Original error: " + details);
   }
 
   inline auto ThrowExceptionIfError() const -> void {
     TransactionStatus::ThrowExceptionIfError(this->code, this->description);
   }
 
-  inline static auto ThrowExceptionIfError(StatusCode code,
-                                           const std::string &description)
+  inline static auto ThrowExceptionIfError(StatusCode code, const std::string &description)
     -> void {
     if (!IsError(code)) {
       return;
@@ -222,18 +210,14 @@ public:
   /**
    * Return true if this TransactionStatus represents an erroneous state.
    */
-  inline auto IsError() const -> bool {
-    return TransactionStatus::IsError(this->code);
-  };
+  inline auto IsError() const -> bool { return TransactionStatus::IsError(this->code); };
 
   /**
    * Return a description of the erroneous state.
    *
    * No description yields an empty string.
    */
-  inline auto GetDescription() const -> const std::string & {
-    return this->description;
-  }
+  inline auto GetDescription() const -> const std::string & { return this->description; }
 
   /**
    * Return the status code of the state.
diff --git a/include/caosdb/unary_rpc_handler.h b/include/caosdb/unary_rpc_handler.h
index 6955504a2baea38cb0bd8075bdca2d20c9f8a52a..0d35eec0f03d546b70ae5c1c59aa057896bb575b 100644
--- a/include/caosdb/unary_rpc_handler.h
+++ b/include/caosdb/unary_rpc_handler.h
@@ -60,8 +60,7 @@ namespace caosdb::transaction {
 class UnaryRpcHandler : public HandlerInterface {
 public:
   inline UnaryRpcHandler(grpc::CompletionQueue *completion_queue)
-    : HandlerInterface(), state_(CallState::NewCall),
-      completion_queue(completion_queue) {}
+    : HandlerInterface(), state_(CallState::NewCall), completion_queue(completion_queue) {}
 
   void Start() override {
     transaction_status = TransactionStatus::EXECUTING();
diff --git a/include/caosdb/utility.h b/include/caosdb/utility.h
index dd53ff952b9737fe76222d998b6813e744b0ad3d..0cadf664346b31f7de19134eed02d13ff148269d 100644
--- a/include/caosdb/utility.h
+++ b/include/caosdb/utility.h
@@ -21,20 +21,25 @@
 
 #ifndef CAOSDB_UTILS_H
 #define CAOSDB_UTILS_H
+#include "caosdb/entity.h"
+#include "caosdb/data_type.h"
 #include <boost/beast/core/detail/base64.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/filesystem/string_file.hpp>
+#include <boost/lexical_cast.hpp> // for lexical_cast
 #include <boost/json.hpp>
 #include <cassert>
 #include <cstdlib>
+#include <exception> // for logic_error
 #include <fstream>
 #include <iostream>
+#include <map>
 #include <memory>
-#include <string>
-#include <string_view>
 #include <mutex>
 #include <shared_mutex>
+#include <string>
+#include <string_view>
 
 namespace caosdb::utility {
 using boost::filesystem::exists;
@@ -43,6 +48,43 @@ using boost::filesystem::path;
 using boost::json::stream_parser;
 using boost::json::value;
 
+/**
+ * @brief Get the name of the enum value.  May be useful for higher-order CaosDB clients.
+ */
+template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string {
+  if (std::is_same_v<std::underlying_type_t<Enum>, int>) {
+    return boost::lexical_cast<std::string>(static_cast<int>(v));
+  }
+  throw std::logic_error(std::string("Enum type ") + typeid(v).name() + " not implemented.");
+}
+
+// Forward declaration of specializations
+template <>
+auto getEnumNameFromValue<caosdb::entity::AtomicDataType>(caosdb::entity::AtomicDataType v)
+  -> std::string;
+template <>
+auto getEnumNameFromValue<caosdb::entity::Importance>(caosdb::entity::Importance v) -> std::string;
+template <> auto getEnumNameFromValue<caosdb::entity::Role>(caosdb::entity::Role v) -> std::string;
+
+/**
+ * @brief Get the enum value from a string.
+ *
+ * @detail May be useful for higher-order CaosDB clients and only makes sense if specialized.
+ */
+template <typename Enum> auto getEnumValueFromName(const std::string &name) -> Enum {
+  throw std::logic_error(std::string("Enum type ") + typeid(Enum).name() + " not implemented.");
+}
+
+// Forward declaration of specializations
+template <>
+auto getEnumValueFromName<caosdb::entity::AtomicDataType>(const std::string &name)
+  -> caosdb::entity::AtomicDataType;
+template <>
+auto getEnumValueFromName<caosdb::entity::Importance>(const std::string &name)
+  -> caosdb::entity::Importance;
+template <>
+auto getEnumValueFromName<caosdb::entity::Role>(const std::string &name) -> caosdb::entity::Role;
+
 /**
  * @brief Read a text file into a string and return the file's content.
  */
@@ -68,8 +110,7 @@ inline auto get_env_var(const char *key, const char *fallback) -> const char * {
  * @brief Return the value of an environment variable or - if undefined - the
  * fallback value.
  */
-inline auto get_env_var(const std::string &key, const std::string &fallback)
-  -> const std::string {
+inline auto get_env_var(const std::string &key, const std::string &fallback) -> const std::string {
   const char *val = get_env_var(key.c_str(), fallback.c_str());
 
   auto const result = std::string(val);
@@ -84,8 +125,7 @@ inline auto base64_encode(const std::string &plain) -> std::string {
   auto size_encoded = boost::beast::detail::base64::encoded_size(size_plain);
 
   std::unique_ptr<char[]> encoded(new char[size_encoded]);
-  boost::beast::detail::base64::encode(encoded.get(), plain.c_str(),
-                                       size_plain);
+  boost::beast::detail::base64::encode(encoded.get(), plain.c_str(), size_plain);
 
   // the encoded char[] is not null terminated, so explicitely set the length
   return std::string(encoded.get(), encoded.get() + size_encoded);
diff --git a/include/caosdb/value.h b/include/caosdb/value.h
new file mode 100644
index 0000000000000000000000000000000000000000..989f780ed25a535fb34a97281f55e29c005a6c53
--- /dev/null
+++ b/include/caosdb/value.h
@@ -0,0 +1,213 @@
+/*
+ * 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/>.
+ *
+ */
+
+#ifndef CAOSDB_VALUE_H
+#define CAOSDB_VALUE_H
+#include "caosdb/protobuf_helper.h"         // for ProtoMessageWrapper
+#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message
+#include "caosdb/logging.h"
+#include <google/protobuf/util/json_util.h> // for MessageToJson...
+#include <memory>                           // for unique_ptr
+#include <string>                           // for string
+#include <vector>                           // for vector
+
+#define LIST_VALUE_CONSTRUCTOR(TYPE, SETTER)                                                       \
+  explicit inline Value(const std::vector<TYPE> &values) : ProtoMessageWrapper<ProtoValue>() {     \
+    for (const auto &value : values) {                                                             \
+      this->wrapped->mutable_list_values()->add_values()->SETTER(value);                           \
+    }                                                                                              \
+  }
+
+namespace caosdb::entity {
+using caosdb::utility::ProtoMessageWrapper;
+using ProtoSpecialValue = caosdb::entity::v1alpha1::SpecialValue;
+using ProtoValue = caosdb::entity::v1alpha1::Value;
+using ProtoScalarValue = caosdb::entity::v1alpha1::ScalarValue;
+using ValueCase = caosdb::entity::v1alpha1::Value::ValueCase;
+using ScalarValueCase = caosdb::entity::v1alpha1::ScalarValue::ScalarValueCase;
+
+class Entity;
+class Property;
+
+// Represents special values which are otherwise hard to tranfer via protobuf.
+enum SpecialValue {
+  // Represent the NULL value.
+  NULL_VALUE = ProtoSpecialValue::SPECIAL_VALUE_UNSPECIFIED,
+  // The empty string.
+  EMPTY_STRING = ProtoSpecialValue::SPECIAL_VALUE_EMPTY_STRING,
+};
+
+class ScalarValue : public ProtoMessageWrapper<ProtoScalarValue> {
+public:
+  inline ScalarValue(ProtoScalarValue *wrapped) : ProtoMessageWrapper<ProtoScalarValue>(wrapped) {}
+
+  [[nodiscard]] inline auto IsString() const noexcept -> bool {
+    return (this->wrapped->scalar_value_case() == ScalarValueCase::kStringValue) ||
+           (this->wrapped->scalar_value_case() == ScalarValueCase::kSpecialValue &&
+            this->wrapped->special_value() == ProtoSpecialValue::SPECIAL_VALUE_EMPTY_STRING);
+    return false;
+  }
+  [[nodiscard]] inline auto AsString() const noexcept -> const std::string & {
+    return this->wrapped->string_value();
+    ;
+  }
+
+  [[nodiscard]] inline auto IsDouble() const noexcept -> bool {
+    return (this->wrapped->scalar_value_case() == ScalarValueCase::kDoubleValue);
+  }
+  [[nodiscard]] inline auto AsDouble() const noexcept -> double {
+    return this->wrapped->double_value();
+  }
+
+  [[nodiscard]] inline auto IsInteger() const noexcept -> bool {
+    return (this->wrapped->scalar_value_case() == ScalarValueCase::kIntegerValue);
+  }
+  [[nodiscard]] inline auto AsInteger() const noexcept -> int64_t {
+    return this->wrapped->integer_value();
+  }
+
+  [[nodiscard]] inline auto IsBool() const noexcept -> bool {
+    return (this->wrapped->scalar_value_case() == ScalarValueCase::kBooleanValue);
+  }
+  [[nodiscard]] inline auto AsBool() const noexcept -> bool {
+    return this->wrapped->boolean_value();
+  }
+};
+
+class Value : public ProtoMessageWrapper<ProtoValue> {
+public:
+  inline Value() : ProtoMessageWrapper<ProtoValue>() {
+    // has NULL_VALUE now
+  }
+  explicit inline Value(ProtoValue *wrapped) : ProtoMessageWrapper<ProtoValue>(wrapped) {}
+  explicit inline Value(const std::string &value) : ProtoMessageWrapper<ProtoValue>() {
+    this->wrapped->mutable_scalar_value()->set_string_value(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);
+  }
+  explicit inline Value(int64_t value) : ProtoMessageWrapper<ProtoValue>() {
+    this->wrapped->mutable_scalar_value()->set_integer_value(value);
+  }
+  explicit inline Value(int value) : Value((int64_t)value) {}
+  explicit inline Value(bool value) : ProtoMessageWrapper<ProtoValue>() {
+    this->wrapped->mutable_scalar_value()->set_boolean_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() const noexcept -> bool {
+    return this->wrapped->value_case() == ValueCase::VALUE_NOT_SET;
+  }
+
+  [[nodiscard]] inline auto IsString() const noexcept -> bool {
+    if (this->wrapped->value_case() == ValueCase::kScalarValue) {
+
+      return (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kStringValue) ||
+             (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kSpecialValue &&
+              this->wrapped->scalar_value().special_value() ==
+                ProtoSpecialValue::SPECIAL_VALUE_EMPTY_STRING);
+    }
+    return false;
+  }
+  [[nodiscard]] inline auto AsString() const noexcept -> const std::string & {
+    return this->wrapped->scalar_value().string_value();
+    ;
+  }
+
+  [[nodiscard]] inline auto IsDouble() const noexcept -> bool {
+    if (this->wrapped->value_case() == ValueCase::kScalarValue) {
+
+      return (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kDoubleValue);
+    }
+    return false;
+  }
+  [[nodiscard]] inline auto AsDouble() const noexcept -> double {
+    return this->wrapped->scalar_value().double_value();
+  }
+
+  [[nodiscard]] inline auto IsInteger() const noexcept -> bool {
+    if (this->wrapped->value_case() == ValueCase::kScalarValue) {
+
+      return (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kIntegerValue);
+    }
+    return false;
+  }
+  [[nodiscard]] inline auto AsInteger() const noexcept -> int64_t {
+    return this->wrapped->scalar_value().integer_value();
+  }
+
+  [[nodiscard]] inline auto IsBool() const noexcept -> bool {
+    if (this->wrapped->value_case() == ValueCase::kScalarValue) {
+
+      return (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kBooleanValue);
+    }
+    return false;
+  }
+  [[nodiscard]] inline auto AsBool() const noexcept -> bool {
+    return this->wrapped->scalar_value().boolean_value();
+  }
+
+  [[nodiscard]] inline auto IsList() const noexcept -> bool {
+    return this->wrapped->value_case() == ValueCase::kListValues;
+  }
+  [[nodiscard]] inline auto AsList() const noexcept -> const std::vector<ScalarValue> & {
+    if (!IsList()) {
+      // create empty list
+      this->list_values = std::make_unique<std::vector<ScalarValue>>();
+    }
+    if (this->list_values == nullptr) {
+      this->list_values = std::make_unique<std::vector<ScalarValue>>();
+      for (auto &scalar : *(this->wrapped->mutable_list_values()->mutable_values())) {
+        this->list_values->push_back(ScalarValue(&scalar));
+      }
+    }
+    return *(this->list_values);
+  }
+
+  inline auto operator==(const Value &other) const noexcept -> bool {
+    return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString();
+  }
+
+  inline auto ToString() const noexcept -> const std::string {
+    CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out)
+    CAOSDB_LOG_DEBUG("caosdb::entity") << "HERE 1 [" << wrapped << "] " << out;
+    return out;
+  }
+
+  friend class Entity;
+  friend class Property;
+
+private:
+  mutable std::unique_ptr<std::vector<ScalarValue>> list_values;
+};
+
+} // namespace caosdb::entity
+
+#endif
diff --git a/include/ccaosdb.h b/include/ccaosdb.h
index 4597690ee2f77e18b086df702b97642b18d19744..d2f899fd7657fa4c3867f2e008ff9fb270ca8490 100644
--- a/include/ccaosdb.h
+++ b/include/ccaosdb.h
@@ -137,8 +137,7 @@ int caosdb_connection_create_pem_file_certificate_provider(
  *
  * EXPERT USE ONLY.  Only use it when you know what you are doing.
  */
-int caosdb_connection_delete_certificate_provider(
-  caosdb_connection_certificate_provider *provider);
+int caosdb_connection_delete_certificate_provider(caosdb_connection_certificate_provider *provider);
 
 /**
  * Create a tls-secured connection configuration.
@@ -153,8 +152,8 @@ int caosdb_connection_delete_certificate_provider(
  * Only use it when you know what you are doing.
  */
 int caosdb_connection_create_tls_connection_configuration(
-  caosdb_connection_connection_configuration *out, const char *host,
-  const int port, caosdb_authentication_authenticator *authenticator,
+  caosdb_connection_connection_configuration *out, const char *host, const int port,
+  caosdb_authentication_authenticator *authenticator,
   caosdb_connection_certificate_provider *provider);
 
 /**
@@ -173,8 +172,7 @@ int caosdb_connection_create_tls_connection_configuration(
  * Only use it when you know what you are doing.
  */
 int caosdb_connection_create_insecure_connection_configuration(
-  caosdb_connection_connection_configuration *out, const char *host,
-  const int port);
+  caosdb_connection_connection_configuration *out, const char *host, const int port);
 
 /**
  * Destructor function for the caosdb_connection_connection_configuration
@@ -192,8 +190,7 @@ int caosdb_connection_delete_connection_configuration(
  * @param cacert path to a pem-file.
  */
 int caosdb_connection_configuration_add_cacert(
-  caosdb_connection_connection_configuration *configuration,
-  const char *cacert);
+  caosdb_connection_connection_configuration *configuration, const char *cacert);
 
 /**
  * Create a plain password authenticator.
@@ -206,16 +203,14 @@ int caosdb_connection_configuration_add_cacert(
  * Only use it when you know what you are doing.
  */
 int caosdb_authentication_create_plain_password_authenticator(
-  caosdb_authentication_authenticator *out, const char *username,
-  const char *password);
+  caosdb_authentication_authenticator *out, const char *username, const char *password);
 
 /**
  * Destructor function for the caosdb_authentication_authenticator struct.
  *
  * EXPERT USE ONLY.  Only use it when you know what you are doing.
  */
-int caosdb_authentication_delete_authenticator(
-  caosdb_authentication_authenticator *authenticator);
+int caosdb_authentication_delete_authenticator(caosdb_authentication_authenticator *authenticator);
 
 /**
  * Create a connection instance.
@@ -239,31 +234,28 @@ int caosdb_connection_create_connection(
  *
  * EXPERT USE ONLY.  Only use it when you know what you are doing.
  */
-int caosdb_connection_delete_connection(
-  caosdb_connection_connection *connection);
+int caosdb_connection_delete_connection(caosdb_connection_connection *connection);
 
 /**
  * Request the version of the server.
  */
-int caosdb_connection_get_version_info(
-  caosdb_info_version_info *out,
-  const caosdb_connection_connection *connection);
+int caosdb_connection_get_version_info(caosdb_info_version_info *out,
+                                       const caosdb_connection_connection *connection);
 
 /**
  * Get the default connection from the ConnectionManager.
  *
  * The default connection is to be specified in a configuration file.
  */
-int caosdb_connection_connection_manager_get_default_connection(
-  caosdb_connection_connection *out);
+int caosdb_connection_connection_manager_get_default_connection(caosdb_connection_connection *out);
 
 /**
  * Get a named connection from the ConnectionManager.
  *
  * The named connection is to be specified in a configuration file.
  */
-int caosdb_connection_connection_manager_get_connection(
-  caosdb_connection_connection *out, const char *name);
+int caosdb_connection_connection_manager_get_connection(caosdb_connection_connection *out,
+                                                        const char *name);
 
 /****************************************************************************
  * ENTITY STUFF AND TRANSACTIONS
@@ -282,19 +274,16 @@ typedef struct {
  * This transaction has to be deleted manually by
  * caosdb_transaction_delete_transaction() later on.
  */
-int caosdb_connection_connection_create_transaction(
-  caosdb_connection_connection *connection,
-  caosdb_transaction_transaction *out);
-int caosdb_transaction_delete_transaction(
-  caosdb_transaction_transaction *transaction);
-int caosdb_transaction_transaction_retrieve_by_id(
-  caosdb_transaction_transaction *transaction, const char *id);
-int caosdb_transaction_transaction_retrieve_by_ids(
-  caosdb_transaction_transaction *transaction, const char *ids[], int length);
-int caosdb_transaction_transaction_query(
-  caosdb_transaction_transaction *transaction, const char *query);
-int caosdb_transaction_transaction_execute(
-  caosdb_transaction_transaction *transaction);
+int caosdb_connection_connection_create_transaction(caosdb_connection_connection *connection,
+                                                    caosdb_transaction_transaction *out);
+int caosdb_transaction_delete_transaction(caosdb_transaction_transaction *transaction);
+int caosdb_transaction_transaction_retrieve_by_id(caosdb_transaction_transaction *transaction,
+                                                  const char *id);
+int caosdb_transaction_transaction_retrieve_by_ids(caosdb_transaction_transaction *transaction,
+                                                   const char *ids[], int length);
+int caosdb_transaction_transaction_query(caosdb_transaction_transaction *transaction,
+                                         const char *query);
+int caosdb_transaction_transaction_execute(caosdb_transaction_transaction *transaction);
 // TODO(fspreck) execute_asynchronously may be added as a separate
 // function once we actually support asynchronous execution.
 
@@ -303,12 +292,11 @@ typedef struct {
   bool _deletable = false;
 } caosdb_transaction_result_set;
 
-int caosdb_transaction_transaction_get_result_set(
-  caosdb_transaction_transaction *transaction,
-  caosdb_transaction_result_set *out);
+int caosdb_transaction_transaction_get_result_set(caosdb_transaction_transaction *transaction,
+                                                  caosdb_transaction_result_set *out);
 
-int caosdb_transaction_transaction_get_count_result(
-  caosdb_transaction_transaction *transaction, long *out);
+int caosdb_transaction_transaction_get_count_result(caosdb_transaction_transaction *transaction,
+                                                    long *out);
 
 typedef struct {
   void *wrapped_entity;
@@ -317,8 +305,7 @@ typedef struct {
 
 int caosdb_transaction_result_set_at(caosdb_transaction_result_set *result_set,
                                      caosdb_entity_entity *entity, int index);
-int caosdb_transaction_result_set_size(
-  caosdb_transaction_result_set *result_set, int *out);
+int caosdb_transaction_result_set_size(caosdb_transaction_result_set *result_set, int *out);
 
 typedef struct {
   void *wrapped_property;
@@ -337,55 +324,41 @@ typedef struct {
 int caosdb_entity_entity_get_id(caosdb_entity_entity *entity, char *out);
 int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char *out);
 int caosdb_entity_entity_get_name(caosdb_entity_entity *entity, char *out);
-int caosdb_entity_entity_get_description(caosdb_entity_entity *entity,
-                                         char *out);
+int caosdb_entity_entity_get_description(caosdb_entity_entity *entity, char *out);
 int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, char *out);
 int caosdb_entity_entity_get_unit(caosdb_entity_entity *entity, char *out);
 int caosdb_entity_entity_get_value(caosdb_entity_entity *entity, char *out);
-int caosdb_entity_entity_get_version_id(caosdb_entity_entity *entity,
-                                        char *out);
-int caosdb_entity_entity_get_errors_size(caosdb_entity_entity *entity,
-                                         int *out);
-int caosdb_entity_entity_get_error(caosdb_entity_entity *entity,
-                                   caosdb_entity_message *out, int index);
-int caosdb_entity_entity_get_warnings_size(caosdb_entity_entity *entity,
-                                           int *out);
-int caosdb_entity_entity_get_warning(caosdb_entity_entity *entity,
-                                     caosdb_entity_message *out, int index);
+int caosdb_entity_entity_get_version_id(caosdb_entity_entity *entity, char *out);
+int caosdb_entity_entity_get_errors_size(caosdb_entity_entity *entity, int *out);
+int caosdb_entity_entity_get_error(caosdb_entity_entity *entity, caosdb_entity_message *out,
+                                   int index);
+int caosdb_entity_entity_get_warnings_size(caosdb_entity_entity *entity, int *out);
+int caosdb_entity_entity_get_warning(caosdb_entity_entity *entity, caosdb_entity_message *out,
+                                     int index);
 int caosdb_entity_entity_get_infos_size(caosdb_entity_entity *entity, int *out);
-int caosdb_entity_entity_get_info(caosdb_entity_entity *entity,
-                                  caosdb_entity_message *out, int index);
-int caosdb_entity_entity_get_properties_size(caosdb_entity_entity *entity,
-                                             int *out);
-int caosdb_entity_entity_get_property(caosdb_entity_entity *entity,
-                                      caosdb_entity_property *out, int index);
-int caosdb_entity_entity_get_parents_size(caosdb_entity_entity *entity,
-                                          int *out);
-int caosdb_entity_entity_get_parent(caosdb_entity_entity *entity,
-                                    caosdb_entity_parent *out, int index);
+int caosdb_entity_entity_get_info(caosdb_entity_entity *entity, caosdb_entity_message *out,
+                                  int index);
+int caosdb_entity_entity_get_properties_size(caosdb_entity_entity *entity, int *out);
+int caosdb_entity_entity_get_property(caosdb_entity_entity *entity, caosdb_entity_property *out,
+                                      int index);
+int caosdb_entity_entity_get_parents_size(caosdb_entity_entity *entity, int *out);
+int caosdb_entity_entity_get_parent(caosdb_entity_entity *entity, caosdb_entity_parent *out,
+                                    int index);
 
 int caosdb_entity_property_get_id(caosdb_entity_property *property, char *out);
-int caosdb_entity_property_get_name(caosdb_entity_property *property,
-                                    char *out);
-int caosdb_entity_property_get_description(caosdb_entity_property *property,
-                                           char *out);
-int caosdb_entity_property_get_importance(caosdb_entity_property *property,
-                                          char *out);
-int caosdb_entity_property_get_datatype(caosdb_entity_property *property,
-                                        char *out);
-int caosdb_entity_property_get_unit(caosdb_entity_property *property,
-                                    char *out);
-int caosdb_entity_property_get_value(caosdb_entity_property *property,
-                                     char *out);
+int caosdb_entity_property_get_name(caosdb_entity_property *property, char *out);
+int caosdb_entity_property_get_description(caosdb_entity_property *property, char *out);
+int caosdb_entity_property_get_importance(caosdb_entity_property *property, char *out);
+int caosdb_entity_property_get_datatype(caosdb_entity_property *property, char *out);
+int caosdb_entity_property_get_unit(caosdb_entity_property *property, char *out);
+int caosdb_entity_property_get_value(caosdb_entity_property *property, char *out);
 
 int caosdb_entity_parent_get_id(caosdb_entity_parent *parent, char *out);
 int caosdb_entity_parent_get_name(caosdb_entity_parent *parent, char *out);
-int caosdb_entity_parent_get_description(caosdb_entity_parent *parent,
-                                         char *out);
+int caosdb_entity_parent_get_description(caosdb_entity_parent *parent, char *out);
 
 int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out);
-int caosdb_entity_message_get_description(caosdb_entity_message *message,
-                                          char *out);
+int caosdb_entity_message_get_description(caosdb_entity_message *message, char *out);
 
 // CONSTRUCTORS AND DESTRUCTORS
 int caosdb_entity_create_entity(caosdb_entity_entity *out);
@@ -396,42 +369,27 @@ int caosdb_entity_create_parent(caosdb_entity_parent *out);
 int caosdb_entity_delete_parent(caosdb_entity_parent *out);
 
 // SETTERS FOR EVERYTHING THAT MAY BE SET
-int caosdb_entity_entity_set_role(caosdb_entity_entity *entity,
-                                  const char *role);
-int caosdb_entity_entity_set_name(caosdb_entity_entity *entity,
-                                  const char *name);
-int caosdb_entity_entity_set_description(caosdb_entity_entity *entity,
-                                         const char *description);
-int caosdb_entity_entity_set_datatype(caosdb_entity_entity *entity,
-                                      const char *datatype);
-int caosdb_entity_entity_set_unit(caosdb_entity_entity *entity,
-                                  const char *unit);
-int caosdb_entity_entity_set_value(caosdb_entity_entity *entity,
-                                   const char *value);
-int caosdb_entity_entity_append_parent(caosdb_entity_entity *entity,
-                                       caosdb_entity_parent *parent);
+int caosdb_entity_entity_set_role(caosdb_entity_entity *entity, const char *role);
+int caosdb_entity_entity_set_name(caosdb_entity_entity *entity, const char *name);
+int caosdb_entity_entity_set_description(caosdb_entity_entity *entity, const char *description);
+int caosdb_entity_entity_set_datatype(caosdb_entity_entity *entity, const char *datatype);
+int caosdb_entity_entity_set_unit(caosdb_entity_entity *entity, const char *unit);
+int caosdb_entity_entity_set_value(caosdb_entity_entity *entity, const char *value);
+int caosdb_entity_entity_append_parent(caosdb_entity_entity *entity, caosdb_entity_parent *parent);
 int caosdb_entity_entity_remove_parent(caosdb_entity_entity *entity, int index);
 int caosdb_entity_entity_append_property(caosdb_entity_entity *entity,
                                          caosdb_entity_property *property);
-int caosdb_entity_entity_remove_property(caosdb_entity_entity *entity,
-                                         int index);
-
-int caosdb_entity_property_set_id(caosdb_entity_property *property,
-                                  const char *id);
-int caosdb_entity_property_set_name(caosdb_entity_property *property,
-                                    const char *name);
-int caosdb_entity_property_set_datatype(caosdb_entity_property *property,
-                                        const char *datatype);
-int caosdb_entity_property_set_importance(caosdb_entity_property *property,
-                                          const char *importance);
-int caosdb_entity_property_set_unit(caosdb_entity_property *property,
-                                    const char *unit);
-int caosdb_entity_property_set_value(caosdb_entity_property *property,
-                                     const char *value);
+int caosdb_entity_entity_remove_property(caosdb_entity_entity *entity, int index);
+
+int caosdb_entity_property_set_id(caosdb_entity_property *property, const char *id);
+int caosdb_entity_property_set_name(caosdb_entity_property *property, const char *name);
+int caosdb_entity_property_set_datatype(caosdb_entity_property *property, const char *datatype);
+int caosdb_entity_property_set_importance(caosdb_entity_property *property, const char *importance);
+int caosdb_entity_property_set_unit(caosdb_entity_property *property, const char *unit);
+int caosdb_entity_property_set_value(caosdb_entity_property *property, const char *value);
 
 int caosdb_entity_parent_set_id(caosdb_entity_parent *parent, const char *id);
-int caosdb_entity_parent_set_name(caosdb_entity_parent *parent,
-                                  const char *name);
+int caosdb_entity_parent_set_name(caosdb_entity_parent *parent, const char *name);
 
 #ifdef __cplusplus
 }
diff --git a/proto b/proto
index 485173a714d9ff7c2388945b0a4cad35980cda69..6f81c44a02b9258293bfb83b4de7831ef8d7c4e9 160000
--- a/proto
+++ b/proto
@@ -1 +1 @@
-Subproject commit 485173a714d9ff7c2388945b0a4cad35980cda69
+Subproject commit 6f81c44a02b9258293bfb83b4de7831ef8d7c4e9
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 89180ee81fc6b07d4f081c90fd1200530a2d60b6..cb00898b70776b99c197556c435398d254578cbf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ set(libcaosdb_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/protobuf_helper.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction_handler.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utility.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/unary_rpc_handler.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_upload_handler.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/upload_request_handler.cpp
diff --git a/src/caosdb/authentication.cpp b/src/caosdb/authentication.cpp
index a1c84e5b5b04ebc5e0e6909ad4d274f5389117bb..50ff24455ac87227f475775974abae1228fc50d3 100644
--- a/src/caosdb/authentication.cpp
+++ b/src/caosdb/authentication.cpp
@@ -34,28 +34,28 @@ using grpc::MetadataCredentialsPlugin;
 using grpc::Status;
 using grpc::string_ref;
 
-MetadataCredentialsPluginImpl::MetadataCredentialsPluginImpl(std::string key,
-                                                             std::string value)
+MetadataCredentialsPluginImpl::MetadataCredentialsPluginImpl(std::string key, std::string value)
   : key(std::move(key)), value(std::move(value)) {}
 
-auto MetadataCredentialsPluginImpl::GetMetadata(
-  string_ref /*service_url*/, string_ref /*method_name*/,
-  const AuthContext & /*channel_auth_context*/,
-  std::multimap<grpc::string, grpc::string> *metadata) -> Status {
+auto MetadataCredentialsPluginImpl::GetMetadata(string_ref /*service_url*/,
+                                                string_ref /*method_name*/,
+                                                const AuthContext & /*channel_auth_context*/,
+                                                std::multimap<grpc::string, grpc::string> *metadata)
+  -> Status {
 
   metadata->insert(std::make_pair(this->key, this->value));
   return Status::OK;
 }
 
-PlainPasswordAuthenticator::PlainPasswordAuthenticator(
-  const std::string &username, const std::string &password) {
+PlainPasswordAuthenticator::PlainPasswordAuthenticator(const std::string &username,
+                                                       const std::string &password) {
   this->basic = "Basic " + base64_encode(username + ":" + password);
 }
 
 auto PlainPasswordAuthenticator::GetCallCredentials() const
   -> std::shared_ptr<grpc::CallCredentials> {
-  auto call_creds = grpc::MetadataCredentialsFromPlugin(
-    std::unique_ptr<grpc::MetadataCredentialsPlugin>(
+  auto call_creds =
+    grpc::MetadataCredentialsFromPlugin(std::unique_ptr<grpc::MetadataCredentialsPlugin>(
       new MetadataCredentialsPluginImpl("authentication", this->basic)));
   return call_creds;
 }
diff --git a/src/caosdb/configuration.cpp b/src/caosdb/configuration.cpp
index 5ebda79ff7e8f8cc59a72f19a8ec4970ace5c1b4..edce302e00bcb5645d734e2ff577be23d0a8bd67 100644
--- a/src/caosdb/configuration.cpp
+++ b/src/caosdb/configuration.cpp
@@ -75,8 +75,7 @@ auto PemFileCertificateProvider::GetCertificatePem() const -> std::string {
   return this->certificate_provider;
 }
 
-PemCertificateProvider::PemCertificateProvider(
-  const std::string &certificate_provider) {
+PemCertificateProvider::PemCertificateProvider(const std::string &certificate_provider) {
   this->certificate_provider = certificate_provider;
 }
 
@@ -84,26 +83,21 @@ auto PemCertificateProvider::GetCertificatePem() const -> std::string {
   return this->certificate_provider;
 }
 
-ConnectionConfiguration::ConnectionConfiguration(const std::string &host,
-                                                 int port) {
+ConnectionConfiguration::ConnectionConfiguration(const std::string &host, int port) {
   this->host = host;
   this->port = port;
 }
 
-auto ConnectionConfiguration::GetHost() const -> std::string {
-  return this->host;
-}
+auto ConnectionConfiguration::GetHost() const -> std::string { return this->host; }
 
 auto ConnectionConfiguration::GetPort() const -> int { return this->port; }
 
-auto operator<<(std::ostream &out, const ConnectionConfiguration &configuration)
-  -> std::ostream & {
+auto operator<<(std::ostream &out, const ConnectionConfiguration &configuration) -> std::ostream & {
   out << configuration.ToString();
   return out;
 }
 
-InsecureConnectionConfiguration::InsecureConnectionConfiguration(
-  const std::string &host, int port)
+InsecureConnectionConfiguration::InsecureConnectionConfiguration(const std::string &host, int port)
   : ConnectionConfiguration(host, port) {
   this->credentials = InsecureChannelCredentials();
 }
@@ -118,41 +112,38 @@ auto InsecureConnectionConfiguration::ToString() const -> std::string {
          std::to_string(this->GetPort()) + ")";
 }
 
-TlsConnectionConfiguration::TlsConnectionConfiguration(const std::string &host,
-                                                       int port)
+TlsConnectionConfiguration::TlsConnectionConfiguration(const std::string &host, int port)
   : ConnectionConfiguration(host, port) {
   SslCredentialsOptions options;
   this->credentials = SslCredentials(options);
 }
 
 TlsConnectionConfiguration::TlsConnectionConfiguration(
-  const std::string &host, int port,
-  const CertificateProvider &certificate_provider)
+  const std::string &host, int port, const CertificateProvider &certificate_provider)
   : ConnectionConfiguration(host, port) {
   SslCredentialsOptions options;
   options.pem_root_certs = certificate_provider.GetCertificatePem();
   this->credentials = SslCredentials(options);
 }
 
-TlsConnectionConfiguration::TlsConnectionConfiguration(
-  const std::string &host, int port, const Authenticator &authenticator)
+TlsConnectionConfiguration::TlsConnectionConfiguration(const std::string &host, int port,
+                                                       const Authenticator &authenticator)
   : ConnectionConfiguration(host, port) {
 
   SslCredentialsOptions options;
-  this->credentials = grpc::CompositeChannelCredentials(
-    SslCredentials(options), authenticator.GetCallCredentials());
+  this->credentials =
+    grpc::CompositeChannelCredentials(SslCredentials(options), authenticator.GetCallCredentials());
 }
 
 TlsConnectionConfiguration::TlsConnectionConfiguration(
-  const std::string &host, int port,
-  const CertificateProvider &certificate_provider,
+  const std::string &host, int port, const CertificateProvider &certificate_provider,
   const Authenticator &authenticator)
   : ConnectionConfiguration(host, port) {
 
   SslCredentialsOptions options;
   options.pem_root_certs = certificate_provider.GetCertificatePem();
-  this->credentials = grpc::CompositeChannelCredentials(
-    SslCredentials(options), authenticator.GetCallCredentials());
+  this->credentials =
+    grpc::CompositeChannelCredentials(SslCredentials(options), authenticator.GetCallCredentials());
 }
 
 auto TlsConnectionConfiguration::GetChannelCredentials() const
@@ -161,31 +152,29 @@ auto TlsConnectionConfiguration::GetChannelCredentials() const
 }
 
 auto TlsConnectionConfiguration::ToString() const -> std::string {
-  return "TlsConnectionConfiguration(" + this->GetHost() + "," +
-         std::to_string(this->GetPort()) + "," + this->certificate_provider +
-         ")";
+  return "TlsConnectionConfiguration(" + this->GetHost() + "," + std::to_string(this->GetPort()) +
+         "," + this->certificate_provider + ")";
 }
 
-auto ConnectionConfigurationHelper::CreateCertificateProvider(
-  const object &from) const -> std::unique_ptr<CertificateProvider> {
+auto ConnectionConfigurationHelper::CreateCertificateProvider(const object &from) const
+  -> std::unique_ptr<CertificateProvider> {
   std::unique_ptr<CertificateProvider> certificate_provider;
   if (from.contains("server_certificate_path")) {
     const value &path_str = from.at("server_certificate_path");
     assert(path_str.is_string() == true);
     const path certificate_file = path(path_str.as_string().c_str());
     if (!exists(certificate_file)) {
-      throw ConfigurationError(
-        "File does not exist (server_certificate_path): " +
-        certificate_file.string());
+      throw ConfigurationError("File does not exist (server_certificate_path): " +
+                               certificate_file.string());
     }
-    certificate_provider = std::make_unique<PemFileCertificateProvider>(
-      path(path_str.as_string().c_str()));
+    certificate_provider =
+      std::make_unique<PemFileCertificateProvider>(path(path_str.as_string().c_str()));
   }
   return certificate_provider;
 }
 
-auto ConnectionConfigurationHelper::CreateAuthenticator(
-  const object &from) const -> std::unique_ptr<Authenticator> {
+auto ConnectionConfigurationHelper::CreateAuthenticator(const object &from) const
+  -> std::unique_ptr<Authenticator> {
   std::unique_ptr<Authenticator> authenticator;
   if (from.contains("authentication")) {
     assert(from.at("authentication").is_object());
@@ -205,8 +194,7 @@ auto ConnectionConfigurationHelper::CreateAuthenticator(
       assert(password.is_string());
 
       authenticator = std::make_unique<PlainPasswordAuthenticator>(
-        std::string(username.as_string().c_str()),
-        std::string(password.as_string().c_str()));
+        std::string(username.as_string().c_str()), std::string(password.as_string().c_str()));
     } else {
       throw ConfigurationError("Unknow authentication type: '" + type + "'.");
     }
@@ -216,22 +204,19 @@ auto ConnectionConfigurationHelper::CreateAuthenticator(
 
 auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
   const bool tls, const std::string &host, const int port,
-  const CertificateProvider *certificate_provider,
-  const Authenticator *authenticator) const
+  const CertificateProvider *certificate_provider, const Authenticator *authenticator) const
   -> std::unique_ptr<ConnectionConfiguration> {
   if (tls) {
     if (certificate_provider != nullptr && authenticator != nullptr) {
       // authenticated and special certificate
-      return std::make_unique<TlsConnectionConfiguration>(
-        host, port, *certificate_provider, *authenticator);
+      return std::make_unique<TlsConnectionConfiguration>(host, port, *certificate_provider,
+                                                          *authenticator);
     } else if (certificate_provider != nullptr) {
       // unauthenticated, special certificate
-      return std::make_unique<TlsConnectionConfiguration>(
-        host, port, *certificate_provider);
+      return std::make_unique<TlsConnectionConfiguration>(host, port, *certificate_provider);
     } else if (authenticator != nullptr) {
       // authenticated, no special certificate
-      return std::make_unique<TlsConnectionConfiguration>(host, port,
-                                                          *authenticator);
+      return std::make_unique<TlsConnectionConfiguration>(host, port, *authenticator);
     }
     // unauthenticated, no special certificate
     return std::make_unique<TlsConnectionConfiguration>(host, port);
@@ -250,8 +235,8 @@ auto ConnectionConfigurationHelper::IsTls(const object &from) const -> bool {
   return tls;
 }
 
-auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
-  const object &from) const -> std::unique_ptr<ConnectionConfiguration> {
+auto ConnectionConfigurationHelper::CreateConnectionConfiguration(const object &from) const
+  -> std::unique_ptr<ConnectionConfiguration> {
   assert(from.contains("host"));
   const auto &host = from.at("host");
   assert(host.is_string());
@@ -266,28 +251,30 @@ auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
 
   auto authenticator = CreateAuthenticator(from);
 
-  return CreateConnectionConfiguration(
-    tls, std::string(host.as_string().c_str()),
-    static_cast<int>(port.as_int64()), certificate_provider.get(),
-    authenticator.get());
+  return CreateConnectionConfiguration(tls, std::string(host.as_string().c_str()),
+                                       static_cast<int>(port.as_int64()),
+                                       certificate_provider.get(), authenticator.get());
 }
 
-auto LoggingConfigurationHelper::CreateConsoleSinkConfiguration(
-  const object & /*from*/, const std::string &name, int level) const
+auto LoggingConfigurationHelper::CreateConsoleSinkConfiguration(const object & /*from*/,
+                                                                const std::string &name,
+                                                                int level) const
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<ConsoleSinkConfiguration>(name, level);
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateSyslogSinkConfiguration(
-  const object & /*from*/, const std::string &name, int level) const
+auto LoggingConfigurationHelper::CreateSyslogSinkConfiguration(const object & /*from*/,
+                                                               const std::string &name,
+                                                               int level) const
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<SyslogSinkConfiguration>(name, level);
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateFileSinkConfiguration(
-  const object &from, const std::string &name, int level) const
+auto LoggingConfigurationHelper::CreateFileSinkConfiguration(const object &from,
+                                                             const std::string &name,
+                                                             int level) const
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<FileSinkConfiguration>(name, level);
   if (from.contains("directory")) {
@@ -296,16 +283,15 @@ auto LoggingConfigurationHelper::CreateFileSinkConfiguration(
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateSinkConfiguration(
-  const object &from, const std::string &name, int default_level) const
+auto LoggingConfigurationHelper::CreateSinkConfiguration(const object &from,
+                                                         const std::string &name,
+                                                         int default_level) const
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   assert(from.contains("destination"));
-  const auto &destination =
-    std::string(from.at("destination").as_string().c_str());
+  const auto &destination = std::string(from.at("destination").as_string().c_str());
 
-  int level = from.contains("level")
-                ? ConvertLogLevel(from.at("level").as_string().c_str())
-                : default_level;
+  int level =
+    from.contains("level") ? ConvertLogLevel(from.at("level").as_string().c_str()) : default_level;
 
   if (destination == "file") {
     return CreateFileSinkConfiguration(from, name, level);
@@ -318,8 +304,7 @@ auto LoggingConfigurationHelper::CreateSinkConfiguration(
   }
 }
 
-auto LoggingConfigurationHelper::ConvertLogLevel(
-  const std::string &string_level) const -> int {
+auto LoggingConfigurationHelper::ConvertLogLevel(const std::string &string_level) const -> int {
   static std::map<std::string, int> log_level_names = {
     {"", CAOSDB_DEFAULT_LOG_LEVEL},    {"off", CAOSDB_LOG_LEVEL_OFF},
     {"fatal", CAOSDB_LOG_LEVEL_FATAL}, {"error", CAOSDB_LOG_LEVEL_ERROR},
@@ -333,11 +318,10 @@ auto LoggingConfigurationHelper::ConvertLogLevel(
   }
 }
 
-auto LoggingConfigurationHelper::CreateLoggingConfiguration(
-  const object &from) const -> LoggingConfiguration {
-  auto default_level_str = from.contains("level")
-                             ? std::string(from.at("level").as_string().c_str())
-                             : "";
+auto LoggingConfigurationHelper::CreateLoggingConfiguration(const object &from) const
+  -> LoggingConfiguration {
+  auto default_level_str =
+    from.contains("level") ? std::string(from.at("level").as_string().c_str()) : "";
   int default_level = ConvertLogLevel(default_level_str);
 
   auto result = LoggingConfiguration(default_level);
@@ -351,8 +335,8 @@ auto LoggingConfigurationHelper::CreateLoggingConfiguration(
       const auto *elem = sinks.begin();
 
       while (elem != sinks.end()) {
-        result.AddSink(CreateSinkConfiguration(
-          elem->value().as_object(), elem->key().to_string(), default_level));
+        result.AddSink(CreateSinkConfiguration(elem->value().as_object(), elem->key().to_string(),
+                                               default_level));
         elem = std::next(elem);
       }
     }
@@ -369,9 +353,8 @@ auto ConfigurationManager::mReset() noexcept -> int {
   } catch (const caosdb::exceptions::Exception &exc) {
     return exc.GetCode();
   } catch (const std::exception &exc) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "Unknown error during the reset of the ConfigurationManager: "
-      << exc.what();
+    CAOSDB_LOG_ERROR(logger_name) << "Unknown error during the reset of the ConfigurationManager: "
+                                  << exc.what();
     return StatusCode::CONFIGURATION_ERROR;
   }
 }
@@ -384,15 +367,13 @@ auto ConfigurationManager::mClear() noexcept -> int {
   } catch (const caosdb::exceptions::Exception &exc) {
     return exc.GetCode();
   } catch (const std::exception &exc) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "Unknown error during the reset of the ConfigurationManager: "
-      << exc.what();
+    CAOSDB_LOG_ERROR(logger_name) << "Unknown error during the reset of the ConfigurationManager: "
+                                  << exc.what();
     return StatusCode::CONFIGURATION_ERROR;
   }
 }
 
-auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file)
-  -> void {
+auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file) -> void {
   if (!json_configuration.is_null()) {
     throw ConfigurationError("This CaosDB client has already been configured.");
   }
@@ -403,11 +384,10 @@ auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file)
   json_configuration = load_json_file(json_file);
 }
 
-auto ConfigurationManager::mGetConnectionConfiguration(
-  const std::string &name) const -> std::unique_ptr<ConnectionConfiguration> {
+auto ConfigurationManager::mGetConnectionConfiguration(const std::string &name) const
+  -> std::unique_ptr<ConnectionConfiguration> {
   auto connection_json = GetConnection(name);
-  return connection_configuration_helper.CreateConnectionConfiguration(
-    connection_json);
+  return connection_configuration_helper.CreateConnectionConfiguration(connection_json);
 }
 
 auto ConfigurationManager::mGetDefaultConnectionName() const -> std::string {
@@ -442,33 +422,28 @@ auto ConfigurationManager::GetConfiguration() const -> const object & {
 auto ConfigurationManager::GetConnections() const -> const object & {
   const auto &configuration = GetConfiguration();
   if (!configuration.contains("connections")) {
-    throw ConfigurationError(
-      "This CaosDB client hasn't any configured connections.");
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
   }
   const auto &connections_value = configuration.at("connections");
   if (connections_value.is_null()) {
-    throw ConfigurationError(
-      "This CaosDB client hasn't any configured connections.");
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
   }
   assert(connections_value.is_object());
   const auto &connections_object = connections_value.as_object();
   if (connections_object.empty()) {
-    throw ConfigurationError(
-      "This CaosDB client hasn't any configured connections.");
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
   }
   return connections_object;
 }
 
-auto ConfigurationManager::GetConnection(const std::string &name) const
-  -> const object & {
+auto ConfigurationManager::GetConnection(const std::string &name) const -> const object & {
   const auto &connections = GetConnections();
   if (connections.contains(name)) {
     const auto &result_connection = connections.at(name);
     assert(result_connection.is_object());
     return result_connection.as_object();
   }
-  throw ConfigurationError("The connection '" + name +
-                           "' has not been defined.");
+  throw ConfigurationError("The connection '" + name + "' has not been defined.");
 }
 
 // TODO(tf) This has apparently a cognitive complexity of 34>25 (threshold).
@@ -476,13 +451,11 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
 
   // find the configuration file...
   std::unique_ptr<path> configuration_file_path;
-  for (const char *const &configuration_file :
-       caosdb::LIBCAOSDB_CONFIGURATION_FILES_PRECEDENCE) {
+  for (const char *const &configuration_file : caosdb::LIBCAOSDB_CONFIGURATION_FILES_PRECEDENCE) {
     if (strcmp(configuration_file, "$CAOSDB_CLIENT_CONFIGURATION") == 0) {
       // user specified a file via the environment variable
       // TODO(tf) make this thread-secure (concurrency-mt-unsafe)
-      const auto *from_env_var =
-        getenv("CAOSDB_CLIENT_CONFIGURATION"); // NOLINT
+      const auto *from_env_var = getenv("CAOSDB_CLIENT_CONFIGURATION"); // NOLINT
       if (from_env_var != nullptr) {
         configuration_file_path = std::make_unique<path>(from_env_var);
         if (exists(*configuration_file_path)) {
@@ -532,10 +505,9 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
                                     "We are using the default configuration";
   }
 
-  if (configuration_file_path != nullptr &&
-      this->json_configuration.is_object()) {
-    CAOSDB_LOG_INFO(logger_name) << "Loaded configuration from "
-                                 << *(configuration_file_path.get()) << ".";
+  if (configuration_file_path != nullptr && this->json_configuration.is_object()) {
+    CAOSDB_LOG_INFO(logger_name) << "Loaded configuration from " << *(configuration_file_path.get())
+                                 << ".";
   }
 
   return 0;
diff --git a/src/caosdb/connection.cpp b/src/caosdb/connection.cpp
index b43444ce085d262a0ed8e960001e31c8da1a0124..d6782f8ffa42238888998bdff65dc666fbf55c18 100644
--- a/src/caosdb/connection.cpp
+++ b/src/caosdb/connection.cpp
@@ -48,17 +48,14 @@ using caosdb::transaction::TransactionStatus;
 Connection::Connection(const ConnectionConfiguration &configuration) {
   const std::string target =
     configuration.GetHost() + ":" + std::to_string(configuration.GetPort());
-  this->channel =
-    grpc::CreateChannel(target, configuration.GetChannelCredentials());
+  this->channel = grpc::CreateChannel(target, configuration.GetChannelCredentials());
   this->general_info_service = GeneralInfoService::NewStub(this->channel);
   this->entity_transaction_service =
     std::make_shared<EntityTransactionService::Stub>(this->channel);
-  this->file_transmission_service =
-    std::make_shared<FileTransmissionService::Stub>(this->channel);
+  this->file_transmission_service = std::make_shared<FileTransmissionService::Stub>(this->channel);
 }
 
-auto Connection::RetrieveVersionInfoNoExceptions() const noexcept
-  -> TransactionStatus {
+auto Connection::RetrieveVersionInfoNoExceptions() const noexcept -> TransactionStatus {
 
   const GetVersionInfoRequest request;
   GetVersionInfoResponse response;
@@ -70,20 +67,18 @@ auto Connection::RetrieveVersionInfoNoExceptions() const noexcept
   if (!grpc_status.ok()) {
     switch (grpc_status.error_code()) {
     case grpc::StatusCode::UNAUTHENTICATED:
-      status =
-        TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
+      status = TransactionStatus::AUTHENTICATION_ERROR(grpc_status.error_message());
       break;
     case grpc::StatusCode::UNAVAILABLE:
       status = TransactionStatus::CONNECTION_ERROR();
       break;
     default:
       auto error_message = grpc_status.error_message();
-      status = TransactionStatus::RPC_ERROR(
-        std::to_string(grpc_status.error_code()) + " - " + error_message);
+      status = TransactionStatus::RPC_ERROR(std::to_string(grpc_status.error_code()) + " - " +
+                                            error_message);
     }
   } else {
-    this->version_info =
-      std::make_unique<VersionInfo>(response.release_version_info());
+    this->version_info = std::make_unique<VersionInfo>(response.release_version_info());
   }
 
   return status;
@@ -96,8 +91,7 @@ auto Connection::RetrieveVersionInfo() const -> const VersionInfo & {
   return *GetVersionInfo();
 }
 
-[[nodiscard]] auto Connection::CreateTransaction() const
-  -> std::unique_ptr<Transaction> {
+[[nodiscard]] auto Connection::CreateTransaction() const -> std::unique_ptr<Transaction> {
   auto entity_service = this->entity_transaction_service;
   auto file_service = this->file_transmission_service;
   return std::make_unique<Transaction>(entity_service, file_service);
@@ -115,19 +109,17 @@ auto ConnectionManager::mGetConnection(const std::string &name) const
       auto connection = ConfigurationManager::GetConnectionConfiguration(name);
       connections[name] = std::make_shared<Connection>(*connection.release());
     } catch (const caosdb::exceptions::ConfigurationError &exc) {
-      throw caosdb::exceptions::UnknownConnectionError("No connection named '" +
-                                                       name + "' present.");
+      throw caosdb::exceptions::UnknownConnectionError("No connection named '" + name +
+                                                       "' present.");
     }
   }
   return this->connections.at(name);
 }
 
-auto ConnectionManager::mGetDefaultConnection() const
-  -> const std::shared_ptr<Connection> & {
+auto ConnectionManager::mGetDefaultConnection() const -> const std::shared_ptr<Connection> & {
   if (!HasConnection(default_connection_name)) {
     default_connection_name = ConfigurationManager::GetDefaultConnectionName();
-    auto default_connection =
-      ConfigurationManager::GetDefaultConnectionConfiguration();
+    auto default_connection = ConfigurationManager::GetDefaultConnectionConfiguration();
     connections[default_connection_name] =
       std::make_shared<Connection>(*default_connection.release());
   }
diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp
index 8f410a3c6c454375fe827ba8058e20423ef9ccce..16ea5dbfc99b173efdac9bdbbfe0d87a2e289fee 100644
--- a/src/caosdb/entity.cpp
+++ b/src/caosdb/entity.cpp
@@ -20,16 +20,21 @@
  *
  */
 #include "caosdb/entity.h"
-#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Property
-#include "caosdb/protobuf_helper.h"         // for get_arena
-#include <google/protobuf/arena.h>          // for Arena
-#include <new>                              // for operator new
+#include "caosdb/data_type.h"                       // for DataType
+#include "caosdb/entity/v1alpha1/main.pb.h"         // for Messages
+#include "caosdb/protobuf_helper.h"                 // for get_arena
+#include "caosdb/value.h"                           // for Value
+#include <google/protobuf/arena.h>                  // for Arena
+#include <google/protobuf/generated_message_util.h> // for Arena::Create...
+#include <new>                                      // for operator new
 
 namespace caosdb::entity {
 using caosdb::entity::v1alpha1::IdResponse;
 using ProtoParent = caosdb::entity::v1alpha1::Parent;
 using ProtoProperty = caosdb::entity::v1alpha1::Property;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
+using ProtoImportance = caosdb::entity::v1alpha1::Importance;
+using caosdb::entity::v1alpha1::EntityRole;
 using ProtoMessage = caosdb::entity::v1alpha1::Message;
 using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor;
 using caosdb::utility::get_arena;
@@ -49,33 +54,25 @@ 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::SetName(const std::string &name) -> void { this->wrapped->set_name(name); }
 
 auto Parent::SetId(const std::string &id) -> void { this->wrapped->set_id(id); }
 
-[[nodiscard]] auto Parent::GetId() const -> const std::string & {
-  return this->wrapped->id();
-}
+[[nodiscard]] auto Parent::GetId() const -> const std::string & { return this->wrapped->id(); }
 
-[[nodiscard]] auto Parent::GetName() const -> const std::string & {
-  return this->wrapped->name();
-}
+[[nodiscard]] auto Parent::GetName() const -> const std::string & { return this->wrapped->name(); }
 
 [[nodiscard]] auto Parent::GetDescription() const -> const std::string & {
   return this->wrapped->description();
 }
 
-Property::Property() : wrapped(Property::CreateProtoProperty()) {}
+Property::Property() : Property(Property::CreateProtoProperty()) {}
 
 auto Property::CreateProtoProperty() -> ProtoProperty * {
   return Arena::CreateMessage<ProtoProperty>(get_arena());
 }
 
-[[nodiscard]] auto Property::GetId() const -> const std::string & {
-  return this->wrapped->id();
-}
+[[nodiscard]] auto Property::GetId() const -> const std::string & { return this->wrapped->id(); }
 
 [[nodiscard]] auto Property::GetName() const -> const std::string & {
   return this->wrapped->name();
@@ -85,87 +82,104 @@ auto Property::CreateProtoProperty() -> ProtoProperty * {
   return this->wrapped->description();
 }
 
-[[nodiscard]] auto Property::GetImportance() const -> const std::string & {
-  return this->wrapped->importance();
+[[nodiscard]] auto Property::GetImportance() const -> Importance {
+  return static_cast<Importance>(this->wrapped->importance());
 }
 
-[[nodiscard]] auto Property::GetValue() const -> const std::string & {
-  return this->wrapped->value();
-}
+[[nodiscard]] auto Property::GetValue() const -> const Value & { return this->value; }
 
 [[nodiscard]] auto Property::GetUnit() const -> const std::string & {
   return this->wrapped->unit();
 }
 
-[[nodiscard]] auto Property::GetDatatype() const -> const std::string & {
-  return this->wrapped->datatype();
-}
+[[nodiscard]] auto Property::GetDataType() const -> const DataType & { return this->data_type; }
 
-auto Property::SetId(const std::string &id) -> void {
-  this->wrapped->set_id(id);
-}
+auto Property::SetId(const std::string &id) -> void { this->wrapped->set_id(id); }
 
-auto Property::SetName(const std::string &name) -> void {
-  this->wrapped->set_name(name);
-}
+auto Property::SetName(const std::string &name) -> void { this->wrapped->set_name(name); }
 
 auto Property::SetDescription(const std::string &description) -> void {
   this->wrapped->set_description(description);
 }
 
-auto Property::SetImportance(const std::string &importance) -> void {
-  this->wrapped->set_importance(importance);
+auto Property::SetImportance(Importance importance) -> void {
+  this->wrapped->set_importance(static_cast<ProtoImportance>(importance));
 }
 
-auto Property::SetValue(const std::string &value) -> void {
-  this->wrapped->set_value(value);
+auto Property::SetValue(const Value &value) -> StatusCode { return this->value.CopyFrom(value); }
+
+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::SetUnit(const std::string &unit) -> void {
-  this->wrapped->set_unit(unit);
+auto Property::SetValue(const std::vector<char *> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Property::SetDatatype(const std::string &datatype) -> void {
-  this->wrapped->set_datatype(datatype);
+auto Property::SetValue(const std::vector<int64_t> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-[[nodiscard]] auto Entity::GetParents() const -> const Parents & {
-  return parents;
+auto Property::SetValue(const std::vector<double> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Entity::AppendParent(const Parent &parent) -> void {
-  this->parents.Append(parent);
+auto Property::SetValue(const std::vector<bool> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Entity::RemoveParent(int index) -> void { this->parents.remove(index); }
+auto Property::SetValue(const int64_t value) -> StatusCode { return SetValue(Value(value)); }
+
+auto Property::SetValue(const bool value) -> StatusCode { return SetValue(Value(value)); }
 
-[[nodiscard]] auto Entity::GetProperties() const -> const Properties & {
-  return properties;
+auto Property::SetUnit(const std::string &unit) -> void { this->wrapped->set_unit(unit); }
+
+auto Property::SetDataType(const DataType &new_data_type) -> StatusCode {
+  return this->data_type.CopyFrom(new_data_type);
 }
 
-auto Entity::AppendProperty(const Property &property) -> void {
-  this->properties.Append(property);
+auto Property::SetDataType(const AtomicDataType new_data_type, bool list_type) -> StatusCode {
+  return SetDataType(DataType(new_data_type, list_type));
 }
 
-auto Entity::RemoveProperty(int index) -> void {
-  this->properties.remove(index);
+auto Property::SetDataType(const std::string &new_data_type, bool list_type) -> StatusCode {
+  return SetDataType(DataType(new_data_type, list_type));
 }
 
+[[nodiscard]] auto Entity::GetParents() const -> const Parents & { return parents; }
+
+auto Entity::AppendParent(const Parent &parent) -> void { this->parents.Append(parent); }
+
+auto Entity::RemoveParent(int index) -> void { this->parents.Remove(index); }
+
+[[nodiscard]] auto Entity::GetProperties() const -> const Properties & { return properties; }
+
+auto Entity::AppendProperty(const Property &property) -> void { this->properties.Append(property); }
+
+auto Entity::RemoveProperty(int index) -> void { this->properties.Remove(index); }
+
 auto Entity::CreateProtoEntity() -> ProtoEntity * {
   return Arena::CreateMessage<ProtoEntity>(get_arena());
 }
 
-auto Entity::CreateMessagesField() -> RepeatedPtrField<ProtoMessage> * {
-  return Arena::CreateMessage<RepeatedPtrField<ProtoMessage>>(get_arena());
+Entity::Entity(IdResponse *id_response) : Entity() {
+  this->wrapped->set_id(id_response->id());
+  this->wrapped->mutable_version()->Swap(id_response->mutable_version());
+  this->errors.wrapped->Swap(id_response->mutable_errors());
+  this->warnings.wrapped->Swap(id_response->mutable_warnings());
+  this->infos.wrapped->Swap(id_response->mutable_infos());
 }
 
 Entity::Entity() : Entity(Entity::CreateProtoEntity()) {}
 
-Entity::Entity(IdResponse *idResponse) : Entity() {
-  this->wrapped->set_id(idResponse->id());
-  this->errors.wrapped->Swap(idResponse->mutable_errors());
-  this->warnings.wrapped->Swap(idResponse->mutable_warnings());
-  this->infos.wrapped->Swap(idResponse->mutable_infos());
+auto Entity::CreateMessagesField() -> RepeatedPtrField<ProtoMessage> * {
+  return Arena::CreateMessage<RepeatedPtrField<ProtoMessage>>(get_arena());
 }
 
 auto Entity::SetId(const std::string &id) -> void { this->wrapped->set_id(id); }
@@ -174,32 +188,68 @@ auto Entity::SetVersionId(const std::string &id) -> void {
   this->wrapped->mutable_version()->set_id(id);
 }
 
-auto Entity::CopyTo(ProtoEntity *target) -> void {
-  target->CopyFrom(*(this->wrapped));
+auto Entity::CopyTo(ProtoEntity *target) -> void { target->CopyFrom(*(this->wrapped)); }
+
+auto Entity::SetRole(Role role) -> void { this->wrapped->set_role(static_cast<EntityRole>(role)); }
+
+auto Entity::SetName(const std::string &name) -> void { this->wrapped->set_name(name); }
+
+auto Entity::SetDescription(const std::string &description) -> void {
+  this->wrapped->set_description(description);
+}
+
+auto Entity::SetValue(const Value &value) -> StatusCode {
+  if (GetRole() != Role::PROPERTY) {
+    return StatusCode::ENTITY_CANNOT_HAVE_A_VALUE;
+  }
+  return this->value.CopyFrom(value);
+}
+
+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::SetRole(const std::string &role) -> void {
-  this->wrapped->set_role(role);
+auto Entity::SetValue(const std::vector<char *> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Entity::SetName(const std::string &name) -> void {
-  this->wrapped->set_name(name);
+auto Entity::SetValue(const std::vector<int64_t> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Entity::SetDescription(const std::string &description) -> void {
-  this->wrapped->set_description(description);
+auto Entity::SetValue(const std::vector<double> &values) -> StatusCode {
+  return SetValue(Value(values));
 }
 
-auto Entity::SetValue(const std::string &value) -> void {
-  this->wrapped->set_value(value);
+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); }
+
+auto Entity::SetDataType(const DataType &new_data_type) -> StatusCode {
+  if (GetRole() != Role::PROPERTY) {
+    return StatusCode::ENTITY_CANNOT_HAVE_A_DATA_TYPE;
+  }
+  return this->data_type.CopyFrom(new_data_type);
 }
 
-auto Entity::SetUnit(const std::string &unit) -> void {
-  this->wrapped->set_unit(unit);
+auto Entity::SetDataType(const AtomicDataType new_data_type, bool list_type) -> StatusCode {
+  return SetDataType(DataType(new_data_type, list_type));
 }
 
-auto Entity::SetDatatype(const std::string &datatype) -> void {
-  this->wrapped->set_datatype(datatype);
+auto Entity::SetDataType(const std::string &new_data_type, bool list_type) -> StatusCode {
+  return SetDataType(DataType(new_data_type, list_type));
 }
 
 auto Entity::SetFilePath(const std::string &path) -> void {
diff --git a/src/caosdb/file_transmission/download_request_handler.cpp b/src/caosdb/file_transmission/download_request_handler.cpp
index fb36ca5b46cbf2c4f08c2c06bc9faf6b00e038be..a157754b337e798fc4c144cb44abea153053ed79 100644
--- a/src/caosdb/file_transmission/download_request_handler.cpp
+++ b/src/caosdb/file_transmission/download_request_handler.cpp
@@ -59,30 +59,30 @@
 #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 <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 <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
 
 namespace caosdb::transaction {
 using caosdb::StatusCode;
 using caosdb::utility::get_arena;
 using google::protobuf::Arena;
 
-DownloadRequestHandler::DownloadRequestHandler(
-  HandlerTag tag, FileTransmissionService::Stub *stub,
-  grpc::CompletionQueue *cq, FileDescriptor file_descriptor)
+DownloadRequestHandler::DownloadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub,
+                                               grpc::CompletionQueue *cq,
+                                               FileDescriptor file_descriptor)
   : tag_(tag), stub_(stub), cq_(cq),
     request_(Arena::CreateMessage<FileDownloadRequest>(get_arena())),
-    response_(Arena::CreateMessage<FileDownloadResponse>(get_arena())),
-    state_(CallState::NewCall), file_descriptor_(std::move(file_descriptor)),
-    bytesReceived_(0) {}
+    response_(Arena::CreateMessage<FileDownloadResponse>(get_arena())), state_(CallState::NewCall),
+    file_descriptor_(std::move(file_descriptor)), bytesReceived_(0) {}
 
 bool DownloadRequestHandler::OnNext(bool ok) {
   try {
@@ -104,15 +104,13 @@ bool DownloadRequestHandler::OnNext(bool ok) {
 
     return true;
   } catch (std::exception &e) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "DownloadRequestHandler caught an exception: " << e.what();
+    CAOSDB_LOG_ERROR(logger_name) << "DownloadRequestHandler caught an exception: " << e.what();
     transaction_status = TransactionStatus::GENERIC_ERROR(e.what());
     state_ = CallState::CallComplete;
   } catch (...) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "Transaction error: unknown exception caught";
-    transaction_status = TransactionStatus::GENERIC_ERROR(
-      "DownloadRequestHandler caught an unknown exception");
+    CAOSDB_LOG_ERROR(logger_name) << "Transaction error: unknown exception caught";
+    transaction_status =
+      TransactionStatus::GENERIC_ERROR("DownloadRequestHandler caught an unknown exception");
     state_ = CallState::CallComplete;
   }
 
@@ -128,36 +126,30 @@ bool DownloadRequestHandler::OnNext(bool ok) {
 void DownloadRequestHandler::Cancel() { ctx_.TryCancel(); }
 
 void DownloadRequestHandler::handleNewCallState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter DownloadRequestHandler::handleNewCallState. local_path = "
-    << file_descriptor_.local_path
-    << ", download_id = " << file_descriptor_.file_transmission_id;
+  CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleNewCallState. local_path = "
+                                << file_descriptor_.local_path
+                                << ", download_id = " << file_descriptor_.file_transmission_id;
   fileWriter_ = std::make_unique<FileWriter>(file_descriptor_.local_path);
 
-  request_->mutable_file_transmission_id()->CopyFrom(
-    *(file_descriptor_.file_transmission_id));
+  request_->mutable_file_transmission_id()->CopyFrom(*(file_descriptor_.file_transmission_id));
 
   rpc_ = stub_->PrepareAsyncFileDownload(&ctx_, *request_, cq_);
 
   transaction_status = TransactionStatus::EXECUTING();
   state_ = CallState::SendingRequest;
   rpc_->StartCall(tag_);
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave DownloadRequestHandler::handleNewCallState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleNewCallState";
 }
 
 void DownloadRequestHandler::handleSendingRequestState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter DownloadRequestHandler::handleSendingRequestState";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleSendingRequestState";
   state_ = CallState::ReceivingFile;
   rpc_->Read(response_, tag_);
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave DownloadRequestHandler::handleSendingRequestState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleSendingRequestState";
 }
 
 void DownloadRequestHandler::handleReceivingFileState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter DownloadRequestHandler::handleReceivingFileState";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleReceivingFileState";
   if (response_->has_chunk()) {
     const auto &chunkData = response_->chunk().data();
     if (chunkData.empty()) {
@@ -173,35 +165,30 @@ void DownloadRequestHandler::handleReceivingFileState() {
   } else {
     throw std::runtime_error("File chunk expected");
   }
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave DownloadRequestHandler::handleReceivingFileState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleReceivingFileState";
 }
 
 void DownloadRequestHandler::handleCallCompleteState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter DownloadRequestHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleCallCompleteState";
 
   switch (status_.error_code()) {
   case grpc::OK: {
-    CAOSDB_LOG_INFO(logger_name)
-      << "DownloadRequestHandler finished successfully ("
-      << file_descriptor_.local_path << "): Download complete, "
-      << bytesReceived_ << " bytes received.";
+    CAOSDB_LOG_INFO(logger_name) << "DownloadRequestHandler finished successfully ("
+                                 << file_descriptor_.local_path << "): Download complete, "
+                                 << bytesReceived_ << " bytes received.";
   } break;
   default: {
     auto code(static_cast<StatusCode>(status_.error_code()));
     std::string description(get_status_description(code) +
                             " Original message: " + status_.error_message());
     transaction_status = TransactionStatus(code, description);
-    CAOSDB_LOG_ERROR(logger_name)
-      << "DownloadRequestHandler finished with an error ("
-      << file_descriptor_.local_path << "): Download aborted with code " << code
-      << " - " << description;
+    CAOSDB_LOG_ERROR(logger_name) << "DownloadRequestHandler finished with an error ("
+                                  << file_descriptor_.local_path << "): Download aborted with code "
+                                  << code << " - " << description;
   } break;
   }
 
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave DownloadRequestHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleCallCompleteState";
 }
 
 } // namespace caosdb::transaction
diff --git a/src/caosdb/file_transmission/file_writer.cpp b/src/caosdb/file_transmission/file_writer.cpp
index 90c816fa8c6d3d43ecad3e4e0dbf575d7016d15e..5cf7d3a798942fc2ab9a3fe4a278b0e29d362f6e 100644
--- a/src/caosdb/file_transmission/file_writer.cpp
+++ b/src/caosdb/file_transmission/file_writer.cpp
@@ -53,8 +53,7 @@
 
 namespace caosdb::transaction {
 
-FileWriter::FileWriter(boost::filesystem::path filename)
-  : filename_(std::move(filename)) {
+FileWriter::FileWriter(boost::filesystem::path filename) : filename_(std::move(filename)) {
   this->openFile();
 }
 
diff --git a/src/caosdb/file_transmission/register_file_upload_handler.cpp b/src/caosdb/file_transmission/register_file_upload_handler.cpp
index b2020223f1c79f69e77b1e0950bac1c8f1220986..7b5c18c83729060768d882132067c5c8dd496d67 100644
--- a/src/caosdb/file_transmission/register_file_upload_handler.cpp
+++ b/src/caosdb/file_transmission/register_file_upload_handler.cpp
@@ -59,26 +59,24 @@ namespace caosdb::transaction {
 
 RegisterFileUploadHandler::~RegisterFileUploadHandler() = default;
 
-RegisterFileUploadHandler::RegisterFileUploadHandler(
-  HandlerTag tag, FileTransmissionService::Stub *stub,
-  grpc::CompletionQueue *completion_queue, RegisterFileUploadRequest *request,
-  RegisterFileUploadResponse *response)
-  : UnaryRpcHandler(completion_queue), tag_(tag), stub_(stub),
-    request_(request), response_(response) {}
+RegisterFileUploadHandler::RegisterFileUploadHandler(HandlerTag tag,
+                                                     FileTransmissionService::Stub *stub,
+                                                     grpc::CompletionQueue *completion_queue,
+                                                     RegisterFileUploadRequest *request,
+                                                     RegisterFileUploadResponse *response)
+  : UnaryRpcHandler(completion_queue), tag_(tag), stub_(stub), request_(request),
+    response_(response) {}
 
 void RegisterFileUploadHandler::handleNewCallState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter RegisterFileUploadHandler::handleNewCallState.";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter RegisterFileUploadHandler::handleNewCallState.";
 
-  rpc_ = stub_->PrepareAsyncRegisterFileUpload(&call_context, *request_,
-                                               completion_queue);
+  rpc_ = stub_->PrepareAsyncRegisterFileUpload(&call_context, *request_, completion_queue);
 
   state_ = CallState::CallComplete;
   rpc_->StartCall();
   rpc_->Finish(response_, &status_, tag_);
 
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave RegisterFileUploadHandler::handleNewCallState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave RegisterFileUploadHandler::handleNewCallState";
 }
 
 } // namespace caosdb::transaction
diff --git a/src/caosdb/file_transmission/upload_request_handler.cpp b/src/caosdb/file_transmission/upload_request_handler.cpp
index 27926bfaabe4dd18feca80f191ff496573196e52..cc8170249b932fb8bfa572fd345746bbbacc16af 100644
--- a/src/caosdb/file_transmission/upload_request_handler.cpp
+++ b/src/caosdb/file_transmission/upload_request_handler.cpp
@@ -61,31 +61,29 @@
 #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 <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 <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
 
 namespace caosdb::transaction {
 using caosdb::StatusCode;
 using caosdb::utility::get_arena;
 using google::protobuf::Arena;
 
-UploadRequestHandler::UploadRequestHandler(HandlerTag tag,
-                                           FileTransmissionService::Stub *stub,
+UploadRequestHandler::UploadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub,
                                            grpc::CompletionQueue *cq,
                                            FileDescriptor file_descriptor)
-  : tag_(tag), stub_(stub), cq_(cq),
-    request_(Arena::CreateMessage<FileUploadRequest>(get_arena())),
-    response_(Arena::CreateMessage<FileUploadResponse>(get_arena())),
-    state_(CallState::NewCall), file_descriptor_(std::move(file_descriptor)),
-    bytesToSend_(0) {}
+  : tag_(tag), stub_(stub), cq_(cq), request_(Arena::CreateMessage<FileUploadRequest>(get_arena())),
+    response_(Arena::CreateMessage<FileUploadResponse>(get_arena())), state_(CallState::NewCall),
+    file_descriptor_(std::move(file_descriptor)), bytesToSend_(0) {}
 
 bool UploadRequestHandler::OnNext(bool ok) {
   try {
@@ -109,15 +107,13 @@ bool UploadRequestHandler::OnNext(bool ok) {
 
     return true;
   } catch (std::exception &e) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "UploadRequestHandler caught an exception: " << e.what();
+    CAOSDB_LOG_ERROR(logger_name) << "UploadRequestHandler caught an exception: " << e.what();
     transaction_status = TransactionStatus::GENERIC_ERROR(e.what());
     state_ = CallState::CallComplete;
   } catch (...) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "Transaction error: unknown exception caught";
-    transaction_status = TransactionStatus::GENERIC_ERROR(
-      "UploadRequestHandler caught an unknown exception");
+    CAOSDB_LOG_ERROR(logger_name) << "Transaction error: unknown exception caught";
+    transaction_status =
+      TransactionStatus::GENERIC_ERROR("UploadRequestHandler caught an unknown exception");
     state_ = CallState::CallComplete;
   }
 
@@ -187,31 +183,27 @@ void UploadRequestHandler::handleExpectingResponseState() {
 }
 
 void UploadRequestHandler::handleCallCompleteState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter UploadRequestHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter UploadRequestHandler::handleCallCompleteState";
 
   switch (status_.error_code()) {
   case grpc::OK: {
     auto bytesSent = fileReader_ != nullptr ? fileReader_->fileSize() : 0;
-    CAOSDB_LOG_INFO(logger_name)
-      << "UploadRequestHandler finished successfully ("
-      << file_descriptor_.local_path << "): upload complete, " << bytesSent
-      << " bytes sent";
+    CAOSDB_LOG_INFO(logger_name) << "UploadRequestHandler finished successfully ("
+                                 << file_descriptor_.local_path << "): upload complete, "
+                                 << bytesSent << " bytes sent";
   } break;
   default: {
     auto code(static_cast<StatusCode>(status_.error_code()));
     std::string description(get_status_description(code) +
                             " Original message: " + status_.error_message());
     transaction_status = TransactionStatus(code, description);
-    CAOSDB_LOG_ERROR(logger_name)
-      << "UploadRequestHandler finished with an error ("
-      << file_descriptor_.local_path << "): Upload aborted with code " << code
-      << " - " << description;
+    CAOSDB_LOG_ERROR(logger_name) << "UploadRequestHandler finished with an error ("
+                                  << file_descriptor_.local_path << "): Upload aborted with code "
+                                  << code << " - " << description;
   } break;
   }
 
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave UploadRequestHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave UploadRequestHandler::handleCallCompleteState";
 }
 
 } // namespace caosdb::transaction
diff --git a/src/caosdb/logging.cpp b/src/caosdb/logging.cpp
index 5e6cd4e3577b57ec7491a26ae71982667a096609..4070786b2bb4073da5800f4a57b9c0dfcff5d6ac 100644
--- a/src/caosdb/logging.cpp
+++ b/src/caosdb/logging.cpp
@@ -48,11 +48,9 @@ BOOST_LOG_GLOBAL_LOGGER_INIT(logger, boost_logger_class) {
   boost_logger_class lg;
   return lg;
 }
-LoggingConfiguration::LoggingConfiguration(int level)
-  : LevelConfiguration(level) {}
+LoggingConfiguration::LoggingConfiguration(int level) : LevelConfiguration(level) {}
 
-auto LoggingConfiguration::AddSink(
-  const std::shared_ptr<SinkConfiguration> &sink) -> void {
+auto LoggingConfiguration::AddSink(const std::shared_ptr<SinkConfiguration> &sink) -> void {
   this->sinks.push_back(sink);
 }
 
@@ -64,14 +62,10 @@ auto LoggingConfiguration::GetSinks() const
 SinkConfiguration::SinkConfiguration(std::string name, int level)
   : LevelConfiguration(level), name(std::move(name)) {}
 
-[[nodiscard]] auto SinkConfiguration::GetName() const -> const std::string & {
-  return this->name;
-}
+[[nodiscard]] auto SinkConfiguration::GetName() const -> const std::string & { return this->name; }
 
-auto SinkConfiguration::Configure(boost::log::settings &settings) const
-  -> void {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter SinkConfiguration::Configure(&settings)";
+auto SinkConfiguration::Configure(boost::log::settings &settings) const -> void {
+  CAOSDB_LOG_TRACE(logger_name) << "Enter SinkConfiguration::Configure(&settings)";
   auto sink = "Sinks." + GetName();
   settings[sink]["Destination"] = GetDestination();
   settings[sink]["Filter"] = "%Severity% >= " + std::to_string(GetLevel());
@@ -79,31 +73,24 @@ auto SinkConfiguration::Configure(boost::log::settings &settings) const
   settings[sink]["Format"] = "[%TimeStamp%][%Severity%] %Channel% - %Message%";
 }
 
-ConsoleSinkConfiguration::ConsoleSinkConfiguration(const std::string &name,
-                                                   int level)
+ConsoleSinkConfiguration::ConsoleSinkConfiguration(const std::string &name, int level)
   : SinkConfiguration(name, level) {}
 
-[[nodiscard]] auto ConsoleSinkConfiguration::GetDestination() const
-  -> const std::string & {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter ConsoleSinkConfiguration::GetDestination()";
+[[nodiscard]] auto ConsoleSinkConfiguration::GetDestination() const -> const std::string & {
+  CAOSDB_LOG_TRACE(logger_name) << "Enter ConsoleSinkConfiguration::GetDestination()";
   return this->destination;
 }
 
-auto ConsoleSinkConfiguration::Configure(boost::log::settings &settings) const
-  -> void {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter ConsoleSinkConfiguration::Configure(&settings)";
+auto ConsoleSinkConfiguration::Configure(boost::log::settings &settings) const -> void {
+  CAOSDB_LOG_TRACE(logger_name) << "Enter ConsoleSinkConfiguration::Configure(&settings)";
   sink_configuration::Configure(settings);
 }
 
 FileSinkConfiguration::FileSinkConfiguration(const std::string &name, int level)
   : SinkConfiguration(name, level) {}
 
-[[nodiscard]] auto FileSinkConfiguration::GetDestination() const
-  -> const std::string & {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter FileSinkConfiguration::GetDestination()";
+[[nodiscard]] auto FileSinkConfiguration::GetDestination() const -> const std::string & {
+  CAOSDB_LOG_TRACE(logger_name) << "Enter FileSinkConfiguration::GetDestination()";
   return this->destination;
 }
 
@@ -111,20 +98,16 @@ auto FileSinkConfiguration::SetDirectory(const std::string &directory) -> void {
   this->directory = std::string(directory);
 }
 
-auto FileSinkConfiguration::Configure(boost::log::settings &settings) const
-  -> void {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter FileSinkConfiguration::Configure(&settings)";
+auto FileSinkConfiguration::Configure(boost::log::settings &settings) const -> void {
+  CAOSDB_LOG_TRACE(logger_name) << "Enter FileSinkConfiguration::Configure(&settings)";
   sink_configuration::Configure(settings);
   settings["Sink." + GetName() + ".Target"] = this->directory;
 }
 
-SyslogSinkConfiguration::SyslogSinkConfiguration(const std::string &name,
-                                                 int level)
+SyslogSinkConfiguration::SyslogSinkConfiguration(const std::string &name, int level)
   : SinkConfiguration(name, level) {}
 
-[[nodiscard]] auto SyslogSinkConfiguration::GetDestination() const
-  -> const std::string & {
+[[nodiscard]] auto SyslogSinkConfiguration::GetDestination() const -> const std::string & {
   return this->destination;
 }
 
@@ -137,8 +120,7 @@ auto initialize_logging_defaults() -> int {
 
   // now set everything up
   const static std::vector<std::shared_ptr<SinkConfiguration>> default_sinks = {
-    std::make_shared<ConsoleSinkConfiguration>("DEFAULT_SINK_1",
-                                               CAOSDB_DEFAULT_LOG_LEVEL)};
+    std::make_shared<ConsoleSinkConfiguration>("DEFAULT_SINK_1", CAOSDB_DEFAULT_LOG_LEVEL)};
 
   boost::log::settings default_settings;
 
@@ -150,8 +132,7 @@ auto initialize_logging_defaults() -> int {
 
   boost::log::init_from_settings(default_settings);
   auto core = boost::log::core::get();
-  core->add_global_attribute("TimeStamp",
-                             boost::log::attributes::local_clock());
+  core->add_global_attribute("TimeStamp", boost::log::attributes::local_clock());
 
   CAOSDB_LOG_DEBUG(logger_name) << "Initialized default settings.";
 
@@ -185,39 +166,27 @@ auto initialize_logging(const LoggingConfiguration &configuration) -> void {
 }
 
 void caosdb_log_fatal(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_FATAL)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_FATAL) << msg;
 }
 
 void caosdb_log_error(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_ERROR)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_ERROR) << msg;
 }
 
 void caosdb_log_warn(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_WARN)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_WARN) << msg;
 }
 
 void caosdb_log_info(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_INFO)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_INFO) << msg;
 }
 
 void caosdb_log_debug(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_DEBUG)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_DEBUG) << msg;
 }
 
 void caosdb_log_trace(const char *channel, const char *msg) {
-  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel,
-                        CAOSDB_LOG_LEVEL_TRACE)
-    << msg;
+  BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_TRACE) << msg;
 }
 
 } // namespace caosdb::logging
diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp
index a46019f3a5b83cc0bb058aa6446100bceac87242..75350b2680b55976d9a7a96b58962540216d4eae 100644
--- a/src/caosdb/transaction.cpp
+++ b/src/caosdb/transaction.cpp
@@ -18,32 +18,33 @@
  *
  */
 #include "caosdb/transaction.h"
-#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransac...
-#include "caosdb/entity/v1alpha1/main.pb.h"      // for TransactionRe...
-#include "caosdb/file_transmission/download_request_handler.h" // Download...
-#include "caosdb/file_transmission/file_reader.h"              // for path
-#include "caosdb/file_transmission/register_file_upload_handler.h"
-#include "caosdb/file_transmission/upload_request_handler.h" // Upload...
-#include "caosdb/logging.h"     // for CAOSDB_LOG_FATAL
-#include "caosdb/status_code.h" // for StatusCode
-#include "caosdb/transaction_handler.h"
-#include <algorithm>                                   // for max
-#include <boost/filesystem/path.hpp>                   // for operator<<, path
-#include <boost/log/core/record.hpp>                   // for record
-#include <boost/log/detail/attachable_sstream_buf.hpp> // for basic_ostring...
-#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 "caosdb/entity/v1alpha1/main.grpc.pb.h"                   // for EntityTransac...
+#include "caosdb/entity/v1alpha1/main.pb.h"                        // for TransactionRe...
+#include "caosdb/file_transmission/download_request_handler.h"     // Download...
+#include "caosdb/file_transmission/file_reader.h"                  // for path
+#include "caosdb/file_transmission/register_file_upload_handler.h" // for RegisterFileUploadHandler
+#include "caosdb/file_transmission/upload_request_handler.h"       // Upload...
+#include "caosdb/logging.h"                                        // for CAOSDB_LOG_FATAL
+#include "caosdb/status_code.h"                                    // for StatusCode
+#include "caosdb/transaction_handler.h"                            // for EntityTransactionHandler
+#include <algorithm>                                               // for max
+#include <boost/filesystem/path.hpp>                               // for operator<<, path
+#include <boost/log/core/record.hpp>                               // for record
+#include <boost/log/detail/attachable_sstream_buf.hpp>             // for basic_ostring...
+#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_...
 // IWYU pragma: no_include <bits/exception.h>
-#include <exception>               // IWYU pragma: keep
-#include <google/protobuf/arena.h> // for Arena
-#include <grpc/impl/codegen/gpr_types.h>
-#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue
-#include <iosfwd>                                 // for streamsize
-#include <map>                                    // for map, operator!=
-#include <memory>                                 // for unique_ptr
-#include <stdexcept>                              // for out_of_range
-#include <utility>                                // for move, pair
+#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 <stdexcept>                                // for out_of_range
+#include <utility>                                  // for move, pair
 
 namespace caosdb {
 
@@ -51,14 +52,11 @@ namespace caosdb {
 auto get_status_description(int code) -> const std::string & {
   static const std::string MISSING_DESCRIPTION = "MISSING DESCRIPTION";
   static const std::map<int, std::string> descriptions = {
-    {StatusCode::INITIAL,
-     "The transaction has just been intialized. It has not been executed yet "
-     "and clients can still change it and add sub-transactions."},
-    {StatusCode::GO_ON,
-     "The transaction has a transaction_type yet and clients may add matching "
-     "sub-transaction or execute it right-away."},
-    {StatusCode::READY,
-     "The transaction is ready for execution and cannot be changed anymore."},
+    {StatusCode::INITIAL, "The transaction has just been intialized. It has not been executed yet "
+                          "and clients can still change it and add sub-transactions."},
+    {StatusCode::GO_ON, "The transaction has a transaction_type yet and clients may add matching "
+                        "sub-transaction or execute it right-away."},
+    {StatusCode::READY, "The transaction is ready for execution and cannot be changed anymore."},
     {StatusCode::EXECUTING, "The transaction is currently being executed."},
     {StatusCode::SUCCESS, "The action was successful"},
     {StatusCode::CONNECTION_ERROR,
@@ -70,8 +68,7 @@ auto get_status_description(int code) -> const std::string & {
     {StatusCode::GENERIC_RPC_ERROR,
      "The attempt to execute this transaction was not successful because an "
      "error occured in the transport or RPC protocol layer."},
-    {StatusCode::GENERIC_ERROR,
-     "An error occured. Please review the logs for more information."},
+    {StatusCode::GENERIC_ERROR, "An error occured. Please review the logs for more information."},
     {StatusCode::GENERIC_TRANSACTION_ERROR,
      "The transaction terminated unsuccessfully with transaction errors."},
     {StatusCode::CONFIGURATION_ERROR,
@@ -92,10 +89,8 @@ auto get_status_description(int code) -> const std::string & {
     {StatusCode::PATH_IS_A_DIRECTORY, "The given path is a directory."},
     {StatusCode::FILE_DOES_NOT_EXIST_LOCALLY,
      "The file does not not exist in the local file system."},
-    {StatusCode::FILE_DOWNLOAD_ERROR,
-     "The transaction failed during the download of the files"},
-    {StatusCode::FILE_UPLOAD_ERROR,
-     "The transaction failed during the upload of the files"},
+    {StatusCode::FILE_DOWNLOAD_ERROR, "The transaction failed during the download of the files"},
+    {StatusCode::FILE_UPLOAD_ERROR, "The transaction failed during the upload of the files"},
     {StatusCode::UNSUPPORTED_FEATURE,
      "This feature is not available in the this client implementation."},
     {StatusCode::EXTERN_C_ASSIGNMENT_ERROR,
@@ -121,8 +116,7 @@ using caosdb::entity::v1alpha1::MultiTransactionRequest;
 using caosdb::entity::v1alpha1::MultiTransactionResponse;
 using TransactionResponseCase =
   caosdb::entity::v1alpha1::TransactionResponse::TransactionResponseCase;
-using RetrieveResponseCase =
-  caosdb::entity::v1alpha1::RetrieveResponse::RetrieveResponseCase;
+using RetrieveResponseCase = caosdb::entity::v1alpha1::RetrieveResponse::RetrieveResponseCase;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 using google::protobuf::Arena;
 using NextStatus = grpc::CompletionQueue::NextStatus;
@@ -150,20 +144,15 @@ auto ResultSet::iterator::operator!=(const iterator &rhs) const -> bool {
   return this->current_index != rhs.current_index;
 }
 
-auto ResultSet::begin() const -> ResultSet::iterator {
-  return ResultSet::iterator(this, 0);
-}
+auto ResultSet::begin() const -> ResultSet::iterator { return ResultSet::iterator(this, 0); }
 
-auto ResultSet::end() const -> ResultSet::iterator {
-  return ResultSet::iterator(this, size());
-}
+auto ResultSet::end() const -> ResultSet::iterator { return ResultSet::iterator(this, size()); }
 
 MultiResultSet::MultiResultSet(std::vector<std::unique_ptr<Entity>> result_set)
   : AbstractMultiResultSet(std::move(result_set)) {}
 
-Transaction::Transaction(
-  std::shared_ptr<EntityTransactionService::Stub> entity_service,
-  std::shared_ptr<FileTransmissionService::Stub> file_service)
+Transaction::Transaction(std::shared_ptr<EntityTransactionService::Stub> entity_service,
+                         std::shared_ptr<FileTransmissionService::Stub> file_service)
   : request(Arena::CreateMessage<MultiTransactionRequest>(GetArena())),
     response(Arena::CreateMessage<MultiTransactionResponse>(GetArena())) {
   this->entity_service = std::move(entity_service);
@@ -181,12 +170,12 @@ auto Transaction::RetrieveById(const std::string &id) noexcept -> StatusCode {
   return this->status.GetCode();
 }
 
-auto Transaction::RetrieveAndDownloadFilesById(
-  const std::string &id, const std::string &local_path) noexcept -> StatusCode {
+auto Transaction::RetrieveAndDownloadFilesById(const std::string &id,
+                                               const std::string &local_path) noexcept
+  -> StatusCode {
   ASSERT_CAN_ADD_RETRIEVAL
 
-  auto *retrieve_request =
-    this->request->add_requests()->mutable_retrieve_request();
+  auto *retrieve_request = this->request->add_requests()->mutable_retrieve_request();
   retrieve_request->set_id(id);
   retrieve_request->set_register_file_download(true);
 
@@ -222,9 +211,8 @@ auto Transaction::DeleteById(const std::string &id) noexcept -> StatusCode {
 auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode {
   ASSERT_CAN_ADD_INSERTION
 
-  auto *entity_request = this->request->add_requests()
-                           ->mutable_insert_request()
-                           ->mutable_entity_request();
+  auto *entity_request =
+    this->request->add_requests()->mutable_insert_request()->mutable_entity_request();
   auto *proto_entity = entity_request->mutable_entity();
 
   // copy the original entity for the transaction
@@ -241,9 +229,8 @@ auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode {
 auto Transaction::UpdateEntity(Entity *entity) noexcept -> StatusCode {
   ASSERT_CAN_ADD_UPDATE
 
-  auto *entity_request = this->request->add_requests()
-                           ->mutable_update_request()
-                           ->mutable_entity_request();
+  auto *entity_request =
+    this->request->add_requests()->mutable_update_request()->mutable_entity_request();
   auto *proto_entity = entity_request->mutable_entity();
 
   entity->CopyTo(proto_entity);
@@ -258,8 +245,8 @@ auto Transaction::UpdateEntity(Entity *entity) noexcept -> StatusCode {
 
 auto Transaction::Execute() -> TransactionStatus {
   auto status_code = ExecuteAsynchronously();
-  TransactionStatus::ThrowExceptionIfError(
-    status_code, caosdb::get_status_description(status_code));
+  TransactionStatus::ThrowExceptionIfError(status_code,
+                                           caosdb::get_status_description(status_code));
   auto status = WaitForIt();
   status.ThrowExceptionIfError();
   return status;
@@ -267,8 +254,7 @@ auto Transaction::Execute() -> TransactionStatus {
 
 // TODO(tf) This has apparently a cognitive complexity of 39>25 (threshold).
 auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
-  if (!IsStatus(TransactionStatus::READY()) &&
-      !IsStatus(TransactionStatus::GO_ON())) {
+  if (!IsStatus(TransactionStatus::READY()) && !IsStatus(TransactionStatus::GO_ON())) {
     return StatusCode::TRANSACTION_STATUS_ERROR;
   }
   switch (this->transaction_type) {
@@ -291,21 +277,17 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
 
   // upload files first
   if (!upload_files.empty()) {
-    CAOSDB_LOG_INFO(logger_name)
-      << "Number of files to be uploaded: " << upload_files.size();
+    CAOSDB_LOG_INFO(logger_name) << "Number of files to be uploaded: " << upload_files.size();
 
-    auto *registration_request =
-      Arena::CreateMessage<RegisterFileUploadRequest>(GetArena());
-    auto *registration_response =
-      Arena::CreateMessage<RegisterFileUploadResponse>(GetArena());
+    auto *registration_request = Arena::CreateMessage<RegisterFileUploadRequest>(GetArena());
+    auto *registration_response = Arena::CreateMessage<RegisterFileUploadResponse>(GetArena());
 
-    handler_ = std::make_unique<RegisterFileUploadHandler>(
-      &handler_, file_service.get(), &completion_queue, registration_request,
-      registration_response);
+    handler_ =
+      std::make_unique<RegisterFileUploadHandler>(&handler_, file_service.get(), &completion_queue,
+                                                  registration_request, registration_response);
     this->status = ProcessCalls();
 
-    if (registration_response->status() !=
-        RegistrationStatus::REGISTRATION_STATUS_ACCEPTED) {
+    if (registration_response->status() != RegistrationStatus::REGISTRATION_STATUS_ACCEPTED) {
       this->status = TransactionStatus::FILE_UPLOAD_ERROR();
       return StatusCode::EXECUTING;
     }
@@ -313,10 +295,9 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
     for (auto &file_descriptor : upload_files) {
       file_descriptor.file_transmission_id->set_registration_id(
         registration_response->registration_id());
-      CAOSDB_LOG_INFO(logger_name)
-        << "Uploading " << file_descriptor.local_path;
-      handler_ = std::make_unique<UploadRequestHandler>(
-        &handler_, file_service.get(), &completion_queue, file_descriptor);
+      CAOSDB_LOG_INFO(logger_name) << "Uploading " << file_descriptor.local_path;
+      handler_ = std::make_unique<UploadRequestHandler>(&handler_, file_service.get(),
+                                                        &completion_queue, file_descriptor);
       this->status = ProcessCalls();
       if (this->status.GetCode() != StatusCode::EXECUTING) {
         return StatusCode::EXECUTING;
@@ -324,8 +305,9 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
     }
   }
 
-  handler_ = std::make_unique<EntityTransactionHandler>(
-    &handler_, entity_service.get(), &completion_queue, request, response);
+  CAOSDB_LOG_DEBUG(logger_name) << "RPC Request: " << RequestToString();
+  handler_ = std::make_unique<EntityTransactionHandler>(&handler_, entity_service.get(),
+                                                        &completion_queue, request, response);
   this->status = ProcessCalls();
   if (this->status.GetCode() != StatusCode::EXECUTING) {
     return StatusCode::EXECUTING;
@@ -335,16 +317,12 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
   if (status.GetCode() == StatusCode::EXECUTING && !download_files.empty()) {
     // run over all retrieved entities and get the download_id
     for (auto sub_response : *(response->mutable_responses())) {
-      if (sub_response.transaction_response_case() ==
-          TransactionResponseCase::kRetrieveResponse) {
-        if (sub_response.retrieve_response()
-              .entity_response()
-              .has_download_id()) {
+      if (sub_response.transaction_response_case() == TransactionResponseCase::kRetrieveResponse) {
+        if (sub_response.retrieve_response().entity_response().has_download_id()) {
           auto *entity_response =
             sub_response.mutable_retrieve_response()->mutable_entity_response();
           auto entity_id = entity_response->entity().id();
-          download_files[entity_id].file_transmission_id =
-            entity_response->release_download_id();
+          download_files[entity_id].file_transmission_id = entity_response->release_download_id();
           // TODO(tf) handle error
         }
       }
@@ -352,11 +330,10 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT
 
     for (const auto &item : download_files) {
       auto file_descriptor(item.second);
-      CAOSDB_LOG_INFO(logger_name)
-        << "Downloading " << file_descriptor.local_path;
+      CAOSDB_LOG_INFO(logger_name) << "Downloading " << file_descriptor.local_path;
 
-      handler_ = std::make_unique<DownloadRequestHandler>(
-        &handler_, file_service.get(), &completion_queue, file_descriptor);
+      handler_ = std::make_unique<DownloadRequestHandler>(&handler_, file_service.get(),
+                                                          &completion_queue, file_descriptor);
       this->status = ProcessCalls();
       if (this->status.GetCode() != StatusCode::EXECUTING) {
         return StatusCode::EXECUTING;
@@ -384,8 +361,7 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { // NOLINT
 
       switch (retrieve_response->retrieve_response_case()) {
       case RetrieveResponseCase::kEntityResponse: {
-        auto *retrieve_entity_response =
-          retrieve_response->release_entity_response();
+        auto *retrieve_entity_response = retrieve_response->release_entity_response();
         result = std::make_unique<Entity>(retrieve_entity_response);
       } break;
       case RetrieveResponseCase::kSelectResult: {
@@ -416,26 +392,22 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { // NOLINT
     }
 
     case TransactionResponseCase::kInsertResponse: {
-      auto *inserted_id_response =
-        sub_response.mutable_insert_response()->release_id_response();
+      auto *inserted_id_response = sub_response.mutable_insert_response()->release_id_response();
       result = std::make_unique<Entity>(inserted_id_response);
       break;
     }
     case TransactionResponseCase::kDeleteResponse: {
-      auto *deleted_id_response =
-        sub_response.mutable_delete_response()->release_id_response();
+      auto *deleted_id_response = sub_response.mutable_delete_response()->release_id_response();
       result = std::make_unique<Entity>(deleted_id_response);
       break;
     }
     case TransactionResponseCase::kUpdateResponse: {
-      auto *updated_id_response =
-        sub_response.mutable_update_response()->release_id_response();
+      auto *updated_id_response = sub_response.mutable_update_response()->release_id_response();
       result = std::make_unique<Entity>(updated_id_response);
       break;
     }
     default:
-      CAOSDB_LOG_FATAL(logger_name)
-        << "Received invalid TransactionResponseCase.";
+      CAOSDB_LOG_FATAL(logger_name) << "Received invalid TransactionResponseCase.";
       break;
     }
     if (result != nullptr) {
@@ -457,8 +429,7 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { // NOLINT
   this->result_set = std::make_unique<MultiResultSet>(std::move(entities));
 
   if (set_error) {
-    this->status = TransactionStatus::TRANSACTION_ERROR(
-      "The request terminated with errors.");
+    this->status = TransactionStatus::TRANSACTION_ERROR("The request terminated with errors.");
   }
 
   return this->status;
@@ -493,8 +464,7 @@ auto Transaction::ProcessCalls() -> TransactionStatus {
       }
     } break;
     case NextStatus::SHUTDOWN: {
-      CAOSDB_LOG_ERROR(logger_name)
-        << "Notification queue has been shut down unexpectedly.";
+      CAOSDB_LOG_ERROR(logger_name) << "Notification queue has been shut down unexpectedly.";
       result = handler_->GetStatus();
       handler_.reset();
       return result;
@@ -503,8 +473,7 @@ auto Transaction::ProcessCalls() -> TransactionStatus {
       CAOSDB_LOG_DEBUG(logger_name) << "Timeout, waiting...";
     } break;
     default:
-      CAOSDB_LOG_FATAL(logger_name)
-        << "Got an invalid NextStatus from CompletionQueue.";
+      CAOSDB_LOG_FATAL(logger_name) << "Got an invalid NextStatus from CompletionQueue.";
       result = handler_->GetStatus();
       handler_.reset();
       return result;
diff --git a/src/caosdb/transaction_handler.cpp b/src/caosdb/transaction_handler.cpp
index cf020af35bf56b2e68da11a92b0961995397f2fd..e97e626139dd967353491310627f96acefbdb8eb 100644
--- a/src/caosdb/transaction_handler.cpp
+++ b/src/caosdb/transaction_handler.cpp
@@ -13,28 +13,26 @@
 
 namespace caosdb::transaction {
 
-EntityTransactionHandler::EntityTransactionHandler(
-  HandlerTag tag, EntityTransactionService::Stub *stub,
-  grpc::CompletionQueue *completion_queue, MultiTransactionRequest *request,
-  MultiTransactionResponse *response)
-  : UnaryRpcHandler(completion_queue), tag_(tag), stub_(stub),
-    request_(request), response_(response) {}
+EntityTransactionHandler::EntityTransactionHandler(HandlerTag tag,
+                                                   EntityTransactionService::Stub *stub,
+                                                   grpc::CompletionQueue *completion_queue,
+                                                   MultiTransactionRequest *request,
+                                                   MultiTransactionResponse *response)
+  : UnaryRpcHandler(completion_queue), tag_(tag), stub_(stub), request_(request),
+    response_(response) {}
 
 void EntityTransactionHandler::handleNewCallState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter EntityTransactionHandler::handleNewCallState with "
-       "CompletionQueue "
-    << completion_queue;
+  CAOSDB_LOG_TRACE(logger_name) << "Enter EntityTransactionHandler::handleNewCallState with "
+                                   "CompletionQueue "
+                                << completion_queue;
 
-  rpc_ = stub_->PrepareAsyncMultiTransaction(&call_context, *request_,
-                                             completion_queue);
+  rpc_ = stub_->PrepareAsyncMultiTransaction(&call_context, *request_, completion_queue);
 
   state_ = CallState::CallComplete;
   rpc_->StartCall();
   rpc_->Finish(response_, &status_, tag_);
 
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave EntityTransactionHandler::handleNewCallState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave EntityTransactionHandler::handleNewCallState";
 }
 
 } // namespace caosdb::transaction
diff --git a/src/caosdb/unary_rpc_handler.cpp b/src/caosdb/unary_rpc_handler.cpp
index 4d1e1cf618ef119278b02fdc3657d17482a87601..f2307549f575f3311a5c096007a1c98b12db1722 100644
--- a/src/caosdb/unary_rpc_handler.cpp
+++ b/src/caosdb/unary_rpc_handler.cpp
@@ -74,8 +74,7 @@ bool UnaryRpcHandler::OnNext(bool ok) {
         return false;
       }
     } else {
-      CAOSDB_LOG_ERROR(logger_name)
-        << "UnaryRpcHandler::OnNext(false)!. This should not happen.";
+      CAOSDB_LOG_ERROR(logger_name) << "UnaryRpcHandler::OnNext(false)!. This should not happen.";
       // TODO(tf) Handle this error:
       // in CallComplete state: "Client-side Finish: ok should always be true"
       // in ReceivingFile state: "ok indicates that the RPC is going to go to
@@ -88,15 +87,13 @@ bool UnaryRpcHandler::OnNext(bool ok) {
 
     return true;
   } catch (std::exception &e) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "UnaryRpcHandler caught an exception: " << e.what();
+    CAOSDB_LOG_ERROR(logger_name) << "UnaryRpcHandler caught an exception: " << e.what();
     transaction_status = TransactionStatus::GENERIC_ERROR(e.what());
     state_ = CallState::CallComplete;
   } catch (...) {
-    CAOSDB_LOG_ERROR(logger_name)
-      << "Transaction error: unknown exception caught";
-    transaction_status = TransactionStatus::GENERIC_ERROR(
-      "UnaryRpcHandler caught an unknown exception");
+    CAOSDB_LOG_ERROR(logger_name) << "Transaction error: unknown exception caught";
+    transaction_status =
+      TransactionStatus::GENERIC_ERROR("UnaryRpcHandler caught an unknown exception");
     state_ = CallState::CallComplete;
   }
 
@@ -110,8 +107,7 @@ bool UnaryRpcHandler::OnNext(bool ok) {
 void UnaryRpcHandler::Cancel() { call_context.TryCancel(); }
 
 void UnaryRpcHandler::handleCallCompleteState() {
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Enter UnaryRpcHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Enter UnaryRpcHandler::handleCallCompleteState";
 
   switch (status_.error_code()) {
   case grpc::OK:
@@ -122,14 +118,12 @@ void UnaryRpcHandler::handleCallCompleteState() {
     std::string description(get_status_description(code) +
                             " Original message: " + status_.error_message());
     transaction_status = TransactionStatus(code, description);
-    CAOSDB_LOG_ERROR(logger_name)
-      << "UnaryRpcHandler finished with an error (Code " << code
-      << "): " << description;
+    CAOSDB_LOG_ERROR(logger_name) << "UnaryRpcHandler finished with an error (Code " << code
+                                  << "): " << description;
     break;
   }
 
-  CAOSDB_LOG_TRACE(logger_name)
-    << "Leave UnaryRpcHandler::handleCallCompleteState";
+  CAOSDB_LOG_TRACE(logger_name) << "Leave UnaryRpcHandler::handleCallCompleteState";
 }
 
 } // namespace caosdb::transaction
diff --git a/src/caosdb/utility.cpp b/src/caosdb/utility.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d049b91c4ce06337de57f24715df983e80ba88e3
--- /dev/null
+++ b/src/caosdb/utility.cpp
@@ -0,0 +1,89 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 Daniel Hornung <d.hornung@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"
+#include "caosdb/entity.h"
+#include "caosdb/utility.h"
+#include <algorithm>
+
+namespace caosdb::utility {
+
+using caosdb::entity::AtomicDataType;
+using caosdb::entity::Importance;
+using caosdb::entity::Role;
+
+// using emap = std::map<int, std::string>;          // enum mapping
+
+// Enum helper template specializations //////////////////////////////////////
+template <> auto getEnumNameFromValue<Importance>(Importance v) -> std::string {
+  auto result = caosdb::entity::importance_names.at(v);
+  return result;
+}
+
+template <> auto getEnumNameFromValue<Role>(Role v) -> std::string {
+  auto result = caosdb::entity::role_names.at(v);
+  return result;
+}
+
+template <> auto getEnumNameFromValue<AtomicDataType>(AtomicDataType v) -> std::string {
+  auto result = caosdb::entity::atomicdatatype_names.at(v);
+  return result;
+}
+
+template <> auto getEnumValueFromName<Importance>(const std::string &name) -> Importance {
+  // TODO (dh): Why does this compile?
+  // if (caosdb::entity::importance_names.begin()->second == name) {}
+  // std::for_each(caosdb::entity::importance_names.begin(),
+  //               caosdb::entity::importance_names.end(),
+  //               [](const auto &entry){});
+  // TODO (dh): Whereas this does not?
+  // auto result = std::find(caosdb::entity::importance_names.cbegin(),
+  //                         caosdb::entity::importance_names.cend(),
+  //                         [name](const auto& entry){ return entry.second == name; });
+  // Workaround: plaint old iteration:
+  for (auto const &entry : caosdb::entity::importance_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+
+template <> auto getEnumValueFromName<AtomicDataType>(const std::string &name) -> AtomicDataType {
+  for (auto const &entry : caosdb::entity::atomicdatatype_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+
+template <> auto getEnumValueFromName<Role>(const std::string &name) -> Role {
+  for (auto const &entry : caosdb::entity::role_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+
+// End of template specialization /////////////////////////////////////////////
+
+} // namespace caosdb::utility
diff --git a/src/ccaosdb.cpp b/src/ccaosdb.cpp
index d962c5bae38d655b90ce4e208bac9f042aabc7fa..dce0970bf21343eb12ffac6098450d507de70e59 100644
--- a/src/ccaosdb.cpp
+++ b/src/ccaosdb.cpp
@@ -41,112 +41,91 @@ extern "C" {
  * Macro for wrapping every function into a try-catch clause. If an exception
  * occurs, the given StatusCode is being returned.
  */
-#define ERROR_RETURN_CODE(code, fun, body)                                     \
-  fun {                                                                        \
-    CAOSDB_LOG_TRACE(CCAOSDB_LOGGER_NAME) << "Enter " << #fun;                 \
-    try {                                                                      \
-      body                                                                     \
-    } catch (const std::exception &exc) {                                      \
-      caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what());      \
-      return caosdb::StatusCode::code;                                         \
-    }                                                                          \
+#define ERROR_RETURN_CODE(code, fun, body)                                                         \
+  fun {                                                                                            \
+    CAOSDB_LOG_TRACE(CCAOSDB_LOGGER_NAME) << "Enter " << #fun;                                     \
+    try {                                                                                          \
+      body                                                                                         \
+    } catch (const std::exception &exc) {                                                          \
+      caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what());                          \
+      return caosdb::StatusCode::code;                                                             \
+    }                                                                                              \
   }
 
 /**
  * Macro for entity getters
  */
-#define CAOSDB_ENTITY_GET(element, body_part)                                  \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_entity_get_##element(caosdb_entity_entity *entity,       \
-                                           char *out),                         \
-    {                                                                          \
-      auto *wrapped_entity =                                                   \
-        static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);         \
-      body_part return 0;                                                      \
+#define CAOSDB_ENTITY_GET(element, body_part)                                                      \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_entity_get_##element(caosdb_entity_entity *entity, char *out), {             \
+      auto *wrapped_entity = static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);        \
+      body_part return 0;                                                                          \
     })
 
 /**
  * Macro for entity setters
  */
-#define CAOSDB_ENTITY_SET(element, value, body_part)                           \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_entity_set_##element(caosdb_entity_entity *entity,       \
-                                           const char *value),                 \
-    {                                                                          \
-      auto *wrapped_entity =                                                   \
-        static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);         \
-      body_part return 0;                                                      \
+#define CAOSDB_ENTITY_SET(element, value, body_part)                                               \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_entity_set_##element(caosdb_entity_entity *entity, const char *value), {     \
+      auto *wrapped_entity = static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);        \
+      body_part return 0;                                                                          \
     })
 
 /**
  * Macro for property getters
  */
-#define CAOSDB_PROPERTY_GET(element, body_part)                                \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_property_get_##element(caosdb_entity_property *property, \
-                                             char *out),                       \
-    {                                                                          \
-      auto *wrapped_property =                                                 \
-        static_cast<caosdb::entity::Property *>(property->wrapped_property);   \
-      body_part return 0;                                                      \
+#define CAOSDB_PROPERTY_GET(element, body_part)                                                    \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_property_get_##element(caosdb_entity_property *property, char *out), {       \
+      auto *wrapped_property =                                                                     \
+        static_cast<caosdb::entity::Property *>(property->wrapped_property);                       \
+      body_part return 0;                                                                          \
     })
 
 /**
  * Macro for property setters
  */
-#define CAOSDB_PROPERTY_SET(element, value, body_part)                         \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_property_set_##element(caosdb_entity_property *property, \
-                                             const char *value),               \
-    {                                                                          \
-      auto *wrapped_property =                                                 \
-        static_cast<caosdb::entity::Property *>(property->wrapped_property);   \
-      body_part return 0;                                                      \
+#define CAOSDB_PROPERTY_SET(element, value, body_part)                                             \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_property_set_##element(caosdb_entity_property *property, const char *value), \
+    {                                                                                              \
+      auto *wrapped_property =                                                                     \
+        static_cast<caosdb::entity::Property *>(property->wrapped_property);                       \
+      body_part return 0;                                                                          \
     })
 
 /**
  * Macro for parent getters
  */
-#define CAOSDB_PARENT_GET(element, body_part)                                  \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_parent_get_##element(caosdb_entity_parent *parent,       \
-                                           char *out),                         \
-    {                                                                          \
-      auto *wrapped_parent =                                                   \
-        static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);         \
-      body_part return 0;                                                      \
+#define CAOSDB_PARENT_GET(element, body_part)                                                      \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_parent_get_##element(caosdb_entity_parent *parent, char *out), {             \
+      auto *wrapped_parent = static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);        \
+      body_part return 0;                                                                          \
     })
 
 /**
  * Macro for parent setters
  */
-#define CAOSDB_PARENT_SET(element, value, body_part)                           \
-  ERROR_RETURN_CODE(                                                           \
-    GENERIC_ERROR,                                                             \
-    int caosdb_entity_parent_set_##element(caosdb_entity_parent *parent,       \
-                                           const char *value),                 \
-    {                                                                          \
-      auto *wrapped_parent =                                                   \
-        static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);         \
-      body_part return 0;                                                      \
+#define CAOSDB_PARENT_SET(element, value, body_part)                                               \
+  ERROR_RETURN_CODE(                                                                               \
+    GENERIC_ERROR,                                                                                 \
+    int caosdb_entity_parent_set_##element(caosdb_entity_parent *parent, const char *value), {     \
+      auto *wrapped_parent = static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);        \
+      body_part return 0;                                                                          \
     })
 
-int caosdb_constants_LIBCAOSDB_VERSION_MAJOR() {
-  return caosdb::LIBCAOSDB_VERSION_MAJOR;
-}
+int caosdb_constants_LIBCAOSDB_VERSION_MAJOR() { return caosdb::LIBCAOSDB_VERSION_MAJOR; }
 
-int caosdb_constants_LIBCAOSDB_VERSION_MINOR() {
-  return caosdb::LIBCAOSDB_VERSION_MINOR;
-}
+int caosdb_constants_LIBCAOSDB_VERSION_MINOR() { return caosdb::LIBCAOSDB_VERSION_MINOR; }
 
-int caosdb_constants_LIBCAOSDB_VERSION_PATCH() {
-  return caosdb::LIBCAOSDB_VERSION_PATCH;
-}
+int caosdb_constants_LIBCAOSDB_VERSION_PATCH() { return caosdb::LIBCAOSDB_VERSION_PATCH; }
 
 int caosdb_constants_COMPATIBLE_SERVER_VERSION_MAJOR() {
   return caosdb::COMPATIBLE_SERVER_VERSION_MAJOR;
@@ -164,9 +143,7 @@ const char *caosdb_constants_COMPATIBLE_SERVER_VERSION_PRE_RELEASE() {
   return caosdb::COMPATIBLE_SERVER_VERSION_PRE_RELEASE;
 }
 
-int caosdb_status_code_OTHER_CLIENT_ERROR() {
-  return caosdb::StatusCode::OTHER_CLIENT_ERROR;
-}
+int caosdb_status_code_OTHER_CLIENT_ERROR() { return caosdb::StatusCode::OTHER_CLIENT_ERROR; }
 
 const char *caosdb_utility_get_env_var(const char *name, const char *fallback) {
   return caosdb::utility::get_env_var(name, fallback);
@@ -178,65 +155,61 @@ const char *caosdb_get_status_description(int code) {
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_create_pem_file_certificate_provider(
-                    caosdb_connection_certificate_provider *out,
-                    const char *path),
+                    caosdb_connection_certificate_provider *out, const char *path),
                   {
                     if (out->_deletable) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_certificate_provider =
-                      new caosdb::configuration::PemFileCertificateProvider(
-                        std::string(path));
+                      new caosdb::configuration::PemFileCertificateProvider(std::string(path));
                     out->_deletable = true;
                     return 0;
                   })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_connection_delete_certificate_provider(
-    caosdb_connection_certificate_provider *provider),
-  {
-    if (provider->_deletable) {
-      delete static_cast<caosdb::configuration::CertificateProvider *>(
-        provider->wrapped_certificate_provider);
-    }
-    provider->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_connection_delete_certificate_provider(
+                    caosdb_connection_certificate_provider *provider),
+                  {
+                    if (provider->_deletable) {
+                      delete static_cast<caosdb::configuration::CertificateProvider *>(
+                        provider->wrapped_certificate_provider);
+                    }
+                    provider->_deletable = false;
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_authentication_create_plain_password_authenticator(
-                    caosdb_authentication_authenticator *out,
-                    const char *username, const char *password),
+                    caosdb_authentication_authenticator *out, const char *username,
+                    const char *password),
                   {
                     if (out->_deletable) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_authenticator =
-                      new caosdb::authentication::PlainPasswordAuthenticator(
-                        std::string(username), std::string(password));
+                      new caosdb::authentication::PlainPasswordAuthenticator(std::string(username),
+                                                                             std::string(password));
                     out->_deletable = true;
                     return 0;
                   })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_authentication_delete_authenticator(
-    caosdb_authentication_authenticator *authenticator),
-  {
-    if (authenticator->_deletable) {
-      delete static_cast<caosdb::authentication::Authenticator *>(
-        authenticator->wrapped_authenticator);
-    }
-    authenticator->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_authentication_delete_authenticator(
+                    caosdb_authentication_authenticator *authenticator),
+                  {
+                    if (authenticator->_deletable) {
+                      delete static_cast<caosdb::authentication::Authenticator *>(
+                        authenticator->wrapped_authenticator);
+                    }
+                    authenticator->_deletable = false;
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(
   GENERIC_ERROR,
   int caosdb_connection_create_tls_connection_configuration(
-    caosdb_connection_connection_configuration *out, const char *host,
-    const int port, caosdb_authentication_authenticator *authenticator,
+    caosdb_connection_connection_configuration *out, const char *host, const int port,
+    caosdb_authentication_authenticator *authenticator,
     caosdb_connection_certificate_provider *provider),
   {
     if (out->_deletable) {
@@ -244,29 +217,22 @@ ERROR_RETURN_CODE(
     }
     auto host_str = std::string(host);
     if (authenticator != nullptr && provider != nullptr) {
-      auto wrapped_provider =
-        static_cast<caosdb::configuration::CertificateProvider *>(
-          provider->wrapped_certificate_provider);
+      auto wrapped_provider = static_cast<caosdb::configuration::CertificateProvider *>(
+        provider->wrapped_certificate_provider);
       auto wrapped_authenticator =
-        static_cast<caosdb::authentication::Authenticator *>(
-          authenticator->wrapped_authenticator);
-      out->wrapped_connection_configuration =
-        new caosdb::configuration::TlsConnectionConfiguration(
-          host_str, port, *wrapped_provider, *wrapped_authenticator);
+        static_cast<caosdb::authentication::Authenticator *>(authenticator->wrapped_authenticator);
+      out->wrapped_connection_configuration = new caosdb::configuration::TlsConnectionConfiguration(
+        host_str, port, *wrapped_provider, *wrapped_authenticator);
     } else if (authenticator != nullptr) {
       auto wrapped_authenticator =
-        static_cast<caosdb::authentication::Authenticator *>(
-          authenticator->wrapped_authenticator);
-      out->wrapped_connection_configuration =
-        new caosdb::configuration::TlsConnectionConfiguration(
-          host_str, port, *wrapped_authenticator);
+        static_cast<caosdb::authentication::Authenticator *>(authenticator->wrapped_authenticator);
+      out->wrapped_connection_configuration = new caosdb::configuration::TlsConnectionConfiguration(
+        host_str, port, *wrapped_authenticator);
     } else if (provider != nullptr) {
-      auto wrapped_provider =
-        static_cast<caosdb::configuration::CertificateProvider *>(
-          provider->wrapped_certificate_provider);
+      auto wrapped_provider = static_cast<caosdb::configuration::CertificateProvider *>(
+        provider->wrapped_certificate_provider);
       out->wrapped_connection_configuration =
-        new caosdb::configuration::TlsConnectionConfiguration(
-          host_str, port, *wrapped_provider);
+        new caosdb::configuration::TlsConnectionConfiguration(host_str, port, *wrapped_provider);
     } else {
       out->wrapped_connection_configuration =
         new caosdb::configuration::TlsConnectionConfiguration(host_str, port);
@@ -275,54 +241,50 @@ ERROR_RETURN_CODE(
     return 0;
   })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_connection_create_insecure_connection_configuration(
-    caosdb_connection_connection_configuration *out, const char *host,
-    const int port),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    out->wrapped_connection_configuration =
-      new caosdb::configuration::InsecureConnectionConfiguration(host, port);
-    out->_deletable = true;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_connection_create_insecure_connection_configuration(
+                    caosdb_connection_connection_configuration *out, const char *host,
+                    const int port),
+                  {
+                    if (out->_deletable) {
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+                    }
+                    out->wrapped_connection_configuration =
+                      new caosdb::configuration::InsecureConnectionConfiguration(host, port);
+                    out->_deletable = true;
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_connection_delete_connection_configuration(
-    caosdb_connection_connection_configuration *configuration),
-  {
-    if (configuration->_deletable) {
-      delete static_cast<caosdb::configuration::ConnectionConfiguration *>(
-        configuration->wrapped_connection_configuration);
-    }
-    configuration->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_connection_delete_connection_configuration(
+                    caosdb_connection_connection_configuration *configuration),
+                  {
+                    if (configuration->_deletable) {
+                      delete static_cast<caosdb::configuration::ConnectionConfiguration *>(
+                        configuration->wrapped_connection_configuration);
+                    }
+                    configuration->_deletable = false;
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_connection_create_connection(
-    caosdb_connection_connection *out,
-    const caosdb_connection_connection_configuration *configuration),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    caosdb::configuration::ConnectionConfiguration *config =
-      static_cast<caosdb::configuration::ConnectionConfiguration *>(
-        configuration->wrapped_connection_configuration);
-    out->wrapped_connection = new caosdb::connection::Connection(*config);
-    out->_deletable = true;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_connection_create_connection(
+                    caosdb_connection_connection *out,
+                    const caosdb_connection_connection_configuration *configuration),
+                  {
+                    if (out->_deletable) {
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+                    }
+                    caosdb::configuration::ConnectionConfiguration *config =
+                      static_cast<caosdb::configuration::ConnectionConfiguration *>(
+                        configuration->wrapped_connection_configuration);
+                    out->wrapped_connection = new caosdb::connection::Connection(*config);
+                    out->_deletable = true;
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_connection_delete_connection(
-                    caosdb_connection_connection *connection),
+                  int caosdb_connection_delete_connection(caosdb_connection_connection *connection),
                   {
                     if (connection->_deletable) {
                       delete static_cast<caosdb::connection::Connection *>(
@@ -334,12 +296,11 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
 
 ERROR_RETURN_CODE(
   GENERIC_ERROR,
-  int caosdb_connection_get_version_info(
-    caosdb_info_version_info *out,
-    const caosdb_connection_connection *connection),
+  int caosdb_connection_get_version_info(caosdb_info_version_info *out,
+                                         const caosdb_connection_connection *connection),
   {
-    auto *wrapped_connection = static_cast<caosdb::connection::Connection *>(
-      connection->wrapped_connection);
+    auto *wrapped_connection =
+      static_cast<caosdb::connection::Connection *>(connection->wrapped_connection);
 
     auto status = wrapped_connection->RetrieveVersionInfoNoExceptions();
     if (status.IsError()) {
@@ -352,33 +313,30 @@ ERROR_RETURN_CODE(
     out->patch = (int)version_info->GetPatch();
 
     // copy pre_release, needs local variable because out->pre_release is const
-    char *pre_release = (char *)malloc(
-      sizeof(char) * (version_info->GetPreRelease().length() + 1));
+    char *pre_release = (char *)malloc(sizeof(char) * (version_info->GetPreRelease().length() + 1));
     strcpy(pre_release, version_info->GetPreRelease().c_str());
     out->pre_release = pre_release;
 
     // copy build, needs local variable because out->build is const
-    char *build =
-      (char *)malloc(sizeof(char) * (version_info->GetBuild().length() + 1));
+    char *build = (char *)malloc(sizeof(char) * (version_info->GetBuild().length() + 1));
     strcpy(build, version_info->GetBuild().c_str());
     out->build = build;
 
     return 0;
   })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_connection_connection_manager_get_default_connection(
-    caosdb_connection_connection *out),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    out->wrapped_connection =
-      caosdb::connection::ConnectionManager::GetDefaultConnection().get();
-    out->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_connection_connection_manager_get_default_connection(
+                    caosdb_connection_connection *out),
+                  {
+                    if (out->_deletable) {
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+                    }
+                    out->wrapped_connection =
+                      caosdb::connection::ConnectionManager::GetDefaultConnection().get();
+                    out->_deletable = false;
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_connection_manager_get_connection(
@@ -388,9 +346,7 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     out->wrapped_connection =
-                      caosdb::connection::ConnectionManager::GetConnection(
-                        std::string(name))
-                        .get();
+                      caosdb::connection::ConnectionManager::GetConnection(std::string(name)).get();
                     // managed by the connection manager now, so not
                     // to be deleted manually
                     out->_deletable = false;
@@ -402,436 +358,393 @@ ERROR_RETURN_CODE(GENERIC_ERROR,
  ****************************************************************************/
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_connection_connection_create_transaction(
-                    caosdb_connection_connection *connection,
-                    caosdb_transaction_transaction *out),
+                    caosdb_connection_connection *connection, caosdb_transaction_transaction *out),
                   {
                     if (out->_deletable) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
                     auto *wrapped_connection =
-                      static_cast<caosdb::connection::Connection *>(
-                        connection->wrapped_connection);
-                    out->wrapped_transaction =
-                      wrapped_connection->CreateTransaction().release();
+                      static_cast<caosdb::connection::Connection *>(connection->wrapped_connection);
+                    out->wrapped_transaction = wrapped_connection->CreateTransaction().release();
                     out->_deletable = true;
                     return 0;
                   })
 
-ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_transaction_delete_transaction(
-                    caosdb_transaction_transaction *transaction),
-                  {
-                    if (transaction->_deletable) {
-                      delete static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
-                    }
-                    return 0;
-                  })
+ERROR_RETURN_CODE(
+  GENERIC_ERROR,
+  int caosdb_transaction_delete_transaction(caosdb_transaction_transaction *transaction), {
+    if (transaction->_deletable) {
+      delete static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction);
+    }
+    return 0;
+  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_transaction_transaction_retrieve_by_id(
-                    caosdb_transaction_transaction *transaction,
-                    const char *id),
+                    caosdb_transaction_transaction *transaction, const char *id),
                   {
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
+                    auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>(
+                      transaction->wrapped_transaction);
                     return wrapped_transaction->RetrieveById(std::string(id));
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_transaction_transaction_retrieve_by_ids(
-                    caosdb_transaction_transaction *transaction,
-                    const char *ids[], int length),
+                    caosdb_transaction_transaction *transaction, const char *ids[], int length),
                   {
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
+                    auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>(
+                      transaction->wrapped_transaction);
                     return wrapped_transaction->RetrieveById(ids, ids + length);
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_transaction_transaction_query(
-                    caosdb_transaction_transaction *transaction,
-                    const char *query),
+                    caosdb_transaction_transaction *transaction, const char *query),
                   {
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
+                    auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>(
+                      transaction->wrapped_transaction);
                     return wrapped_transaction->Query(std::string(query));
                   })
 
-ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_transaction_transaction_execute(
-                    caosdb_transaction_transaction *transaction),
-                  {
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
-                    wrapped_transaction->ExecuteAsynchronously();
-                    auto status = wrapped_transaction->WaitForIt();
-                    return status.GetCode();
-                  })
+ERROR_RETURN_CODE(
+  GENERIC_ERROR,
+  int caosdb_transaction_transaction_execute(caosdb_transaction_transaction *transaction), {
+    auto *wrapped_transaction =
+      static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction);
+    wrapped_transaction->ExecuteAsynchronously();
+    auto status = wrapped_transaction->WaitForIt();
+    return status.GetCode();
+  })
 
-ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_transaction_transaction_get_result_set(
-                    caosdb_transaction_transaction *transaction,
-                    caosdb_transaction_result_set *out),
-                  {
-                    if (out->_deletable) {
-                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-                    }
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
-                    out->wrapped_result_set =
-                      (void *)(&(wrapped_transaction->GetResultSet()));
-                    out->_deletable = false;
-                    return 0;
-                  })
+ERROR_RETURN_CODE(
+  GENERIC_ERROR,
+  int caosdb_transaction_transaction_get_result_set(caosdb_transaction_transaction *transaction,
+                                                    caosdb_transaction_result_set *out),
+  {
+    if (out->_deletable) {
+      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+    }
+    auto *wrapped_transaction =
+      static_cast<caosdb::transaction::Transaction *>(transaction->wrapped_transaction);
+    out->wrapped_result_set = (void *)(&(wrapped_transaction->GetResultSet()));
+    out->_deletable = false;
+    return 0;
+  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
                   int caosdb_transaction_transaction_get_count_result(
                     caosdb_transaction_transaction *transaction, long *out),
                   {
-                    auto *wrapped_transaction =
-                      static_cast<caosdb::transaction::Transaction *>(
-                        transaction->wrapped_transaction);
+                    auto *wrapped_transaction = static_cast<caosdb::transaction::Transaction *>(
+                      transaction->wrapped_transaction);
                     long cr(wrapped_transaction->GetCountResult());
                     *out = cr;
                     return 0;
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_transaction_result_set_at(
-                    caosdb_transaction_result_set *result_set,
-                    caosdb_entity_entity *entity, int index),
+                  int caosdb_transaction_result_set_at(caosdb_transaction_result_set *result_set,
+                                                       caosdb_entity_entity *entity, int index),
                   {
-                    auto *wrapped_result_set =
-                      static_cast<caosdb::transaction::MultiResultSet *>(
-                        result_set->wrapped_result_set);
-                    entity->wrapped_entity =
-                      wrapped_result_set->mutable_at(index);
+                    auto *wrapped_result_set = static_cast<caosdb::transaction::MultiResultSet *>(
+                      result_set->wrapped_result_set);
+                    entity->wrapped_entity = wrapped_result_set->mutable_at(index);
                     return 0;
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_transaction_result_set_size(
-                    caosdb_transaction_result_set *result_set, int *out),
+                  int caosdb_transaction_result_set_size(caosdb_transaction_result_set *result_set,
+                                                         int *out),
                   {
-                    auto *wrapped_result_set =
-                      static_cast<caosdb::transaction::MultiResultSet *>(
-                        result_set->wrapped_result_set);
+                    auto *wrapped_result_set = static_cast<caosdb::transaction::MultiResultSet *>(
+                      result_set->wrapped_result_set);
                     int size(wrapped_result_set->size());
                     *out = size;
                     return 0;
                   })
 
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_entity(caosdb_entity_entity *out), {
+  if (out->_deletable) {
+    return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+  }
+  out->wrapped_entity = new caosdb::entity::Entity();
+  out->_deletable = true;
+  return 0;
+})
+
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_entity(caosdb_entity_entity *out), {
+  if (out->_deletable) {
+    delete static_cast<caosdb::entity::Entity *>(out->wrapped_entity);
+  }
+  out->_deletable = false;
+  return 0;
+})
+
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_property(caosdb_entity_property *out), {
+  if (out->_deletable) {
+    return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+  }
+  out->wrapped_property = new caosdb::entity::Property();
+  out->_deletable = true;
+  return 0;
+})
+
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_property(caosdb_entity_property *out), {
+  if (out->_deletable) {
+    delete static_cast<caosdb::entity::Property *>(out->wrapped_property);
+  }
+  out->_deletable = false;
+  return 0;
+})
+
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_create_parent(caosdb_entity_parent *out), {
+  if (out->_deletable) {
+    return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+  }
+  out->wrapped_parent = new caosdb::entity::Parent();
+  out->_deletable = true;
+  return 0;
+})
+
+ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_parent(caosdb_entity_parent *out), {
+  if (out->_deletable) {
+    delete static_cast<caosdb::entity::Parent *>(out->wrapped_parent);
+  }
+  out->_deletable = false;
+  return 0;
+})
+
+CAOSDB_ENTITY_GET(id, strcpy(out, wrapped_entity->GetId().c_str());)
+// TODO(fspreck)
+// CAOSDB_ENTITY_GET(role, strcpy(out, wrapped_entity->GetRole().c_str());)
+CAOSDB_ENTITY_GET(name, strcpy(out, wrapped_entity->GetName().c_str());)
+CAOSDB_ENTITY_GET(description, strcpy(out, wrapped_entity->GetDescription().c_str());)
+// TODO(fspreck)
+// CAOSDB_ENTITY_GET(datatype, strcpy(out,
+// wrapped_entity->GetDatatype().c_str());)
+// TODO(fspreck)
+// CAOSDB_ENTITY_GET(value, strcpy(out, wrapped_entity->GetValue().c_str());)
+CAOSDB_ENTITY_GET(unit, strcpy(out, wrapped_entity->GetUnit().c_str());)
+CAOSDB_ENTITY_GET(version_id, strcpy(out, wrapped_entity->GetVersionId().c_str());)
+
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_entity_create_entity(caosdb_entity_entity *out), {
+                  int caosdb_entity_entity_get_errors_size(caosdb_entity_entity *entity, int *out),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    *out = wrapped_entity->GetErrors().size();
+                    return 0;
+                  })
+
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_error(caosdb_entity_entity *entity,
+                                                     caosdb_entity_message *out, int index),
+                  {
                     if (out->_deletable) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
-                    out->wrapped_entity = new caosdb::entity::Entity();
-                    out->_deletable = true;
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    out->wrapped_message = wrapped_entity->GetErrors().mutable_at(index);
+                    out->_deletable = false;
+                    return 0;
+                  })
+
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_warnings_size(caosdb_entity_entity *entity,
+                                                             int *out),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    *out = wrapped_entity->GetWarnings().size();
                     return 0;
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_entity_delete_entity(caosdb_entity_entity *out), {
+                  int caosdb_entity_entity_get_warning(caosdb_entity_entity *entity,
+                                                       caosdb_entity_message *out, int index),
+                  {
                     if (out->_deletable) {
-                      delete static_cast<caosdb::entity::Entity *>(
-                        out->wrapped_entity);
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    out->wrapped_message = wrapped_entity->GetWarnings().mutable_at(index);
                     out->_deletable = false;
                     return 0;
                   })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR, int caosdb_entity_create_property(caosdb_entity_property *out),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    out->wrapped_property = new caosdb::entity::Property();
-    out->_deletable = true;
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR, int caosdb_entity_delete_property(caosdb_entity_property *out),
-  {
-    if (out->_deletable) {
-      delete static_cast<caosdb::entity::Property *>(out->wrapped_property);
-    }
-    out->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_infos_size(caosdb_entity_entity *entity, int *out), {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    *out = wrapped_entity->GetInfos().size();
+                    return 0;
+                  })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_entity_create_parent(caosdb_entity_parent *out), {
+                  int caosdb_entity_entity_get_info(caosdb_entity_entity *entity,
+                                                    caosdb_entity_message *out, int index),
+                  {
                     if (out->_deletable) {
                       return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
-                    out->wrapped_parent = new caosdb::entity::Parent();
-                    out->_deletable = true;
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    out->wrapped_message = wrapped_entity->GetInfos().mutable_at(index);
+                    out->_deletable = false;
+                    return 0;
+                  })
+
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_properties_size(caosdb_entity_entity *entity,
+                                                               int *out),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    *out = wrapped_entity->GetProperties().size();
                     return 0;
                   })
 
 ERROR_RETURN_CODE(GENERIC_ERROR,
-                  int caosdb_entity_delete_parent(caosdb_entity_parent *out), {
+                  int caosdb_entity_entity_get_property(caosdb_entity_entity *entity,
+                                                        caosdb_entity_property *out, int index),
+                  {
                     if (out->_deletable) {
-                      delete static_cast<caosdb::entity::Parent *>(
-                        out->wrapped_parent);
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
                     }
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    out->wrapped_property = wrapped_entity->GetProperties().mutable_at(index);
                     out->_deletable = false;
                     return 0;
                   })
 
-CAOSDB_ENTITY_GET(id, strcpy(out, wrapped_entity->GetId().c_str());)
-CAOSDB_ENTITY_GET(role, strcpy(out, wrapped_entity->GetRole().c_str());)
-CAOSDB_ENTITY_GET(name, strcpy(out, wrapped_entity->GetName().c_str());)
-CAOSDB_ENTITY_GET(description,
-                  strcpy(out, wrapped_entity->GetDescription().c_str());)
-CAOSDB_ENTITY_GET(datatype, strcpy(out, wrapped_entity->GetDatatype().c_str());)
-CAOSDB_ENTITY_GET(value, strcpy(out, wrapped_entity->GetValue().c_str());)
-CAOSDB_ENTITY_GET(unit, strcpy(out, wrapped_entity->GetUnit().c_str());)
-CAOSDB_ENTITY_GET(version_id,
-                  strcpy(out, wrapped_entity->GetVersionId().c_str());)
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_errors_size(caosdb_entity_entity *entity,
-                                           int *out),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    *out = wrapped_entity->GetErrors().size();
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_error(caosdb_entity_entity *entity,
-                                     caosdb_entity_message *out, int index),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    out->wrapped_message = wrapped_entity->GetErrors().mutable_at(index);
-    out->_deletable = false;
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_warnings_size(caosdb_entity_entity *entity,
-                                             int *out),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    *out = wrapped_entity->GetWarnings().size();
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_warning(caosdb_entity_entity *entity,
-                                       caosdb_entity_message *out, int index),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    out->wrapped_message = wrapped_entity->GetWarnings().mutable_at(index);
-    out->_deletable = false;
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_infos_size(caosdb_entity_entity *entity,
-                                          int *out),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    *out = wrapped_entity->GetInfos().size();
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_info(caosdb_entity_entity *entity,
-                                    caosdb_entity_message *out, int index),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    out->wrapped_message = wrapped_entity->GetInfos().mutable_at(index);
-    out->_deletable = false;
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_properties_size(caosdb_entity_entity *entity,
-                                               int *out),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    *out = wrapped_entity->GetProperties().size();
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_property(caosdb_entity_entity *entity,
-                                        caosdb_entity_property *out, int index),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    out->wrapped_property = wrapped_entity->GetProperties().mutable_at(index);
-    out->_deletable = false;
-    return 0;
-  })
-
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_parents_size(caosdb_entity_entity *entity,
-                                            int *out),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    *out = wrapped_entity->GetParents().size();
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_parents_size(caosdb_entity_entity *entity, int *out),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    *out = wrapped_entity->GetParents().size();
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_get_parent(caosdb_entity_entity *entity,
-                                      caosdb_entity_parent *out, int index),
-  {
-    if (out->_deletable) {
-      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
-    }
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    out->wrapped_parent = wrapped_entity->GetParents().mutable_at(index);
-    out->_deletable = false;
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_get_parent(caosdb_entity_entity *entity,
+                                                      caosdb_entity_parent *out, int index),
+                  {
+                    if (out->_deletable) {
+                      return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR;
+                    }
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    out->wrapped_parent = wrapped_entity->GetParents().mutable_at(index);
+                    out->_deletable = false;
+                    return 0;
+                  })
 
 CAOSDB_PARENT_GET(id, strcpy(out, wrapped_parent->GetId().c_str());)
 CAOSDB_PARENT_GET(name, strcpy(out, wrapped_parent->GetName().c_str());)
-CAOSDB_PARENT_GET(description,
-                  strcpy(out, wrapped_parent->GetDescription().c_str());)
+CAOSDB_PARENT_GET(description, strcpy(out, wrapped_parent->GetDescription().c_str());)
 
 CAOSDB_PROPERTY_GET(id, strcpy(out, wrapped_property->GetId().c_str());)
 CAOSDB_PROPERTY_GET(name, strcpy(out, wrapped_property->GetName().c_str());)
-CAOSDB_PROPERTY_GET(description,
-                    strcpy(out, wrapped_property->GetDescription().c_str());)
-CAOSDB_PROPERTY_GET(importance,
-                    strcpy(out, wrapped_property->GetImportance().c_str());)
-CAOSDB_PROPERTY_GET(datatype,
-                    strcpy(out, wrapped_property->GetDatatype().c_str());)
+CAOSDB_PROPERTY_GET(description, strcpy(out, wrapped_property->GetDescription().c_str());)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_GET(importance,
+//                    strcpy(out, wrapped_property->GetImportance().c_str());)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_GET(datatype,
+//                    strcpy(out, wrapped_property->GetDatatype().c_str());)
 CAOSDB_PROPERTY_GET(unit, strcpy(out, wrapped_property->GetUnit().c_str());)
-CAOSDB_PROPERTY_GET(value, strcpy(out, wrapped_property->GetValue().c_str());)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_GET(value, strcpy(out,
+// wrapped_property->GetValue().c_str());)
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out),
-  {
-    auto *wrapped_message =
-      static_cast<caosdb::entity::Message *>(message->wrapped_message);
-    *out = wrapped_message->GetCode();
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out), {
+                    auto *wrapped_message =
+                      static_cast<caosdb::entity::Message *>(message->wrapped_message);
+                    *out = wrapped_message->GetCode();
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_message_get_description(caosdb_entity_message *message,
-                                            char *out),
-  {
-    auto *wrapped_message =
-      static_cast<caosdb::entity::Message *>(message->wrapped_message);
-    strcpy(out, wrapped_message->GetDescription().c_str());
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_message_get_description(caosdb_entity_message *message,
+                                                            char *out),
+                  {
+                    auto *wrapped_message =
+                      static_cast<caosdb::entity::Message *>(message->wrapped_message);
+                    strcpy(out, wrapped_message->GetDescription().c_str());
+                    return 0;
+                  })
 
-CAOSDB_ENTITY_SET(role, role, wrapped_entity->SetRole(std::string(role));)
+// TODO(fspreck)
+// CAOSDB_ENTITY_SET(role, role, wrapped_entity->SetRole(std::string(role));)
 CAOSDB_ENTITY_SET(name, name, wrapped_entity->SetName(std::string(name));)
 CAOSDB_ENTITY_SET(description, description,
                   wrapped_entity->SetDescription(std::string(description));)
-CAOSDB_ENTITY_SET(datatype, datatype,
-                  wrapped_entity->SetDatatype(std::string(datatype));)
+// TODO(fspreck)
+// CAOSDB_ENTITY_SET(datatype, datatype,
+//                  wrapped_entity->SetDataType(std::string(datatype));)
 CAOSDB_ENTITY_SET(unit, unit, wrapped_entity->SetUnit(std::string(unit));)
-CAOSDB_ENTITY_SET(value, value, wrapped_entity->SetValue(std::string(value));)
+// TODO(fspreck)
+// CAOSDB_ENTITY_SET(value, value,
+// wrapped_entity->SetValue(std::string(value));)
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_append_parent(caosdb_entity_entity *entity,
-                                         caosdb_entity_parent *parent),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    auto *wrapped_parent =
-      static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);
-    wrapped_entity->AppendParent(*wrapped_parent);
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_append_parent(caosdb_entity_entity *entity,
+                                                         caosdb_entity_parent *parent),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    auto *wrapped_parent =
+                      static_cast<caosdb::entity::Parent *>(parent->wrapped_parent);
+                    wrapped_entity->AppendParent(*wrapped_parent);
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_remove_parent(caosdb_entity_entity *entity,
-                                         int index),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    wrapped_entity->RemoveParent(index);
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_remove_parent(caosdb_entity_entity *entity, int index), {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    wrapped_entity->RemoveParent(index);
+                    return 0;
+                  })
 
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_append_property(caosdb_entity_entity *entity,
-                                           caosdb_entity_property *property),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    auto *wrapped_property =
-      static_cast<caosdb::entity::Property *>(property->wrapped_property);
-    wrapped_entity->AppendProperty(*wrapped_property);
-    return 0;
-  })
-ERROR_RETURN_CODE(
-  GENERIC_ERROR,
-  int caosdb_entity_entity_remove_property(caosdb_entity_entity *entity,
-                                           int index),
-  {
-    auto *wrapped_entity =
-      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
-    wrapped_entity->RemoveProperty(index);
-    return 0;
-  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_append_property(caosdb_entity_entity *entity,
+                                                           caosdb_entity_property *property),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    auto *wrapped_property =
+                      static_cast<caosdb::entity::Property *>(property->wrapped_property);
+                    wrapped_entity->AppendProperty(*wrapped_property);
+                    return 0;
+                  })
+ERROR_RETURN_CODE(GENERIC_ERROR,
+                  int caosdb_entity_entity_remove_property(caosdb_entity_entity *entity, int index),
+                  {
+                    auto *wrapped_entity =
+                      static_cast<caosdb::entity::Entity *>(entity->wrapped_entity);
+                    wrapped_entity->RemoveProperty(index);
+                    return 0;
+                  })
 
 CAOSDB_PARENT_SET(id, id, wrapped_parent->SetId(std::string(id));)
 CAOSDB_PARENT_SET(name, name, wrapped_parent->SetName(std::string(name));)
 
 CAOSDB_PROPERTY_SET(name, name, wrapped_property->SetName(std::string(name));)
 CAOSDB_PROPERTY_SET(id, id, wrapped_property->SetId(std::string(id));)
-CAOSDB_PROPERTY_SET(datatype, datatype,
-                    wrapped_property->SetDatatype(std::string(datatype));)
-CAOSDB_PROPERTY_SET(importance, importance,
-                    wrapped_property->SetImportance(std::string(importance));)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_SET(datatype, datatype,
+//                    wrapped_property->SetDataType(std::string(datatype));)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_SET(importance, importance,
+//                    wrapped_property->SetImportance(std::string(importance));)
 CAOSDB_PROPERTY_SET(unit, unit, wrapped_property->SetUnit(std::string(unit));)
-CAOSDB_PROPERTY_SET(value, value,
-                    wrapped_property->SetValue(std::string(value));)
+// TODO(fspreck)
+// CAOSDB_PROPERTY_SET(value, value,
+//                    wrapped_property->SetValue(std::string(value));)
 }
diff --git a/src/ccaosdbcli.c b/src/ccaosdbcli.c
index e06dff51bcc62fcc8ae2bc4e2db53647d6c3de06..e3ce7dea431441b5ef6f827f02f8741681f631c2 100644
--- a/src/ccaosdbcli.c
+++ b/src/ccaosdbcli.c
@@ -4,30 +4,25 @@
 
 int main(void) {
   int status = 0; // last function return value
-  printf(
-    "CaosDB C client (libcaosdb %d.%d.%d)\nWe don't miss the H of caos.\n\n",
-    LIBCAOSDB_VERSION_MAJOR, LIBCAOSDB_VERSION_MINOR, LIBCAOSDB_VERSION_PATCH);
+  printf("CaosDB C client (libcaosdb %d.%d.%d)\nWe don't miss the H of caos.\n\n",
+         LIBCAOSDB_VERSION_MAJOR, LIBCAOSDB_VERSION_MINOR, LIBCAOSDB_VERSION_PATCH);
 
   caosdb_connection_connection connection;
-  status =
-    caosdb_connection_connection_manager_get_default_connection(&connection);
+  status = caosdb_connection_connection_manager_get_default_connection(&connection);
   if (status != 0) {
-    printf("An error occured: ERROR %d - %s\n", status,
-           caosdb_get_status_description(status));
+    printf("An error occured: ERROR %d - %s\n", status, caosdb_get_status_description(status));
     return status;
   }
 
   caosdb_info_version_info version_info;
   status = caosdb_connection_get_version_info(&version_info, &connection);
   if (status != 0) {
-    printf("An error occured: ERROR %d - %s\n", status,
-           caosdb_get_status_description(status));
+    printf("An error occured: ERROR %d - %s\n", status, caosdb_get_status_description(status));
     return status;
   }
 
-  printf("Server version: %d.%d.%d-%s-%s\n", version_info.major,
-         version_info.minor, version_info.patch, version_info.pre_release,
-         version_info.build);
+  printf("Server version: %d.%d.%d-%s-%s\n", version_info.major, version_info.minor,
+         version_info.patch, version_info.pre_release, version_info.build);
 
   return 0;
 }
diff --git a/src/cxxcaosdbcli.cpp b/src/cxxcaosdbcli.cpp
index f94144923b79fc4f2a511b6248f158067085b222..1760975460281614051c1ac9790be840d7c36c4f 100644
--- a/src/cxxcaosdbcli.cpp
+++ b/src/cxxcaosdbcli.cpp
@@ -33,23 +33,19 @@
 
 auto main() -> int {
 
-  std::cout << "CaosDB C++ client (libcaosdb "
-            << caosdb::LIBCAOSDB_VERSION_MINOR << "."
-            << caosdb::LIBCAOSDB_VERSION_MINOR << "."
-            << caosdb::LIBCAOSDB_VERSION_PATCH << ")\n"
+  std::cout << "CaosDB C++ client (libcaosdb " << caosdb::LIBCAOSDB_VERSION_MINOR << "."
+            << caosdb::LIBCAOSDB_VERSION_MINOR << "." << caosdb::LIBCAOSDB_VERSION_PATCH << ")\n"
             << "We don't miss the H of caos.\n"
             << std::endl;
 
   try {
-    const auto &connection =
-      caosdb::connection::ConnectionManager::GetDefaultConnection();
+    const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection();
 
     connection->RetrieveVersionInfoNoExceptions();
     // get version info of the server
     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::cout << "Server Version: " << v_info->GetMajor() << "." << v_info->GetMinor() << "."
+              << v_info->GetPatch() << "-" << v_info->GetPreRelease() << "-" << v_info->GetBuild()
               << std::endl;
 
     // retrieve an entity
@@ -57,12 +53,10 @@ auto main() -> int {
     transaction->RetrieveById("20");
     transaction->Execute();
     const auto &result_set =
-      dynamic_cast<const caosdb::transaction::UniqueResult &>(
-        transaction->GetResultSet());
+      dynamic_cast<const caosdb::transaction::UniqueResult &>(transaction->GetResultSet());
 
     // print description
-    std::cout << "Entity Description: "
-              << result_set.GetEntity().GetDescription() << std::endl;
+    std::cout << "Entity Description: " << result_set.GetEntity().GetDescription() << std::endl;
 
     return 0;
   } catch (const caosdb::exceptions::ConfigurationError &exc) {
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 0ecb50169e94b5f758a429054c80c80e9d420c4d..6edff54857aca64b64c99a47ea8344ebf9eee265 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -20,14 +20,17 @@
 
 # append all the test cases here (file name without the ".cpp" suffix)
 set(test_cases
+    test_data_type
     test_configuration
     test_connection
     test_entity
     test_file_transmission
     test_info
+    test_list_properties
     test_protobuf
     test_transaction
     test_utility
+    test_value
     test_ccaosdb
     )
 
@@ -57,15 +60,16 @@ foreach (i RANGE "${len_test_cases}")
     target_include_directories(${test_case_name}
       PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
     if(_LINTING)
-    set_target_properties(${test_case_name}
-        PROPERTIES
-        CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS}"
-        CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}")
+        set_target_properties(${test_case_name}
+            PROPERTIES
+            CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS}"
+            CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}")
     endif()
     gtest_discover_tests(${test_case_name}
         WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
         PROPERTIES
-            LABELS "caosdb-cpplib-unit-tests")
+            LABELS "caosdb-cpplib-unit-tests"
+        )
 endforeach ()
 
 # copy test data to build dir
diff --git a/test/caosdb_test_utility.h.in b/test/caosdb_test_utility.h.in
index baac638f5668a05c6464fef99410bb345ba8b3c3..8c3761e9f57432c8345f56bd4734fe633247228a 100644
--- a/test/caosdb_test_utility.h.in
+++ b/test/caosdb_test_utility.h.in
@@ -29,31 +29,47 @@
  * @author Timm Fitschen
  * @date 2021-07-07
  */
-#define EXPECT_THROW_MESSAGE(statement, exeption_type, message)                \
-  EXPECT_THROW(                                                                \
-    try { statement; } catch (const exeption_type &e) {                        \
-      EXPECT_EQ(std::string(e.what()), message);                               \
-      throw;                                                                   \
-    },                                                                         \
-    exeption_type)
-#define ASSERT_THROW_MESSAGE(statement, exeption_type, message)                \
-  ASSERT_THROW(                                                                \
-    try { statement; } catch (const exeption_type &e) {                        \
-      ASSERT_EQ(std::string(e.what()), message);                               \
-      throw;                                                                   \
-    },                                                                         \
-    exeption_type)
-#define EXPECT_NULL(statement)                                                 \
-  if (statement != nullptr) {                                                  \
-    FAIL() << "Should be a nullptr";                                           \
-  } else {                                                                     \
-    SUCCEED();                                                                 \
+#define EXPECT_THROW_MESSAGE(statement, exception_type, message)                                   \
+  EXPECT_THROW(                                                                                    \
+    try { statement; } catch (const exception_type &e) {                                           \
+      EXPECT_EQ(std::string(e.what()), message);                                                   \
+      throw;                                                                                       \
+    },                                                                                             \
+    exception_type)
+#define ASSERT_THROW_MESSAGE(statement, exception_type, message)                                   \
+  ASSERT_THROW(                                                                                    \
+    try { statement; } catch (const exception_type &e) {                                           \
+      ASSERT_EQ(std::string(e.what()), message);                                                   \
+      throw;                                                                                       \
+    },                                                                                             \
+    exception_type)
+#define EXPECT_THROW_STARTS_WITH(statement, exception_type, pattern)                               \
+  EXPECT_THROW(                                                                                    \
+    try { statement; } catch (const exception_type &e) {                                           \
+      auto pat_s = std::string(pattern);                                                           \
+      EXPECT_EQ(std::string(e.what()).substr(0, pat_s.size()), pat_s);                             \
+      throw;                                                                                       \
+    },                                                                                             \
+    exception_type)
+#define ASSERT_THROW_STARTS_WITH(statement, exception_type, message)                               \
+  ASSERT_THROW(                                                                                    \
+    try { statement; } catch (const exception_type &e) {                                           \
+      auto pat_s = std::string(pattern);                                                           \
+      ASSERT_EQ(std::string(e.what()).substr(0, pat_s.size()), pat_s);                             \
+      throw;                                                                                       \
+    },                                                                                             \
+    exception_type)
+#define EXPECT_NULL(statement)                                                                     \
+  if (statement != nullptr) {                                                                      \
+    FAIL() << "Should be a nullptr";                                                               \
+  } else {                                                                                         \
+    SUCCEED();                                                                                     \
   }
-#define ASSERT_NULL(statement)                                                 \
-  if (statement != nullptr) {                                                  \
-    ADD_FAIL() << "Should be a nullptr";                                       \
-  } else {                                                                     \
-    SUCCEED();                                                                 \
+#define ASSERT_NULL(statement)                                                                     \
+  if (statement != nullptr) {                                                                      \
+    ADD_FAIL() << "Should be a nullptr";                                                           \
+  } else {                                                                                         \
+    SUCCEED();                                                                                     \
   }
 #endif
 
diff --git a/test/test_ccaosdb.cpp b/test/test_ccaosdb.cpp
index 1009cc5962c6a309052509e36d39c3f6ee97ea98..2c45ef7bf3986c8461a9ffe0943e8d1ba1112621 100644
--- a/test/test_ccaosdb.cpp
+++ b/test/test_ccaosdb.cpp
@@ -39,20 +39,16 @@ protected:
       TEST_DATA_DIR + "/test_caosdb_client.json");
   }
 
-  void TearDown() override {
-    caosdb::configuration::ConfigurationManager::Clear();
-  }
+  void TearDown() override { caosdb::configuration::ConfigurationManager::Clear(); }
 };
 
 TEST_F(test_ccaosdb, test_get_env_var) {
-  const char *const some_var =
-    caosdb_utility_get_env_var("SOME_ENV_VAR", "fall-back");
+  const char *const some_var = caosdb_utility_get_env_var("SOME_ENV_VAR", "fall-back");
   EXPECT_EQ("fall-back", some_var);
 }
 
 TEST_F(test_ccaosdb, test_other_client_error) {
-  EXPECT_EQ(caosdb_status_code_OTHER_CLIENT_ERROR(),
-            caosdb::StatusCode::OTHER_CLIENT_ERROR);
+  EXPECT_EQ(caosdb_status_code_OTHER_CLIENT_ERROR(), caosdb::StatusCode::OTHER_CLIENT_ERROR);
 }
 
 TEST_F(test_ccaosdb, test_get_default_connection) {
@@ -65,23 +61,20 @@ TEST_F(test_ccaosdb, test_get_default_connection) {
 TEST_F(test_ccaosdb, test_get_connection) {
   caosdb_connection_connection out;
 
-  caosdb_connection_connection_manager_get_connection(&out,
-                                                      "local-caosdb-admin");
+  caosdb_connection_connection_manager_get_connection(&out, "local-caosdb-admin");
   EXPECT_TRUE(out.wrapped_connection);
 }
 
 TEST_F(test_ccaosdb, test_execute_transaction) {
   caosdb_connection_connection connection;
-  caosdb_connection_connection_manager_get_connection(&connection,
-                                                      "local-caosdb-admin");
+  caosdb_connection_connection_manager_get_connection(&connection, "local-caosdb-admin");
 
   caosdb_transaction_transaction transaction;
   caosdb_connection_connection_create_transaction(&connection, &transaction);
 
   EXPECT_TRUE(transaction.wrapped_transaction);
 
-  int return_code(
-    caosdb_transaction_transaction_retrieve_by_id(&transaction, "some_id"));
+  int return_code(caosdb_transaction_transaction_retrieve_by_id(&transaction, "some_id"));
   EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON);
 
   return_code = caosdb_transaction_transaction_execute(&transaction);
@@ -91,14 +84,12 @@ TEST_F(test_ccaosdb, test_execute_transaction) {
   EXPECT_EQ(return_code, 0);
 
   caosdb_transaction_transaction multi_transaction;
-  caosdb_connection_connection_create_transaction(&connection,
-                                                  &multi_transaction);
+  caosdb_connection_connection_create_transaction(&connection, &multi_transaction);
 
   // We explicitely want to define a C-style array here, so we disable
   // linting
   const char *ids[] = {"id1", "id2", "id3"}; // NOLINT
-  return_code =
-    caosdb_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3);
+  return_code = caosdb_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3);
   EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON);
 
   return_code = caosdb_transaction_delete_transaction(&multi_transaction);
@@ -108,20 +99,17 @@ TEST_F(test_ccaosdb, test_execute_transaction) {
 TEST_F(test_ccaosdb, test_multi_retrieve) {
   std::cout << "Entering test_multi_retrieve ..." << std::endl;
   caosdb_connection_connection connection;
-  caosdb_connection_connection_manager_get_connection(&connection,
-                                                      "local-caosdb-admin");
+  caosdb_connection_connection_manager_get_connection(&connection, "local-caosdb-admin");
 
   std::cout << "Creating transaction" << std::endl;
   caosdb_transaction_transaction multi_transaction;
-  caosdb_connection_connection_create_transaction(&connection,
-                                                  &multi_transaction);
+  caosdb_connection_connection_create_transaction(&connection, &multi_transaction);
 
   // We explicitely want to define a C-style array here, so we disable
   // linting
   const char *ids[] = {"id1", "id2", "id3"}; // NOLINT
   std::cout << "Adding mutli retrieval ..." << std::endl;
-  int return_code(
-    caosdb_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3));
+  int return_code(caosdb_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3));
   EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON);
 
   std::cout << "Deleting transaction ..." << std::endl;
@@ -131,14 +119,12 @@ TEST_F(test_ccaosdb, test_multi_retrieve) {
 
 TEST_F(test_ccaosdb, test_query) {
   caosdb_connection_connection connection;
-  caosdb_connection_connection_manager_get_connection(&connection,
-                                                      "local-caosdb-admin");
+  caosdb_connection_connection_manager_get_connection(&connection, "local-caosdb-admin");
 
   caosdb_transaction_transaction transaction;
   caosdb_connection_connection_create_transaction(&connection, &transaction);
 
-  int return_code(caosdb_transaction_transaction_query(
-    &transaction, "FIND ENTITY WITH id=123"));
+  int return_code(caosdb_transaction_transaction_query(&transaction, "FIND ENTITY WITH id=123"));
   EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON);
 
   return_code = caosdb_transaction_delete_transaction(&transaction);
@@ -170,25 +156,28 @@ TEST_F(test_ccaosdb, test_entity) {
   EXPECT_EQ(return_code, 0);
   EXPECT_EQ(strcmp(out, "length"), 0);
 
-  caosdb_entity_entity_set_role(&entity, "Property");
-  caosdb_entity_entity_get_role(&entity, out);
-  EXPECT_EQ(strcmp(out, "Property"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_entity_set_role(&entity, "Property");
+  // caosdb_entity_entity_get_role(&entity, out);
+  // EXPECT_EQ(strcmp(out, "Property"), 0);
 
   caosdb_entity_entity_set_description(&entity, "The length of an object");
   caosdb_entity_entity_get_description(&entity, out);
   EXPECT_EQ(strcmp(out, "The length of an object"), 0);
 
-  caosdb_entity_entity_set_datatype(&entity, "DOUBLE");
-  caosdb_entity_entity_get_datatype(&entity, out);
-  EXPECT_EQ(strcmp(out, "DOUBLE"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_entity_set_datatype(&entity, "DOUBLE");
+  // caosdb_entity_entity_get_datatype(&entity, out);
+  // EXPECT_EQ(strcmp(out, "DOUBLE"), 0);
 
   caosdb_entity_entity_set_unit(&entity, "m");
   caosdb_entity_entity_get_unit(&entity, out);
   EXPECT_EQ(strcmp(out, "m"), 0);
 
-  caosdb_entity_entity_set_value(&entity, "5.0");
-  caosdb_entity_entity_get_value(&entity, out);
-  EXPECT_EQ(strcmp(out, "5.0"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_entity_set_value(&entity, "5.0");
+  // caosdb_entity_entity_get_value(&entity, out);
+  // EXPECT_EQ(strcmp(out, "5.0"), 0);
 
   return_code = caosdb_entity_delete_entity(&entity);
   EXPECT_EQ(return_code, 0);
@@ -222,10 +211,13 @@ TEST_F(test_ccaosdb, test_property) {
 
   caosdb_entity_property_set_id(&property, "some_id");
   caosdb_entity_property_set_name(&property, "some_name");
-  caosdb_entity_property_set_datatype(&property, "some_datatype");
-  caosdb_entity_property_set_importance(&property, "some_importance");
+  // TODO(fspreck)
+  // caosdb_entity_property_set_datatype(&property, "some_datatype");
+  // TODO(fspreck)
+  // caosdb_entity_property_set_importance(&property, "some_importance");
   caosdb_entity_property_set_unit(&property, "some_unit");
-  caosdb_entity_property_set_value(&property, "some_value");
+  // TODO(fspreck)
+  // caosdb_entity_property_set_value(&property, "some_value");
 
   char out[255] = {"a"}; // NOLINT
   caosdb_entity_property_get_id(&property, out);
@@ -234,17 +226,20 @@ TEST_F(test_ccaosdb, test_property) {
   caosdb_entity_property_get_name(&property, out);
   EXPECT_EQ(strcmp(out, "some_name"), 0);
 
-  caosdb_entity_property_get_datatype(&property, out);
-  EXPECT_EQ(strcmp(out, "some_datatype"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_property_get_datatype(&property, out);
+  // EXPECT_EQ(strcmp(out, "some_datatype"), 0);
 
-  caosdb_entity_property_get_importance(&property, out);
-  EXPECT_EQ(strcmp(out, "some_importance"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_property_get_importance(&property, out);
+  // EXPECT_EQ(strcmp(out, "some_importance"), 0);
 
   caosdb_entity_property_get_unit(&property, out);
   EXPECT_EQ(strcmp(out, "some_unit"), 0);
 
-  caosdb_entity_property_get_value(&property, out);
-  EXPECT_EQ(strcmp(out, "some_value"), 0);
+  // TODO(fspreck)
+  // caosdb_entity_property_get_value(&property, out);
+  // EXPECT_EQ(strcmp(out, "some_value"), 0);
 
   return_code = caosdb_entity_delete_property(&property);
   EXPECT_EQ(return_code, 0);
@@ -265,8 +260,10 @@ TEST_F(test_ccaosdb, test_entity_with_parent_and_property) {
 
   caosdb_entity_property_set_id(&input_property, "property_id");
   caosdb_entity_property_set_name(&input_property, "property_name");
-  caosdb_entity_property_set_datatype(&input_property, "property_datatype");
-  caosdb_entity_property_set_value(&input_property, "property_value");
+  // TODO(fspreck)
+  // caosdb_entity_property_set_datatype(&input_property, "property_datatype");
+  // TODO(fspreck)
+  // caosdb_entity_property_set_value(&input_property, "property_value");
 
   caosdb_entity_entity entity;
   return_code = caosdb_entity_create_entity(&entity);
@@ -311,13 +308,15 @@ TEST_F(test_ccaosdb, test_entity_with_parent_and_property) {
   caosdb_entity_property_get_name(&output_property, out);
   EXPECT_EQ(strcmp(in, out), 0);
 
-  caosdb_entity_property_get_datatype(&input_property, in);
-  caosdb_entity_property_get_datatype(&output_property, out);
-  EXPECT_EQ(strcmp(in, out), 0);
+  // TODO(fspreck)
+  // caosdb_entity_property_get_datatype(&input_property, in);
+  // caosdb_entity_property_get_datatype(&output_property, out);
+  // EXPECT_EQ(strcmp(in, out), 0);
 
-  caosdb_entity_property_get_value(&input_property, in);
-  caosdb_entity_property_get_value(&output_property, out);
-  EXPECT_EQ(strcmp(in, out), 0);
+  // TODO(fspreck)
+  // caosdb_entity_property_get_value(&input_property, in);
+  // caosdb_entity_property_get_value(&output_property, out);
+  // EXPECT_EQ(strcmp(in, out), 0);
 
   std::cout << "Comparing parent..." << std::endl;
   caosdb_entity_parent output_parent;
diff --git a/test/test_configuration.cpp b/test/test_configuration.cpp
index abc797fbe97fb408e0ff05ea5deab2a8581f194a..6d5f2e9449e5be21452fdcca6a04f4e02f531d13 100644
--- a/test/test_configuration.cpp
+++ b/test/test_configuration.cpp
@@ -39,52 +39,43 @@ protected:
 };
 
 TEST_F(test_configuration, load_json) {
-  ConfigurationManager::LoadSingleJSONConfiguration(TEST_DATA_DIR +
-                                                    "/test_caosdb_client.json");
-  EXPECT_THROW_MESSAGE(
-    ConfigurationManager::LoadSingleJSONConfiguration("anything"),
-    ConfigurationError, "This CaosDB client has already been configured.");
+  ConfigurationManager::LoadSingleJSONConfiguration(TEST_DATA_DIR + "/test_caosdb_client.json");
+  EXPECT_THROW_MESSAGE(ConfigurationManager::LoadSingleJSONConfiguration("anything"),
+                       ConfigurationError, "This CaosDB client has already been configured.");
 
   ConfigurationManager::Clear();
-  EXPECT_THROW_MESSAGE(
-    ConfigurationManager::LoadSingleJSONConfiguration("anything"),
-    ConfigurationError, "Configuration file does not exist.");
+  EXPECT_THROW_MESSAGE(ConfigurationManager::LoadSingleJSONConfiguration("anything"),
+                       ConfigurationError, "Configuration file does not exist.");
   ConfigurationManager::Clear();
 }
 
 TEST_F(test_configuration, get_default_connection_configuration_error) {
-  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(),
-                       ConfigurationError,
+  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(), ConfigurationError,
                        "This CaosDB client has not been configured.");
 
   ConfigurationManager::LoadSingleJSONConfiguration(
     TEST_DATA_DIR + "/test_broken_caosdb_client_no_connections1.json");
-  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(),
-                       ConfigurationError,
+  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(), ConfigurationError,
                        "This CaosDB client hasn't any configured connections.");
   ConfigurationManager::Clear();
 
   ConfigurationManager::LoadSingleJSONConfiguration(
     TEST_DATA_DIR + "/test_broken_caosdb_client_no_connections2.json");
-  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(),
-                       ConfigurationError,
+  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(), ConfigurationError,
                        "This CaosDB client hasn't any configured connections.");
   ConfigurationManager::Clear();
 
   ConfigurationManager::LoadSingleJSONConfiguration(
     TEST_DATA_DIR + "/test_broken_caosdb_client_no_connections3.json");
-  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(),
-                       ConfigurationError,
+  EXPECT_THROW_MESSAGE(ConfigurationManager::GetDefaultConnectionName(), ConfigurationError,
                        "This CaosDB client hasn't any configured connections.");
   ConfigurationManager::Clear();
 }
 
 TEST_F(test_configuration, initialize_logging) {
-  auto logging_configuration =
-    caosdb::logging::LoggingConfiguration(CAOSDB_LOG_LEVEL_ALL);
-  auto console_sink =
-    std::make_shared<caosdb::logging::ConsoleSinkConfiguration>(
-      "console", CAOSDB_DEFAULT_LOG_LEVEL);
+  auto logging_configuration = caosdb::logging::LoggingConfiguration(CAOSDB_LOG_LEVEL_ALL);
+  auto console_sink = std::make_shared<caosdb::logging::ConsoleSinkConfiguration>(
+    "console", CAOSDB_DEFAULT_LOG_LEVEL);
   logging_configuration.AddSink(console_sink);
 
   initialize_logging(logging_configuration);
diff --git a/test/test_connection.cpp b/test/test_connection.cpp
index 7c2efab9566d58c709c060e4206fc0d193ac75df..99391536edf031fbe4a326f56e24f68e5a50b5d3 100644
--- a/test/test_connection.cpp
+++ b/test/test_connection.cpp
@@ -40,8 +40,7 @@ class test_connection : public ::testing::Test {
 protected:
   void SetUp() override {
     ConfigurationManager::Clear();
-    ConfigurationManager::LoadSingleJSONConfiguration(
-      TEST_DATA_DIR + "/test_caosdb_client.json");
+    ConfigurationManager::LoadSingleJSONConfiguration(TEST_DATA_DIR + "/test_caosdb_client.json");
   };
   void TearDown() override { ConfigurationManager::Clear(); };
 };
diff --git a/test/test_data_type.cpp b/test/test_data_type.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9200a68356695b5bde9bbd1e2125e604ea2c078c
--- /dev/null
+++ b/test/test_data_type.cpp
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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/logging.h"                            // for CAOSDB_LOG_DEBUG
+#include <boost/log/core/record.hpp>                   // for record
+#include <boost/log/detail/attachable_sstream_buf.hpp> // for basic_ostring...
+#include <boost/log/sources/record_ostream.hpp>        // for operator<<
+#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 <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 <iosfwd>                                      // for streamsize
+#include <string>                                      // for allocator
+
+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_data_type, test_atomic) {
+  ProtoDataType proto_data_type;
+
+  for (const auto &map_el : atomicdatatype_names) {
+    Entity entity;
+    entity.SetRole(Role::PROPERTY);
+    // the different AtomicDataType are associated with integers
+    entity.SetDataType(map_el.first);
+    EXPECT_TRUE(entity.GetDataType().IsAtomic());
+    EXPECT_EQ(entity.GetDataType().AsAtomic(), map_el.first);
+
+    proto_data_type.set_atomic_data_type(static_cast<ProtoAtomicDataType>(map_el.first));
+    DataType data_type(&proto_data_type);
+    entity.SetDataType(data_type);
+
+    EXPECT_FALSE(data_type.IsReference());
+    EXPECT_EQ(data_type.AsReference().GetName(), std::basic_string<char>(""));
+    EXPECT_FALSE(data_type.IsList());
+    EXPECT_TRUE(data_type.IsAtomic());
+    EXPECT_EQ(data_type.AsAtomic(), map_el.first);
+  }
+}
+
+TEST(test_data_type, test_reference) {
+  ProtoDataType proto_data_type;
+
+  Entity entity;
+  entity.SetRole(Role::PROPERTY);
+  entity.SetDataType("Person");
+  EXPECT_TRUE(entity.GetDataType().IsReference());
+  EXPECT_EQ(entity.GetDataType().AsReference().GetName(), "Person");
+
+  proto_data_type.mutable_reference_data_type()->set_name("Person");
+  DataType data_type(&proto_data_type);
+  entity.SetDataType(data_type);
+
+  EXPECT_TRUE(data_type.IsReference());
+  EXPECT_FALSE(data_type.IsList());
+  EXPECT_FALSE(data_type.IsAtomic());
+  EXPECT_EQ(data_type.AsReference().GetName(), "Person");
+}
+
+TEST(test_data_type, test_list_of_atomic) {
+  for (const auto &map_el : atomicdatatype_names) {
+    DataType data_type(map_el.first, true);
+
+    EXPECT_FALSE(data_type.IsReference());
+    EXPECT_FALSE(data_type.IsAtomic());
+    EXPECT_TRUE(data_type.IsList());
+    const auto &list_data_type = data_type.AsList();
+    EXPECT_EQ(list_data_type.GetReferenceDataType().GetName(), std::basic_string<char>(""));
+    EXPECT_TRUE(list_data_type.IsListOfAtomic());
+    EXPECT_FALSE(list_data_type.IsListOfReference());
+    EXPECT_EQ(list_data_type.GetAtomicDataType(), map_el.first);
+  }
+}
+
+TEST(test_data_type, test_list_of_reference) {
+  auto data_type = DataType("person", true);
+
+  EXPECT_FALSE(data_type.IsReference());
+  EXPECT_FALSE(data_type.IsAtomic());
+  EXPECT_TRUE(data_type.IsList());
+
+  const auto &list_data_type = data_type.AsList();
+  EXPECT_TRUE(list_data_type.IsListOfReference());
+  EXPECT_FALSE(list_data_type.IsListOfAtomic());
+  const auto *wrapped = list_data_type.GetReferenceDataType().GetWrapped();
+  CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out)
+  CAOSDB_LOG_DEBUG("caosdb::entity") << "wrapped " + out;
+  EXPECT_EQ(list_data_type.GetReferenceDataType().GetName(), "person");
+}
+
+} // namespace caosdb::entity
diff --git a/test/test_entity.cpp b/test/test_entity.cpp
index 3d2343bbb17e3fb484ebebb8c5db471ab336e3c2..95c451d8d83154352731f1947d3972586e5b6a79 100644
--- a/test/test_entity.cpp
+++ b/test/test_entity.cpp
@@ -21,6 +21,7 @@
  *
  */
 #include "caosdb_test_utility.h"
+#include "caosdb/data_type.h"                    // for DataType, AtomicDat...
 #include "caosdb/entity.h"                       // for Entity, Parent, Par...
 #include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransactionSe...
 #include "caosdb/entity/v1alpha1/main.pb.h"      // for IdResponse, Message
@@ -28,12 +29,15 @@
 #include "caosdb/protobuf_helper.h"              // for get_arena
 #include "caosdb/status_code.h"                  // for StatusCode, FILE_DO...
 #include "caosdb/transaction.h"                  // for Transaction
-#include <google/protobuf/arena.h>               // for Arena
-#include <gtest/gtest-message.h>                 // for Message
-#include <gtest/gtest-test-part.h>               // for TestPartResult, Sui...
-#include <gtest/gtest_pred_impl.h>               // for Test, EXPECT_EQ
+#include "caosdb/value.h"                        // for Value
+#include <exception>
+#include <google/protobuf/arena.h> // for Arena
+#include <gtest/gtest-message.h>   // for Message
+#include <gtest/gtest-test-part.h> // for TestPartResult, Sui...
+#include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ
 #include <iostream>
 #include <memory> // for allocator, shared_ptr
+#include <stdexcept>
 #include <string> // for operator+, string
 
 namespace caosdb::entity {
@@ -68,17 +72,42 @@ TEST(test_entity, test_property_setters) {
   auto prop = Property();
   prop.SetName("prop_name");
   prop.SetId("prop_id");
-  prop.SetImportance("prop_importance");
+  prop.SetImportance(Importance::OBLIGATORY);
   prop.SetValue("prop_value");
   prop.SetUnit("prop_unit");
-  prop.SetDatatype("prop_dtype");
+  prop.SetDataType("prop_dtype");
 
   EXPECT_EQ(prop.GetName(), "prop_name");
   EXPECT_EQ(prop.GetId(), "prop_id");
-  EXPECT_EQ(prop.GetImportance(), "prop_importance");
-  EXPECT_EQ(prop.GetValue(), "prop_value");
+  EXPECT_EQ(prop.GetImportance(), Importance::OBLIGATORY);
+  EXPECT_TRUE(prop.GetValue().IsString());
+  EXPECT_EQ(prop.GetValue().AsString(), "prop_value");
   EXPECT_EQ(prop.GetUnit(), "prop_unit");
-  EXPECT_EQ(prop.GetDatatype(), "prop_dtype");
+  EXPECT_TRUE(prop.GetDataType().IsReference());
+  EXPECT_EQ(prop.GetDataType().AsReference().GetName(), "prop_dtype");
+  EXPECT_FALSE(prop.GetDataType().IsList());
+
+  prop.SetDataType(AtomicDataType::DATETIME);
+  EXPECT_TRUE(prop.GetDataType().IsAtomic());
+  EXPECT_EQ(prop.GetDataType().AsAtomic(), AtomicDataType::DATETIME);
+  EXPECT_FALSE(prop.GetDataType().IsList());
+}
+
+TEST(test_entity, test_list_property_setters) {
+  auto prop = Property();
+
+  prop.SetDataType(AtomicDataType::DATETIME); // Set as atomic first.
+  EXPECT_TRUE(prop.GetDataType().IsAtomic());
+  EXPECT_EQ(prop.GetDataType().AsAtomic(), AtomicDataType::DATETIME);
+
+  prop.SetDataType(AtomicDataType::DOUBLE, true);
+  auto const &dtype = prop.GetDataType();
+  EXPECT_FALSE(dtype.IsAtomic()); // Should not be true anymore.
+  EXPECT_FALSE(dtype.IsReference());
+  EXPECT_TRUE(dtype.IsList());
+  EXPECT_NE(dtype.AsAtomic(), AtomicDataType::DATETIME); // Should be overwritten.
+  EXPECT_TRUE(dtype.AsList().IsListOfAtomic());
+  EXPECT_EQ(dtype.AsList().GetAtomicDataType(), AtomicDataType::DOUBLE);
 }
 
 TEST(test_entity, test_append_property) {
@@ -87,28 +116,31 @@ TEST(test_entity, test_append_property) {
   auto prop = Property();
   prop.SetName("prop_name");
   prop.SetId("prop_id");
-  prop.SetImportance("prop_importance");
+  prop.SetImportance(Importance::RECOMMENDED);
   prop.SetValue("prop_value");
   prop.SetUnit("prop_unit");
-  prop.SetDatatype("prop_dtype");
+  prop.SetDataType("prop_dtype");
 
   EXPECT_EQ(entity.GetProperties().size(), 0);
   entity.AppendProperty(prop);
   EXPECT_EQ(entity.GetProperties().size(), 1);
 
-  auto same_prop = entity.GetProperties().at(0);
+  // also test RepeatedPtrFieldWrapper.at()
+  const auto &same_prop = entity.GetProperties().at(0);
+  EXPECT_THROW((void)entity.GetProperties().at(2), std::out_of_range);
+  EXPECT_THROW((void)entity.GetProperties().at(-1), std::out_of_range);
 
   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.GetUnit(), same_prop.GetUnit());
-  EXPECT_EQ(prop.GetDatatype(), same_prop.GetDatatype());
+  EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType());
 }
 
 TEST(test_entity, test_copy_to) {
   auto entity = Entity();
-  entity.SetRole("original_role");
+  entity.SetRole(Role::RECORD);
   entity.SetName("orignial_name");
 
   auto parent = Parent();
@@ -123,8 +155,7 @@ TEST(test_entity, test_copy_to) {
 
   // create protobuf entity to which all fields ae copied and then a
   // CaoosDB entity from that protobuf entity.
-  auto *proto_copy =
-    google::protobuf::Arena::CreateMessage<ProtoEntity>(get_arena());
+  auto *proto_copy = google::protobuf::Arena::CreateMessage<ProtoEntity>(get_arena());
   entity.CopyTo(proto_copy);
   auto copied = Entity(proto_copy);
 
@@ -142,15 +173,15 @@ TEST(test_entity, test_insert_entity) {
     std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
 
   auto entity = Entity();
-  entity.SetRole("entity_role");
+  entity.SetRole(Role::RECORD_TYPE);
   entity.SetName("entity_name");
 
-  EXPECT_EQ(entity.GetRole(), "entity_role");
+  EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
   EXPECT_EQ(entity.GetName(), "entity_name");
 
   transaction.InsertEntity(&entity);
 
-  EXPECT_EQ(entity.GetRole(), "entity_role");
+  EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
   EXPECT_EQ(entity.GetName(), "entity_name");
 }
 
@@ -160,19 +191,21 @@ TEST(test_entity, test_insert_with_role) {
     std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
 
   auto entity = Entity();
-  entity.SetRole("Property");
-  entity.SetDatatype("DOUBLE");
+  entity.SetRole(Role::PROPERTY);
+  entity.SetDataType(AtomicDataType::DOUBLE);
   entity.SetName("Length");
   entity.SetUnit("m");
-  entity.SetValue("5.5");
+  entity.SetValue(5.5);
 
   transaction.InsertEntity(&entity);
 
-  EXPECT_EQ(entity.GetRole(), "Property");
-  EXPECT_EQ(entity.GetDatatype(), "DOUBLE");
+  EXPECT_EQ(entity.GetRole(), Role::PROPERTY);
+  EXPECT_TRUE(entity.GetDataType().IsAtomic());
+  EXPECT_EQ(entity.GetDataType().AsAtomic(), AtomicDataType::DOUBLE);
   EXPECT_EQ(entity.GetName(), "Length");
   EXPECT_EQ(entity.GetUnit(), "m");
-  EXPECT_EQ(entity.GetValue(), "5.5");
+  EXPECT_TRUE(entity.GetValue().IsDouble());
+  EXPECT_DOUBLE_EQ(entity.GetValue().AsDouble(), 5.5);
 }
 
 TEST(test_entity, test_insert_with_parent) {
@@ -211,10 +244,10 @@ TEST(test_entity, test_insert_with_property) {
   auto prop = Property();
   prop.SetName("prop_name");
   prop.SetId("prop_id");
-  prop.SetImportance("prop_importance");
-  prop.SetValue("prop_value");
+  prop.SetImportance(Importance::FIX);
+  prop.SetValue(Value("prop_value"));
   prop.SetUnit("prop_unit");
-  prop.SetDatatype("prop_dtype");
+  prop.SetDataType("prop_dtype");
 
   entity.AppendProperty(prop);
 
@@ -222,14 +255,15 @@ TEST(test_entity, test_insert_with_property) {
 
   EXPECT_EQ(entity.GetProperties().size(), 1);
 
-  auto inserted_prop = entity.GetProperties().at(0);
+  const auto &inserted_prop = entity.GetProperties().at(0);
 
   EXPECT_EQ(prop.GetName(), inserted_prop.GetName());
   EXPECT_EQ(prop.GetId(), inserted_prop.GetId());
   EXPECT_EQ(prop.GetImportance(), inserted_prop.GetImportance());
+  EXPECT_EQ(prop.GetValue().ToString(), inserted_prop.GetValue().ToString());
   EXPECT_EQ(prop.GetValue(), inserted_prop.GetValue());
   EXPECT_EQ(prop.GetUnit(), inserted_prop.GetUnit());
-  EXPECT_EQ(prop.GetDatatype(), inserted_prop.GetDatatype());
+  EXPECT_EQ(prop.GetDataType(), inserted_prop.GetDataType());
 }
 
 TEST(test_entity, test_from_id_response) {
@@ -245,8 +279,7 @@ TEST(test_entity, test_from_id_response) {
   EXPECT_TRUE(entity.HasErrors());
   EXPECT_EQ(entity.GetErrors().size(), 1);
   EXPECT_EQ(entity.GetErrors().at(0).GetDescription(), "error_desc");
-  EXPECT_EQ(entity.GetErrors().at(0).GetCode(),
-            MessageCode::ENTITY_DOES_NOT_EXIST);
+  EXPECT_EQ(entity.GetErrors().at(0).GetCode(), MessageCode::ENTITY_DOES_NOT_EXIST);
 
   IdResponse idr_warnings_and_infos;
   idr_warnings_and_infos.set_id("other_entity_id");
@@ -263,8 +296,7 @@ TEST(test_entity, test_from_id_response) {
   EXPECT_EQ(other_ent.GetWarnings().size(), 1);
   EXPECT_TRUE(other_ent.HasWarnings());
   EXPECT_EQ(other_ent.GetWarnings().at(0).GetDescription(), "warning_desc");
-  EXPECT_EQ(other_ent.GetWarnings().at(0).GetCode(),
-            MessageCode::ENTITY_HAS_NO_PROPERTIES);
+  EXPECT_EQ(other_ent.GetWarnings().at(0).GetCode(), MessageCode::ENTITY_HAS_NO_PROPERTIES);
   EXPECT_EQ(other_ent.GetInfos().size(), 1);
   EXPECT_EQ(other_ent.GetInfos().at(0).GetDescription(), "info_desc");
   EXPECT_EQ(other_ent.GetInfos().at(0).GetCode(), MessageCode::UNSPECIFIED);
@@ -277,14 +309,13 @@ TEST(test_entity, test_add_file_to_non_file_entity) {
 
 TEST(test_entity, test_add_non_existing_file) {
   Entity entity;
-  entity.SetRole("File");
-  EXPECT_EQ(entity.SetLocalPath("non-existing/path"),
-            StatusCode::FILE_DOES_NOT_EXIST_LOCALLY);
+  entity.SetRole(Role::FILE);
+  EXPECT_EQ(entity.SetLocalPath("non-existing/path"), StatusCode::FILE_DOES_NOT_EXIST_LOCALLY);
 }
 
 TEST(test_entity, test_add_directory_path) {
   Entity entity;
-  entity.SetRole("File");
+  entity.SetRole(Role::FILE);
   EXPECT_EQ(entity.SetLocalPath("./"), StatusCode::PATH_IS_A_DIRECTORY);
 }
 
@@ -386,8 +417,11 @@ TEST(test_entity, test_property_iterator) {
   ASSERT_EQ(entity.GetProperties().size(), 5);
   int counter = 0;
   for (auto &property : entity.GetProperties()) {
+    // TODO(tf) Copy constructor was deleted
+    // auto nonref_property = entity.GetProperties().at(counter);
     auto name = "PROPERTY-" + std::to_string(counter);
     EXPECT_EQ(property.GetName(), name);
+    // EXPECT_EQ(nonref_property.GetName(), name);
     counter++;
   }
   EXPECT_EQ(counter, 5);
@@ -414,10 +448,17 @@ TEST(test_entity, test_description) {
   EXPECT_EQ(parent.GetDescription(), "desc parent");
 }
 
+TEST(test_entity, test_role) {
+  Entity entity;
+  entity.SetRole(Role::RECORD_TYPE);
+
+  EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
+}
+
 TEST(test_entity, test_add_file) {
   Entity entity;
-  entity.SetRole("File");
-  EXPECT_EQ(entity.SetLocalPath(TEST_DATA_DIR + "/test.json"),
-            StatusCode::SUCCESS);
+  entity.SetRole(Role::FILE);
+  EXPECT_EQ(entity.SetLocalPath(TEST_DATA_DIR + "/test.json"), StatusCode::SUCCESS);
 }
+
 } // namespace caosdb::entity
diff --git a/test/test_file_transmission.cpp b/test/test_file_transmission.cpp
index 801b89db3a07f5b96e530cfbdfc8335c892a1331..7c5eb745e8f451b0282fa844510dc71ad402ed18 100644
--- a/test/test_file_transmission.cpp
+++ b/test/test_file_transmission.cpp
@@ -23,9 +23,9 @@
 #include <boost/filesystem/path.hpp>        // for path
 #include <boost/filesystem/path_traits.hpp> // for filesystem
 #include <gtest/gtest-message.h>            // for Message
-#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver
-#include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ, AssertionResult
-#include <string>                  // for string
+#include <gtest/gtest-test-part.h>          // for TestPartResult, SuiteApiResolver
+#include <gtest/gtest_pred_impl.h>          // for Test, EXPECT_EQ, AssertionResult
+#include <string>                           // for string
 
 namespace fs = boost::filesystem;
 
@@ -35,9 +35,7 @@ class test_file_transmission : public ::testing::Test {
 protected:
   fs::path test_file_name;
 
-  void SetUp() override {
-    test_file_name = fs::path("this_is_a_test_file_remove_me.dat");
-  }
+  void SetUp() override { test_file_name = fs::path("this_is_a_test_file_remove_me.dat"); }
 
   void TearDown() override { fs::remove(test_file_name); }
 };
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_protobuf.cpp b/test/test_protobuf.cpp
index 9dc957a2f85cd95ce3ead5f59ab8c10868582003..43ab6883b42f1dca1c2785103f6a274eb2b2f1bc 100644
--- a/test/test_protobuf.cpp
+++ b/test/test_protobuf.cpp
@@ -19,14 +19,17 @@
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
  *
  */
+#include "caosdb/data_type.h"               // for DataType, ReferenceDataType
+#include "caosdb/entity.h"                  // for Entity
 #include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message
-#include "gtest/gtest-message.h"            // for Message
-#include "gtest/gtest-test-part.h"          // for SuiteApiResolver, TestPa...
-#include "gtest/gtest_pred_impl.h"          // for Test, TestInfo, TEST
+#include <gtest/gtest-message.h>            // for Message
+#include <gtest/gtest-test-part.h>          // for SuiteApiResolver, TestPa...
+#include <gtest/gtest_pred_impl.h>          // for Test, TestInfo, TEST
 #include <memory>                           // for allocator
 
 namespace caosdb {
-using caosdb::entity::v1alpha1::Entity;
+using ProtoEntity = caosdb::entity::v1alpha1::Entity;
+using caosdb::entity::Entity;
 using caosdb::entity::v1alpha1::Message;
 
 TEST(test_protobuf, test_swap_trivial) {
@@ -50,12 +53,12 @@ TEST(test_protobuf, test_swap_trivial) {
 }
 
 TEST(test_protobuf, test_swap_nested) {
-  Entity entity_source;
+  ProtoEntity entity_source;
   entity_source.set_id("entity_id");
   auto *version_source = entity_source.mutable_version();
   version_source->set_id("version_id");
 
-  Entity entity_destination;
+  ProtoEntity entity_destination;
   auto *version_destination = entity_destination.mutable_version();
 
   EXPECT_EQ(entity_source.id(), "entity_id");
@@ -81,4 +84,28 @@ TEST(test_protobuf, test_swap_nested) {
   EXPECT_EQ(entity_destination.mutable_version(), version_source);
 }
 
+TEST(test_protobuf, test_copy_nested) {
+  ProtoEntity entity_source;
+  auto *data_type_source = entity_source.mutable_data_type();
+  data_type_source->mutable_reference_data_type()->set_name("src_per");
+
+  ProtoEntity entity_destination;
+  auto *data_type_destination = entity_destination.mutable_data_type();
+  data_type_destination->mutable_reference_data_type()->set_name("dest_per");
+
+  EXPECT_EQ(entity_source.data_type().reference_data_type().name(), "src_per");
+  EXPECT_EQ(entity_destination.data_type().reference_data_type().name(), "dest_per");
+
+  entity_destination.CopyFrom(entity_source);
+
+  EXPECT_EQ(entity_source.data_type().reference_data_type().name(), "src_per");
+  EXPECT_EQ(entity_destination.data_type().reference_data_type().name(), "src_per");
+
+  Entity entity(&entity_destination);
+  EXPECT_EQ(entity.GetDataType().AsReference().GetName(), "src_per");
+
+  const Entity &copy_entity(entity);
+  EXPECT_EQ(copy_entity.GetDataType().AsReference().GetName(), "src_per");
+}
+
 } // namespace caosdb
diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp
index 70ba13a78b10db3af421411ae7f9ba631a49ff03..21c00f86b20758e03dc6f1d78e4aad11b469479e 100644
--- a/test/test_transaction.cpp
+++ b/test/test_transaction.cpp
@@ -42,6 +42,7 @@ using caosdb::connection::Connection;
 using caosdb::entity::Entity;
 using caosdb::exceptions::ConnectionError;
 using ProtoEntity = caosdb::entity::v1alpha1::Entity;
+using caosdb::entity::Role;
 using caosdb::entity::v1alpha1::RetrieveResponse;
 
 TEST(test_transaction, create_transaction) {
@@ -51,11 +52,10 @@ TEST(test_transaction, create_transaction) {
   auto transaction = connection.CreateTransaction();
 
   ASSERT_EQ(StatusCode::GO_ON, transaction->RetrieveById("100"));
-  EXPECT_THROW_MESSAGE(
-    transaction->Execute(), ConnectionError,
-    "The attempt to execute this transaction was not successful because the "
-    "connection to the server could not be established. "
-    "Original message: failed to connect to all addresses");
+  EXPECT_THROW_MESSAGE(transaction->Execute(), ConnectionError,
+                       "The attempt to execute this transaction was not successful because the "
+                       "connection to the server could not be established. "
+                       "Original message: failed to connect to all addresses");
 }
 
 TEST(test_transaction, test_multi_result_set) {
@@ -115,8 +115,7 @@ TEST(test_transaction, test_multi_result_iterator) {
   std::vector<std::unique_ptr<Entity>> one_elem;
   RetrieveResponse response;
   response.mutable_entity_response()->mutable_entity()->set_id("100");
-  one_elem.push_back(
-    std::make_unique<Entity>(response.release_entity_response()));
+  one_elem.push_back(std::make_unique<Entity>(response.release_entity_response()));
 
   MultiResultSet rs(std::move(one_elem));
   EXPECT_EQ(rs.size(), 1);
@@ -130,8 +129,7 @@ TEST(test_transaction, test_multi_result_set_one) {
   std::vector<std::unique_ptr<Entity>> one_elem;
   RetrieveResponse response;
   response.mutable_entity_response()->mutable_entity()->set_id("100");
-  one_elem.push_back(
-    std::make_unique<Entity>(response.release_entity_response()));
+  one_elem.push_back(std::make_unique<Entity>(response.release_entity_response()));
 
   MultiResultSet rs(std::move(one_elem));
   EXPECT_EQ(rs.size(), 1);
@@ -147,9 +145,8 @@ TEST(test_transaction, test_multi_result_set_three) {
     ->mutable_entity_response()
     ->mutable_entity()
     ->set_id("100");
-  auto *entity_with_error = response.add_responses()
-                              ->mutable_retrieve_response()
-                              ->mutable_entity_response();
+  auto *entity_with_error =
+    response.add_responses()->mutable_retrieve_response()->mutable_entity_response();
   entity_with_error->mutable_entity()->set_id("101");
   entity_with_error->add_errors()->set_code(1);
   response.add_responses()
@@ -177,7 +174,7 @@ TEST(test_transaction, test_update_entity) {
   auto transaction = connection.CreateTransaction();
 
   caosdb::entity::Entity update_entity;
-  update_entity.SetRole("New role");
+  update_entity.SetName("New Name");
   auto error = transaction->UpdateEntity(&update_entity);
 
   EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID);
@@ -216,7 +213,7 @@ TEST(test_transaction, test_insert_with_file) {
   Connection connection(configuration);
   auto transaction = connection.CreateTransaction();
   Entity entity;
-  entity.SetRole("File");
+  entity.SetRole(Role::FILE);
   entity.SetLocalPath(TEST_DATA_DIR + "/test.json");
 
   EXPECT_TRUE(transaction->GetUploadFiles().empty());
diff --git a/test/test_utility.cpp b/test/test_utility.cpp
index cb6021dc631c90b49ab8c3538f2b09fcc47723a3..a64fcee8c94fa527692bbd96ca0b54f94bd6f524 100644
--- a/test/test_utility.cpp
+++ b/test/test_utility.cpp
@@ -24,6 +24,8 @@
 #include "boost/beast/core/detail/base64.hpp" // for encoded_size
 #include "boost/json/object.hpp"              // for object
 #include "boost/json/value.hpp"               // for value
+#include "caosdb/data_type.h"                 // for atomicdatatype_names
+#include "caosdb/entity.h"                    // for importance_names, role...
 #include "caosdb/utility.h"                   // for base64_encode, load_js...
 #include "caosdb_test_utility.h"              // for TEST_DATA_DIR
 #include <gtest/gtest-message.h>              // for Message
@@ -53,4 +55,27 @@ TEST(test_utility, test_load_json_file) {
   EXPECT_THAT(sub["see?"].as_array(), ElementsAre(true, false));
 }
 
+TEST(test_utility, enum_names) {
+  // All working enums
+  for (const auto &entry : caosdb::entity::importance_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::Importance>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::Importance>(entry.second), entry.first);
+  }
+  for (const auto &entry : caosdb::entity::role_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::Role>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::Role>(entry.second), entry.first);
+  }
+  for (const auto &entry : caosdb::entity::atomicdatatype_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::AtomicDataType>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::AtomicDataType>(entry.second), entry.first);
+  }
+
+  // Some non-working examples
+  EXPECT_THROW_MESSAGE(getEnumValueFromName<caosdb::entity::Importance>("Invalid name"),
+                       std::out_of_range, "Could not find enum value for string 'Invalid name'.");
+  enum e1 { a };
+  EXPECT_THROW_STARTS_WITH(getEnumNameFromValue<e1>(a), std::logic_error, "Enum type ");
+  EXPECT_THROW_STARTS_WITH(getEnumValueFromName<e1>("Hello!"), std::logic_error, "Enum type ");
+}
+
 } // namespace caosdb::utility
diff --git a/test/test_value.cpp b/test/test_value.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74d30f04b621a0e118bc7591a07aab052786c790
--- /dev/null
+++ b/test/test_value.cpp
@@ -0,0 +1,138 @@
+/*
+ *
+ * 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/value.h"                   // for Value
+#include "caosdb/entity/v1alpha1/main.pb.h" // for AtomicDataType, DataType
+#include <algorithm>                        // for max
+#include <cmath>                            // for isnan
+#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 <initializer_list>                 // for initializer_list
+#include <string>                           // for string, basic_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_value, test_null) {
+  Value value;
+  EXPECT_TRUE(value.IsNull());
+  EXPECT_FALSE(value.IsDouble());
+  EXPECT_FALSE(value.IsBool());
+  EXPECT_FALSE(value.IsInteger());
+  EXPECT_FALSE(value.IsString());
+  EXPECT_FALSE(value.IsList());
+}
+
+TEST(test_value, test_string) {
+  Value value(std::string("test"));
+  EXPECT_FALSE(value.IsNull());
+  EXPECT_TRUE(value.IsString());
+  EXPECT_FALSE(value.IsDouble());
+  EXPECT_FALSE(value.IsBool());
+  EXPECT_FALSE(value.IsInteger());
+
+  EXPECT_EQ(value.AsString(), "test");
+
+  Value empty_string(std::string(""));
+  EXPECT_FALSE(empty_string.IsNull());
+  EXPECT_TRUE(empty_string.IsString());
+  EXPECT_FALSE(empty_string.IsDouble());
+  EXPECT_FALSE(empty_string.IsBool());
+  EXPECT_FALSE(empty_string.IsInteger());
+
+  EXPECT_EQ(empty_string.AsString(), "");
+
+  // Test inequality
+  Value string1("1");
+  Value int1(1);
+  EXPECT_FALSE(string1 == int1);
+}
+
+TEST(test_value, test_double) {
+  Value value(2.26);
+  EXPECT_FALSE(value.IsNull());
+  EXPECT_FALSE(value.IsString());
+  EXPECT_TRUE(value.IsDouble());
+  EXPECT_FALSE(value.IsBool());
+  EXPECT_FALSE(value.IsInteger());
+
+  EXPECT_EQ(value.AsDouble(), 2.26);
+
+  Value nan(std::sqrt(-1.0));
+  EXPECT_FALSE(nan.IsNull());
+  EXPECT_FALSE(nan.IsString());
+  EXPECT_TRUE(nan.IsDouble());
+  EXPECT_FALSE(nan.IsBool());
+  EXPECT_FALSE(nan.IsInteger());
+
+  EXPECT_TRUE(std::isnan(nan.AsDouble()));
+}
+
+TEST(test_value, test_integer) {
+  Value value(1337);
+  EXPECT_FALSE(value.IsNull());
+  EXPECT_FALSE(value.IsString());
+  EXPECT_FALSE(value.IsDouble());
+  EXPECT_FALSE(value.IsBool());
+  EXPECT_TRUE(value.IsInteger());
+
+  EXPECT_EQ(value.AsInteger(), 1337);
+}
+
+TEST(test_value, test_boolean) {
+  Value value(true);
+  EXPECT_FALSE(value.IsNull());
+  EXPECT_FALSE(value.IsString());
+  EXPECT_FALSE(value.IsDouble());
+  EXPECT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.IsInteger());
+
+  EXPECT_EQ(value.AsBool(), true);
+}
+
+TEST(test_value, test_list) {
+  std::vector<std::string> ids;
+  for (std::string id : {"id0", "id1", "id2"}) {
+    ids.push_back(id);
+  }
+  Value value(ids);
+
+  EXPECT_FALSE(value.IsNull());
+  EXPECT_TRUE(value.IsList());
+  EXPECT_FALSE(value.IsString());
+  EXPECT_FALSE(value.IsDouble());
+  EXPECT_FALSE(value.IsBool());
+  EXPECT_FALSE(value.IsInteger());
+
+  auto list_value = value.AsList();
+  int counter = 0;
+  for (auto item : list_value) {
+    EXPECT_EQ(item.IsString(), true);
+    EXPECT_EQ(item.AsString(), "id" + std::to_string(counter++));
+  }
+}
+} // namespace caosdb::entity