[med-svn] [odil] 01/05: Imported Upstream version 0.7.3

Julien Lamy lamy-guest at moszumanska.debian.org
Fri Oct 21 10:13:43 UTC 2016


This is an automated email from the git hooks/post-receive script.

lamy-guest pushed a commit to branch master
in repository odil.

commit ef8f6c6d9f42e598242a279a312f6f0cecf17cf2
Author: Julien Lamy <lamy at unistra.fr>
Date:   Thu Oct 20 14:20:25 2016 +0200

    Imported Upstream version 0.7.3
---
 applications/print_.py                             |   4 +-
 src/odil/AssociationParameters.cpp                 | 135 +++++++++-
 src/odil/AssociationParameters.h                   |  48 ++++
 src/odil/pdu/AsynchronousOperationsWindow.cpp      |  87 +++++++
 src/odil/pdu/AsynchronousOperationsWindow.h        |  55 ++++
 src/odil/pdu/SOPClassCommonExtendedNegotiation.cpp | 190 ++++++++++++++
 src/odil/pdu/SOPClassCommonExtendedNegotiation.h   |  69 ++++++
 src/odil/pdu/SOPClassExtendedNegotiation.cpp       | 120 +++++++++
 src/odil/pdu/SOPClassExtendedNegotiation.h         |  63 +++++
 src/odil/pdu/UserInformation.cpp                   |  35 ++-
 src/odil/registry.cpp                              | 276 +++++++++++++++++++--
 src/odil/registry.h                                |  92 ++++++-
 tests/code/AssociationParameters.cpp               |  24 +-
 tests/code/dul/Transport.cpp                       |   1 -
 tests/code/pdu/AsynchronousOperationsWindow.cpp    |  59 +++++
 .../code/pdu/SOPClassCommonExtendedNegotiation.cpp |  87 +++++++
 tests/code/pdu/SOPClassExtendedNegotiation.cpp     |  71 ++++++
 wrappers/json_converter.cpp                        |   8 +-
 18 files changed, 1389 insertions(+), 35 deletions(-)

diff --git a/applications/print_.py b/applications/print_.py
index 2a7be04..0179984 100644
--- a/applications/print_.py
+++ b/applications/print_.py
@@ -50,7 +50,9 @@ def print_data_set(data_set, decode_uids, padding, max_length):
                 "s" if sum(lengths)>1 else "")
         else:
             getter = None
-            if element.is_int():
+            if element.empty():
+                getter = lambda: []
+            elif element.is_int():
                 getter = element.as_int
             elif element.is_real():
                 getter = element.as_real
diff --git a/src/odil/AssociationParameters.cpp b/src/odil/AssociationParameters.cpp
index e152cee..6d9d605 100644
--- a/src/odil/AssociationParameters.cpp
+++ b/src/odil/AssociationParameters.cpp
@@ -18,11 +18,14 @@
 #include "odil/pdu/AAssociateRQ.h"
 #include "odil/Exception.h"
 #include "odil/uid.h"
+#include "odil/pdu/AsynchronousOperationsWindow.h"
 #include "odil/pdu/ImplementationClassUID.h"
 #include "odil/pdu/ImplementationVersionName.h"
 #include "odil/pdu/PresentationContextAC.h"
 #include "odil/pdu/PresentationContextRQ.h"
 #include "odil/pdu/RoleSelection.h"
+#include "odil/pdu/SOPClassExtendedNegotiation.h"
+#include "odil/pdu/SOPClassCommonExtendedNegotiation.h"
 
 namespace odil
 {
@@ -102,7 +105,9 @@ AssociationParameters::UserIdentity
 AssociationParameters
 ::AssociationParameters()
 : _called_ae_title(""), _calling_ae_title(""), _presentation_contexts(),
-  _user_identity(), _maximum_length(16384)
+  _user_identity({UserIdentity::Type::None, "", ""}), _maximum_length(16384),
+  _maximum_number_operations_invoked(1), _maximum_number_operations_performed(1),
+  _sop_class_extended_negotiation(), _sop_class_common_extended_negotiation()
 {
     // Nothing else.
 }
@@ -178,6 +183,20 @@ AssociationParameters
     {
         this->set_maximum_length(maximum_length[0].get_maximum_length());
     }
+
+    // Maximum number of operations performed/invoked
+    auto const asynchronous_operations_window =
+        user_information.get_sub_items<pdu::AsynchronousOperationsWindow>();
+    if(!asynchronous_operations_window.empty())
+    {
+        this->_maximum_number_operations_invoked =
+            asynchronous_operations_window[0].get_maximum_number_operations_invoked();
+        this->_maximum_number_operations_performed =
+            asynchronous_operations_window[0].get_maximum_number_operations_performed();
+    }
+    
+    this->_sop_class_common_extended_negotiation =
+        user_information.get_sub_items<pdu::SOPClassCommonExtendedNegotiation>();
 }
 
 AssociationParameters
@@ -252,6 +271,19 @@ AssociationParameters
     {
         this->set_maximum_length(maximum_length[0].get_maximum_length());
     }
+
+    // Maximum number of operations performed/invoked
+    auto const asynchronous_operations_window =
+        user_information.get_sub_items<pdu::AsynchronousOperationsWindow>();
+    if(!asynchronous_operations_window.empty())
+    {
+        this->_maximum_number_operations_invoked =
+            asynchronous_operations_window[0].get_maximum_number_operations_invoked();
+        this->_maximum_number_operations_performed =
+            asynchronous_operations_window[0].get_maximum_number_operations_performed();
+    }
+    
+    // No SOPClassCommonExtendedNegotiation in AC
 }
 
 std::string const &
@@ -384,6 +416,66 @@ AssociationParameters
     return *this;
 }
 
+uint16_t
+AssociationParameters
+::get_maximum_number_operations_invoked() const
+{
+    return this->_maximum_number_operations_invoked;
+}
+
+AssociationParameters &
+AssociationParameters
+::set_maximum_number_operations_invoked(uint16_t value)
+{
+    this->_maximum_number_operations_invoked = value;
+    return *this;
+}
+
+uint16_t
+AssociationParameters
+::get_maximum_number_operations_performed() const
+{
+    return this->_maximum_number_operations_performed;
+}
+
+AssociationParameters &
+AssociationParameters
+::set_maximum_number_operations_performed(uint16_t value)
+{
+    this->_maximum_number_operations_performed = value;
+    return *this;
+}
+
+std::vector<pdu::SOPClassExtendedNegotiation>
+AssociationParameters
+::get_sop_class_extended_negotiation() const
+{
+    return this->_sop_class_extended_negotiation;
+}
+
+void
+AssociationParameters
+::set_sop_class_extended_negotiation(
+    std::vector<pdu::SOPClassExtendedNegotiation> const & value)
+{
+    this->_sop_class_extended_negotiation = value;
+}
+
+std::vector<pdu::SOPClassCommonExtendedNegotiation>
+AssociationParameters
+::get_sop_class_common_extended_negotiation() const
+{
+    return this->_sop_class_common_extended_negotiation;
+}
+
+void 
+AssociationParameters
+::set_sop_class_common_extended_negotiation(
+    std::vector<pdu::SOPClassCommonExtendedNegotiation> const & value)
+{
+    this->_sop_class_common_extended_negotiation = value;
+}
+
 pdu::AAssociateRQ
 AssociationParameters
 ::as_a_associate_rq() const
@@ -419,6 +511,22 @@ AssociationParameters
 
     user_information.set_sub_items<pdu::ImplementationClassUID>(
         {implementation_class_uid});
+
+    if(this->_maximum_number_operations_invoked != 1 ||
+        this->_maximum_number_operations_performed != 1)
+    {
+        user_information.set_sub_items<pdu::AsynchronousOperationsWindow>({{
+            this->_maximum_number_operations_invoked,
+            this->_maximum_number_operations_performed
+        }});
+    }
+
+    user_information.set_sub_items<pdu::SOPClassExtendedNegotiation>(
+        this->_sop_class_extended_negotiation);
+    
+    user_information.set_sub_items<pdu::SOPClassCommonExtendedNegotiation>(
+        this->_sop_class_common_extended_negotiation);
+
     user_information.set_sub_items<pdu::ImplementationVersionName>(
         {implementation_version_name});
 
@@ -487,6 +595,21 @@ AssociationParameters
 
     user_information.set_sub_items<pdu::ImplementationClassUID>(
         {implementation_class_uid});
+
+    if(this->_maximum_number_operations_invoked != 1 ||
+        this->_maximum_number_operations_performed != 1)
+    {
+        user_information.set_sub_items<pdu::AsynchronousOperationsWindow>({{
+            this->_maximum_number_operations_invoked,
+            this->_maximum_number_operations_performed
+        }});
+    }
+    
+    user_information.set_sub_items<pdu::SOPClassExtendedNegotiation>(
+        this->_sop_class_extended_negotiation);
+
+    // No SOPClassCommonExtendedNegotiation in AC
+
     user_information.set_sub_items<pdu::ImplementationVersionName>(
         {implementation_version_name});
 
@@ -515,7 +638,15 @@ AssociationParameters
         this->get_calling_ae_title() == other.get_calling_ae_title() &&
         this->get_presentation_contexts() == other.get_presentation_contexts() &&
         this->get_user_identity() == other.get_user_identity() &&
-        this->get_maximum_length() == other.get_maximum_length()
+        this->get_maximum_length() == other.get_maximum_length() &&
+        this->get_maximum_number_operations_invoked() ==
+            other.get_maximum_number_operations_invoked() &&
+        this->get_maximum_number_operations_performed() ==
+            other.get_maximum_number_operations_performed() && 
+        this->get_sop_class_extended_negotiation() ==
+            other.get_sop_class_extended_negotiation() &&
+        this->get_sop_class_common_extended_negotiation() ==
+            other.get_sop_class_common_extended_negotiation()
     );
 }
 
diff --git a/src/odil/AssociationParameters.h b/src/odil/AssociationParameters.h
index 19e88e7..d11d582 100644
--- a/src/odil/AssociationParameters.h
+++ b/src/odil/AssociationParameters.h
@@ -15,6 +15,8 @@
 
 #include "odil/pdu/AAssociateAC.h"
 #include "odil/pdu/AAssociateRQ.h"
