~ubuntu-branches/ubuntu/trusty/ginkgocadx/trusty

« back to all changes in this revision

Viewing changes to src/cadxcore/commands/incomingdicomassociationcommand.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2013-07-21 11:58:53 UTC
  • mfrom: (7.2.1 sid)
  • Revision ID: package-import@ubuntu.com-20130721115853-44e7n1xujqglu78e
Tags: 3.4.0.928.29+dfsg-1
* New upstream release [July 2013]
  + new B-D: "libjsoncpp-dev".
  + new patch "unbundle-libjsoncpp.patch" to avoid building bundled
    "libjsoncpp-dev".
  + new patch "fix-wx.patch" to avoid FTBFS due to missing
    "-lwx_gtk2u_html-2.8".
* Removed unnecessary versioned Build-Depends.
* Removed obsolete lintian override.
* Reference get-orig-source implementation for orig.tar clean-up and
  DFSG-repackaging.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include <commands/incomingdicomassociationcommand.h>
18
18
#include <commands/comandoincluirhistorial.h>
19
19
#include <main/controllers/controladorlog.h>
20
 
#include <main/controllers/controladorcomandos.h>
 
20
#include <main/controllers/commandcontroller.h>
21
21
#include <main/entorno.h>
22
22
#include <eventos/mensajes.h>
23
23
 
149
149
                        E_TransferSyntax xfer = (*imageDataSet)->getOriginalXfer();
150
150
 
151
151
                        // store file either with meta header or as pure dataset
152
 
                        LOG_INFO(ambitoLog, "storing DICOM file: " << fileName);
 
152
                        LOG_DEBUG(ambitoLog, "storing DICOM file: " << fileName);
153
153
                        /*   if (OFStandard::fileExists(fileName))
154
154
                        {
155
155
                        LOG_WARN(ambitoLog, "DICOM file already exists, overwriting: " << fileName);
182
182
                        }
183
183
                }
184
184
 
185
 
                // in case opt_bitPreserving is set, do some other things
186
 
                /* if( opt_bitPreserving )
187
 
                {
188
 
                // we need to set outputFileNameArray and outputFileNameArrayCnt to be
189
 
                // able to perform the placeholder substitution in executeOnReception()
190
 
                outputFileNameArray.push_back(OFStandard::getFilenameFromPath(tmpStr, cbdata->imageFileName));
191
 
                }*/
192
 
        }
