/* * * Copyright (C) 2003-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: DSRCodingSchemeIdentificationList * */ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmsr/dsrcsidl.h" #include "dcmtk/dcmsr/dsrxmld.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcuid.h" #include "dcmtk/dcmdata/dcvrcs.h" #include "dcmtk/dcmdata/dcvrlo.h" #include "dcmtk/dcmdata/dcvrsh.h" #include "dcmtk/dcmdata/dcvrst.h" #include "dcmtk/dcmdata/dcvrui.h" DSRCodingSchemeIdentificationList::DSRCodingSchemeIdentificationList() : ItemList(), Iterator(), SpecificCharacterSet() { /* initialize list cursor */ Iterator = ItemList.end(); } DSRCodingSchemeIdentificationList::~DSRCodingSchemeIdentificationList() { /* clear list and delete allocated memory */ clear(); } void DSRCodingSchemeIdentificationList::clear() { Iterator = ItemList.begin(); const OFListIterator(ItemStruct *) last = ItemList.end(); /* delete all items and free memory */ while (Iterator != last) { delete (*Iterator); Iterator = ItemList.erase(Iterator); } /* make sure that the list is empty */ ItemList.clear(); Iterator = ItemList.end(); /* also clear other members */ SpecificCharacterSet.clear(); } OFBool DSRCodingSchemeIdentificationList::isEmpty() const { return ItemList.empty(); } size_t DSRCodingSchemeIdentificationList::getNumberOfItems() const { return ItemList.size(); } OFCondition DSRCodingSchemeIdentificationList::read(DcmItem &dataset, const size_t /*flags*/) { /* first, check whether sequence is present and non-empty */ DcmSequenceOfItems *sequence = NULL; OFCondition result = dataset.findAndGetSequence(DCM_CodingSchemeIdentificationSequence, sequence); checkElementValue(sequence, DCM_CodingSchemeIdentificationSequence, "1-n", "3", result, "SOPCommonModule"); if (result.good()) { ItemStruct *item = NULL; OFString codingSchemeDesignator; /* iterate over all sequence items */ DcmObject *dobj = NULL; while ((dobj = sequence->nextInContainer(dobj)) != NULL) { DcmItem *ditem = OFstatic_cast(DcmItem *, dobj); /* get the coding scheme designator */ if (getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeDesignator, codingSchemeDesignator, "1", "1", "CodingSchemeIdentificationSequence").good()) { /* add new item to the list */ if (addItem(codingSchemeDesignator, item).good()) { /* read additional information */ getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeRegistry, item->CodingSchemeRegistry, "1", "1C", "CodingSchemeIdentificationSequence"); getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeUID, item->CodingSchemeUID, "1", "1C", "CodingSchemeIdentificationSequence"); getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeExternalID, item->CodingSchemeExternalID, "1", "2C", "CodingSchemeIdentificationSequence"); getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeName, item->CodingSchemeName, "1", "3", "CodingSchemeIdentificationSequence"); getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeVersion, item->CodingSchemeVersion, "1", "3", "CodingSchemeIdentificationSequence"); getAndCheckStringValueFromDataset(*ditem, DCM_CodingSchemeResponsibleOrganization, item->CodingSchemeResponsibleOrganization, "1", "3", "CodingSchemeIdentificationSequence"); } } } } return result; } OFCondition DSRCodingSchemeIdentificationList::write(DcmItem &dataset) const { OFCondition result = EC_Normal; /* iterate over all list items */ OFListConstIterator(ItemStruct *) iter = ItemList.begin(); const OFListConstIterator(ItemStruct *) last = ItemList.end(); while ((iter != last) && result.good()) { ItemStruct *item = *iter; /* check whether list item really exists and is valid */ if ((item != NULL) && !item->CodingSchemeDesignator.empty()) { DcmItem *ditem = NULL; /* create a new item (and a sequence if required) */ result = dataset.findOrCreateSequenceItem(DCM_CodingSchemeIdentificationSequence, ditem, -2 /*append new*/); /* write item data */ if (result.good()) { putStringValueToDataset(*ditem, DCM_CodingSchemeDesignator, item->CodingSchemeDesignator); putStringValueToDataset(*ditem, DCM_CodingSchemeRegistry, item->CodingSchemeRegistry, OFFalse /*allowEmpty*/); putStringValueToDataset(*ditem, DCM_CodingSchemeUID, item->CodingSchemeUID, OFFalse /*allowEmpty*/); if (item->CodingSchemeUID.empty()) putStringValueToDataset(*ditem, DCM_CodingSchemeExternalID, item->CodingSchemeExternalID, OFFalse /*allowEmpty*/); else if (!item->CodingSchemeExternalID.empty()) { DCMSR_WARN("Both Coding Scheme UID and Coding Scheme External ID present for \"" << item->CodingSchemeDesignator << "\", the latter will be ignored"); } putStringValueToDataset(*ditem, DCM_CodingSchemeName, item->CodingSchemeName, OFFalse /*allowEmpty*/); putStringValueToDataset(*ditem, DCM_CodingSchemeVersion, item->CodingSchemeVersion, OFFalse /*allowEmpty*/); putStringValueToDataset(*ditem, DCM_CodingSchemeResponsibleOrganization, item->CodingSchemeResponsibleOrganization, OFFalse /*allowEmpty*/); } } ++iter; } return result; } OFCondition DSRCodingSchemeIdentificationList::readXML(const DSRXMLDocument &doc, DSRXMLCursor cursor, const size_t /*flags*/) { OFCondition result = SR_EC_InvalidDocument; ItemStruct *item = NULL; OFString codingSchemeDesignator; /* iterate over all nodes */ while (cursor.valid()) { /* check for known element tags */ if (doc.checkNode(cursor, "scheme").good()) { /* retrieve coding scheme designator */ if (!doc.getStringFromAttribute(cursor, codingSchemeDesignator, "designator", OFTrue /*encoding*/).empty()) { result = addItem(codingSchemeDesignator, item); if (result.good()) { DSRXMLCursor childCursor = cursor.getChild(); /* clear any previously stored information */ item->clear(); while (childCursor.valid()) { /* check for known element tags */ doc.getStringFromNodeContent(childCursor, item->CodingSchemeRegistry, "registry", OFTrue /*encoding*/, OFFalse /*clearString*/); doc.getStringFromNodeContent(childCursor, item->CodingSchemeUID, "uid", OFFalse /*encoding*/, OFFalse /*clearString*/); doc.getStringFromNodeContent(childCursor, item->CodingSchemeExternalID, "id", OFTrue /*encoding*/, OFFalse /*clearString*/); doc.getStringFromNodeContent(childCursor, item->CodingSchemeName, "name", OFTrue /*encoding*/, OFFalse /*clearString*/); doc.getStringFromNodeContent(childCursor, item->CodingSchemeVersion, "version", OFTrue /*encoding*/, OFFalse /*clearString*/); doc.getStringFromNodeContent(childCursor, item->CodingSchemeResponsibleOrganization, "organization", OFTrue /*encoding*/, OFFalse /*clearString*/); /* proceed with next node */ childCursor.gotoNext(); } } } } /* proceed with next node */ cursor.gotoNext(); } return result; } OFCondition DSRCodingSchemeIdentificationList::writeXML(STD_NAMESPACE ostream &stream, const size_t flags) const { OFString tmpString; /* iterate over all list items */ OFListConstIterator(ItemStruct *) iter = ItemList.begin(); const OFListConstIterator(ItemStruct *) last = ItemList.end(); while (iter != last) { ItemStruct *item = *iter; /* check whether list item really exists */ if (item != NULL) { stream << "CodingSchemeDesignator, tmpString) << "\">" << OFendl; writeStringValueToXML(stream, convertToXMLString(item->CodingSchemeRegistry, tmpString), "registry", (flags & DSRTypes::XF_writeEmptyTags) > 0); writeStringValueToXML(stream, item->CodingSchemeUID, "uid", (flags & DSRTypes::XF_writeEmptyTags) > 0); writeStringValueToXML(stream, convertToXMLString(item->CodingSchemeExternalID, tmpString), "identifier", (flags & DSRTypes::XF_writeEmptyTags) > 0); writeStringValueToXML(stream, convertToXMLString(item->CodingSchemeName, tmpString), "name", (flags & DSRTypes::XF_writeEmptyTags) > 0); writeStringValueToXML(stream, convertToXMLString(item->CodingSchemeVersion, tmpString), "version", (flags & DSRTypes::XF_writeEmptyTags) > 0); writeStringValueToXML(stream, convertToXMLString(item->CodingSchemeResponsibleOrganization, tmpString), "organization", (flags & DSRTypes::XF_writeEmptyTags) > 0); stream << "" << OFendl; } ++iter; } return EC_Normal; } OFCondition DSRCodingSchemeIdentificationList::setSpecificCharacterSet(const OFString &value, const OFBool check) { OFCondition result = (check) ? DcmCodeString::checkStringValue(value, "1-n") : EC_Normal; if (result.good()) SpecificCharacterSet = value; return result; } OFCondition DSRCodingSchemeIdentificationList::addPrivateDcmtkCodingScheme() { /* add private coding scheme (if not already existent) */ return addItem(OFFIS_CODING_SCHEME_DESIGNATOR, OFFIS_CODING_SCHEME_UID, OFFIS_CODING_SCHEME_NAME, OFFIS_CODING_SCHEME_RESPONSIBLE_ORGANIZATION); } OFCondition DSRCodingSchemeIdentificationList::addItem(const OFString &codingSchemeDesignator, ItemStruct *&item) { OFCondition result = EC_IllegalParameter; /* check parameter first */ if (!codingSchemeDesignator.empty()) { result = EC_Normal; OFListIterator(ItemStruct *) oldCursor = Iterator; /* check whether item already exists */ if (gotoItem(codingSchemeDesignator).bad()) { /* if not create new item and add it to the list */ item = new ItemStruct(codingSchemeDesignator); if (item != NULL) { ItemList.push_back(item); /* set cursor to new position */ Iterator = --ItemList.end(); } else { /* restore old cursor */ Iterator = oldCursor; result = EC_MemoryExhausted; } } else { DCMSR_WARN("Coding Scheme Designator \"" << codingSchemeDesignator << "\" already exists in Coding Scheme Identification Sequence ... overwriting"); /* gotoItem() was successful, set item pointer */ item = *Iterator; } } else item = NULL; return result; } OFCondition DSRCodingSchemeIdentificationList::addItem(const OFString &codingSchemeDesignator, const OFBool check) { OFCondition result = EC_Normal; /* make sure that the mandatory value is non-empty */ if (codingSchemeDesignator.empty()) result = EC_IllegalParameter; else if (check) { /* check whether the passed value is valid */ result = DcmShortString::checkStringValue(codingSchemeDesignator, "1", SpecificCharacterSet); } if (result.good()) { ItemStruct *item = NULL; /* call the "real" function */ result = addItem(codingSchemeDesignator, item); } return result; } OFCondition DSRCodingSchemeIdentificationList::addItem(const OFString &codingSchemeDesignator, const OFString &codingSchemeUID, const OFString &codingSchemeName, const OFString &responsibleOrganization, const OFBool check) { OFCondition result = EC_Normal; /* make sure that the mandatory designator value is non-empty */ if (codingSchemeDesignator.empty()) result = EC_IllegalParameter; else if (check) { /* check whether the passed values are valid */ result = DcmShortString::checkStringValue(codingSchemeDesignator, "1", SpecificCharacterSet); if (result.good()) result = DcmUniqueIdentifier::checkStringValue(codingSchemeUID, "1"); if (result.good()) result = DcmShortText::checkStringValue(codingSchemeName, SpecificCharacterSet); if (result.good()) result = DcmShortText::checkStringValue(responsibleOrganization, SpecificCharacterSet); } if (result.good()) { ItemStruct *item = NULL; /* add coding scheme (if not already existent) */ result = addItem(codingSchemeDesignator, item); if (result.good()) { /* set additional information */ item->CodingSchemeRegistry.clear(); item->CodingSchemeUID = codingSchemeUID; item->CodingSchemeExternalID.clear(); item->CodingSchemeName = codingSchemeName; item->CodingSchemeVersion.clear(); item->CodingSchemeResponsibleOrganization = responsibleOrganization; } } return result; } OFCondition DSRCodingSchemeIdentificationList::removeItem() { OFCondition result = EC_IllegalCall; /* check whether list is empty or iterator is invalid */ if (!ItemList.empty() && (Iterator != ItemList.end())) { /* free memory */ delete (*Iterator); /* remove item from list */ Iterator = ItemList.erase(Iterator); result = EC_Normal; } return result; } OFCondition DSRCodingSchemeIdentificationList::removeItem(const OFString &codingSchemeDesignator) { /* goto specified item ... */ OFCondition result = gotoItem(codingSchemeDesignator); /* ... and remove it */ if (result.good()) result = removeItem(); return result; } OFCondition DSRCodingSchemeIdentificationList::gotoItem(const OFString &codingSchemeDesignator) { OFCondition result = EC_IllegalParameter; /* check parameter first */ if (!codingSchemeDesignator.empty()) { result = SR_EC_CodingSchemeNotFound; /* start with first item */ Iterator = ItemList.begin(); const OFListIterator(ItemStruct *) last = ItemList.end(); /* search for given item */ while ((Iterator != last) && result.bad()) { if ((*Iterator != NULL) && ((*Iterator)->CodingSchemeDesignator == codingSchemeDesignator)) result = EC_Normal; else ++Iterator; } } return result; } OFCondition DSRCodingSchemeIdentificationList::gotoFirstItem() { OFCondition result = EC_IllegalCall; /* check for empty item list */ if (!ItemList.empty()) { /* set cursor to first list item */ Iterator = ItemList.begin(); result = EC_Normal; } return result; } OFCondition DSRCodingSchemeIdentificationList::gotoNextItem() { OFCondition result = EC_IllegalCall; /* goto next list item */ if (++Iterator != ItemList.end()) { /* check whether list item is valid */ if (*Iterator != NULL) result = EC_Normal; else result = EC_CorruptedData; } return result; } DSRCodingSchemeIdentificationList::ItemStruct *DSRCodingSchemeIdentificationList::getCurrentItem() const { ItemStruct *item = NULL; /* check whether current item is valid */ OFListConstIterator(ItemStruct *) it = Iterator; if (it != ItemList.end()) item = *Iterator; return item; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeDesignator(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeDesignator; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeRegistry(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeRegistry; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeUID(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeUID; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeExternalID(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeExternalID; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeName(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeName; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeVersion(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeVersion; else stringValue.clear(); return stringValue; } const OFString &DSRCodingSchemeIdentificationList::getCodingSchemeResponsibleOrganization(OFString &stringValue) const { /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); /* get requested value or clear string if invalid */ if (item != NULL) stringValue = item->CodingSchemeResponsibleOrganization; else stringValue.clear(); return stringValue; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeRegistry(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmLongString::checkStringValue(value, "1", SpecificCharacterSet) : EC_Normal; if (result.good()) item->CodingSchemeRegistry = value; } return result; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeUID(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal; if (result.good()) item->CodingSchemeUID = value; } return result; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeExternalID(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmShortText::checkStringValue(value, SpecificCharacterSet) : EC_Normal; if (result.good()) item->CodingSchemeExternalID = value; } return result; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeName(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmShortText::checkStringValue(value, SpecificCharacterSet) : EC_Normal; if (result.good()) item->CodingSchemeName = value; } return result; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeVersion(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmShortString::checkStringValue(value, "1", SpecificCharacterSet) : EC_Normal; if (result.good()) item->CodingSchemeVersion = value; } return result; } OFCondition DSRCodingSchemeIdentificationList::setCodingSchemeResponsibleOrganization(const OFString &value, const OFBool check) { OFCondition result = EC_IllegalCall; /* check whether current item is valid */ ItemStruct *item = getCurrentItem(); if (item != NULL) { /* set the value (if valid) */ result = (check) ? DcmShortText::checkStringValue(value, SpecificCharacterSet) : EC_Normal; if (result.good()) item->CodingSchemeResponsibleOrganization = value; } return result; }