+#include "odil/pdu/SOPClassCommonExtendedNegotiation.h"
+#include "odil/pdu/SOPClassExtendedNegotiation.h"
 
 namespace odil
 {
@@ -170,6 +172,46 @@ public:
      * no maximum length.
      */
     AssociationParameters & set_maximum_length(uint32_t value);
+    
+    /// @brief Return the maximum number of outstanding operations invoked
+    uint16_t get_maximum_number_operations_invoked() const;
+
+    /**
+     * @brief Set the maximum number of outstanding operations invoked,
+     * default to 1.
+     */
+    AssociationParameters & set_maximum_number_operations_invoked(uint16_t value);
+
+    /// @brief Return the maximum number of outstanding operations performed
+    uint16_t get_maximum_number_operations_performed() const;
+
+    /**
+     * @brief Set the maximum number of outstanding operations performed,
+     * default to 1.
+     */
+    AssociationParameters & set_maximum_number_operations_performed(uint16_t value);
+    
+    /// @brief Return the list of SOP Class Extended Negotiation items.
+    std::vector<pdu::SOPClassExtendedNegotiation>
+    get_sop_class_extended_negotiation() const;
+
+    /**
+     * @brief Set the list of SOP Class Extended Negotiation items, default
+     * to an empty list.
+     */
+    void set_sop_class_extended_negotiation(
+        std::vector<pdu::SOPClassExtendedNegotiation> const & value);
+
+    /// @brief Return the list of SOP Class Extended Negotiation items.
+    std::vector<pdu::SOPClassCommonExtendedNegotiation>
+        get_sop_class_common_extended_negotiation() const;
+    
+    /**
+     * @brief Set the list of SOP Class Common Extend Negotiation items, default
+     * to an empty list.
+     */
+    void set_sop_class_common_extended_negotiation(
+        std::vector<pdu::SOPClassCommonExtendedNegotiation> const & value);
 
     /// @brief Create an A-ASSOCIATE-RQ PDU.
     pdu::AAssociateRQ as_a_associate_rq() const;
@@ -186,6 +228,12 @@ private:
     std::vector<PresentationContext> _presentation_contexts;
     UserIdentity _user_identity;
     uint32_t _maximum_length;
+    uint16_t _maximum_number_operations_invoked;
+    uint16_t _maximum_number_operations_performed;
+    std::vector<pdu::SOPClassExtendedNegotiation>
+        _sop_class_extended_negotiation;
+    std::vector<pdu::SOPClassCommonExtendedNegotiation> 
+        _sop_class_common_extended_negotiation;
 
     /// @brief Set the user identity.
     AssociationParameters & _set_user_identity(UserIdentity const & value);
diff --git a/src/odil/pdu/AsynchronousOperationsWindow.cpp b/src/odil/pdu/AsynchronousOperationsWindow.cpp
new file mode 100644
index 0000000..67ff5e5
--- /dev/null
+++ b/src/odil/pdu/AsynchronousOperationsWindow.cpp
@@ -0,0 +1,87 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "odil/pdu/AsynchronousOperationsWindow.h"
+
+#include <cstdint>
+#include <istream>
+
+#include "odil/Exception.h"
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+AsynchronousOperationsWindow
+::AsynchronousOperationsWindow(
+    uint16_t maximum_number_operations_invoked,
+    uint16_t maximum_number_operations_performed)
+{
+    this->_item.add("Item-type", this->type);
+    this->_item.add("Reserved", uint8_t(0));
+    this->_item.add("Item-length", uint16_t(4));
+    this->_item.add("Maximum-number-operations-invoked", uint16_t(0));
+    this->_item.add("Maximum-number-operations-performed", uint16_t(0));
+
+    this->set_maximum_number_operations_invoked(maximum_number_operations_invoked);
+    this->set_maximum_number_operations_performed(maximum_number_operations_performed);
+}
+
+AsynchronousOperationsWindow
+::AsynchronousOperationsWindow(std::istream & stream)
+{
+    this->_item.read(stream, "Item-type", Item::Field::Type::unsigned_int_8);
+    if(this->_item.as_unsigned_int_8("Item-type") != this->type)
+    {
+        throw Exception("Invalid item type");
+    }
+
+    this->_item.read(stream, "Reserved", Item::Field::Type::unsigned_int_8);
+    this->_item.read(stream, "Item-length", Item::Field::Type::unsigned_int_16);
+    this->_item.read(
+        stream, "Maximum-number-operations-invoked", 
+        Item::Field::Type::unsigned_int_16);
+    this->_item.read(
+        stream, "Maximum-number-operations-performed", 
+        Item::Field::Type::unsigned_int_16);
+}
+
+uint16_t
+AsynchronousOperationsWindow
+::get_maximum_number_operations_invoked() const
+{
+    return this->_item.as_unsigned_int_16("Maximum-number-operations-invoked");
+}
+
+void
+AsynchronousOperationsWindow
+::set_maximum_number_operations_invoked(uint16_t value)
+{
+    this->_item.as_unsigned_int_16("Maximum-number-operations-invoked") = value;
+}
+
+uint16_t
+AsynchronousOperationsWindow
+::get_maximum_number_operations_performed() const
+{
+    return this->_item.as_unsigned_int_16("Maximum-number-operations-performed");
+}
+
+void
+AsynchronousOperationsWindow
+::set_maximum_number_operations_performed(uint16_t value)
+{
+    this->_item.as_unsigned_int_16("Maximum-number-operations-performed") = value;
+}
+
+}
+
+}
diff --git a/src/odil/pdu/AsynchronousOperationsWindow.h b/src/odil/pdu/AsynchronousOperationsWindow.h
new file mode 100644
index 0000000..608246b
--- /dev/null
+++ b/src/odil/pdu/AsynchronousOperationsWindow.h
@@ -0,0 +1,55 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _a24346ab_a585_4412_9237_5b2142f2d6eb
+#define _a24346ab_a585_4412_9237_5b2142f2d6eb
+
+#include <cstdint>
+#include <istream>
+
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+/// @brief Asynchronous Operations Window Sub-Item (PS 3.7, D.3.3.3.1 and D.3.3.3.2).
+class AsynchronousOperationsWindow: public Object
+{
+public:
+    /// @brief Item type.
+    static uint8_t const type=0x53;
+
+    /// @brief Create a Asynchronous Operations Window item.
+    AsynchronousOperationsWindow(
+        uint16_t maximum_number_operations_invoked,
+        uint16_t maximum_number_operations_performed);
+
+    /// @brief Read a Asynchronous Operations Window item from a stream.
+    AsynchronousOperationsWindow(std::istream & stream);
+
+    /// @brief Return the Maximum-number-operations-invoked.
+    uint16_t get_maximum_number_operations_invoked() const;
+
+    /// @brief Set the Maximum-number-operations-invoked.
+    void set_maximum_number_operations_invoked(uint16_t value);
+    
+    /// @brief Return the Maximum-number-operations-performed.
+    uint16_t get_maximum_number_operations_performed() const;
+
+    /// @brief Set the Maximum-number-operations-performed.
+    void set_maximum_number_operations_performed(uint16_t value);
+};
+
+}
+
+}
+
+#endif // _a24346ab_a585_4412_9237_5b2142f2d6eb
diff --git a/src/odil/pdu/SOPClassCommonExtendedNegotiation.cpp b/src/odil/pdu/SOPClassCommonExtendedNegotiation.cpp
new file mode 100644
index 0000000..fdafbb7
--- /dev/null
+++ b/src/odil/pdu/SOPClassCommonExtendedNegotiation.cpp
@@ -0,0 +1,190 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "odil/pdu/SOPClassCommonExtendedNegotiation.h"
+
+#include <algorithm>
+#include <istream>
+#include <string>
+#include <vector>
+
+#include "odil/Exception.h"
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+SOPClassCommonExtendedNegotiation
+::SOPClassCommonExtendedNegotiation(
+    std::string const & sop_class_uid, std::string const & service_class_uid,
+    std::vector<std::string> const & related_general_sop_class_uids)
+{
+    this->_item.add("Item-type", this->type);
+    this->_item.add("Sub-item-version", uint8_t(0));
+    this->_item.add("Item-length", uint16_t(0));
+    this->_item.add("SOP-class-uid-length", uint16_t(0));
+    this->_item.add("SOP-class-uid", std::string());
+    this->_item.add("Service-class-uid-length", uint16_t(0));
+    this->_item.add("Service-class-uid", std::string());
+    this->_item.add(
+        "Related-general-sop-class-identification-length", uint16_t(0));
+    this->_item.add(
+        "Related-general-sop-class-identification", std::vector<Item>());
+
+    this->set_sop_class_uid(sop_class_uid);
+    this->set_service_class_uid(service_class_uid);
+    this->set_related_general_sop_class_uids(related_general_sop_class_uids);
+}
+
+SOPClassCommonExtendedNegotiation
+::SOPClassCommonExtendedNegotiation(std::istream & stream)
+{
+    this->_item.read(stream, "Item-type", Item::Field::Type::unsigned_int_8);
+    if(this->_item.as_unsigned_int_8("Item-type") != this->type)
+    {
+        throw Exception("Invalid item type");
+    }
+
+    this->_item.read(
+        stream, "Sub-item-version", Item::Field::Type::unsigned_int_8);
+    this->_item.read(stream, "Item-length", Item::Field::Type::unsigned_int_16);
+
+    this->_item.read(
+        stream, "SOP-class-uid-length", Item::Field::Type::unsigned_int_16);
+    this->_item.read(
+        stream, "SOP-class-uid", Item::Field::Type::string,
+        this->_item.as_unsigned_int_16("SOP-class-uid-length"));
+
+    this->_item.read(
+        stream, "Service-class-uid-length", Item::Field::Type::unsigned_int_16);
+    this->_item.read(
+        stream, "Service-class-uid", Item::Field::Type::string,
+        this->_item.as_unsigned_int_16("Service-class-uid-length"));
+
+    this->_item.read(
+        stream, "Related-general-sop-class-identification-length",
+        Item::Field::Type::unsigned_int_16);
+    auto const related_classes_length = this->_item.as_unsigned_int_16(
+        "Related-general-sop-class-identification-length");
+
+    auto const begin = stream.tellg();
+    std::vector<Item> sub_items;
+    while(stream.tellg()-begin < related_classes_length)
+    {
+        Item item;
+        item.read(
+            stream, "Related-general-sop-class-uid-length",
+            Item::Field::Type::unsigned_int_16);
+        item.read(
+            stream, "Related-general-sop-class-uid", Item::Field::Type::string,
+            item.as_unsigned_int_16("Related-general-sop-class-uid-length"));
+        sub_items.push_back(item);
+    }
+    this->_item.add("Related-general-sop-class-identification", sub_items);
+}
+
+bool
+SOPClassCommonExtendedNegotiation
+::operator==(SOPClassCommonExtendedNegotiation const & other) const
+{
+    return (
+        this->get_sop_class_uid() == other.get_sop_class_uid()
+        && this->get_service_class_uid() == other.get_service_class_uid()
+        && this->get_related_general_sop_class_uids() ==
+            other.get_related_general_sop_class_uids()
+    );
+}
+
+std::string const &
+SOPClassCommonExtendedNegotiation
+::get_sop_class_uid() const
+{
+    return this->_item.as_string("SOP-class-uid");
+}
+
+void
+SOPClassCommonExtendedNegotiation
+::set_sop_class_uid(std::string const & value)
+{
+    this->_item.as_unsigned_int_16("SOP-class-uid-length") = value.size();
+    this->_item.as_string("SOP-class-uid") = value;
+    this->_item.as_unsigned_int_16("Item-length") = this->_compute_length();
+}
+
+std::string const &
+SOPClassCommonExtendedNegotiation
+::get_service_class_uid() const
+{
+    return this->_item.as_string("Service-class-uid");
+}
+
+void
+SOPClassCommonExtendedNegotiation
+::set_service_class_uid(std::string const & value)
+{
+    this->_item.as_unsigned_int_16("Service-class-uid-length") = value.size();
+    this->_item.as_string("Service-class-uid") = value;
+    this->_item.as_unsigned_int_16("Item-length") = this->_compute_length();
+}
+
+std::vector<std::string>
+SOPClassCommonExtendedNegotiation
+::get_related_general_sop_class_uids() const
+{
+    auto const & sub_items = this->_item.as_items(
+        "Related-general-sop-class-identification");
+
+    std::vector<std::string> result(sub_items.size());
+    std::transform(
+        sub_items.begin(), sub_items.end(),
+        result.begin(),
+        [](Item const & item)
+        {
+            return item.as_string("Related-general-sop-class-uid");
+        });
+
+    return result;
+}
+
+void
+SOPClassCommonExtendedNegotiation
+::set_related_general_sop_class_uids(std::vector<std::string> const & value)
+{
+    auto & sub_items = this->_item.as_items(
+        "Related-general-sop-class-identification");
+    sub_items.resize(value.size());
+    uint16_t size=0;
+    std::transform(
+        value.begin(), value.end(),
+        sub_items.begin(),
+        [&size](std::string const & sop_class_uid)
+        {
+            Item item;
+            item.add(
+                "Related-general-sop-class-uid-length",
+                uint16_t(sop_class_uid.size()));
+            item.add("Related-general-sop-class-uid", sop_class_uid);
+
+            size += (2+sop_class_uid.size());
+
+            return item;
+        });
+
+    this->_item.as_unsigned_int_16(
+        "Related-general-sop-class-identification-length") = size;
+    this->_item.as_items(
+        "Related-general-sop-class-identification") = sub_items;
+    this->_item.as_unsigned_int_16("Item-length") = this->_compute_length();
+}
+
+}
+
+}
diff --git a/src/odil/pdu/SOPClassCommonExtendedNegotiation.h b/src/odil/pdu/SOPClassCommonExtendedNegotiation.h
new file mode 100644
index 0000000..36ef78d
--- /dev/null
+++ b/src/odil/pdu/SOPClassCommonExtendedNegotiation.h
@@ -0,0 +1,69 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _4182d886_9654_4ec2_8cd6_7f334f290e56
+#define _4182d886_9654_4ec2_8cd6_7f334f290e56
+
+#include <istream>
+#include <string>
+#include <vector>
+
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+/// @brief SOP Class Common Extended Negotiation sub-item (PS 3.7, D.3.3.6).
+class SOPClassCommonExtendedNegotiation: public Object
+{
+public:
+    /// @brief Item type.
+    static uint8_t const type=0x57;
+
+    /// @brief Constructor.
+    SOPClassCommonExtendedNegotiation(
+        std::string const & sop_class_uid,
+        std::string const & service_class_uid="",
+        std::vector<std::string> const &
+            related_general_sop_class_uids=std::vector<std::string>());
+
+    /// @brief Read a SOP Class Common Extended Negotiation from a stream.
+    SOPClassCommonExtendedNegotiation(std::istream & stream);
+
+    /// @brief Comparison.
+    bool operator==(SOPClassCommonExtendedNegotiation const & other) const;
+
+    /// @brief Return the SOP Class UID.
+    std::string const & get_sop_class_uid() const;
+
+    /// @brief Set the SOP Class UID.
+    void set_sop_class_uid(std::string const & value);
+
+    /// @brief Return the Service Class UID.
+    std::string const & get_service_class_uid() const;
+
+    /// @brief Set the Service Class UID (default to "").
+    void set_service_class_uid(std::string const & value);
+
+    /// @brief Return the Related General SOP Class UIDs.
+    std::vector<std::string> get_related_general_sop_class_uids() const;
+
+    /// @brief Set the Related General SOP Class UIDs (default to empty).
+    void set_related_general_sop_class_uids(
+        std::vector<std::string> const & value);
+
+};
+
+}
+
+}
+
+#endif // _4182d886_9654_4ec2_8cd6_7f334f290e56
diff --git a/src/odil/pdu/SOPClassExtendedNegotiation.cpp b/src/odil/pdu/SOPClassExtendedNegotiation.cpp
new file mode 100644
index 0000000..a8fcab2
--- /dev/null
+++ b/src/odil/pdu/SOPClassExtendedNegotiation.cpp
@@ -0,0 +1,120 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#include "odil/pdu/SOPClassExtendedNegotiation.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <istream>
+#include <string>
+#include <vector>
+
+#include "odil/Exception.h"
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+SOPClassExtendedNegotiation
+::SOPClassExtendedNegotiation(
+    std::string const & sop_class_uid,
+    std::vector<uint8_t> const & service_class_application_information)
+{
+    this->_item.add("Item-type", this->type);
+    this->_item.add("Reserved", uint8_t(0));
+    this->_item.add("Item-length", uint16_t(0));
+    this->_item.add("SOP-class-uid-length", uint16_t(0));
+    this->_item.add("SOP-class-uid", std::string());
+    this->_item.add("Service-class-application-information", std::string());
+
+    this->set_sop_class_uid(sop_class_uid);
+    this->set_service_class_application_information(
+        service_class_application_information);
+}
+
+SOPClassExtendedNegotiation
+::SOPClassExtendedNegotiation(std::istream & stream)
+{
+    this->_item.read(stream, "Item-type", Item::Field::Type::unsigned_int_8);
+    if(this->_item.as_unsigned_int_8("Item-type") != this->type)
+    {
+        throw Exception("Invalid item type");
+    }
+
+    this->_item.read(stream, "Reserved", Item::Field::Type::unsigned_int_8);
+    this->_item.read(stream, "Item-length", Item::Field::Type::unsigned_int_16);
+
+    this->_item.read(
+        stream, "SOP-class-uid-length", Item::Field::Type::unsigned_int_16);
+    this->_item.read(
+        stream, "SOP-class-uid", Item::Field::Type::string,
+        this->_item.as_unsigned_int_16("SOP-class-uid-length"));
+
+    this->_item.read(
+        stream, "Service-class-application-information",
+        Item::Field::Type::string,
+        this->_item.as_unsigned_int_16("Item-length")
+            -this->_item.as_unsigned_int_16("SOP-class-uid-length")
+            -2);
+}
+
+bool
+SOPClassExtendedNegotiation
+::operator==(SOPClassExtendedNegotiation const & other) const
+{
+    return (
+        this->get_sop_class_uid() == other.get_sop_class_uid()
+        && this->get_service_class_application_information() ==
+            other.get_service_class_application_information()
+    );
+}
+
+std::string const &
+SOPClassExtendedNegotiation
+::get_sop_class_uid() const
+{
+    return this->_item.as_string("SOP-class-uid");
+}
+
+void
+SOPClassExtendedNegotiation
+::set_sop_class_uid(std::string const & value)
+{
+    this->_item.as_unsigned_int_16("SOP-class-uid-length") = value.size();
+    this->_item.as_string("SOP-class-uid") = value;
+    this->_item.as_unsigned_int_16("Item-length") = this->_compute_length();
+}
+
+std::vector<uint8_t>
+SOPClassExtendedNegotiation
+::get_service_class_application_information() const
+{
+    auto const & string = this->_item.as_string(
+        "Service-class-application-information");
+    std::vector<uint8_t> result(string.size());
+    std::copy(string.begin(), string.end(), result.begin());
+    return result;
+}
+
+void
+SOPClassExtendedNegotiation
+::set_service_class_application_information(std::vector<uint8_t> const & value)
+{
+    std::string string(value.size(), '\0');
+    std::copy(value.begin(), value.end(), string.begin());
+
+    this->_item.as_string("Service-class-application-information") = string;
+    this->_item.as_unsigned_int_16("Item-length") = this->_compute_length();
+}
+
+}
+
+}
diff --git a/src/odil/pdu/SOPClassExtendedNegotiation.h b/src/odil/pdu/SOPClassExtendedNegotiation.h
new file mode 100644
index 0000000..91acf0f
--- /dev/null
+++ b/src/odil/pdu/SOPClassExtendedNegotiation.h
@@ -0,0 +1,63 @@
+/*************************************************************************
+ * odil - Copyright (C) Universite de Strasbourg
+ * Distributed under the terms of the CeCILL-B license, as published by
+ * the CEA-CNRS-INRIA. Refer to the LICENSE file or to
+ * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+ * for details.
+ ************************************************************************/
+
+#ifndef _6e3d351d_e5dc_4ab6_9c2d_8582e4fe2aa5
+#define _6e3d351d_e5dc_4ab6_9c2d_8582e4fe2aa5
+
+#include <cstdint>
+#include <istream>
+#include <string>
+#include <vector>
+
+#include "odil/pdu/Object.h"
+
+namespace odil
+{
+
+namespace pdu
+{
+
+/// @brief SOP Class Extended Negotiation sub-item (PS 3.7, D.3.3.5).
+class SOPClassExtendedNegotiation: public Object
+{
+public:
+    /// @brief Item type.
+    static uint8_t const type=0x56;
+
+    /// @brief Constructor.
+    SOPClassExtendedNegotiation(
+        std::string const & sop_class_uid,
+        std::vector<uint8_t> const & service_class_application_information);
+
+    /// @brief Read a SOP Class Common Extended Negotiation from a stream.
+    SOPClassExtendedNegotiation(std::istream & stream);
+
+    /// @brief Comparison.
+    bool operator==(SOPClassExtendedNegotiation const & other) const;
+
+    /// @brief Return the SOP Class UID.
+    std::string const & get_sop_class_uid() const;
+
+    /// @brief Set the SOP Class UID.
+    void set_sop_class_uid(std::string const & value);
+
+    /// @brief Return the Service Class Application Information.
+    std::vector<uint8_t> get_service_class_application_information() const;
+
+    /// @brief Set the Service Class Application Information.
+    void set_service_class_application_information(
+        std::vector<uint8_t> const & value);
+
+
+};
+
+}
+
+}
+
+#endif // _6e3d351d_e5dc_4ab6_9c2d_8582e4fe2aa5
diff --git a/src/odil/pdu/UserInformation.cpp b/src/odil/pdu/UserInformation.cpp
index e788519..0576b49 100644
--- a/src/odil/pdu/UserInformation.cpp
+++ b/src/odil/pdu/UserInformation.cpp
@@ -15,11 +15,14 @@
 #include "odil/endian.h"
 #include "odil/Exception.h"
 #include "odil/logging.h"