193
 
 
194
 
 
195
 
 
196
 
        /*
197
 
 
198
 
 
199
 
        // determine if the association shall be aborted
200
 
        if( (opt_abortDuringStore && progress->state != DIMSE_StoreBegin) ||
201
 
        (opt_abortAfterStore && progress->state == DIMSE_StoreEnd) )
202
 
        {
203
 
        OFLOG_INFO(storescpLogger, "ABORT initiated (due to command line options)");
204
 
        ASC_abortAssociation((OFstatic_cast(StoreCallbackData*, callbackData))->assoc);
205
 
        rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources;
206
 
        return;
207
 
        }
208
 
 
209
 
        // if opt_sleepAfter is set, the user requires that the application shall
210
 
        // sleep a certain amount of seconds after having received one PDU.
211
 
        if (opt_sleepDuring > 0)
212
 
        {
213
 
        OFStandard::sleep(OFstatic_cast(unsigned int, opt_sleepDuring));
214
 
        }
215
 
 
216
 
        // dump some information if required (depending on the progress state)
217
 
        // We can't use oflog for the pdu output, but we use a special logger for
218
 
        // generating this output. If it is set to level "INFO" we generate the
219
 
        // output, if it's set to "DEBUG" then we'll assume that there is debug output
220
 
        // generated for each PDU elsewhere.
221
 
        OFLogger progressLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION ".progress");
222
 
        if (progressLogger.getChainedLogLevel() == OFLogger::INFO_LOG_LEVEL)
223
 
        {
224
 
        switch (progress->state)
225
 
        {
226
 
        case DIMSE_StoreBegin:
227
 
        COUT << "RECV: ";
228
 
        break;
229
 
        case DIMSE_StoreEnd:
230
 
        COUT << OFendl;
231
 
        break;
232
 
        default:
233
 
        COUT << '.';
234
 
        break;
235
 
        }
236
 
        COUT.flush();
237
 
        }
238
 
 
239
 
        // if this is the final call of this function, save the data which was received to a file
240
 
        // (note that we could also save the image somewhere else, put it in database, etc.)
241
 
        if (progress->state == DIMSE_StoreEnd)
242
 
        {
243
 
        OFString tmpStr;
244
 
 
245
 
        // do not send status detail information
246
 
        *statusDetail = NULL;
247
 
 
248
 
        // remember callback data
249
 
        StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData);
250
 
 
251
 
        // Concerning the following line: an appropriate status code is already set in the resp structure,
252
 
        // it need not be success. For example, if the caller has already detected an out of resources problem
253
 
        // then the status will reflect this.  The callback function is still called to allow cleanup.
254
 
        //rsp->DimseStatus = STATUS_Success;
255
 
 
256
 
        // we want to write the received information to a file only if this information
257
 
        // is present and the options opt_bitPreserving and opt_ignore are not set.
258
 
        if ((imageDataSet != NULL) && (*imageDataSet != NULL) && !opt_bitPreserving && !opt_ignore)
259
 
        {
260
 
        OFString fileName;
261
 
 
262
 
        // in case one of the --sort-xxx options is set, we need to perform some particular steps to
263
 
        // determine the actual name of the output file
264
 
        if (opt_sortStudyMode != ESM_None)
265
 
        {
266
 
        // determine the study instance UID in the (current) DICOM object that has just been received
267
 
        OFString currentStudyInstanceUID;
268
 
        if ((*imageDataSet)->findAndGetOFString(DCM_StudyInstanceUID, currentStudyInstanceUID).bad() || currentStudyInstanceUID.empty())
269
 
        {
270
 
        OFLOG_ERROR(storescpLogger, "element StudyInstanceUID " << DCM_StudyInstanceUID << " absent or empty in data set");
271
 
        rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand;
272
 
        return;
273
 
        }
274
 
 
275
 
        // if --sort-on-patientname is active, we need to extract the
276
 
        // patient's name (format: last_name^first_name)
277
 
        OFString currentPatientName;
278
 
        if (opt_sortStudyMode == ESM_PatientName)
279
 
        {
280
 
        OFString tmpName;
281
 
        if ((*imageDataSet)->findAndGetOFString(DCM_PatientName, tmpName).bad() || tmpName.empty())
282
 
        {
283
 
        // default if patient name is missing or empty
284
 
        tmpName = "ANONYMOUS";
285
 
        OFLOG_WARN(storescpLogger, "element PatientName " << DCM_PatientName << " absent or empty in data set, using '"
286
 
        << tmpName << "' instead");
287
 
        }
288
 
 
289
 
        // substitute non-ASCII characters in patient name to ASCII "equivalent" 
290
 
        const size_t length = tmpName.length();
291
 
        for (size_t i = 0; i < length; i++)
292
 
        mapCharacterAndAppendToString(tmpName[i], currentPatientName);
293
 
        }
294
 
 
295
 
        // if this is the first DICOM object that was received or if the study instance UID in the
296
 
        // current DICOM object does not equal the last object's study instance UID we need to create
297
 
        // a new subdirectory in which the current DICOM object will be stored
298
 
        if (lastStudyInstanceUID.empty() || (lastStudyInstanceUID != currentStudyInstanceUID))
299
 
        {
300
 
        // if lastStudyInstanceUID is non-empty, we have just completed receiving all objects for one
301
 
        // study. In such a case, we need to set a certain indicator variable (lastStudySubdirectoryPathAndName),
302
 
        // so that we know that executeOnEndOfStudy() might have to be executed later. In detail, this indicator
303
 
        // variable will contain the path and name of the last study's subdirectory, so that we can still remember
304
 
        // this directory, when we execute executeOnEndOfStudy(). The memory that is allocated for this variable
305
 
        // here will be freed after the execution of executeOnEndOfStudy().
306
 
        if (!lastStudyInstanceUID.empty())
307
 
        lastStudySubdirectoryPathAndName = subdirectoryPathAndName;
308
 
 
309
 
        // create the new lastStudyInstanceUID value according to the value in the current DICOM object
310
 
        lastStudyInstanceUID = currentStudyInstanceUID;
311
 
 
312
 
        // get the current time (needed for subdirectory name)
313
 
        OFDateTime dateTime;
314
 
        dateTime.setCurrentDateTime();
315
 
 
316
 
        // create a name for the new subdirectory.
317
 
        char timestamp[32];
318
 
        sprintf(timestamp, "%04u%02u%02u_%02u%02u%02u%03u",
319
 
        dateTime.getDate().getYear(), dateTime.getDate().getMonth(), dateTime.getDate().getDay(),
320
 
        dateTime.getTime().getHour(), dateTime.getTime().getMinute(), dateTime.getTime().getIntSecond(), dateTime.getTime().getMilliSecond());
321
 
 
322
 
        OFString subdirectoryName;
323
 
        switch (opt_sortStudyMode)
324
 
        {
325
 
        case ESM_Timestamp:
326
 
        // pattern: "[prefix]_[YYYYMMDD]_[HHMMSSMMM]"
327
 
        subdirectoryName = opt_sortStudyDirPrefix;
328
 
        if (!subdirectoryName.empty())
329
 
        subdirectoryName += '_';
330
 
        subdirectoryName += timestamp;
331
 
        break;
332
 
        case ESM_StudyInstanceUID:
333
 
        // pattern: "[prefix]_[Study Instance UID]"
334
 
        subdirectoryName = opt_sortStudyDirPrefix;
335
 
        if (!subdirectoryName.empty())
336
 
        subdirectoryName += '_';
337
 
        subdirectoryName += currentStudyInstanceUID;
338
 
        break;
339
 
        case ESM_PatientName:
340
 
        // pattern: "[Patient's Name]_[YYYYMMDD]_[HHMMSSMMM]"
341
 
        subdirectoryName = currentPatientName;
342
 
        subdirectoryName += '_';
343
 
        subdirectoryName += timestamp;
344
 
        break;
345
 
        case ESM_None:
346
 
        break;
347
 
        }
348
 
 
349
 
        // create subdirectoryPathAndName (string with full path to new subdirectory)
350
 
        OFStandard::combineDirAndFilename(subdirectoryPathAndName, OFStandard::getDirNameFromPath(tmpStr, cbdata->imageFileName), subdirectoryName);
351
 
 
352
 
        // check if the subdirectory already exists
353
 
        // if it already exists dump a warning
354
 
        if( OFStandard::dirExists(subdirectoryPathAndName) )
355
 
        OFLOG_WARN(storescpLogger, "subdirectory for study already exists: " << subdirectoryPathAndName);
356
 
        else
357
 
        {
358
 
        // if it does not exist create it
359
 
        OFLOG_INFO(storescpLogger, "creating new subdirectory for study: " << subdirectoryPathAndName);
360
 
        #ifdef HAVE_WINDOWS_H
361
 
        if( _mkdir( subdirectoryPathAndName.c_str() ) == -1 )
362
 
        #else
363
 
        if( mkdir( subdirectoryPathAndName.c_str(), S_IRWXU | S_IRWXG | S_IRWXO ) == -1 )
364
 
        #endif
365
 
        {
366
 
        OFLOG_ERROR(storescpLogger, "could not create subdirectory for study: " << subdirectoryPathAndName);
367
 
        rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand;
368
 
        return;
369
 
        }
370
 
        // all objects of a study have been received, so a new subdirectory is started.
371
 
        // ->timename counter can be reset, because the next filename can't cause a duplicate.
372
 
        // if no reset would be done, files of a new study (->new directory) would start with a counter in filename
373
 
        if (opt_timeNames)
374
 
        timeNameCounter = -1;
375
 
        }
376
 
        }
377
 
 
378
 
        // integrate subdirectory name into file name (note that cbdata->imageFileName currently contains both
379
 
        // path and file name; however, the path refers to the output directory captured in opt_outputDirectory)
380
 
        OFStandard::combineDirAndFilename(fileName, subdirectoryPathAndName, OFStandard::getFilenameFromPath(tmpStr, cbdata->imageFileName));
381
 
 
382
 
        // update global variable outputFileNameArray
383
 
        // (might be used in executeOnReception() and renameOnEndOfStudy)
384
 
        outputFileNameArray.push_back(tmpStr);
385
 
        }
386
 
        // if no --sort-xxx option is set, the determination of the output file name is simple
387
 
        else
388
 
        {
389
 
        fileName = cbdata->imageFileName;
390
 
 
391
 
        // update global variables outputFileNameArray
392
 
        // (might be used in executeOnReception() and renameOnEndOfStudy)
393
 
        outputFileNameArray.push_back(OFStandard::getFilenameFromPath(tmpStr, fileName));
394
 
        }
395
 
 
396
 
        // determine the transfer syntax which shall be used to write the information to the file
397
 
        E_TransferSyntax xfer = opt_writeTransferSyntax;
398
 
        if (xfer == EXS_Unknown) xfer = (*imageDataSet)->getOriginalXfer();
399
 
 
400
 
        // store file either with meta header or as pure dataset
401
 
        OFLOG_INFO(storescpLogger, "storing DICOM file: " << fileName);
402
 
        if (OFStandard::fileExists(fileName))
403
 
        {
404
 
        OFLOG_WARN(storescpLogger, "DICOM file already exists, overwriting: " << fileName);
405
 
        }
406
 
        OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, opt_sequenceType, opt_groupLength,
407
 
        opt_paddingType, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad),
408
 
        (opt_useMetaheader) ? EWM_fileformat : EWM_dataset);
409
 
        if (cond.bad())
410
 
        {
411
 
        OFLOG_ERROR(storescpLogger, "cannot write DICOM file: " << fileName << ": " << cond.text());
412
 
        rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources;
413
 
        }
414
 
 
415
 
        // check the image to make sure it is consistent, i.e. that its sopClass and sopInstance correspond
416
 
        // to those mentioned in the request. If not, set the status in the response message variable.
417
 
        if ((rsp->DimseStatus == STATUS_Success)&&(!opt_ignore))
418
 
        {
419
 
        // which SOP class and SOP instance ?
420
 
        if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, opt_correctUIDPadding))
421
 
        {
422
 
        OFLOG_ERROR(storescpLogger, "bad DICOM file: " << fileName);
423
 
        rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand;
424
 
        }
425
 
        else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0)
426
 
        {
427
 
        rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass;
428
 
        }
429
 
        else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0)
430
 
        {
431
 
        rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass;
432
 
        }
433
 
        }
434
 
        }
435
 
 
436
 
        // in case opt_bitPreserving is set, do some other things
437
 
        if( opt_bitPreserving )
438
 
        {
439
 
        // we need to set outputFileNameArray and outputFileNameArrayCnt to be
440
 
        // able to perform the placeholder substitution in executeOnReception()
441
 
        outputFileNameArray.push_back(OFStandard::getFilenameFromPath(tmpStr, cbdata->imageFileName));
442
 
        }
443
 
        }
444
 
        */
 
