521 lines
23 KiB
C++
521 lines
23 KiB
C++
/*
|
|
*
|
|
* Copyright (C) 2008-2012, 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: dcmdata
|
|
*
|
|
* Author: Michael Onken
|
|
*
|
|
* Purpose: Class declarations for accessing DICOM dataset structures (items,
|
|
* sequences and leaf elements via string-based path access.
|
|
*
|
|
*/
|
|
|
|
#ifndef DCPATH_H
|
|
#define DCPATH_H
|
|
|
|
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
|
|
|
|
#include "dcmtk/dcmdata/dcdatset.h"
|
|
|
|
|
|
/** Class representing a node in DcmPath. A node contains just
|
|
* a pointer to a DcmObject (e.g. a sequence or an item). Additionally
|
|
* an item number is stored which also makes sense in case that the
|
|
* object pointed to is an item. The item number is necessary because
|
|
* when having only a pointer to a DcmItem there is no way to find out
|
|
* at which position the item actually has in the surrounding sequence.
|
|
*/
|
|
class DCMTK_DCMDATA_EXPORT DcmPathNode
|
|
{
|
|
|
|
public:
|
|
|
|
/** Constructor. Creates empty path node.
|
|
*/
|
|
DcmPathNode() : m_obj(NULL), m_itemNo(0) {}
|
|
|
|
/** Constructor. Creates search node from object pointer and item number.
|
|
* @param obj [in] The object the search node points to. The memory of the
|
|
* given DICOM object is not handled by the node itself but
|
|
* must be handled (i.e. freed) from outside.
|
|
* @param itemNo [in] The item number that should be set. Only relevant
|
|
* if obj parameter contains an item
|
|
*/
|
|
DcmPathNode(DcmObject* obj, Uint32 itemNo) : m_obj(obj), m_itemNo(itemNo) {}
|
|
|
|
/** Destructor. Nothing to do, the DICOM object is not freed automatically!
|
|
*/
|
|
~DcmPathNode() { }
|
|
|
|
/// Pointer to object this search node points to
|
|
DcmObject* m_obj;
|
|
|
|
/// The item number of the item in m_obj; only useful if m_obj is an item
|
|
Uint32 m_itemNo;
|
|
|
|
private:
|
|
|
|
/** Private undefined copy constructor
|
|
*/
|
|
DcmPathNode(const DcmPathNode& rhs);
|
|
|
|
/** Private undefined assignment operator
|
|
*/
|
|
DcmPathNode& operator=(const DcmPathNode& arg);
|
|
};
|
|
|
|
|
|
/** Class representing a path of DICOM objects. A path is a "way" through
|
|
* a DICOM dataset, i.e. it starts e.g. with an item, followed by a sequence
|
|
* originally contained in this item. The sequence then could be followed by
|
|
* another item which is part of the sequence and so on. Thus the path
|
|
* should be well-formed, but if it is created manually (e.g. using append())
|
|
* there is no corresponding checking.
|
|
*/
|
|
class DCMTK_DCMDATA_EXPORT DcmPath
|
|
{
|
|
|
|
public:
|
|
|
|
/** Constructor, creates an empty search result
|
|
*/
|
|
DcmPath();
|
|
|
|
/** Constructor, creates a search result from a list of search nodes.
|
|
* @param currentPath [in] The list of search nodes representing a
|
|
* "path" through a DICOM dataset
|
|
*/
|
|
DcmPath(const OFList<DcmPathNode*>& currentPath);
|
|
|
|
/** Appends a search node at the end of the search result path. It is not
|
|
* checked whether the resulting path is still valid.
|
|
* @param node [in] The node to append.
|
|
*
|
|
*/
|
|
void append(DcmPathNode* node);
|
|
|
|
/** Removes last path node from path. Also frees memory of path node
|
|
* but does _not_ free memory of the underlying DICOM item or element.
|
|
* @return none
|
|
*/
|
|
void deleteBackNode();
|
|
|
|
/** Returns iterator pointing to first path component.
|
|
* @return Iterator to first path node.
|
|
*/
|
|
OFListIterator(DcmPathNode*) begin();
|
|
|
|
/** Returns last path component.
|
|
* @return The last path component, NULL if none exists.
|
|
*/
|
|
DcmPathNode* back();
|
|
|
|
/** Returns iterator pointing to last path component.
|
|
* @return Iterator to last path node.
|
|
*/
|
|
OFListIterator(DcmPathNode*) end();
|
|
|
|
/** Returns number of path components.
|
|
* @return The number of path components
|
|
*/
|
|
Uint32 size() const;
|
|
|
|
/** Returns whether path is empty, ie does not contain any path nodes
|
|
* @return OFTrue, if path is empty, OFFalse otherwise
|
|
*/
|
|
OFBool empty() const;
|
|
|
|
/** Returns a string representation of the path,
|
|
* e.g.\ "SourceImageSequence[0].ReferencedSOPInstanceUID"
|
|
* @return String representing path
|
|
*/
|
|
OFString toString() const;
|
|
|
|
/** Returns whether the path contains tags of a given group.
|
|
* Might be useful for looking after (unwanted) meta header tags etc.
|
|
* @param groupNo [in] The group number to look for
|
|
* @return OFTrue if group number is found in path, OFFalse otherwise
|
|
*/
|
|
OFBool containsGroup(const Uint16 groupNo) const;
|
|
|
|
/** Returns a string representation of each path node separately.
|
|
* Tags are represented as numbers surrounded by braces "(gggg,eeee)",
|
|
* not dictionary names. Items are represented by a number or wildcard
|
|
* in square brackets, eg. "[12]" or "[*]".
|
|
* @param path The path to parse into different nodes
|
|
* @param result [out] List containing the resulting strings
|
|
* @return none
|
|
*/
|
|
static OFCondition separatePathNodes(const OFString& path, OFList<OFString>& result);
|
|
|
|
/** Helper function for findOrCreatePath(). Parses an item number from
|
|
* the beginning of the path string. The item number must be positive,
|
|
* starting with 0.
|
|
* The path must start like "[itemnumber]...".
|
|
* @param path [in/out] The path starting with the item number in square
|
|
* brackets, e.g.\ "[3]". The parsed item number and a
|
|
* potentially following "." are removed from the path
|
|
* @param itemNo [out] The parsed item number. If a wildcard was parsed,
|
|
* this output parameter is not set at all.
|
|
* @param wasWildcard [out] Is set to OFTrue, if wildcard was parsed
|
|
* (instead of concrete item number).
|
|
* @return EC_Normal, if concrete item number or wildcard was parsed
|
|
*/
|
|
static OFCondition parseItemNoFromPath(OFString& path, // inout
|
|
Uint32& itemNo, // out
|
|
OFBool& wasWildcard); // out
|
|
|
|
/** Function that parses a tag from the beginning of a path string.
|
|
* The tag has to be either in numeric format, e.g. "(0010,0010)" or
|
|
* a dictionary name, e.g. "PatientName". If successful, the
|
|
* parsed tag is removed from the path string.
|
|
* @param path [in/out] The path string, starting with the attribute
|
|
* to parse
|
|
* @param tag [out] The tag parsed
|
|
* @return EC_Normal if successful, error code otherwise
|
|
*/
|
|
static OFCondition parseTagFromPath(OFString& path, // inout
|
|
DcmTag& tag); // out
|
|
|
|
/** Desctructor, cleans up memory of path nodes. Does not delete
|
|
* the DcmObjects the nodes point to (this is also not done
|
|
* by the desctructor of the path nodes, so the caller is responsible
|
|
* for freeing any related DICOM objects.
|
|
*/
|
|
~DcmPath();
|
|
|
|
private:
|
|
|
|
/// Internal list representing the nodes in the path.
|
|
OFList<DcmPathNode*> m_path;
|
|
|
|
/** Private undefined copy constructor
|
|
*/
|
|
DcmPath(const DcmPath& rhs);
|
|
|
|
/** Private undefined assignment operator
|
|
*/
|
|
DcmPath& operator=(const DcmPath& arg);
|
|
};
|
|
|
|
|
|
class DCMTK_DCMDATA_EXPORT DcmPathProcessor
|
|
{
|
|
|
|
public:
|
|
|
|
/** Constructor, creates an empty search object.
|
|
*/
|
|
DcmPathProcessor();
|
|
|
|
/** Sets whether searching/creating paths will support wildcard for
|
|
* items. If set to false, any path operation with item wildcard characters
|
|
* will return an error.
|
|
* @param supported [in] If true, wildcard are enabled (default)
|
|
* If false, item wildcard support is disabled.
|
|
*/
|
|
void setItemWildcardSupport(const OFBool supported);
|
|
|
|
|
|
/** Enables (class default: enabled) or disables checking of private
|
|
* reservations when inserting private tags. If enabled and a private
|
|
* tag is created that has no private reservation, an error is returned.
|
|
* If disabled, it is possible to insert private tags that do not have
|
|
* a reservation in the corresponding item/dataset.
|
|
* @param doChecking [in] OFTrue enables reservation checking,
|
|
* OFFalse disables it.
|
|
*/
|
|
void checkPrivateReservations(const OFBool doChecking);
|
|
|
|
/** Checks in item, whether a private reservation for a given
|
|
* tag key exists.
|
|
* @param item [in] The item to search in
|
|
* @param tagKey [in/out] The tag to be checked.
|
|
* @param privateCreator [in] The private creator to check for (if known,
|
|
* can be left empty)
|
|
* @return Return EC_Normal if reservation checking was successful.
|
|
* Otherwise an error code is returned.
|
|
*/
|
|
static OFCondition checkPrivateTagReservation(DcmItem* item,
|
|
const DcmTagKey& tagKey,
|
|
const OFString& privateCreator = "");
|
|
|
|
/** Checks in item, whether a private reservation for a given
|
|
* tag key. If so, a dictionary lookup is performed and the VR and private
|
|
* creator of the tag is updated correspondingly.
|
|
* @param item [in] The item to search in
|
|
* @param tag [in/out] The tag to be checked. Will be updated with VR and
|
|
* private creator.
|
|
* @param privateCreator [in] The private creator to check for (if known,
|
|
* can be left empty)
|
|
* @return Return EC_Normal if reservation checking and updating the
|
|
* tag was successful. Otherwise an error code is returned.
|
|
*/
|
|
static OFCondition checkPrivateTagReservation(DcmItem* item,
|
|
DcmTag& tag,
|
|
const OFString& privateCreator = "");
|
|
|
|
/** Function that allows for finding and/or inserting a hierarchy of items
|
|
* and attributes as defined by a path string; also returns a list of
|
|
* pointers for each successfully found or inserted paths. Every list
|
|
* contains pointers pointing to all the objects along the path
|
|
* starting from the object given as parameter. The pointer to the
|
|
* starting object will not be part of the result.
|
|
*
|
|
* In principle, the path string must have the following format (in
|
|
* arbitrary depth). Note that for searching a sequence, the example
|
|
* below would start with [ITEMNO] instead:
|
|
* SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE
|
|
* . ITEMNO must be a positive integer starting with 0.
|
|
* SEQUENCE and ATTRIBUTE must be a tag, written e.g.
|
|
* "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the
|
|
* path cannot be fully created (see option createIfNecessary), any
|
|
* possibly object changes are reverted. So a path is either fully created
|
|
* or no path component is created at all. The result can be obtained
|
|
* by calling the getResults() function.
|
|
*
|
|
* Example: The path
|
|
* "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content
|
|
* Sequence in the given object, therein the 5th item, therein the "Concept
|
|
* Name Code Sequence" denoted by (0040,a043), therein the first item
|
|
* and finally therein the tag "Code Value".
|
|
* The resulting object list should (if success is returned) contain
|
|
* 1 result, consisting of a list with 5 pointers to 5 objects in the order
|
|
* in their logical order as they occur in the path string
|
|
* (in total 2 sequences, 2 items, and one leaf attribute).
|
|
* @param obj [in] The object to search (or create) a path in
|
|
* @param path [in] The path either starting with an attribute (either a
|
|
* sequence or a a leaf attribute as a dicitionary name or
|
|
* tag) or starting with an item
|
|
* @param createIfNecessary [in] If set, all missing objects found
|
|
* in the path string are created. If not set,
|
|
* only existing paths can be accessed and
|
|
* no new attribute or item is created.
|
|
* @return EC_Normal if successful, error code otherwise.
|
|
*/
|
|
OFCondition findOrCreatePath(DcmObject* obj,
|
|
const OFString& path,
|
|
OFBool createIfNecessary = OFFalse);
|
|
|
|
/** Function that allows for deleting elements and items from
|
|
* a DICOM object tree.
|
|
* In principle, the path string must have the following format (in
|
|
* arbitrary depth). Note that for searching in a sequence, the example
|
|
* below would start with [ITEMNO] instead:
|
|
* SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE
|
|
* . ITEMNO must be a positive integer starting with 0.
|
|
* SEQUENCE and ATTRIBUTE must be a tag, written e.g.
|
|
* "(0010,0010)" or as a dictionary name, e.g. "PatientName".
|
|
*
|
|
* Example: The path
|
|
* "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content
|
|
* Sequence in the given object, therein the 5th item, therein the "Concept
|
|
* Name Code Sequence" denoted by (0040,a043), therein the first item
|
|
* and finally therein the tag "Code Value". Only "Code Value" will be
|
|
* deleted by the function.
|
|
* @param obj [in] The object to delete attribute or item from
|
|
* @param path [in] The path either starting with an attribute (either a
|
|
* sequence or a a leaf attribute as a dicitionary name or
|
|
* tag) or starting with an item
|
|
* @param numDeleted [out] Number of deleted attributes/items
|
|
* @return EC_Normal if successful, error code otherwise. If the desired
|
|
* attribute/item was not found, EC_TagNotFound is returned.
|
|
*/
|
|
OFCondition findOrDeletePath(DcmObject* obj,
|
|
const OFString& path,
|
|
Uint32& numDeleted);
|
|
|
|
/** Returns the results from the search / creation call.
|
|
* @param searchResults [out] The resulting paths that were created/searched
|
|
* Note that the memory of the search results is freed
|
|
* automatically by the destructor and must not be freed
|
|
* by the caller.
|
|
* @return Number of results returned
|
|
*/
|
|
Uint32 getResults(OFList<DcmPath*>& searchResults);
|
|
|
|
|
|
/** Helper function that applies a specified "override key" in path syntax
|
|
* to the given dataset. The name "override" indicates that these keys have
|
|
* higher precedence than identical keys in a request dataset that might
|
|
* possibly read from a DICOM query file.
|
|
* @param dataset [in/out] the dataset (e.g.\ query keys) the override key is
|
|
* applied to. Must be non-NULL.
|
|
* @param overrideKey [in] the override key in path syntax (see class DcmPath).
|
|
* Also the path can end with a value assignment, e.g.
|
|
* "PatientName=Doe^John". An empty (or missing value) will
|
|
* not be ignored but will be written as empty to the
|
|
* attribute (if not a sequence or item).
|
|
* @return EC_Normal if adding was successful, error code otherwise
|
|
*/
|
|
OFCondition applyPathWithValue(DcmDataset* dataset,
|
|
const OFString& overrideKey);
|
|
|
|
/** Deconstructor, cleans up memory that was allocated for any
|
|
* search results.
|
|
*/
|
|
~DcmPathProcessor();
|
|
|
|
protected:
|
|
|
|
/** Function that allows for finding and/or inserting a hierarchy of items
|
|
* and attributes as defined by a path string; also returns a list of
|
|
* pointers for each successfully found or inserted paths. Every list
|
|
* contains pointers pointing to all the objects along the path
|
|
* starting from the object given as parameter. The pointer to the
|
|
* starting object will not be part of the result.
|
|
*
|
|
* In principle, the path string must have the following format (in
|
|
* arbitrary depth).
|
|
* SEQUENCE[ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE
|
|
* . ITEMNO must be a positive integer starting with 0.
|
|
* SEQUENCE and ATTRIBUTE must be a tag, written e.g.
|
|
* "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the
|
|
* path cannot be fully created (see option createIfNecessary), any
|
|
* possibly object changes are reverted. So a path is either fully created
|
|
* or no path component is created at all. The result can be obtained
|
|
* by calling the getResults() function.
|
|
*
|
|
* Example: The path
|
|
* "ContentSequence[4].(0040,a043)[0].CodeValue" selects the Content
|
|
* Sequence in the given item, therein the 5th item, therein the "Concept
|
|
* Name Code Sequence" denoted by (0040,a043), therein the first item
|
|
* and finally therein the tag "Code Value".
|
|
* The resulting object list should (if success is returned) contain
|
|
* 1 result, consisting of a list with 5 pointers to 5 objects in the order
|
|
* in their logical order as they occur in the path string
|
|
* (in total 2 sequences, 2 items, and one leaf attribute).
|
|
* @param item [in] The object to search (or create) a path in
|
|
* @param path [in] The path starting with an attribute (either a
|
|
* sequence or a a leaf attribute) as a dicitionary name or
|
|
* tag. The parsed attribute is removed from the path string.
|
|
* @return EC_Normal if successful, error code otherwise.
|
|
*/
|
|
OFCondition findOrCreateItemPath(DcmItem* item,
|
|
OFString& path);
|
|
|
|
/** Function that allows for finding and/or inserting a hierarchy of items
|
|
* and attributes as defined by a path string; also returns a list of
|
|
* pointers for each successfully found or inserted paths. Every list
|
|
* contains pointers pointing to all the objects along the path
|
|
* starting from the object given as parameter. The pointer to the
|
|
* starting object will not be part of the result.
|
|
*
|
|
* In principle, the path string must have the following format (in
|
|
* arbitrary depth).
|
|
* [ITEMNO].SEQUENCE[ITEMNO].ATTRIBUTE
|
|
* . ITEMNO must be a positive integer starting with 0.
|
|
* SEQUENCE and ATTRIBUTE must be a tag, written e.g.
|
|
* "(0010,0010)" or as a dictionary name, e.g. "PatientName". If the
|
|
* path cannot be fully created (see option createIfNecessary), any
|
|
* possibly object changes are reverted. So a path is either fully created
|
|
* or no path component is created at all. The result can be obtained
|
|
* by calling the getResults() function.
|
|
*
|
|
* Example: The path
|
|
* "[4].(0040,a043)[0].CodeValue" selects the 5th item in the given
|
|
* sequence, therein the "Concept Name Code Sequence" denoted by
|
|
* (0040,a043), therein the first item and finally therein the
|
|
* tag "Code Value".
|
|
* The resulting object list should (if success is returned) contain
|
|
* 1 result, consisting of a list with 4 pointers to 4 objects in the order
|
|
* in their logical order as they occur in the path string
|
|
* (in total 1 sequence, 2 items, and one leaf element).
|
|
* @param seq [in] The object to search (or create) a path in
|
|
* @param path [in] The path starting with an item. The parsed item number
|
|
* (e.g. "[0]") is removed from the path string.
|
|
* @return EC_Normal if successful, error code otherwise.
|
|
*/
|
|
OFCondition findOrCreateSequencePath(DcmSequenceOfItems* seq,
|
|
OFString& path);
|
|
|
|
/** Helper function that looks at the last node in a given path and deletes
|
|
* the corresponding DICOM object. Does not delete the path node itself:
|
|
* That is done by the calling function, findOrCreateItemPath().
|
|
* @param objSearchedIn [in/out] The object the given path starts in.
|
|
* @param path [in/out] The complete path to the DICOM object to delete
|
|
* @param toDelete [in/out] The path node to delete. This node must be
|
|
* identical to the last node in the path parameter. Also
|
|
* the node must represent a DICOM sequence or leaf element,
|
|
* not an item. However, because it is isolated already by
|
|
* the calling function, it is provided here for convenience.
|
|
*/
|
|
static OFCondition deleteLastElemFromPath(DcmObject* objSearchedIn,
|
|
DcmPath* path,
|
|
DcmPathNode* toDelete);
|
|
|
|
/** Helper function that looks at the last node in a given path and deletes
|
|
* the corresponding DICOM object. Does not delete the path node itself:
|
|
* That is done by the calling function, findOrCreateItemPath().
|
|
* @param objSearchedIn [in/out] The object the given path starts in.
|
|
* @param path [in/out] The complete path to the DICOM object to delete
|
|
* @param toDelete [in/out] The path node to delete. This node must be
|
|
* identical to the last node in the path parameter. Also
|
|
* the node must represent a DICOM item, not a sequence
|
|
* However, because it is isolated already by the calling
|
|
* function, it is provided here for convenience.
|
|
*/
|
|
static OFCondition deleteLastItemFromPath(DcmObject* objSearchedIn,
|
|
DcmPath* path,
|
|
DcmPathNode* toDelete);
|
|
|
|
/** Returns the private reservation tag key for a given private tag
|
|
* @param privateKey [in] The private key to calculate reservation tag for
|
|
* @return The reservation key. If given key is not private or an error,
|
|
* return DCM_UndefinedTagKey. If the given key is a reservation
|
|
* itself, it is directly returned.
|
|
*/
|
|
static DcmTagKey calcPrivateReservationTag(const DcmTagKey& privateKey);
|
|
|
|
/** Cleans up memory that was allocated for any search results.
|
|
* Called when a new search is started or during object destruction.
|
|
* The DICOM data all freed paths and path nodes point to, is not
|
|
* touched, i.e. all memory to the DICOM objects pointed to must be
|
|
* freed from outside. Processing options like checking for private
|
|
* reservations and so on are not reset to default values but
|
|
* keep valid.
|
|
*/
|
|
void clear();
|
|
|
|
private:
|
|
|
|
/// Internal list that is during search for keeping track of current path
|
|
OFList<DcmPathNode*> m_currentPath;
|
|
|
|
/// Internal list that represents the search results found
|
|
OFList<DcmPath*> m_results;
|
|
|
|
/// Denotes whether missing items/sequences/attributes should be
|
|
/// automatically inserted when using findAndCreate routines
|
|
OFBool m_createIfNecessary;
|
|
|
|
/// If enabled (default), any insertions of private tags will fail, if no
|
|
/// corresponding reservation exists in the underlying item
|
|
OFBool m_checkPrivateReservations;
|
|
|
|
/// Denotes, whether a path is accepted that contains wildcards.
|
|
/// If false, then any search containing wildcards will return an error.
|
|
OFBool m_itemWildcardsEnabled;
|
|
|
|
/** Private undefined copy constructor
|
|
*/
|
|
DcmPathProcessor(const DcmPathProcessor& rhs);
|
|
|
|
/** Private undefined assignment operator
|
|
*/
|
|
DcmPathProcessor& operator=(const DcmPathProcessor& arg);
|
|
};
|
|
|
|
|
|
#endif // DCPATH_H
|