+#include "odil/pdu/AsynchronousOperationsWindow.h"
 #include "odil/pdu/ImplementationClassUID.h"
 #include "odil/pdu/ImplementationVersionName.h"
 #include "odil/pdu/MaximumLength.h"
 #include "odil/pdu/Object.h"
 #include "odil/pdu/RoleSelection.h"
+#include "odil/pdu/SOPClassCommonExtendedNegotiation.h"
+#include "odil/pdu/SOPClassExtendedNegotiation.h"
 #include "odil/pdu/UserIdentityAC.h"
 #include "odil/pdu/UserIdentityRQ.h"
 
@@ -60,8 +63,12 @@ UserInformation
 
     std::vector<MaximumLength> maximum_length;
     std::vector<ImplementationClassUID> implementation_class_uid;
+    std::vector<AsynchronousOperationsWindow> asynchronous_operation_window;
     std::vector<RoleSelection> role_selection;
     std::vector<ImplementationVersionName> implementation_version_name;
+    std::vector<SOPClassExtendedNegotiation> sop_class_extended_negotiation;
+    std::vector<SOPClassCommonExtendedNegotiation>
+        sop_class_common_extended_negotiation;
     std::vector<UserIdentityRQ> user_identity_rq;
     std::vector<UserIdentityAC> user_identity_ac;
 
@@ -70,31 +77,39 @@ UserInformation
         uint8_t const type = stream.peek();
         if(type == 0x51)
         {
-            maximum_length.push_back(MaximumLength(stream));
+            maximum_length.emplace_back(stream);
         }
         else if(type == 0x52)
         {
-            implementation_class_uid.push_back(ImplementationClassUID(stream));
+            implementation_class_uid.emplace_back(stream);
+        }
+        else if(type == 0x53)
+        {
+            asynchronous_operation_window.emplace_back(stream);
         }
-        // 0x53: Asynchronous Operations Window, PS 3.7, D.3.3.3.1
         else if(type == 0x54)
         {
-            role_selection.push_back(RoleSelection(stream));
+            role_selection.emplace_back(stream);
         }
         else if(type == 0x55)
         {
-            implementation_version_name.push_back(
-                ImplementationVersionName(stream));
+            implementation_version_name.emplace_back(stream);
+        }
+        else if(type == 0x56)
+        {
+            sop_class_extended_negotiation.emplace_back(stream);
+        }
+        else if(type == 0x57)
+        {
+            sop_class_common_extended_negotiation.emplace_back(stream);
         }
-        // 0x56: SOP Class Extended Negotiation, PS 3.7, D.3.3.5.1
-        // 0x57: SOP Class Common Extended Negotiation, PS 3.7, D.3.3.6.1
         else if(type == 0x58)
         {
-            user_identity_rq.push_back(UserIdentityRQ(stream));
+            user_identity_rq.emplace_back(stream);
         }
         else if(type == 0x59)
         {
-            user_identity_ac.push_back(UserIdentityAC(stream));
+            user_identity_ac.emplace_back(stream);
         }
         else
         {
diff --git a/src/odil/registry.cpp b/src/odil/registry.cpp
index e8b39d7..d15a09d 100644
--- a/src/odil/registry.cpp
+++ b/src/odil/registry.cpp
@@ -304,6 +304,12 @@ ElementsDictionary create_public_dictionary()
           "Mapping Resource Identification Sequence", "MappingResourceIdentificationSequence",  "SQ", "1" },
         { Tag(0x0008, 0x0201),
           "Timezone Offset From UTC", "TimezoneOffsetFromUTC",  "SH", "1" },
+        { Tag(0x0008, 0x0220),
+          "Responsible Group Code Sequence", "ResponsibleGroupCodeSequence",  "SQ", "1" },
+        { Tag(0x0008, 0x0221),
+          "Equipment Modality", "EquipmentModality",  "CS", "1" },
+        { Tag(0x0008, 0x0222),
+          "Manufacturer's Related Model Group", "ManufacturerRelatedModelGroup",  "LO", "1" },
         { Tag(0x0008, 0x0300),
           "Private Data Element Characteristics Sequence", "PrivateDataElementCharacteristicsSequence",  "SQ", "1" },
         { Tag(0x0008, 0x0301),
@@ -320,6 +326,24 @@ ElementsDictionary create_public_dictionary()
           "Deidentification Action Sequence", "DeidentificationActionSequence",  "SQ", "1" },
         { Tag(0x0008, 0x0307),
           "Deidentification Action", "DeidentificationAction",  "CS", "1" },
+        { Tag(0x0008, 0x0308),
+          "Private Data Element", "PrivateDataElement",  "US", "1" },
+        { Tag(0x0008, 0x0309),
+          "Private Data Element Value Multiplicity", "PrivateDataElementValueMultiplicity",  "UL", "1-3" },
+        { Tag(0x0008, 0x030a),
+          "Private Data Element Value Representation", "PrivateDataElementValueRepresentation",  "CS", "1" },
+        { Tag(0x0008, 0x030b),
+          "Private Data Element Number of Items", "PrivateDataElementNumberOfItems",  "UL", "1-2" },
+        { Tag(0x0008, 0x030c),
+          "Private Data Element Name", "PrivateDataElementName",  "UC", "1" },
+        { Tag(0x0008, 0x030d),
+          "Private Data Element Keyword", "PrivateDataElementKeyword",  "UC", "1" },
+        { Tag(0x0008, 0x030e),
+          "Private Data Element Description", "PrivateDataElementDescription",  "UT", "1" },
+        { Tag(0x0008, 0x030f),
+          "Private Data Element Encoding", "PrivateDataElementEncoding",  "UT", "1" },
+        { Tag(0x0008, 0x0310),
+          "Private Data Element Definition Sequence", "PrivateDataElementDefinitionSequence",  "SQ", "1" },
         { Tag(0x0008, 0x1000),
           "Network ID", "NetworkID",  "AE", "1" },
         { Tag(0x0008, 0x1010),
@@ -608,6 +632,12 @@ ElementsDictionary create_public_dictionary()
           "Patient's Size", "PatientSize",  "DS", "1" },
         { Tag(0x0010, 0x1021),
           "Patient's Size Code Sequence", "PatientSizeCodeSequence",  "SQ", "1" },