185
        }
445
186
}
446
187
 
447
 
 
448
188
GADAPI::PACS::IncomingDicomAssociationCommandParams::IncomingDicomAssociationCommandParams(T_ASC_Association* assoc, unsigned long rcvTimeout) {
449
189
        m_pAssoc = assoc;
450
190
        m_rcvTimeout = rcvTimeout;
451
191
}
452
192
 
 
193
GADAPI::PACS::IncomingDicomAssociationCommandParams::~IncomingDicomAssociationCommandParams()
 
194
{
 
195
        if (m_pAssoc != NULL) {
 
196
                CONDITION cond = ASC_dropSCPAssociation(m_pAssoc);
 
197
                OFString temp_str;
 
198
 
 
199
                if (cond.bad())
 
200
                {
 
201
                        LOG_FATAL("IncomingDicomAssociationCommandParams", DimseCondition::dump(temp_str, cond).c_str());
 
202
                }
 
203
 
 
204
                cond = ASC_destroyAssociation(&m_pAssoc);
 
205
                if (cond.bad())
 
206
                {
 
207
                        LOG_FATAL("IncomingDicomAssociationCommandParams", DimseCondition::dump(temp_str, cond).c_str());
 
208
                }
 
209
                m_pAssoc = NULL;
 
210
        }
 
211
}
453
212
//-----------------------------------------------------------------------------------------------
454
213
//-----------------------------------------------------------------------------------------------
455
214
 
