DYT/Tool/3rdParty_x64/include/dcmtk/dcmsr/dsrdocst.h
2024-11-22 23:19:31 +08:00

722 lines
40 KiB
C++

/*
*
* Copyright (C) 2000-2016, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: dcmsr
*
* Author: Joerg Riesmeier
*
* Purpose:
* classes: DSRDocumentSubTree
*
*/
#ifndef DSRDOCST_H
#define DSRDOCST_H
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmsr/dsrtree.h"
#include "dcmtk/dcmsr/dsrdoctn.h"
#include "dcmtk/dcmsr/dsrdncsr.h"
#include "dcmtk/dcmsr/dsrcitem.h"
#include "dcmtk/ofstd/ofmem.h"
/*------------------------*
* forward declarations *
*------------------------*/
class DSRIODConstraintChecker;
class DSRSubTemplate;
/*-------------------*
* type definition *
*-------------------*/
typedef OFshared_ptr<DSRSubTemplate> DSRSharedSubTemplate;
/*--------------------------*
* template instantiation *
*--------------------------*/
// the following is required in order to help older Clang compilers,
// e.g. Clang 3.0 and 3.1 on Mac OS X when building with shared libs
#if defined(__clang__)
template class DSRTree<DSRDocumentTreeNode>;
#endif
/*---------------------*
* class declaration *
*---------------------*/
/** Class managing a SR document subtree.
* A subtree represents an extract of an SR document tree. Compared to the "SR Document
* Content Tree" that is defined in the DICOM standard, there are almost no restrictions
* regarding the value and relationship types. It is also possible to have multiple nodes
* on the top-level, i.e. no dedicated root, or to use "unknown" relationship types.
*/
class DCMTK_DCMSR_EXPORT DSRDocumentSubTree
: public DSRTree<DSRDocumentTreeNode>
{
public:
/** default constructor
*/
DSRDocumentSubTree();
/** copy constructor.
* Please note that the internal cursor is not copied but reset, i.e. set to the root
* node. Also the IOD constraint checker is not copied by this class but recreated
* by the derived class DSRDocumentTree (based on the corresponding document type).
* This constructor also updates any by-reference relationships, i.e. translates the
* references from the source 'tree' (based on the position string) to the IDs of the
* newly created nodes.
** @param tree subtree to be copied
*/
DSRDocumentSubTree(const DSRDocumentSubTree &tree);
/** destructor
*/
virtual ~DSRDocumentSubTree();
/** assignment operator.
* Please note that internally the copy constructor is used, so the same comments apply.
** @param tree subtree to be copied
** @return reference to this subtree after copying
*/
DSRDocumentSubTree &operator=(DSRDocumentSubTree tree);
/** clone this subtree.
* Internally, the copy constructor is used, so the corresponding comments apply.
** @return copy of this subtree
*/
virtual DSRDocumentSubTree *clone() const;
/** clear internal member variables
*/
virtual void clear();
/** check whether the current internal state is valid.
* A subtree is valid if it is not empty.
** @return OFTrue if valid, OFFalse otherwise
*/
virtual OFBool isValid() const;
/** check whether the internal cursor, which points to the current content item, is valid
** @return OFTrue if cursor is valid, OFFalse otherwise
*/
virtual OFBool isCursorValid() const;
/** check whether this subtree is a valid document tree.
* In order to be a valid document tree, there should be a single root node only, with
* the value type "CONTAINER", and the internal relationship type of this node should be
* DSRTypes::RT_isRoot.
** @param defaultRelType default relationship type that is used if the one of the
* top-level node (root node) is "unknown"
** @return OFTrue if subtree is a valid document tree, OFFalse otherwise
*/
virtual OFBool isValidDocumentTree(const E_RelationshipType defaultRelType = RT_unknown) const;
/** check whether this subtree is an expanded document tree.
* Expanded means that no instances of DSRIncludedTemplateTreeNode exist in the document
* tree, i.e. no templates were included or all of them were replaced by their content
* (subtree).
** @return OFTrue if subtree is an expanded document tree, OFFalse otherwise
*/
virtual OFBool isExpandedDocumentTree() const;
/** check whether template identification is set
** @return OFTrue if template identification is set, OFFalse otherwise
*/
virtual OFBool hasTemplateIdentification() const;
/** check whether template identification is possible at all.
* According to the DICOM standard, it can be used if "the template consists of a single
* CONTAINER with nested content, and it is the outermost invocation of a set of nested
* templates that start with the same CONTAINER."
* With other words, the tree should have a single root node with value type "CONTAINER".
** @return OFTrue if template identification is possible, OFFalse otherwise
*/
virtual OFBool canUseTemplateIdentification() const;
/** print current SR document tree to specified output stream
** @param stream output stream
* @param flags optional flag used to customize the output (see DSRTypes::PF_xxx)
* @param posCounter optional pointer to position counter that should be used to
* initialize the counter for line indentation or numbering of
* nested content items
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition print(STD_NAMESPACE ostream &stream,
const size_t flags = 0,
const DSRPositionCounter *posCounter = NULL);
/** write current SR document tree in XML format
** @param stream output stream to which the XML document is written
* @param flags optional flag used to customize the output (see DSRTypes::XF_xxx)
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition writeXML(STD_NAMESPACE ostream &stream,
const size_t flags = 0);
/** get reference to current content item.
* This mechanism allows to access all content items without using pointers.
** @return reference to current content item (might be invalid)
*/
virtual DSRContentItem &getCurrentContentItem();
/** get read-only access to current node (content item)
** @return pointer to current node (might be NULL)
*/
virtual const DSRDocumentTreeNode *getCurrentNode() const;
/** get a cursor to the root node of this document tree.
* This cursor can be used to iterate over the nodes of the document tree without
* changing the internal cursor. Please note that the cursor might become invalid,
* e.g. by pointing to a non-existing node if the content of the document tree is
* modified after the cursor has been retrieved.
* Included sub-templates are not supported by this type of cursor, i.e. the subtree
* that is managed by an instance of DSRIncludedTemplateTreeNode is not iterated.
** @param cursor reference to variable where the cursor is stored
** @return OFTrue is the returned 'cursor' is valid, OFFalse otherwise
*/
virtual OFBool getCursorToRootNode(DSRDocumentTreeNodeCursor &cursor) const;
/** get a cursor to the root node of this document tree.
* This cursor can be used to iterate over the nodes of the document tree without
* changing the internal cursor. Please note that the cursor might become invalid,
* e.g. by pointing to a non-existing node if the content of the document tree is
* modified after the cursor has been retrieved.
* This type of cursor also supports included sub-templates, i.e. the subtree that
* is managed by an instance of DSRIncludedTemplateTreeNode is also iterated.
** @param cursor reference to variable where the cursor is stored
** @return OFTrue is the returned 'cursor' is valid, OFFalse otherwise
*/
virtual OFBool getCursorToRootNode(DSRIncludedTemplateNodeCursor &cursor) const;
/** count number of content items (nodes) in the document tree.
* This method iterates over all nodes that are stored in the document tree.
* By default, included sub-templates are counted as a single node (see options).
** @param searchIntoSubTemplates optional flag indicating whether to also
* count the content of included sub-templates
* (i.e.\ the nodes of the managed subtrees)
* @param countIncludedTemplateNodes optional flag indicating whether to count
* the DSRIncludedTemplateTreeNode instances
* as nodes. See includeTemplate() for details.
** @return number of nodes, 0 if document tree is empty
*/
size_t countNodes(const OFBool searchIntoSubTemplates = OFFalse,
const OFBool countIncludedTemplateNodes = OFTrue) const;
/** set internal cursor to a named node.
* If more than one node exists with the given concept name, the first one will
* be selected. Use gotoNextNamedNode() in order to go to the next matching node.
** @param conceptName concept name of the node to be searched for
* @param startFromRoot flag indicating whether to start from the root node
* or the current one
* @param searchIntoSub flag indicating whether to search into sub-trees
* ("deep search") or on the current level only
** @return ID of the new current node if successful, 0 otherwise
*/
virtual size_t gotoNamedNode(const DSRCodedEntryValue &conceptName,
const OFBool startFromRoot = OFTrue,
const OFBool searchIntoSub = OFTrue);
/** set internal cursor to a named node (starting from the first children of the
* current node).
* If more than one node exists with the given concept name, the first one will
* be selected. Use gotoNextNamedNode() in order to go to the next matching node.
** @param conceptName concept name of the node to be searched for
* @param searchIntoSub flag indicating whether to search into sub-trees
* ("deep search") or on the current level only
** @return ID of the new current node if successful, 0 otherwise
*/
virtual size_t gotoNamedChildNode(const DSRCodedEntryValue &conceptName,
const OFBool searchIntoSub = OFTrue);
/** set internal cursor to the next named node.
* Starts from "next" node, i.e. either the first children of the current node
* or the first sibling following the current node.
** @param conceptName concept name of the node to be searched for
* @param searchIntoSub flag indicating whether to search into sub-trees
* ("deep search") or on the current level only
** @return ID of the new current node if successful, 0 otherwise
*/
virtual size_t gotoNextNamedNode(const DSRCodedEntryValue &conceptName,
const OFBool searchIntoSub = OFTrue);
/** set internal cursor to an annotated node.
* If more than one node exists with the given annotation text, the first one will
* be selected. Use gotoNextAnnotatedNode() in order to go to the next matching
* node. In contrast to gotoNamedNode(), a "deep search" is always performed.
** @param annotationText annotation text of the node to be searched for
* @param startFromRoot flag indicating whether to start from the root node
* or the current one
** @return ID of the new current node if successful, 0 otherwise
*/
virtual size_t gotoAnnotatedNode(const OFString &annotationText,
const OFBool startFromRoot = OFTrue);
/** set internal cursor to the next annotated node.
* Starts from "next" node, i.e. either the first children of the current node
* or the first sibling following the current node.
** @param annotationText annotation text of the node to be searched for
** @return ID of the new current node if successful, 0 otherwise
*/
virtual size_t gotoNextAnnotatedNode(const OFString &annotationText);
/** check whether specified content item can be added to the current one.
* This method can be used to decide which type of content items can be added prior
* to really doing so. Please note that only by-value relationships are supported.
* Always returns true if no constraint checker is available but 'relationshipType'
* and 'valueType' have valid values.
** @param relationshipType relationship type of node to be checked with regard to
* the current one
* @param valueType value type of node to be checked
* @param addMode flag specifying at which position the new node would
* be added (e.g. after or below the current node)
** @return OFTrue if specified node can be added, OFFalse otherwise
*/
virtual OFBool canAddContentItem(const E_RelationshipType relationshipType,
const E_ValueType valueType,
const E_AddMode addMode = AM_afterCurrent) const;
/** check whether specified by-reference relationship can be added to the current
* content item.
* Always returns true if no constraint checker is available but 'relationshipType' and
* 'targetValueType' have valid values. The value type DSRTypes::VT_includedTemplate is
* never allowed for the target content item.
** @param relationshipType type of relationship between current and target node
* @param targetValueType value type of the referenced node (target content item)
** @return OFTrue if specified by-reference relationship can be added, OFFalse otherwise
*/
virtual OFBool canAddByReferenceRelationship(const E_RelationshipType relationshipType,
const E_ValueType targetValueType) const;
/** add specified content item to the current one.
* If possible, this method creates a new node as specified and adds it to the current
* one. The method canAddContentItem() is called internally to check parameters first.
* If the node could be added successfully, the cursor is set to it automatically.
** @param relationshipType relationship type of node to be added with regard to
* the current one
* @param valueType value type of node to be added
* @param addMode flag specifying at which position to add the new node
* (e.g. after or below the current node)
** @return ID of new node if successful, 0 otherwise
*/
virtual size_t addContentItem(const E_RelationshipType relationshipType,
const E_ValueType valueType,
const E_AddMode addMode = AM_afterCurrent);
/** add specified content item to the current one.
* If possible, this method adds a given new node to the current one. The method
* canAddContentItem() is called internally to check parameters first. If the
* node could be added successfully, the cursor is set to it automatically.
* Please note that no copy of the given node is created. Therefore, the node
* has to be created with new() or with DSRTypes::createDocumentTreeNode() - do
* not use a reference to a local variable and do not delete it a second time.
** @param node pointer to the new node to be added (should not be empty).
* Reference remains valid after successful insertion.
* @param addMode flag specifying at which position to add the new node
* (e.g. after or below the current node)
* @param deleteIfFail flag specifying whether to delete the given 'node' if
* adding fails. By default, the item is not deleted, i.e.
* in case of error it has to be deleted by the caller.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition addContentItem(DSRDocumentTreeNode *node,
const E_AddMode addMode = AM_afterCurrent,
const OFBool deleteIfFail = OFFalse);
/** add specified content item after the current one.
* If possible, this method creates a new node as specified and adds it after the current
* one, i.e. on the same level. Internally, the first variant of the addContentItem()
* method is called with the third parameter being DSRTypes::AM_afterCurrent. If
* successful, the given concept name is set for the new node, and the cursor is updated.
* @note This is a convenience function that avoids calling several other functions.
** @param relationshipType relationship type of node to be added with regard
* to the current one
* @param valueType value type of node to be added
* @param conceptName concept name of the node to be added
* @param check if enabled, check 'conceptName for validity before setting it
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition addContentItem(const E_RelationshipType relationshipType,
const E_ValueType valueType,
const DSRCodedEntryValue &conceptName,
const OFBool check = OFTrue);
/** add specified content item below the current one.
* If possible, this method creates a new node as specified and adds it below the current
* one, i.e. as a child. Internally, the first variant of the addContentItem() method
* is called with the third parameter being DSRTypes::AM_belowCurrent. If successful,
* the given concept name is set for the new node, and the cursor is updated.
* @note This is a convenience function that avoids calling several other functions.
** @param relationshipType relationship type of node to be added with regard
* to the current one
* @param valueType value type of node to be added
* @param conceptName concept name of the node to be added
* @param check if enabled, check 'conceptName for validity before setting it
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition addChildContentItem(const E_RelationshipType relationshipType,
const E_ValueType valueType,
const DSRCodedEntryValue &conceptName,
const OFBool check = OFTrue);
/** add specified by-reference relationship to the current content item.
* If possible, this method creates a new pseudo-node (relationship) and adds it to the
* current one. The method canAddByReferenceRelationship() is called internally to check
* parameters first. The internal cursor is automatically re-set to the current node.
** @param relationshipType relationship type between current and referenced node
* @param referencedNodeID ID of the referenced node (target content item)
** @return ID of new pseudo-node if successful, 0 otherwise
*/
virtual size_t addByReferenceRelationship(const E_RelationshipType relationshipType,
const size_t referencedNodeID);
/** update the position strings used to encode by-reference relationships (if any).
* Internally, this method calls checkByReferenceRelationships() with the 'mode'
* parameter being DSRTypes::CM_updatePositionString. It should be called before
* this subtree is cloned in order to make sure that the by-reference relationships
* (if any) still work on the cloned subtree. This method should also be called
* before accessing the position string of a referenced content item, see
* DSRByReferenceTreeNode::getReferencedContentItem().
** @param updateIncludedTemplates optional flag indicating whether to also update
* the subtrees managed by included sub-templates
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition updateByReferenceRelationships(const OFBool updateIncludedTemplates = OFFalse);
/** check whether specified subtree can be inserted at the current position, i.e.\ added
* to the current content item. Internally, the method canAddContentItem() is used for
* all top-level nodes of the document subtree. In addition, if a constraint checker
* is available, the remaining nodes of the given subtree are also checked for their
* compliance with the relationship content constraints of the underlying SR IOD.
** @param tree pointer to new subtree to be inserted (should not be empty)
* @param addMode flag specifying at which position the new subtree would
* be added (e.g. after or below the current node)
* @param defaultRelType default relationship type between the top-level nodes of
* the given subtree and the current node. This relationship
* type is used if the one of a top-level node is "unknown".
** @return OFTrue if specified subtree can be inserted, OFFalse otherwise
*/
virtual OFBool canInsertSubTree(const DSRDocumentSubTree *tree,
const E_AddMode addMode = AM_belowCurrent,
const E_RelationshipType defaultRelType = RT_unknown) const;
/** insert specified subtree to this tree, i.e.\ add it to the current content item.
* If possible, this method adds a given new subtree to the current content item.
* The method canInsertSubTree() is called internally to check the parameters first.
* Please note that no copy of the given subtree is created. Therefore, the subtree
* has to be created with new() or with cloneSubTree() - do not use a reference to a
* local variable and do not delete it a second time.
** @param tree pointer to new subtree to be inserted (should not be empty).
* Reference becomes invalid after successful insertion!
* @param addMode flag specifying at which position to add the new subtree
* (e.g. after or below the current node)
* @param defaultRelType default relationship type between the top-level nodes of
* the given subtree and the current node. This relationship
* type is used if the one of a top-level node is "unknown".
* @param deleteIfFail flag specifying whether to delete the given 'tree' if
* adding fails. By default, the tree is not deleted, i.e.
* in case of error it has to be deleted by the caller.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition insertSubTree(DSRDocumentSubTree *tree,
const E_AddMode addMode = AM_belowCurrent,
const E_RelationshipType defaultRelType = RT_unknown,
const OFBool deleteIfFail = OFFalse);
/** extract a subtree i.e.\ a fragment from this tree.
* The subtree is specified by the current node, which becomes the root of the subtree.
* In contrast to cloneSubTree(), this method also makes sure that the by-reference
* relationships are preserved (as long as both source and target node are contained
* in the same tree). Please note that the returned subtree has to be deleted by the
* caller if it is not inserted into the document tree using insertSubTree().
** @return pointer to the extracted subtree, NULL in case of error
*/
virtual DSRDocumentSubTree *extractSubTree();
/** remove current content item from tree.
* Please note that not only the specified node but also all of its child nodes are
* removed from the tree and then deleted. The internal cursor is set automatically
* to a new valid position.
** @return ID of the node which became the current one after deletion, 0 if an error
* occurred or the tree is now empty.
*/
virtual size_t removeCurrentContentItem();
/** remove a subtree from this tree.
* The subtree to be removed (and deleted) is either specified by the current node or by
* the node with the given ID. Afterwards, the internal cursor is set automatically to
* a new valid position. It would be an error to remove a subtree from an empty tree.
** @param searchID ID of the root node specifying the subtree to be removed.
* By default (0), the current node is used.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition removeSubTree(const size_t searchID = 0);
/** clone the current tree node.
* Internally, the copy constructor of the respective tree node class is used, so the
* corresponding comments apply. Please note that the returned tree node has to be
* deleted by the caller if it is not added to the document tree using addContentItem().
** @return pointer to a copy of the current tree node, NULL in case of error
*/
virtual DSRDocumentTreeNode *cloneCurrentTreeNode() const;
/** clone a subtree i.e.\ a fragment of this tree.
* The cloning starts with the current node and ends with the given node.
* Please note that the returned subtree has to be deleted by the caller if it is not
* inserted into the document tree using insertSubTree().
** @param stopAfterNodeID ID of the node after which the cloning should stop.
* By default (0), the process ends after cloning the
* current node with all of its child nodes (if any).
** @return pointer to a copy of the specified subtree, NULL in case of error
*/
virtual DSRDocumentSubTree *cloneSubTree(const size_t stopAfterNodeID = 0) const;
/** created an expanded version of this (sub)tree.
* Expanded means that no instance of DSRIncludedTemplateTreeNode will exist in the new
* document tree, i.e. all of them are replaced by their content (subtree). Please note
* that the returned subtree has to be deleted by the caller if it is not inserted into
* the document tree using insertSubTree().
** @param tree variable that will store the pointer to the new subtree
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition createExpandedSubTree(DSRDocumentSubTree *&tree) const;
/** compare template identification of the root node with given values.
* Please note that the comparison only takes place if there is a single node at the
* root of the tree and its value type is CONTAINER.
** @param templateIdentifier template identifier to compare with
* @param mappingResource mapping resource that defines the template
* @param mappingResourceUID uniquely identifies the mapping resource (optional).
* Not used for comparison if the value is empty.
** @result OFTrue if template identification can be compared and the values are
* identical, OFFalse otherwise
*/
virtual OFBool compareTemplateIdentification(const OFString &templateIdentifier,
const OFString &mappingResource,
const OFString &mappingResourceUID = "") const;
/** get template identifier and mapping resource from the root node of this tree. See
* DSRDocumentTreeNode::getTemplateIdentification() for details on template identification.
* Please note that the template identification is only retrieved if there is a single node
* at the root of the tree and its value type is CONTAINER.
** @param templateIdentifier identifier of the template (might be empty)
* @param mappingResource mapping resource that defines the template (might be empty)
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition getTemplateIdentification(OFString &templateIdentifier,
OFString &mappingResource) const;
/** get template identifier, mapping resource and optional mapping resource UID from the
* root node of this tree. See DSRDocumentTreeNode::getTemplateIdentification() for
* details on template identification.
* Please note that the template identification is only retrieved if there is a single node
* at the root of the tree and its value type is CONTAINER.
** @param templateIdentifier identifier of the template (might be empty)
* @param mappingResource mapping resource that defines the template (might be empty)
* @param mappingResourceUID uniquely identifies the mapping resource (might be empty)
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition getTemplateIdentification(OFString &templateIdentifier,
OFString &mappingResource,
OFString &mappingResourceUID) const;
/** set template identifier and mapping resource to the root node of this tree.
* The identification is valid if the first two values are either present (non-empty) or
* all three values are absent (empty). See DSRDocumentTreeNode::getTemplateIdentification()
* for details.
* Please note that the template identification is only set if there is a single node at
* the root of the tree and its value type is CONTAINER.
** @param templateIdentifier identifier of the template to be set
* @param mappingResource mapping resource that defines the template
* @param mappingResourceUID uniquely identifies the mapping resource (optional)
* @param check check 'templateIdentifier', 'mappingResource' and
* 'mappingResourceUID' for conformance with VR (CS,UI) and
* VM (1) if enabled
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition setTemplateIdentification(const OFString &templateIdentifier,
const OFString &mappingResource,
const OFString &mappingResourceUID = "",
const OFBool check = OFTrue);
protected:
/** special constructor that receives a pointer to the root node.
* Please note that the 'rootNode' and the associated tree is not copied!
** @param rootNode pointer to the root node of the "new" tree
*/
DSRDocumentSubTree(DSRDocumentTreeNode *rootNode);
/** special copy constructor that clones a particular subtree only
** @param startCursor first node of the subtree to be copied
* @param stopAfterNodeID ID of the node after which the cloning should stop
*/
DSRDocumentSubTree(const DSRDocumentTreeNodeCursor &startCursor,
size_t stopAfterNodeID);
/** fast, non-throwing swap function.
* The time complexity of this function is constant.
** @param tree subtree to swap with
*/
void swap(DSRDocumentSubTree &tree);
/** get pointer to current node.
* Hide this inherited method from the public interface.
** @return pointer to current node (might be NULL)
*/
virtual DSRDocumentTreeNode *getNode() const;
/** add new node to the current one.
* Please note that no copy of the given node is created. Therefore, the node
* has to be created with new() - do not use a reference to a local variable.
* If the node could be added successfully, the cursor is set to it automatically.
** @param node pointer to the new node to be added
* @param addMode flag specifying at which position to add the new node
* (e.g. after or below the current node)
** @return ID of the new node if successful, 0 otherwise
*/
virtual size_t addNode(DSRDocumentTreeNode *node,
const E_AddMode addMode = AM_afterCurrent);
/** replace current node by the given one.
* Please note that no copy of the given node is created. Therefore, the node
* should be created with new() - do not use a reference to a local variable. If
* the node could be replaced successfully, the "old" node (and all of its child
* nodes) are deleted, and the cursor is set to the new one.
** @param node pointer to the new node to replace the current one
** @return ID of the new node if successful, 0 otherwise
*/
virtual size_t replaceNode(DSRDocumentTreeNode *node);
/** extract current node from tree.
* Please note that not only the specified node but also all of its child nodes are
* extracted from the tree. The cursor is set automatically to a new valid position.
** @return pointer to extracted node, NULL in case of error (or the tree was empty)
*/
virtual DSRDocumentTreeNode *extractNode();
/** get pointer to root node and "forget" the internal reference to this node.
* In other words: after calling this method, the stored tree will be empty.
* This also means that the caller is responsible for deleting the allocated memory.
** @return pointer to root node, might be NULL (empty tree)
*/
virtual DSRDocumentTreeNode *getAndRemoveRootNode();
/** remove current node from tree.
* Please note that not only the specified node but also all of his child nodes are
* removed from the tree and deleted afterwards. The cursor is set automatically to
* a new valid position.
** @return ID of the node which became the current one after deletion, 0 if an error
* occurred or the tree is now empty.
*/
virtual size_t removeNode();
/** include specified sub-template, i.e.\ add a new DSRIncludedTemplateTreeNode, which
* references this template, to the current content item.
* Please note that no checks are performed that would make sure that the template
* with its top-level nodes can actually be added, e.g. by using an IOD constraint
* checker. This is also the reason why this method is "protected" and not "public",
* i.e. it can only be used by derived classes, e.g. DSRSubTemplate and its children.
** @param subTemplate shared pointer to a sub-template that should be included
* into this tree (at the current position)
* @param addMode flag specifying at which position to add the 'subTemplate'
* (e.g. after or below the current node)
* @param defaultRelType default relationship type that will be used when the
* subtree that is managed by the 'subTemplate' is inserted
* into this tree and the relationship type of one of the
* top-level nodes is "unknown". Also see documentation of
* createExpandedSubTree().
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition includeTemplate(const DSRSharedSubTemplate &subTemplate,
const E_AddMode addMode = AM_belowCurrent,
const E_RelationshipType defaultRelType = RT_unknown);
/** expand all "included template" content items in a given (sub)tree.
* Expanding means that all instances of DSRIncludedTemplateTreeNode are replaced by
* their content (subtree).
* Please note that the internal cursor of the given 'tree' is set to the root node
* if no error occurred. Otherwise, the cursor points to the content item that
* caused the problem.
** @param tree pointer to the subtree that should be expanded
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition expandIncludedTemplates(DSRDocumentSubTree *tree) const;
/** check the by-reference relationships (if any) for validity.
* This function checks whether all by-reference relationships possibly contained
* in the document tree are valid according to the following restrictions: source
* and target node are not identical and the target node is not an ancestor of the
* source node (requirement from the DICOM standard to prevent loops -> directed
* acyclic graph, though this is not 100% true - see "reportlp.dcm" example).
* In addition, the position strings (used to encode by-reference relationships
* according to the DICOM standard) OR the node IDs (used internally to uniquely
* identify nodes) can be updated.
* Please note that the checking modes DSRTypes::CM_updatePositionString and
* DSRTypes::CM_updateNodeID are mutually exclusive.
** @tparam T_Cursor template type used for the cursor iterating the document (sub)tree
** @param mode mode used to customize the checking process (see DSRTypes::CM_xxx)
* @param flags flag used to customize the reading (see DSRTypes::RF_xxx) and/or
* printing process (see DSRTypes::PF_xxx). Conflicting definitions
* are avoided using the appropriate bit mask (see DSRTypes::CB_xxx).
** @return status, EC_Normal if successful, an error code otherwise
*/
template <typename T_Cursor>
OFCondition checkByReferenceRelationships(const size_t mode = 0,
const size_t flags = 0);
/** reset flag for all content items whether they are target of a by-reference relationship.
* This function calls 'setReferenceTarget(OFFalse)' for all content items in the tree.
*/
virtual void resetReferenceTargetFlag();
/** update the tree for subsequent output, e.g.\ for being printed or added to an SR
* document. By default, this virtual function does nothing but is called automatically
* by the affected output methods and should be overwritten in derived classes.
*/
virtual void updateTreeForOutput();
/** check whether the given subtree complies with the constraints of the given checker
** @param tree pointer to subtree that should be checked
* @param checker pointer to relationship content constraints checker to be used.
* If NULL, no checks are performed by this method.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition checkSubTreeConstraints(const DSRDocumentSubTree *tree,
const DSRIODConstraintChecker *checker) const;
/// check relationship content constraints of the associated IOD
DSRIODConstraintChecker *ConstraintChecker;
private:
/// current content item. Introduced to avoid the external use of pointers.
DSRContentItem CurrentContentItem;
};
#endif