+        { Tag(0x0010, 0x1022),
+          "Patient's Body Mass Index", "PatientBodyMassIndex",  "DS", "1" },
+        { Tag(0x0010, 0x1023),
+          "Measured AP Dimension", "MeasuredAPDimension",  "DS", "1" },
+        { Tag(0x0010, 0x1024),
+          "Measured Lateral Dimension", "MeasuredLateralDimension",  "DS", "1" },
         { Tag(0x0010, 0x1030),
           "Patient's Weight", "PatientWeight",  "DS", "1" },
         { Tag(0x0010, 0x1040),
@@ -718,6 +748,10 @@ ElementsDictionary create_public_dictionary()
           "Distribution Type", "DistributionType",  "CS", "1" },
         { Tag(0x0012, 0x0085),
           "Consent for Distribution Flag", "ConsentForDistributionFlag",  "CS", "1" },
+        { Tag(0x0012, 0x0086),
+          "Ethics Committee Approval Effectiveness Start Date", "EthicsCommitteeApprovalEffectivenessStartDate",  "DA", "1" },
+        { Tag(0x0012, 0x0087),
+          "Ethics Committee Approval Effectiveness End Date", "EthicsCommitteeApprovalEffectivenessEndDate",  "DA", "1" },
         { Tag(0x0014, 0x0023),
           "CAD File Format", "CADFileFormat",  "ST", "1" },
         { Tag(0x0014, 0x0024),
@@ -1222,6 +1256,10 @@ ElementsDictionary create_public_dictionary()
           "Cassette ID", "CassetteID",  "LO", "1" },
         { Tag(0x0018, 0x1008),
           "Gantry ID", "GantryID",  "LO", "1" },
+        { Tag(0x0018, 0x1009),
+          "Unique Device Identifier", "UniqueDeviceIdentifier",  "UT", "1" },
+        { Tag(0x0018, 0x100a),
+          "UDI Sequence", "UDISequence",  "SQ", "1" },
         { Tag(0x0018, 0x1010),
           "Secondary Capture Device ID", "SecondaryCaptureDeviceID",  "LO", "1" },
         { Tag(0x0018, 0x1011),
@@ -2209,7 +2247,7 @@ ElementsDictionary create_public_dictionary()
         { Tag(0x0018, 0x9322),
           "Reconstruction Pixel Spacing", "ReconstructionPixelSpacing",  "FD", "2" },
         { Tag(0x0018, 0x9323),
-          "Exposure Modulation Type", "ExposureModulationType",  "CS", "1" },
+          "Exposure Modulation Type", "ExposureModulationType",  "CS", "1-n" },
         { Tag(0x0018, 0x9324),
           "Estimated Dose Saving", "EstimatedDoseSaving",  "FD", "1" },
         { Tag(0x0018, 0x9325),
@@ -2580,6 +2618,124 @@ ElementsDictionary create_public_dictionary()
           "Transducer Application Code Sequence", "TransducerApplicationCodeSequence",  "SQ", "1" },
         { Tag(0x0018, 0x9810),
           "Zero Velocity Pixel Value", "ZeroVelocityPixelValue",  "US or SS", "1" },
+        { Tag(0x0018, 0x9900),
+          "Reference Location Label", "ReferenceLocationLabel",  "LO", "1" },
+        { Tag(0x0018, 0x9901),
+          "Reference Location Description", "ReferenceLocationDescription",  "UT", "1" },
+        { Tag(0x0018, 0x9902),
+          "Reference Basis Code Sequence", "ReferenceBasisCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9903),
+          "Reference Geometry Code Sequence", "ReferenceGeometryCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9904),
+          "Offset Distance", "OffsetDistance",  "DS", "1" },
+        { Tag(0x0018, 0x9905),
+          "Offset Direction", "OffsetDirection",  "CS", "1" },
+        { Tag(0x0018, 0x9906),
+          "Potential Scheduled Protocol Code Sequence", "PotentialScheduledProtocolCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9907),
+          "Potential Requested Procedure Code Sequence", "PotentialRequestedProcedureCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9908),
+          "Potential Reasons for Procedure", "PotentialReasonsForProcedure",  "UC", "1-n" },
+        { Tag(0x0018, 0x9909),
+          "Potential Reasons for Procedure Code Sequence", "PotentialReasonsForProcedureCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x990a),
+          "Potential Diagnostic Tasks", "PotentialDiagnosticTasks",  "UC", "1-n" },
+        { Tag(0x0018, 0x990b),
+          "Contraindications Code Sequence", "ContraindicationsCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x990c),
+          "Referenced Defined Protocol Sequence", "ReferencedDefinedProtocolSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x990d),
+          "Referenced Performed Protocol Sequence", "ReferencedPerformedProtocolSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x990e),
+          "Predecessor Protocol Sequence", "PredecessorProtocolSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x990f),
+          "Protocol Planning Information", "ProtocolPlanningInformation",  "UT", "1" },
+        { Tag(0x0018, 0x9910),
+          "Protocol Design Rationale", "ProtocolDesignRationale",  "UT", "1" },
+        { Tag(0x0018, 0x9911),
+          "Patient Specification Sequence", "PatientSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9912),
+          "Model Specification Sequence", "ModelSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9913),
+          "Parameters Specification Sequence", "ParametersSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9914),
+          "Instruction Sequence", "InstructionSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9915),
+          "Instruction Index", "InstructionIndex",  "US", "1" },
+        { Tag(0x0018, 0x9916),
+          "Instruction Text", "InstructionText",  "LO", "1" },
+        { Tag(0x0018, 0x9917),
+          "Instruction Description", "InstructionDescription",  "UT", "1" },
+        { Tag(0x0018, 0x9918),
+          "Instruction Performed Flag", "InstructionPerformedFlag",  "CS", "1" },
+        { Tag(0x0018, 0x9919),
+          "Instruction Performed DateTime", "InstructionPerformedDateTime",  "DT", "1" },
+        { Tag(0x0018, 0x991a),
+          "Instruction Performance Comment", "InstructionPerformanceComment",  "UT", "1" },
+        { Tag(0x0018, 0x991b),
+          "Patient Positioning Instruction Sequence", "PatientPositioningInstructionSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x991c),
+          "Positioning Method Code Sequence", "PositioningMethodCodeSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x991d),
+          "Positioning Landmark Sequence", "PositioningLandmarkSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x991e),
+          "Target Frame of Reference UID", "TargetFrameOfReferenceUID",  "UI", "1" },
+        { Tag(0x0018, 0x991f),
+          "Acquisition Protocol Element Specification Sequence", "AcquisitionProtocolElementSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9920),
+          "Acquisition Protocol Element Sequence", "AcquisitionProtocolElementSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9921),
+          "Protocol Element Number", "ProtocolElementNumber",  "US", "1" },
+        { Tag(0x0018, 0x9922),
+          "Protocol Element Name", "ProtocolElementName",  "LO", "1" },
+        { Tag(0x0018, 0x9923),
+          "Protocol Element Characteristics Summary", "ProtocolElementCharacteristicsSummary",  "UT", "1" },
+        { Tag(0x0018, 0x9924),
+          "Protocol Element Purpose", "ProtocolElementPurpose",  "UT", "1" },
+        { Tag(0x0018, 0x9930),
+          "Acquisition Motion", "AcquisitionMotion",  "CS", "1" },
+        { Tag(0x0018, 0x9931),
+          "Acquisition Start Location Sequence", "AcquisitionStartLocationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9932),
+          "Acquisition End Location Sequence", "AcquisitionEndLocationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9933),
+          "Reconstruction Protocol Element Specification Sequence", "ReconstructionProtocolElementSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9934),
+          "Reconstruction Protocol Element Sequence", "ReconstructionProtocolElementSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9935),
+          "Storage Protocol Element Specification Sequence", "StorageProtocolElementSpecificationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9936),
+          "Storage Protocol Element Sequence", "StorageProtocolElementSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9937),
+          "Requested Series Description", "RequestedSeriesDescription",  "LO", "1" },
+        { Tag(0x0018, 0x9938),
+          "Source Acquisition Protocol Element Number", "SourceAcquisitionProtocolElementNumber",  "US", "1-n" },
+        { Tag(0x0018, 0x9939),
+          "Source Acquisition Beam Number", "SourceAcquisitionBeamNumber",  "US", "1-n" },
+        { Tag(0x0018, 0x993a),
+          "Source Reconstruction Protocol Element Number", "SourceReconstructionProtocolElementNumber",  "US", "1-n" },
+        { Tag(0x0018, 0x993b),
+          "Reconstruction Start Location Sequence", "ReconstructionStartLocationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x993c),
+          "Reconstruction End Location Sequence", "ReconstructionEndLocationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x993d),
+          "Reconstruction Algorithm Sequence", "ReconstructionAlgorithmSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x993e),
+          "Reconstruction Target Center Location Sequence", "ReconstructionTargetCenterLocationSequence",  "SQ", "1" },
+        { Tag(0x0018, 0x9941),
+          "Image Filter Description", "ImageFilterDescription",  "UT", "1" },
+        { Tag(0x0018, 0x9942),
+          "CTDIvol Notification Trigger", "CTDIvolNotificationTrigger",  "FD", "1" },
+        { Tag(0x0018, 0x9943),
+          "DLP Notification Trigger", "DLPNotificationTrigger",  "FD", "1" },
+        { Tag(0x0018, 0x9944),
+          "Auto KVP Selection Type", "AutoKVPSelectionType",  "CS", "1" },
+        { Tag(0x0018, 0x9945),
+          "Auto KVP Upper Bound", "AutoKVPUpperBound",  "FD", "1" },
+        { Tag(0x0018, 0x9946),
+          "Auto KVP Lower Bound", "AutoKVPLowerBound",  "FD", "1" },
+        { Tag(0x0018, 0x9947),
+          "Protocol Defined Patient Position", "ProtocolDefinedPatientPosition",  "CS", "1" },
         { Tag(0x0018, 0xa001),
           "Contributing Equipment Sequence", "ContributingEquipmentSequence",  "SQ", "1" },
         { Tag(0x0018, 0xa002),
@@ -2664,6 +2820,8 @@ ElementsDictionary create_public_dictionary()
           "Images in Study", "ImagesInStudy",  "IS", "1" },
         { Tag(0x0020, 0x1020),
           "Reference", "Reference",  "LO", "1-n" },
+        { Tag(0x0020, 0x103f),
+          "Target Position Reference Indicator", "TargetPositionReferenceIndicator",  "LO", "1" },
         { Tag(0x0020, 0x1040),
           "Position Reference Indicator", "PositionReferenceIndicator",  "LO", "1" },
         { Tag(0x0020, 0x1041),
@@ -5686,6 +5844,8 @@ ElementsDictionary create_public_dictionary()
           "Fiducial Set Sequence", "FiducialSetSequence",  "SQ", "1" },
         { Tag(0x0070, 0x031e),
           "Fiducial Sequence", "FiducialSequence",  "SQ", "1" },
+        { Tag(0x0070, 0x031f),
+          "Fiducials Property Category Code Sequence", "FiducialsPropertyCategoryCodeSequence",  "SQ", "1" },
         { Tag(0x0070, 0x0401),
           "Graphic Layer Recommended Display CIELab Value", "GraphicLayerRecommendedDisplayCIELabValue",  "US", "3" },
         { Tag(0x0070, 0x0402),
@@ -6330,6 +6490,8 @@ ElementsDictionary create_public_dictionary()
           "Constraint Violation Significance", "ConstraintViolationSignificance",  "CS", "1" },
         { Tag(0x0082, 0x0037),
           "Constraint Violation Condition", "ConstraintViolationCondition",  "UT", "1" },