458
217
        ambitolog = name;
459
218
}
460
219
 
 
220
 
461
221
GADAPI::PACS::IncomingDicomAssociationCommand::~IncomingDicomAssociationCommand() {
462
 
        T_ASC_Association* assoc = m_pIncommingassociationParams->m_pAssoc;
463
 
        CONDITION cond = ASC_dropSCPAssociation(assoc);
464
 
        OFString temp_str;
465
 
 
466
 
        if (cond.bad())
467
 
        {
468
 
                LOG_FATAL(ambitolog, DimseCondition::dump(temp_str, cond).c_str());
469
 
        }
470
 
 
471
 
        cond = ASC_destroyAssociation(&assoc);
472
 
        if (cond.bad())
473
 
        {
474
 
                LOG_FATAL(ambitolog, DimseCondition::dump(temp_str, cond).c_str());
475
 
        }
 
222
        
476
223
}
477
224
 
478
225
void GADAPI::PACS::IncomingDicomAssociationCommand::Execute() {
610
357
        }
611
358
        else {
612
359
                if (cond == DUL_PEERREQUESTEDRELEASE) {
613
 
                        LOG_INFO(ambitolog, _Std("Association Release"));
 
360
                        LOG_DEBUG(ambitolog, "Association released by remote endpoint");
614
361
                        cond = ASC_acknowledgeRelease(assoc);
615
362
                }
616
363
                else if (cond == DUL_PEERABORTEDASSOCIATION) {
617
 
                        LOG_INFO(ambitolog, _Std("Association Aborted"));
 
364
                        LOG_WARN(ambitolog, "Association Aborted by remote endpoint");
618
365
                }
619
366
                else {
620
367
                        LOG_ERROR(ambitolog, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond).c_str());
669
416
 
670
417
        // dump some information if required
671
418
        OFString str;
672
 
        LOG_INFO(ambitolog, "Received Store Request: MsgID " << req->MessageID << ", (" << dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "OT") << ")");
 
419
        LOG_DEBUG(ambitolog, "Received Store Request: MsgID " << req->MessageID << ", (" << dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "OT") << ")");
673
420
        LOG_DEBUG(ambitolog, DIMSE_dumpMessage(str, *req, DIMSE_INCOMING, NULL, presID));
674
421
 
675
422
        // intialize some variables
723
470
        if (m_DicomFileList.size() > 0) {
724
471
                GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams* pParams = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorialParams(m_DicomFileList, false, GNC::GCS::HistoryController::TAA_MOVE);
725
472
                GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial * pCmd = new GADAPI::ComandoIncluirHistorial::ComandoIncluirHistorial(pParams);
726
 
                GNC::GCS::IControladorComandos::Instance()->ProcessAsync(_Std("Including files..."),pCmd,NULL);
 
473
                GNC::GCS::ICommandController::Instance()->ProcessAsync(_Std("Including files..."),pCmd,NULL);
727
474
        }
728
475
}