+        { Tag(0x0082, 0x0038),
+          "Modifiable Constraint Flag", "ModifiableConstraintFlag",  "CS", "1" },
         { Tag(0x0088, 0x0130),
           "Storage Media File-set ID", "StorageMediaFileSetID",  "SH", "1" },
         { Tag(0x0088, 0x0140),
@@ -8550,7 +8712,10 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Mapping Resource Name", "MappingResourceName",  "LO", "1" },    { Tag(0x0008, 0x0123),
           "Context Group Identification Sequence", "ContextGroupIdentificationSequence",  "SQ", "1" },    { Tag(0x0008, 0x0124),
           "Mapping Resource Identification Sequence", "MappingResourceIdentificationSequence",  "SQ", "1" },    { Tag(0x0008, 0x0201),
-          "Timezone Offset From UTC", "TimezoneOffsetFromUTC",  "SH", "1" },    { Tag(0x0008, 0x0300),
+          "Timezone Offset From UTC", "TimezoneOffsetFromUTC",  "SH", "1" },    { Tag(0x0008, 0x0220),
+          "Responsible Group Code Sequence", "ResponsibleGroupCodeSequence",  "SQ", "1" },    { Tag(0x0008, 0x0221),
+          "Equipment Modality", "EquipmentModality",  "CS", "1" },    { Tag(0x0008, 0x0222),
+          "Manufacturer's Related Model Group", "ManufacturerRelatedModelGroup",  "LO", "1" },    { Tag(0x0008, 0x0300),
           "Private Data Element Characteristics Sequence", "PrivateDataElementCharacteristicsSequence",  "SQ", "1" },    { Tag(0x0008, 0x0301),
           "Private Group Reference", "PrivateGroupReference",  "US", "1" },    { Tag(0x0008, 0x0302),
           "Private Creator Reference", "PrivateCreatorReference",  "LO", "1" },    { Tag(0x0008, 0x0303),
@@ -8558,7 +8723,16 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Nonidentifying Private Elements", "NonidentifyingPrivateElements",  "US", "1-n" },    { Tag(0x0008, 0x0306),
           "Identifying Private Elements", "IdentifyingPrivateElements",  "US", "1-n" },    { Tag(0x0008, 0x0305),
           "Deidentification Action Sequence", "DeidentificationActionSequence",  "SQ", "1" },    { Tag(0x0008, 0x0307),
-          "Deidentification Action", "DeidentificationAction",  "CS", "1" },    { Tag(0x0008, 0x1000),
+          "Deidentification Action", "DeidentificationAction",  "CS", "1" },    { Tag(0x0008, 0x0308),
+          "Private Data Element", "PrivateDataElement",  "US", "1" },    { Tag(0x0008, 0x0309),
+          "Private Data Element Value Multiplicity", "PrivateDataElementValueMultiplicity",  "UL", "1-3" },    { Tag(0x0008, 0x030a),
+          "Private Data Element Value Representation", "PrivateDataElementValueRepresentation",  "CS", "1" },    { Tag(0x0008, 0x030b),
+          "Private Data Element Number of Items", "PrivateDataElementNumberOfItems",  "UL", "1-2" },    { Tag(0x0008, 0x030c),
+          "Private Data Element Name", "PrivateDataElementName",  "UC", "1" },    { Tag(0x0008, 0x030d),
+          "Private Data Element Keyword", "PrivateDataElementKeyword",  "UC", "1" },    { Tag(0x0008, 0x030e),
+          "Private Data Element Description", "PrivateDataElementDescription",  "UT", "1" },    { Tag(0x0008, 0x030f),
+          "Private Data Element Encoding", "PrivateDataElementEncoding",  "UT", "1" },    { Tag(0x0008, 0x0310),
+          "Private Data Element Definition Sequence", "PrivateDataElementDefinitionSequence",  "SQ", "1" },    { Tag(0x0008, 0x1000),
           "Network ID", "NetworkID",  "AE", "1" },    { Tag(0x0008, 0x1010),
           "Station Name", "StationName",  "SH", "1" },    { Tag(0x0008, 0x1030),
           "Study Description", "StudyDescription",  "LO", "1" },    { Tag(0x0008, 0x1032),
@@ -8702,7 +8876,10 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Patient's Birth Name", "PatientBirthName",  "PN", "1" },    { Tag(0x0010, 0x1010),
           "Patient's Age", "PatientAge",  "AS", "1" },    { Tag(0x0010, 0x1020),
           "Patient's Size", "PatientSize",  "DS", "1" },    { Tag(0x0010, 0x1021),
-          "Patient's Size Code Sequence", "PatientSizeCodeSequence",  "SQ", "1" },    { Tag(0x0010, 0x1030),
+          "Patient's Size Code Sequence", "PatientSizeCodeSequence",  "SQ", "1" },    { Tag(0x0010, 0x1022),
+          "Patient's Body Mass Index", "PatientBodyMassIndex",  "DS", "1" },    { Tag(0x0010, 0x1023),
+          "Measured AP Dimension", "MeasuredAPDimension",  "DS", "1" },    { Tag(0x0010, 0x1024),
+          "Measured Lateral Dimension", "MeasuredLateralDimension",  "DS", "1" },    { Tag(0x0010, 0x1030),
           "Patient's Weight", "PatientWeight",  "DS", "1" },    { Tag(0x0010, 0x1040),
           "Patient's Address", "PatientAddress",  "LO", "1" },    { Tag(0x0010, 0x1050),
           "Insurance Plan Identification", "InsurancePlanIdentification",  "LO", "1-n" },    { Tag(0x0010, 0x1060),
@@ -8757,7 +8934,9 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Clinical Trial Protocol Ethics Committee Approval Number", "ClinicalTrialProtocolEthicsCommitteeApprovalNumber",  "LO", "1" },    { Tag(0x0012, 0x0083),
           "Consent for Clinical Trial Use Sequence", "ConsentForClinicalTrialUseSequence",  "SQ", "1" },    { Tag(0x0012, 0x0084),
           "Distribution Type", "DistributionType",  "CS", "1" },    { Tag(0x0012, 0x0085),
-          "Consent for Distribution Flag", "ConsentForDistributionFlag",  "CS", "1" },    { Tag(0x0014, 0x0023),
+          "Consent for Distribution Flag", "ConsentForDistributionFlag",  "CS", "1" },    { Tag(0x0012, 0x0086),
+          "Ethics Committee Approval Effectiveness Start Date", "EthicsCommitteeApprovalEffectivenessStartDate",  "DA", "1" },    { Tag(0x0012, 0x0087),
+          "Ethics Committee Approval Effectiveness End Date", "EthicsCommitteeApprovalEffectivenessEndDate",  "DA", "1" },    { Tag(0x0014, 0x0023),
           "CAD File Format", "CADFileFormat",  "ST", "1" },    { Tag(0x0014, 0x0024),
           "Component Reference System", "ComponentReferenceSystem",  "ST", "1" },    { Tag(0x0014, 0x0025),
           "Component Manufacturing Procedure", "ComponentManufacturingProcedure",  "ST", "1" },    { Tag(0x0014, 0x0028),
@@ -9009,7 +9188,9 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Generator ID", "GeneratorID",  "LO", "1" },    { Tag(0x0018, 0x1006),
           "Grid ID", "GridID",  "LO", "1" },    { Tag(0x0018, 0x1007),
           "Cassette ID", "CassetteID",  "LO", "1" },    { Tag(0x0018, 0x1008),
-          "Gantry ID", "GantryID",  "LO", "1" },    { Tag(0x0018, 0x1010),
+          "Gantry ID", "GantryID",  "LO", "1" },    { Tag(0x0018, 0x1009),
+          "Unique Device Identifier", "UniqueDeviceIdentifier",  "UT", "1" },    { Tag(0x0018, 0x100a),
+          "UDI Sequence", "UDISequence",  "SQ", "1" },    { Tag(0x0018, 0x1010),
           "Secondary Capture Device ID", "SecondaryCaptureDeviceID",  "LO", "1" },    { Tag(0x0018, 0x1011),
           "Hardcopy Creation Device ID", "HardcopyCreationDeviceID",  "LO", "1" },    { Tag(0x0018, 0x1012),
           "Date of Secondary Capture", "DateOfSecondaryCapture",  "DA", "1" },    { Tag(0x0018, 0x1014),
@@ -9503,7 +9684,7 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Image Filter", "ImageFilter",  "SH", "1" },    { Tag(0x0018, 0x9321),
           "CT Exposure Sequence", "CTExposureSequence",  "SQ", "1" },    { Tag(0x0018, 0x9322),
           "Reconstruction Pixel Spacing", "ReconstructionPixelSpacing",  "FD", "2" },    { Tag(0x0018, 0x9323),
-          "Exposure Modulation Type", "ExposureModulationType",  "CS", "1" },    { Tag(0x0018, 0x9324),
+          "Exposure Modulation Type", "ExposureModulationType",  "CS", "1-n" },    { Tag(0x0018, 0x9324),
           "Estimated Dose Saving", "EstimatedDoseSaving",  "FD", "1" },    { Tag(0x0018, 0x9325),
           "CT X-Ray Details Sequence", "CTXRayDetailsSequence",  "SQ", "1" },    { Tag(0x0018, 0x9326),
           "CT Position Sequence", "CTPositionSequence",  "SQ", "1" },    { Tag(0x0018, 0x9327),
@@ -9688,7 +9869,66 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Transducer Geometry Code Sequence", "TransducerGeometryCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x980e),
           "Transducer Beam Steering Code Sequence", "TransducerBeamSteeringCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x980f),
           "Transducer Application Code Sequence", "TransducerApplicationCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x9810),
-          "Zero Velocity Pixel Value", "ZeroVelocityPixelValue",  "US or SS", "1" },    { Tag(0x0018, 0xa001),
+          "Zero Velocity Pixel Value", "ZeroVelocityPixelValue",  "US or SS", "1" },    { Tag(0x0018, 0x9900),
+          "Reference Location Label", "ReferenceLocationLabel",  "LO", "1" },    { Tag(0x0018, 0x9901),
+          "Reference Location Description", "ReferenceLocationDescription",  "UT", "1" },    { Tag(0x0018, 0x9902),
+          "Reference Basis Code Sequence", "ReferenceBasisCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x9903),
+          "Reference Geometry Code Sequence", "ReferenceGeometryCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x9904),
+          "Offset Distance", "OffsetDistance",  "DS", "1" },    { Tag(0x0018, 0x9905),
+          "Offset Direction", "OffsetDirection",  "CS", "1" },    { Tag(0x0018, 0x9906),
+          "Potential Scheduled Protocol Code Sequence", "PotentialScheduledProtocolCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x9907),
+          "Potential Requested Procedure Code Sequence", "PotentialRequestedProcedureCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x9908),
+          "Potential Reasons for Procedure", "PotentialReasonsForProcedure",  "UC", "1-n" },    { Tag(0x0018, 0x9909),
+          "Potential Reasons for Procedure Code Sequence", "PotentialReasonsForProcedureCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x990a),
+          "Potential Diagnostic Tasks", "PotentialDiagnosticTasks",  "UC", "1-n" },    { Tag(0x0018, 0x990b),
+          "Contraindications Code Sequence", "ContraindicationsCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x990c),
+          "Referenced Defined Protocol Sequence", "ReferencedDefinedProtocolSequence",  "SQ", "1" },    { Tag(0x0018, 0x990d),
+          "Referenced Performed Protocol Sequence", "ReferencedPerformedProtocolSequence",  "SQ", "1" },    { Tag(0x0018, 0x990e),
+          "Predecessor Protocol Sequence", "PredecessorProtocolSequence",  "SQ", "1" },    { Tag(0x0018, 0x990f),
+          "Protocol Planning Information", "ProtocolPlanningInformation",  "UT", "1" },    { Tag(0x0018, 0x9910),
+          "Protocol Design Rationale", "ProtocolDesignRationale",  "UT", "1" },    { Tag(0x0018, 0x9911),
+          "Patient Specification Sequence", "PatientSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9912),
+          "Model Specification Sequence", "ModelSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9913),
+          "Parameters Specification Sequence", "ParametersSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9914),
+          "Instruction Sequence", "InstructionSequence",  "SQ", "1" },    { Tag(0x0018, 0x9915),
+          "Instruction Index", "InstructionIndex",  "US", "1" },    { Tag(0x0018, 0x9916),
+          "Instruction Text", "InstructionText",  "LO", "1" },    { Tag(0x0018, 0x9917),
+          "Instruction Description", "InstructionDescription",  "UT", "1" },    { Tag(0x0018, 0x9918),
+          "Instruction Performed Flag", "InstructionPerformedFlag",  "CS", "1" },    { Tag(0x0018, 0x9919),
+          "Instruction Performed DateTime", "InstructionPerformedDateTime",  "DT", "1" },    { Tag(0x0018, 0x991a),
+          "Instruction Performance Comment", "InstructionPerformanceComment",  "UT", "1" },    { Tag(0x0018, 0x991b),
+          "Patient Positioning Instruction Sequence", "PatientPositioningInstructionSequence",  "SQ", "1" },    { Tag(0x0018, 0x991c),
+          "Positioning Method Code Sequence", "PositioningMethodCodeSequence",  "SQ", "1" },    { Tag(0x0018, 0x991d),
+          "Positioning Landmark Sequence", "PositioningLandmarkSequence",  "SQ", "1" },    { Tag(0x0018, 0x991e),
+          "Target Frame of Reference UID", "TargetFrameOfReferenceUID",  "UI", "1" },    { Tag(0x0018, 0x991f),
+          "Acquisition Protocol Element Specification Sequence", "AcquisitionProtocolElementSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9920),
+          "Acquisition Protocol Element Sequence", "AcquisitionProtocolElementSequence",  "SQ", "1" },    { Tag(0x0018, 0x9921),
+          "Protocol Element Number", "ProtocolElementNumber",  "US", "1" },    { Tag(0x0018, 0x9922),
+          "Protocol Element Name", "ProtocolElementName",  "LO", "1" },    { Tag(0x0018, 0x9923),
+          "Protocol Element Characteristics Summary", "ProtocolElementCharacteristicsSummary",  "UT", "1" },    { Tag(0x0018, 0x9924),
+          "Protocol Element Purpose", "ProtocolElementPurpose",  "UT", "1" },    { Tag(0x0018, 0x9930),
+          "Acquisition Motion", "AcquisitionMotion",  "CS", "1" },    { Tag(0x0018, 0x9931),
+          "Acquisition Start Location Sequence", "AcquisitionStartLocationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9932),
+          "Acquisition End Location Sequence", "AcquisitionEndLocationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9933),
+          "Reconstruction Protocol Element Specification Sequence", "ReconstructionProtocolElementSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9934),
+          "Reconstruction Protocol Element Sequence", "ReconstructionProtocolElementSequence",  "SQ", "1" },    { Tag(0x0018, 0x9935),
+          "Storage Protocol Element Specification Sequence", "StorageProtocolElementSpecificationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9936),
+          "Storage Protocol Element Sequence", "StorageProtocolElementSequence",  "SQ", "1" },    { Tag(0x0018, 0x9937),
+          "Requested Series Description", "RequestedSeriesDescription",  "LO", "1" },    { Tag(0x0018, 0x9938),
+          "Source Acquisition Protocol Element Number", "SourceAcquisitionProtocolElementNumber",  "US", "1-n" },    { Tag(0x0018, 0x9939),
+          "Source Acquisition Beam Number", "SourceAcquisitionBeamNumber",  "US", "1-n" },    { Tag(0x0018, 0x993a),
+          "Source Reconstruction Protocol Element Number", "SourceReconstructionProtocolElementNumber",  "US", "1-n" },    { Tag(0x0018, 0x993b),
+          "Reconstruction Start Location Sequence", "ReconstructionStartLocationSequence",  "SQ", "1" },    { Tag(0x0018, 0x993c),
+          "Reconstruction End Location Sequence", "ReconstructionEndLocationSequence",  "SQ", "1" },    { Tag(0x0018, 0x993d),
+          "Reconstruction Algorithm Sequence", "ReconstructionAlgorithmSequence",  "SQ", "1" },    { Tag(0x0018, 0x993e),
+          "Reconstruction Target Center Location Sequence", "ReconstructionTargetCenterLocationSequence",  "SQ", "1" },    { Tag(0x0018, 0x9941),
+          "Image Filter Description", "ImageFilterDescription",  "UT", "1" },    { Tag(0x0018, 0x9942),
+          "CTDIvol Notification Trigger", "CTDIvolNotificationTrigger",  "FD", "1" },    { Tag(0x0018, 0x9943),
+          "DLP Notification Trigger", "DLPNotificationTrigger",  "FD", "1" },    { Tag(0x0018, 0x9944),
+          "Auto KVP Selection Type", "AutoKVPSelectionType",  "CS", "1" },    { Tag(0x0018, 0x9945),
+          "Auto KVP Upper Bound", "AutoKVPUpperBound",  "FD", "1" },    { Tag(0x0018, 0x9946),
+          "Auto KVP Lower Bound", "AutoKVPLowerBound",  "FD", "1" },    { Tag(0x0018, 0x9947),
+          "Protocol Defined Patient Position", "ProtocolDefinedPatientPosition",  "CS", "1" },    { Tag(0x0018, 0xa001),
           "Contributing Equipment Sequence", "ContributingEquipmentSequence",  "SQ", "1" },    { Tag(0x0018, 0xa002),
           "Contribution DateTime", "ContributionDateTime",  "DT", "1" },    { Tag(0x0018, 0xa003),
           "Contribution Description", "ContributionDescription",  "ST", "1" },    { Tag(0x0020, 0x000d),
@@ -9730,7 +9970,8 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Images in Series", "ImagesInSeries",  "IS", "1" },    { Tag(0x0020, 0x1004),
           "Acquisitions in Study", "AcquisitionsInStudy",  "IS", "1" },    { Tag(0x0020, 0x1005),
           "Images in Study", "ImagesInStudy",  "IS", "1" },    { Tag(0x0020, 0x1020),
-          "Reference", "Reference",  "LO", "1-n" },    { Tag(0x0020, 0x1040),
+          "Reference", "Reference",  "LO", "1-n" },    { Tag(0x0020, 0x103f),
+          "Target Position Reference Indicator", "TargetPositionReferenceIndicator",  "LO", "1" },    { Tag(0x0020, 0x1040),
           "Position Reference Indicator", "PositionReferenceIndicator",  "LO", "1" },    { Tag(0x0020, 0x1041),
           "Slice Location", "SliceLocation",  "DS", "1" },    { Tag(0x0020, 0x1070),
           "Other Study Numbers", "OtherStudyNumbers",  "IS", "1-n" },    { Tag(0x0020, 0x1200),
@@ -11226,7 +11467,8 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Graphic Coordinates Data Sequence", "GraphicCoordinatesDataSequence",  "SQ", "1" },    { Tag(0x0070, 0x031a),
           "Fiducial UID", "FiducialUID",  "UI", "1" },    { Tag(0x0070, 0x031c),
           "Fiducial Set Sequence", "FiducialSetSequence",  "SQ", "1" },    { Tag(0x0070, 0x031e),
-          "Fiducial Sequence", "FiducialSequence",  "SQ", "1" },    { Tag(0x0070, 0x0401),
+          "Fiducial Sequence", "FiducialSequence",  "SQ", "1" },    { Tag(0x0070, 0x031f),
+          "Fiducials Property Category Code Sequence", "FiducialsPropertyCategoryCodeSequence",  "SQ", "1" },    { Tag(0x0070, 0x0401),
           "Graphic Layer Recommended Display CIELab Value", "GraphicLayerRecommendedDisplayCIELabValue",  "US", "3" },    { Tag(0x0070, 0x0402),
           "Blending Sequence", "BlendingSequence",  "SQ", "1" },    { Tag(0x0070, 0x0403),
           "Relative Opacity", "RelativeOpacity",  "FL", "1" },    { Tag(0x0070, 0x0404),
@@ -11548,7 +11790,8 @@ std::map<std::string, odil::Tag> create_public_tags()
           "Constraint Value Sequence", "ConstraintValueSequence",  "SQ", "1" },    { Tag(0x0082, 0x0035),
           "Recommended Default Value Sequence", "RecommendedDefaultValueSequence",  "SQ", "1" },    { Tag(0x0082, 0x0036),
           "Constraint Violation Significance", "ConstraintViolationSignificance",  "CS", "1" },    { Tag(0x0082, 0x0037),
-          "Constraint Violation Condition", "ConstraintViolationCondition",  "UT", "1" },    { Tag(0x0088, 0x0130),
+          "Constraint Violation Condition", "ConstraintViolationCondition",  "UT", "1" },    { Tag(0x0082, 0x0038),
+          "Modifiable Constraint Flag", "ModifiableConstraintFlag",  "CS", "1" },    { Tag(0x0088, 0x0130),
           "Storage Media File-set ID", "StorageMediaFileSetID",  "SH", "1" },    { Tag(0x0088, 0x0140),
           "Storage Media File-set UID", "StorageMediaFileSetUID",  "UI", "1" },    { Tag(0x0088, 0x0200),
           "Icon Image Sequence", "IconImageSequence",  "SQ", "1" },    { Tag(0x0088, 0x0904),
@@ -12740,6 +12983,8 @@ UIDsDictionary create_uids_dictionary()
         { "1.2.840.10008.5.1.4.1.1.129", "Standalone PET Curve Storage (Retired)", "StandalonePETCurveStorage_Retired",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.1.130", "Enhanced PET Image Storage", "EnhancedPETImageStorage",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.1.131", "Basic Structured Display Storage", "BasicStructuredDisplayStorage",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.1.1.200.1", "CT Defined Procedure Protocol Storage", "CTDefinedProcedureProtocolStorage",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.1.1.200.2", "CT Performed Procedure Protocol Storage", "CTPerformedProcedureProtocolStorage",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.1.481.1", "RT Image Storage", "RTImageStorage",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.1.481.2", "RT Dose Storage", "RTDoseStorage",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.1.481.3", "RT Structure Set Storage", "RTStructureSetStorage",  "SOP Class" },
@@ -12770,6 +13015,9 @@ UIDsDictionary create_uids_dictionary()
         { "1.2.840.10008.5.1.4.1.2.4.2", "Composite Instance Root Retrieve - MOVE", "CompositeInstanceRootRetrieveMOVE",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.2.4.3", "Composite Instance Root Retrieve - GET", "CompositeInstanceRootRetrieveGET",  "SOP Class" },
         { "1.2.840.10008.5.1.4.1.2.5.3", "Composite Instance Retrieve Without Bulk Data - GET", "CompositeInstanceRetrieveWithoutBulkDataGET",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.20.1", "Defined Procedure Protocol Information Model - FIND", "DefinedProcedureProtocolInformationModelFIND",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.20.2", "Defined Procedure Protocol Information Model - MOVE", "DefinedProcedureProtocolInformationModelMOVE",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.20.3", "Defined Procedure Protocol Information Model - GET", "DefinedProcedureProtocolInformationModelGET",  "SOP Class" },
         { "1.2.840.10008.5.1.4.31", "Modality Worklist Information Model - FIND", "ModalityWorklistInformationModelFIND",  "SOP Class" },
         { "1.2.840.10008.5.1.4.32", "General Purpose Worklist Management Meta SOP Class (Retired)", "GeneralPurposeWorklistManagementMetaSOPClass_Retired",  "Meta SOP Class" },
         { "1.2.840.10008.5.1.4.32.1", "General Purpose Worklist Information Model - FIND (Retired)", "GeneralPurposeWorklistInformationModelFIND_Retired",  "SOP Class" },
@@ -12803,9 +13051,9 @@ UIDsDictionary create_uids_dictionary()
         { "1.2.840.10008.5.1.4.38.3", "Hanging Protocol Information Model - MOVE", "HangingProtocolInformationModelMOVE",  "SOP Class" },
         { "1.2.840.10008.5.1.4.38.4", "Hanging Protocol Information Model - GET", "HangingProtocolInformationModelGET",  "SOP Class" },
         { "1.2.840.10008.5.1.4.39.1", "Color Palette Storage", "ColorPaletteStorage",  "Transfer" },
-        { "1.2.840.10008.5.1.4.39.2", "Color Palette Information Model - FIND", "ColorPaletteInformationModelFIND",  "Query/Retrieve" },
-        { "1.2.840.10008.5.1.4.39.3", "Color Palette Information Model - MOVE", "ColorPaletteInformationModelMOVE",  "Query/Retrieve" },
-        { "1.2.840.10008.5.1.4.39.4", "Color Palette Information Model - GET", "ColorPaletteInformationModelGET",  "Query/Retrieve" },
+        { "1.2.840.10008.5.1.4.39.2", "Color Palette Query/Retrieve Information Model - FIND", "ColorPaletteQueryRetrieveInformationModelFIND",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.39.3", "Color Palette Query/Retrieve Information Model - MOVE", "ColorPaletteQueryRetrieveInformationModelMOVE",  "SOP Class" },
+        { "1.2.840.10008.5.1.4.39.4", "Color Palette Query/Retrieve Information Model - GET", "ColorPaletteQueryRetrieveInformationModelGET",  "SOP Class" },
         { "1.2.840.10008.5.1.4.41", "Product Characteristics Query SOP Class", "ProductCharacteristicsQuerySOPClass",  "SOP Class" },
         { "1.2.840.10008.5.1.4.42", "Substance Approval Query SOP Class", "SubstanceApprovalQuerySOPClass",  "SOP Class" },
         { "1.2.840.10008.5.1.4.43.1", "Generic Implant Template Storage", "GenericImplantTemplateStorage",  "SOP Class" },
diff --git a/src/odil/registry.h b/src/odil/registry.h
index f19064a..ff10bf3 100644
--- a/src/odil/registry.h
+++ b/src/odil/registry.h
@@ -156,6 +156,9 @@ Tag const MappingResourceName(0x0008, 0x0122);
 Tag const ContextGroupIdentificationSequence(0x0008, 0x0123);
 Tag const MappingResourceIdentificationSequence(0x0008, 0x0124);
 Tag const TimezoneOffsetFromUTC(0x0008, 0x0201);
+Tag const ResponsibleGroupCodeSequence(0x0008, 0x0220);
+Tag const EquipmentModality(0x0008, 0x0221);
+Tag const ManufacturerRelatedModelGroup(0x0008, 0x0222);
 Tag const PrivateDataElementCharacteristicsSequence(0x0008, 0x0300);
 Tag const PrivateGroupReference(0x0008, 0x0301);
 Tag const PrivateCreatorReference(0x0008, 0x0302);
@@ -164,6 +167,15 @@ Tag const NonidentifyingPrivateElements(0x0008, 0x0304);
 Tag const IdentifyingPrivateElements(0x0008, 0x0306);
 Tag const DeidentificationActionSequence(0x0008, 0x0305);
 Tag const DeidentificationAction(0x0008, 0x0307);
+Tag const PrivateDataElement(0x0008, 0x0308);
+Tag const PrivateDataElementValueMultiplicity(0x0008, 0x0309);
+Tag const PrivateDataElementValueRepresentation(0x0008, 0x030a);
+Tag const PrivateDataElementNumberOfItems(0x0008, 0x030b);
+Tag const PrivateDataElementName(0x0008, 0x030c);
+Tag const PrivateDataElementKeyword(0x0008, 0x030d);
+Tag const PrivateDataElementDescription(0x0008, 0x030e);
+Tag const PrivateDataElementEncoding(0x0008, 0x030f);
+Tag const PrivateDataElementDefinitionSequence(0x0008, 0x0310);
 Tag const NetworkID(0x0008, 0x1000);
 Tag const StationName(0x0008, 0x1010);
 Tag const StudyDescription(0x0008, 0x1030);
@@ -308,6 +320,9 @@ Tag const PatientBirthName(0x0010, 0x1005);
 Tag const PatientAge(0x0010, 0x1010);
 Tag const PatientSize(0x0010, 0x1020);
 Tag const PatientSizeCodeSequence(0x0010, 0x1021);
+Tag const PatientBodyMassIndex(0x0010, 0x1022);
+Tag const MeasuredAPDimension(0x0010, 0x1023);
+Tag const MeasuredLateralDimension(0x0010, 0x1024);
 Tag const PatientWeight(0x0010, 0x1030);
 Tag const PatientAddress(0x0010, 0x1040);
 Tag const InsurancePlanIdentification(0x0010, 0x1050);
@@ -363,6 +378,8 @@ Tag const ClinicalTrialProtocolEthicsCommitteeApprovalNumber(0x0012, 0x0082);
 Tag const ConsentForClinicalTrialUseSequence(0x0012, 0x0083);
 Tag const DistributionType(0x0012, 0x0084);
 Tag const ConsentForDistributionFlag(0x0012, 0x0085);
+Tag const EthicsCommitteeApprovalEffectivenessStartDate(0x0012, 0x0086);
+Tag const EthicsCommitteeApprovalEffectivenessEndDate(0x0012, 0x0087);
 Tag const CADFileFormat(0x0014, 0x0023);
 Tag const ComponentReferenceSystem(0x0014, 0x0024);
 Tag const ComponentManufacturingProcedure(0x0014, 0x0025);
@@ -615,6 +632,8 @@ Tag const GeneratorID(0x0018, 0x1005);
 Tag const GridID(0x0018, 0x1006);
 Tag const CassetteID(0x0018, 0x1007);
 Tag const GantryID(0x0018, 0x1008);
+Tag const UniqueDeviceIdentifier(0x0018, 0x1009);
+Tag const UDISequence(0x0018, 0x100a);
 Tag const SecondaryCaptureDeviceID(0x0018, 0x1010);
 Tag const HardcopyCreationDeviceID(0x0018, 0x1011);
 Tag const DateOfSecondaryCapture(0x0018, 0x1012);
@@ -1294,6 +1313,65 @@ Tag const TransducerGeometryCodeSequence(0x0018, 0x980d);
 Tag const TransducerBeamSteeringCodeSequence(0x0018, 0x980e);
 Tag const TransducerApplicationCodeSequence(0x0018, 0x980f);
 Tag const ZeroVelocityPixelValue(0x0018, 0x9810);
+Tag const ReferenceLocationLabel(0x0018, 0x9900);
+Tag const ReferenceLocationDescription(0x0018, 0x9901);
+Tag const ReferenceBasisCodeSequence(0x0018, 0x9902);
+Tag const ReferenceGeometryCodeSequence(0x0018, 0x9903);
+Tag const OffsetDistance(0x0018, 0x9904);
+Tag const OffsetDirection(0x0018, 0x9905);
+Tag const PotentialScheduledProtocolCodeSequence(0x0018, 0x9906);
+Tag const PotentialRequestedProcedureCodeSequence(0x0018, 0x9907);
+Tag const PotentialReasonsForProcedure(0x0018, 0x9908);
+Tag const PotentialReasonsForProcedureCodeSequence(0x0018, 0x9909);
+Tag const PotentialDiagnosticTasks(0x0018, 0x990a);
+Tag const ContraindicationsCodeSequence(0x0018, 0x990b);
+Tag const ReferencedDefinedProtocolSequence(0x0018, 0x990c);
+Tag const ReferencedPerformedProtocolSequence(0x0018, 0x990d);
+Tag const PredecessorProtocolSequence(0x0018, 0x990e);
+Tag const ProtocolPlanningInformation(0x0018, 0x990f);
+Tag const ProtocolDesignRationale(0x0018, 0x9910);
+Tag const PatientSpecificationSequence(0x0018, 0x9911);
+Tag const ModelSpecificationSequence(0x0018, 0x9912);
+Tag const ParametersSpecificationSequence(0x0018, 0x9913);
+Tag const InstructionSequence(0x0018, 0x9914);
+Tag const InstructionIndex(0x0018, 0x9915);
+Tag const InstructionText(0x0018, 0x9916);
+Tag const InstructionDescription(0x0018, 0x9917);
+Tag const InstructionPerformedFlag(0x0018, 0x9918);
+Tag const InstructionPerformedDateTime(0x0018, 0x9919);
+Tag const InstructionPerformanceComment(0x0018, 0x991a);
+Tag const PatientPositioningInstructionSequence(0x0018, 0x991b);
+Tag const PositioningMethodCodeSequence(0x0018, 0x991c);
+Tag const PositioningLandmarkSequence(0x0018, 0x991d);
+Tag const TargetFrameOfReferenceUID(0x0018, 0x991e);
+Tag const AcquisitionProtocolElementSpecificationSequence(0x0018, 0x991f);
+Tag const AcquisitionProtocolElementSequence(0x0018, 0x9920);
+Tag const ProtocolElementNumber(0x0018, 0x9921);
+Tag const ProtocolElementName(0x0018, 0x9922);
+Tag const ProtocolElementCharacteristicsSummary(0x0018, 0x9923);
+Tag const ProtocolElementPurpose(0x0018, 0x9924);
+Tag const AcquisitionMotion(0x0018, 0x9930);
+Tag const AcquisitionStartLocationSequence(0x0018, 0x9931);
+Tag const AcquisitionEndLocationSequence(0x0018, 0x9932);
+Tag const ReconstructionProtocolElementSpecificationSequence(0x0018, 0x9933);
+Tag const ReconstructionProtocolElementSequence(0x0018, 0x9934);
+Tag const StorageProtocolElementSpecificationSequence(0x0018, 0x9935);
+Tag const StorageProtocolElementSequence(0x0018, 0x9936);
+Tag const RequestedSeriesDescription(0x0018, 0x9937);
+Tag const SourceAcquisitionProtocolElementNumber(0x0018, 0x9938);
+Tag const SourceAcquisitionBeamNumber(0x0018, 0x9939);
+Tag const SourceReconstructionProtocolElementNumber(0x0018, 0x993a);
+Tag const ReconstructionStartLocationSequence(0x0018, 0x993b);
+Tag const ReconstructionEndLocationSequence(0x0018, 0x993c);
+Tag const ReconstructionAlgorithmSequence(0x0018, 0x993d);
+Tag const ReconstructionTargetCenterLocationSequence(0x0018, 0x993e);
+Tag const ImageFilterDescription(0x0018, 0x9941);
+Tag const CTDIvolNotificationTrigger(0x0018, 0x9942);
+Tag const DLPNotificationTrigger(0x0018, 0x9943);
+Tag const AutoKVPSelectionType(0x0018, 0x9944);
+Tag const AutoKVPUpperBound(0x0018, 0x9945);
+Tag const AutoKVPLowerBound(0x0018, 0x9946);
+Tag const ProtocolDefinedPatientPosition(0x0018, 0x9947);
 Tag const ContributingEquipmentSequence(0x0018, 0xa001);
 Tag const ContributionDateTime(0x0018, 0xa002);
 Tag const ContributionDescription(0x0018, 0xa003);
@@ -1336,6 +1414,7 @@ Tag const ImagesInSeries(0x0020, 0x1003);
 Tag const AcquisitionsInStudy(0x0020, 0x1004);
 Tag const ImagesInStudy(0x0020, 0x1005);
 Tag const Reference(0x0020, 0x1020);
+Tag const TargetPositionReferenceIndicator(0x0020, 0x103f);
 Tag const PositionReferenceIndicator(0x0020, 0x1040);
 Tag const SliceLocation(0x0020, 0x1041);
 Tag const OtherStudyNumbers(0x0020, 0x1070);
@@ -2842,6 +2921,7 @@ Tag const GraphicCoordinatesDataSequence(0x0070, 0x0318);
 Tag const FiducialUID(0x0070, 0x031a);
 Tag const FiducialSetSequence(0x0070, 0x031c);
 Tag const FiducialSequence(0x0070, 0x031e);
+Tag const FiducialsPropertyCategoryCodeSequence(0x0070, 0x031f);
 Tag const GraphicLayerRecommendedDisplayCIELabValue(0x0070, 0x0401);
 Tag const BlendingSequence(0x0070, 0x0402);
 Tag const RelativeOpacity(0x0070, 0x0403);
@@ -3164,6 +3244,7 @@ Tag const ConstraintValueSequence(0x0082, 0x0034);
 Tag const RecommendedDefaultValueSequence(0x0082, 0x0035);
 Tag const ConstraintViolationSignificance(0x0082, 0x0036);
 Tag const ConstraintViolationCondition(0x0082, 0x0037);
+Tag const ModifiableConstraintFlag(0x0082, 0x0038);
 Tag const StorageMediaFileSetID(0x0088, 0x0130);
 Tag const StorageMediaFileSetUID(0x0088, 0x0140);
 Tag const IconImageSequence(0x0088, 0x0200);
@@ -4409,6 +4490,8 @@ std::string const LegacyConvertedEnhancedPETImageStorage("1.2.840.10008.5.1.4.1.
 std::string const StandalonePETCurveStorage_Retired("1.2.840.10008.5.1.4.1.1.129");
 std::string const EnhancedPETImageStorage("1.2.840.10008.5.1.4.1.1.130");
 std::string const BasicStructuredDisplayStorage("1.2.840.10008.5.1.4.1.1.131");
+std::string const CTDefinedProcedureProtocolStorage("1.2.840.10008.5.1.4.1.1.200.1");
+std::string const CTPerformedProcedureProtocolStorage("1.2.840.10008.5.1.4.1.1.200.2");
 std::string const RTImageStorage("1.2.840.10008.5.1.4.1.1.481.1");
 std::string const RTDoseStorage("1.2.840.10008.5.1.4.1.1.481.2");
 std::string const RTStructureSetStorage("1.2.840.10008.5.1.4.1.1.481.3");
@@ -4439,6 +4522,9 @@ std::string const PatientStudyOnlyQueryRetrieveInformationModelGET_Retired("1.2.
 std::string const CompositeInstanceRootRetrieveMOVE("1.2.840.10008.5.1.4.1.2.4.2");
 std::string const CompositeInstanceRootRetrieveGET("1.2.840.10008.5.1.4.1.2.4.3");
 std::string const CompositeInstanceRetrieveWithoutBulkDataGET("1.2.840.10008.5.1.4.1.2.5.3");
+std::string const DefinedProcedureProtocolInformationModelFIND("1.2.840.10008.5.1.4.20.1");
+std::string const DefinedProcedureProtocolInformationModelMOVE("1.2.840.10008.5.1.4.20.2");
+std::string const DefinedProcedureProtocolInformationModelGET("1.2.840.10008.5.1.4.20.3");
 std::string const ModalityWorklistInformationModelFIND("1.2.840.10008.5.1.4.31");
 std::string const GeneralPurposeWorklistManagementMetaSOPClass_Retired("1.2.840.10008.5.1.4.32");
 std::string const GeneralPurposeWorklistInformationModelFIND_Retired("1.2.840.10008.5.1.4.32.1");
@@ -4472,9 +4558,9 @@ std::string const HangingProtocolInformationModelFIND("1.2.840.10008.5.1.4.38.2"
 std::string const HangingProtocolInformationModelMOVE("1.2.840.10008.5.1.4.38.3");
 std::string const HangingProtocolInformationModelGET("1.2.840.10008.5.1.4.38.4");
 std::string const ColorPaletteStorage("1.2.840.10008.5.1.4.39.1");
-std::string const ColorPaletteInformationModelFIND("1.2.840.10008.5.1.4.39.2");
-std::string const ColorPaletteInformationModelMOVE("1.2.840.10008.5.1.4.39.3");
-std::string const ColorPaletteInformationModelGET("1.2.840.10008.5.1.4.39.4");
+std::string const ColorPaletteQueryRetrieveInformationModelFIND("1.2.840.10008.5.1.4.39.2");
+std::string const ColorPaletteQueryRetrieveInformationModelMOVE("1.2.840.10008.5.1.4.39.3");
+std::string const ColorPaletteQueryRetrieveInformationModelGET("1.2.840.10008.5.1.4.39.4");
 std::string const ProductCharacteristicsQuerySOPClass("1.2.840.10008.5.1.4.41");
 std::string const SubstanceApprovalQuerySOPClass("1.2.840.10008.5.1.4.42");
 std::string const GenericImplantTemplateStorage("1.2.840.10008.5.1.4.43.1");
diff --git a/tests/code/AssociationParameters.cpp b/tests/code/AssociationParameters.cpp
index d2ffd2b..73f11d0 100644
--- a/tests/code/AssociationParameters.cpp
+++ b/tests/code/AssociationParameters.cpp
@@ -18,6 +18,9 @@ BOOST_AUTO_TEST_CASE(Constructor)
     BOOST_REQUIRE(parameters.get_user_identity().secondary_field.empty());
 
     BOOST_REQUIRE_EQUAL(parameters.get_maximum_length(), 16384);
+
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_invoked(), 1);
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_performed(), 1);
 }
 
 BOOST_AUTO_TEST_CASE(CalledAETITLE)
@@ -164,6 +167,20 @@ BOOST_AUTO_TEST_CASE(MaximumLength)
     BOOST_REQUIRE_EQUAL(parameters.get_maximum_length(), 0x12345678);
 }
 
+BOOST_AUTO_TEST_CASE(MaximumNumberOperationsInvoked)
+{
+    odil::AssociationParameters parameters;
+    parameters.set_maximum_number_operations_invoked(12);
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_invoked(), 12);
+}
+
+BOOST_AUTO_TEST_CASE(MaximumNumberOperationsPerformed)
+{
+    odil::AssociationParameters parameters;
+    parameters.set_maximum_number_operations_performed(12);
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_performed(), 12);
+}
+
 BOOST_AUTO_TEST_CASE(ChainedSetters)
 {
     odil::AssociationParameters parameters;
@@ -172,7 +189,9 @@ BOOST_AUTO_TEST_CASE(ChainedSetters)
         .set_calling_ae_title("calling")
         .set_presentation_contexts({ { 1, "abstract", { "transfer" }, true, true } })
         .set_user_identity_to_username_and_password("foo", "bar")
-        .set_maximum_length(0x12345678);
+        .set_maximum_length(0x12345678)
+        .set_maximum_number_operations_invoked(12)
+        .set_maximum_number_operations_performed(34);
 
     BOOST_REQUIRE_EQUAL(parameters.get_called_ae_title(), "called");
     BOOST_REQUIRE_EQUAL(parameters.get_calling_ae_title(), "calling");
@@ -185,4 +204,7 @@ BOOST_AUTO_TEST_CASE(ChainedSetters)
     BOOST_REQUIRE_EQUAL(parameters.get_user_identity().secondary_field, "bar");
 
     BOOST_REQUIRE_EQUAL(parameters.get_maximum_length(), 0x12345678);
+
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_invoked(), 12);
+    BOOST_REQUIRE_EQUAL(parameters.get_maximum_number_operations_performed(), 34);
 }
diff --git a/tests/code/dul/Transport.cpp b/tests/code/dul/Transport.cpp
index fd50fea..338be12 100644
--- a/tests/code/dul/Transport.cpp
+++ b/tests/code/dul/Transport.cpp
@@ -41,5 +41,4 @@ BOOST_AUTO_TEST_CASE(NotConnected)
 
     BOOST_REQUIRE_THROW(transport.write("..."), odil::Exception);
     BOOST_REQUIRE_THROW(transport.read(1), odil::Exception);
-    BOOST_REQUIRE_THROW(transport.close(), odil::Exception);
 }
diff --git a/tests/code/pdu/AsynchronousOperationsWindow.cpp b/tests/code/pdu/AsynchronousOperationsWindow.cpp
new file mode 100644
index 0000000..2160969
--- /dev/null
+++ b/tests/code/pdu/AsynchronousOperationsWindow.cpp
@@ -0,0 +1,59 @@
+#define BOOST_TEST_MODULE AsynchronousOperationsWindow
+#include <boost/test/unit_test.hpp>
+
+#include <sstream>
+#include <string>
+
+#include "odil/Exception.h"
+#include "odil/pdu/AsynchronousOperationsWindow.h"
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+    odil::pdu::AsynchronousOperationsWindow const window(123, 456);
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_invoked(), 123);
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_performed(), 456);
+}
+
+BOOST_AUTO_TEST_CASE(FromStream)
+{
+    std::string const data(
+        "\x53\x00\x00\x04"
+        "\x12\x34\x56\x78",
+        8
+    );
+    std::istringstream stream(data);
+
+    odil::pdu::AsynchronousOperationsWindow const window(stream);
+
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_invoked(), 0x1234);
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_performed(), 0x5678);
+}
+
+BOOST_AUTO_TEST_CASE(MaximumNumberOperationsInvoked)
+{
+    odil::pdu::AsynchronousOperationsWindow window(0, 0);
+    window.set_maximum_number_operations_invoked(123);
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_invoked(), 123);
+}
+
+BOOST_AUTO_TEST_CASE(MaximumNumberOperationsPerformed)
+{
+    odil::pdu::AsynchronousOperationsWindow window(0, 0);
+    window.set_maximum_number_operations_performed(123);
+    BOOST_REQUIRE_EQUAL(window.get_maximum_number_operations_performed(), 123);
+}
+
+BOOST_AUTO_TEST_CASE(Write)
+{
+    odil::pdu::AsynchronousOperationsWindow const window(0x1234, 0x5678);
+    std::ostringstream data;
+    data << window;
+
+    std::string const expected(
+        "\x53\x00\x00\x04"
+        "\x12\x34\x56\x78",
+        8
+    );
+
+    BOOST_REQUIRE_EQUAL(data.str(), expected);
+}
diff --git a/tests/code/pdu/SOPClassCommonExtendedNegotiation.cpp b/tests/code/pdu/SOPClassCommonExtendedNegotiation.cpp
new file mode 100644
index 0000000..b92395e
--- /dev/null
+++ b/tests/code/pdu/SOPClassCommonExtendedNegotiation.cpp
@@ -0,0 +1,87 @@
+#define BOOST_TEST_MODULE SOPClassCommonExtendedNegotiation
+#include <boost/test/unit_test.hpp>
+
+#include <sstream>
+#include <string>
+
+#include "odil/Exception.h"
+#include "odil/pdu/SOPClassCommonExtendedNegotiation.h"
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+    odil::pdu::SOPClassCommonExtendedNegotiation const item(
+        "sop_class", "service_class", {"foo", "bar"});
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "sop_class");
+    BOOST_REQUIRE_EQUAL(item.get_service_class_uid(), "service_class");
+    BOOST_REQUIRE(
+        item.get_related_general_sop_class_uids() ==
+            std::vector<std::string>({"foo", "bar"}));
+}
+
+BOOST_AUTO_TEST_CASE(FromStream)
+{
+    std::string const data(
+        "\x57\x00\x00\x26"
+        "\x00\x09" "sop_class"
+        "\x00\x0d" "service_class"
+        "\x00\x0a"
+            "\x00\x03" "foo"
+            "\x00\x03" "bar",
+        42
+    );
+    std::istringstream stream(data);
+
+    odil::pdu::SOPClassCommonExtendedNegotiation const item(stream);
+
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "sop_class");
+    BOOST_REQUIRE_EQUAL(item.get_service_class_uid(), "service_class");
+    BOOST_REQUIRE(
+        item.get_related_general_sop_class_uids() ==
+            std::vector<std::string>({"foo", "bar"}));
+}
+
+BOOST_AUTO_TEST_CASE(SOPClassUID)
+{
+    odil::pdu::SOPClassCommonExtendedNegotiation item(
+        "sop_class", "service_class", {"foo", "bar"});
+    item.set_sop_class_uid("bar");
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "bar");
+}
+
+BOOST_AUTO_TEST_CASE(ServiceClassUID)
+{
+    odil::pdu::SOPClassCommonExtendedNegotiation item(
+        "sop_class", "service_class", {"foo", "bar"});
+    item.set_service_class_uid("bar");
+    BOOST_REQUIRE_EQUAL(item.get_service_class_uid(), "bar");
+}
+
+BOOST_AUTO_TEST_CASE(RelatedClasses)
+{
+    odil::pdu::SOPClassCommonExtendedNegotiation item(
+        "sop_class", "service_class", {"foo", "bar"});
+    item.set_related_general_sop_class_uids({"plip", "plop", "plup"});
+    BOOST_REQUIRE(
+        item.get_related_general_sop_class_uids() ==
+            std::vector<std::string>({"plip", "plop", "plup"}));
+}
+
+BOOST_AUTO_TEST_CASE(Write)
+{
+    odil::pdu::SOPClassCommonExtendedNegotiation const item(
+        "sop_class", "service_class", {"foo", "bar"});
+    std::ostringstream data;
+    data << item;
+
+    std::string const expected(
+        "\x57\x00\x00\x26"
+        "\x00\x09" "sop_class"
+        "\x00\x0d" "service_class"
+        "\x00\x0a"
+            "\x00\x03" "foo"
+            "\x00\x03" "bar",
+        42
+    );
+
+    BOOST_REQUIRE_EQUAL(data.str(), expected);
+}
diff --git a/tests/code/pdu/SOPClassExtendedNegotiation.cpp b/tests/code/pdu/SOPClassExtendedNegotiation.cpp
new file mode 100644
index 0000000..aaf61a5
--- /dev/null
+++ b/tests/code/pdu/SOPClassExtendedNegotiation.cpp
@@ -0,0 +1,71 @@
+#define BOOST_TEST_MODULE SOPClassExtendedNegotiation
+#include <boost/test/unit_test.hpp>
+
+#include <sstream>
+#include <string>
+
+#include "odil/Exception.h"
+#include "odil/pdu/SOPClassExtendedNegotiation.h"
+
+BOOST_AUTO_TEST_CASE(Constructor)
+{
+    odil::pdu::SOPClassExtendedNegotiation const item(
+        "sop_class", {'\x01', '\x02', '\x03', '\x04'});
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "sop_class");
+    BOOST_REQUIRE(
+        item.get_service_class_application_information() ==
+            std::vector<uint8_t>({'\x01', '\x02', '\x03', '\x04'}));
+}
+
+BOOST_AUTO_TEST_CASE(FromStream)
+{
+    std::string const data(
+        "\x56\x00\x00\x0f"
+        "\x00\x09" "sop_class"
+        "\x01\x02\x03\x04",
+        19
+    );
+    std::istringstream stream(data);
+
+    odil::pdu::SOPClassExtendedNegotiation const item(stream);
+
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "sop_class");
+    BOOST_REQUIRE(
+        item.get_service_class_application_information() ==
+            std::vector<uint8_t>({'\x01', '\x02', '\x03', '\x04'}));
+}
+
+BOOST_AUTO_TEST_CASE(SOPClassUID)
+{
+    odil::pdu::SOPClassExtendedNegotiation item(
+        "sop_class", {'\x01', '\x02', '\x03', '\x04'});
+    item.set_sop_class_uid("bar");
+    BOOST_REQUIRE_EQUAL(item.get_sop_class_uid(), "bar");
+}
+
+BOOST_AUTO_TEST_CASE(ServiceClassApplicationInformation)
+{
+    odil::pdu::SOPClassExtendedNegotiation item(
+        "sop_class", {'\x01', '\x02', '\x03', '\x04'});
+    item.set_service_class_application_information({'\x05', '\x06'});
+    BOOST_REQUIRE(
+        item.get_service_class_application_information() ==
+            std::vector<uint8_t>({'\x05', '\x06'}));
+}
+
+BOOST_AUTO_TEST_CASE(Write)
+{
+    odil::pdu::SOPClassExtendedNegotiation const item(
+        "sop_class", {'\x01', '\x02', '\x03', '\x04'});
+    std::ostringstream data;
+    data << item;
+
+    std::string const expected(
+        "\x56\x00\x00\x0f"
+        "\x00\x09" "sop_class"
+        "\x01\x02\x03\x04",
+        19
+    );
+
+    BOOST_REQUIRE_EQUAL(data.str(), expected);
+}
diff --git a/wrappers/json_converter.cpp b/wrappers/json_converter.cpp
index 8503719..6908da1 100644
--- a/wrappers/json_converter.cpp
+++ b/wrappers/json_converter.cpp
@@ -6,6 +6,8 @@
  * for details.
  ************************************************************************/
 
+#include <memory>
+
 #include <boost/python.hpp>
 
 #include <json/json.h>
@@ -20,14 +22,14 @@ std::string as_json(odil::DataSet const & data_set, bool pretty_print)
 {
     auto const json = odil::as_json(data_set);
 
-    Json::Writer * writer = NULL;
+    std::shared_ptr<Json::Writer> writer;
     if(pretty_print)
     {
-        writer = new Json::StyledWriter();
+        writer = std::make_shared<Json::StyledWriter>();
     }
     else
     {
-        writer = new Json::FastWriter();
+        writer = std::make_shared<Json::FastWriter>();
     }
 
     auto const string = writer->write(json);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/odil.git



More information about the debian-med-commit mailing list