1 /*=========================================================================
2
3 Program: GDCM (Grassroots DICOM). A DICOM library
4
5 Copyright (c) 2006-2011 Mathieu Malaterre
6 All rights reserved.
7 See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notice for more information.
12
13 =========================================================================*/
14 /*
15 * Simple command line tool to echo/store/find/move DICOM using
16 * DICOM Query/Retrieve
17 * This is largely inspired by other tool available from other toolkit, namely:
18 * echoscu (DCMTK)
19 * findscu (DCMTK)
20 * movescu (DCMTK)
21 * storescu (DCMTK)
22 */
23
24 #include "gdcmCompositeNetworkFunctions.h"
25
26 #include <iostream>
27 #include <fstream>
28 #include <stdlib.h>
29 #include <getopt.h>
30 #include "gdcmVersion.h"
31 #include "gdcmGlobal.h"
32 #include "gdcmSystem.h"
33 #include "gdcmDirectory.h"
34 #include "gdcmDataSet.h"
35 #include "gdcmFileMetaInformation.h"
36 #include "gdcmUIDGenerator.h"
37
38 #include "gdcmBaseRootQuery.h"
39 #include "gdcmQueryFactory.h"
40 #include "gdcmPrinter.h"
41
42
PrintVersion()43 static void PrintVersion()
44 {
45 std::cout << "gdcmscu: gdcm " << gdcm::Version::GetVersion() << " ";
46 const char date[] = "$Date$";
47 std::cout << date << std::endl;
48 }
49
PrintHelp()50 static void PrintHelp()
51 {
52 PrintVersion();
53 std::cout << "Usage: gdcmscu [OPTION]...[OPERATION]...HOSTNAME...[PORT]..." << std::endl;
54 std::cout << "Execute a DICOM Q/R operation to HOSTNAME, using port PORT (104 when not specified)\n";
55 std::cout << "Options:" << std::endl;
56 std::cout << " -H --hostname Hostname." << std::endl;
57 std::cout << " -p --port Port number." << std::endl;
58 std::cout << " --aetitle Set Calling AE Title." << std::endl;
59 std::cout << " --call Set Called AE Title." << std::endl;
60 std::cout << "Mode Options:" << std::endl;
61 std::cout << " --echo C-ECHO (default when none)." << std::endl;
62 std::cout << " --store C-STORE." << std::endl;
63 std::cout << " --find C-FIND." << std::endl;
64 std::cout << " --move C-MOVE." << std::endl;
65 std::cout << " --get C-GET." << std::endl;
66 std::cout << "C-STORE Options:" << std::endl;
67 std::cout << " -i --input DICOM filename" << std::endl;
68 std::cout << " -r --recursive recursively process (sub-)directories." << std::endl;
69 std::cout << " --store-query Store constructed query in file." << std::endl;
70 std::cout << "C-FIND Options:" << std::endl;
71 std::cout << " --worklist C-FIND Worklist Model." << std::endl;
72 std::cout << " --patientroot C-FIND Patient Root Model." << std::endl;
73 std::cout << " --studyroot C-FIND Study Root Model." << std::endl;
74 std::cout << " --patient C-FIND Query on Patient Info (cannot be used with --studyroot)" << std::endl;
75 std::cout << " --study C-FIND Query on Study Info." << std::endl;
76 std::cout << " --series C-FIND Query on Series Info." << std::endl;
77 std::cout << " --image C-FIND Query on Image Info." << std::endl;
78 //std::cout << " --psonly C-FIND Patient/Study Only Model." << std::endl;
79 std::cout << " --key 0123,4567=VALUE for specifying search criteria (wildcard allowed)." << std::endl;
80 std::cout << " With --key, leave blank (ie, --key 10,10="") to retrieve values" << std::endl;
81 std::cout << "C-MOVE Options:" << std::endl;
82 std::cout << " -o --output DICOM output directory." << std::endl;
83 std::cout << " --port-scp Port used for incoming association." << std::endl;
84 std::cout << " --key 0123,4567=VALUE for specifying search criteria (wildcard not allowed)." << std::endl;
85 std::cout << " Note that C-MOVE supports the same queries as C-FIND, but no wildcards are allowed." << std::endl;
86 std::cout << "C-GET Options:" << std::endl;
87 std::cout << "General Options:" << std::endl;
88 std::cout << " --root-uid Root UID." << std::endl;
89 std::cout << " -V --verbose more verbose (warning+error)." << std::endl;
90 std::cout << " -W --warning print warning info." << std::endl;
91 std::cout << " -D --debug print debug info." << std::endl;
92 std::cout << " -E --error print error info." << std::endl;
93 std::cout << " -h --help print help." << std::endl;
94 std::cout << " --queryhelp print query help." << std::endl;
95 std::cout << " -v --version print version." << std::endl;
96 std::cout << " -L --log-file set log file (instead of cout)." << std::endl;
97
98 try
99 {
100 std::locale l("");
101 std::string loc = l.name();
102 std::cout << std::endl;
103 std::cout << "Local Name: " << loc << std::endl;
104 }
105 catch( const std::exception& e)
106 {
107 std::cerr << e.what() << std::endl;
108 }
109 std::cout << "Local Character Set: " << gdcm::System::GetLocaleCharset() << std::endl;
110 std::vector<gdcm::ECharSet> charsettype;
111 charsettype.push_back( gdcm::QueryFactory::GetCharacterFromCurrentLocale() );
112 gdcm::DataElement de = gdcm::QueryFactory::ProduceCharacterSetDataElement(charsettype);
113 const gdcm::ByteValue *bv = de.GetByteValue();
114 std::string s( bv->GetPointer(), bv->GetLength() );
115 std::cout << "DICOM Character Set: [" << s << "]" << std::endl;
116 }
117
PrintQueryHelp(int inFindPatientRoot)118 static void PrintQueryHelp(int inFindPatientRoot)
119 {
120 gdcm::BaseRootQuery* theBase;
121 if (inFindPatientRoot)
122 {
123 std::cout << "To find the help for a study-level query, type" <<std::endl;
124 std::cout << " --queryhelp --studyroot" << std::endl;
125 theBase = gdcm::QueryFactory::ProduceQuery(gdcm::ePatientRootType, gdcm::eFind, gdcm::ePatient);
126 theBase->WriteHelpFile(std::cout);
127 delete theBase;
128 }
129 else
130 {
131 std::cout << "To find the help for a patient-level query, type" <<std::endl;
132 std::cout << " --queryhelp --patientroot" << std::endl;
133 std::cout << "These are the study level, study root queries: " << std::endl;
134 theBase = gdcm::QueryFactory::ProduceQuery(gdcm::eStudyRootType, gdcm::eFind, gdcm::eStudy);
135 theBase->WriteHelpFile(std::cout);
136 delete theBase;
137 }
138 }
139
main(int argc,char * argv[])140 int main(int argc, char *argv[])
141 {
142 int c;
143 //int digit_optind = 0;
144
145 std::string shostname;
146 std::string callingaetitle = "GDCMSCU";
147 std::string callaetitle = "ANY-SCP";
148 int port = 104; // default
149 int portscp = 0;
150 int outputopt = 0;
151 int portscpnum = 0;
152 gdcm::Directory::FilenamesType filenames;
153 std::string outputdir;
154 int storequery = 0;
155 int verbose = 0;
156 int warning = 0;
157 int debug = 0;
158 int error = 0;
159 int help = 0;
160 int queryhelp = 0;
161 int version = 0;
162 int echomode = 0;
163 int storemode = 0;
164 int findmode = 0;
165 int movemode = 0;
166 int getmode = 0;
167 int findworklist = 0;
168 int findpatientroot = 0;
169 int findstudyroot = 0;
170 int patientquery = 0;
171 int studyquery = 0;
172 int seriesquery = 0;
173 int imagequery = 0;
174 int findpsonly = 0;
175 std::string queryfile;
176 std::string root;
177 int rootuid = 0;
178 int recursive = 0;
179 int logfile = 0;
180 std::string logfilename;
181 gdcm::Tag tag;
182 std::vector< std::pair<gdcm::Tag, std::string> > keys;
183
184 while (true) {
185 //int this_option_optind = optind ? optind : 1;
186 int option_index = 0;
187 /*
188 struct option {
189 const char *name;
190 int has_arg;
191 int *flag;
192 int val;
193 };
194 */
195 static struct option long_options[] = {
196 {"verbose", 0, &verbose, 1},
197 {"warning", 0, &warning, 1},
198 {"debug", 0, &debug, 1},
199 {"error", 0, &error, 1},
200 {"help", 0, &help, 1},
201 {"version", 0, &version, 1},
202 {"hostname", 1, nullptr, 0}, // -h
203 {"aetitle", 1, nullptr, 0}, //
204 {"call", 1, nullptr, 0}, //
205 {"port", 0, &port, 1}, // -p
206 {"input", 1, nullptr, 0}, // dcmfile-in
207 {"echo", 0, &echomode, 1}, // --echo
208 {"store", 0, &storemode, 1}, // --store
209 {"find", 0, &findmode, 1}, // --find
210 {"move", 0, &movemode, 1}, // --move
211 {"key", 1, nullptr, 0}, // (15) --key
212 {"worklist", 0, &findworklist, 1}, // --worklist
213 {"patientroot", 0, &findpatientroot, 1}, // --patientroot
214 {"studyroot", 0, &findstudyroot, 1}, // --studyroot
215 {"psonly", 0, &findpsonly, 1}, // --psonly
216 {"port-scp", 1, &portscp, 1}, // (20) --port-scp
217 {"output", 1, &outputopt, 1}, // --output
218 {"recursive", 0, &recursive, 1},
219 {"store-query", 1, &storequery, 1},
220 {"queryhelp", 0, &queryhelp, 1},
221 {"patient", 0, &patientquery, 1}, // --patient
222 {"study", 0, &studyquery, 1}, // --study
223 {"series", 0, &seriesquery, 1}, // --series
224 {"image", 0, &imagequery, 1}, // --image
225 {"log-file", 1, &logfile, 1}, // --log-file
226 {"get", 0, &getmode, 1}, // --get
227 {nullptr, 0, nullptr, 0} // required
228 };
229 static const char short_options[] = "i:H:p:L:VWDEhvk:o:r";
230 c = getopt_long (argc, argv, short_options,
231 long_options, &option_index);
232 if (c == -1)
233 {
234 break;
235 }
236
237 switch (c)
238 {
239 case 0:
240 case '-':
241 {
242 const char *s = long_options[option_index].name; (void)s;
243 //printf ("option %s", s);
244 if (optarg)
245 {
246 if( option_index == 0 ) /* input */
247 {
248 assert( strcmp(s, "input") == 0 );
249 filenames.push_back( optarg );
250 }
251 else if( option_index == 7 ) /* calling aetitle */
252 {
253 assert( strcmp(s, "aetitle") == 0 );
254 //assert( callingaetitle.empty() );
255 callingaetitle = optarg;
256 }
257 else if( option_index == 8 ) /* called aetitle */
258 {
259 assert( strcmp(s, "call") == 0 );
260 //assert( callaetitle.empty() );
261 callaetitle = optarg;
262 }
263 else if( option_index == 15 ) /* key */
264 {
265 assert( strcmp(s, "key") == 0 );
266 if( !tag.ReadFromCommaSeparatedString(optarg) )
267 {
268 std::cerr << "Could not read Tag: " << optarg << std::endl;
269 return 1;
270 }
271 std::stringstream ss;
272 ss.str( optarg );
273 uint16_t dummy;
274 char cdummy; // comma
275 ss >> std::hex >> dummy;
276 assert( tag.GetGroup() == dummy );
277 ss >> cdummy;
278 assert( cdummy == ',' );
279 ss >> std::hex >> dummy;
280 assert( tag.GetElement() == dummy );
281 ss >> cdummy;
282 assert( cdummy == ',' || cdummy == '=' );
283 std::string str;
284 //ss >> str;
285 std::getline(ss, str); // do not skip whitespace
286 if( str.size() % 2 == 1 ) str += " ";
287 keys.emplace_back(tag, str );
288 }
289 else if( option_index == 20 ) /* port-scp */
290 {
291 assert( strcmp(s, "port-scp") == 0 );
292 portscpnum = atoi(optarg);
293 }
294 else if( option_index == 21 ) /* output */
295 {
296 assert( strcmp(s, "output") == 0 );
297 outputdir = optarg;
298 }
299 else if( option_index == 23 ) /* store-query */
300 {
301 assert( strcmp(s, "store-query") == 0 );
302 queryfile = optarg;
303 }
304 else if( option_index == 29 ) /* log-file */
305 {
306 assert( strcmp(s, "log-file") == 0 );
307 logfilename = optarg;
308 }
309 else
310 {
311 // If you reach here someone mess-up the index and the argument in
312 // the getopt table
313 assert( 0 );
314 }
315 //printf (" with arg %s", optarg);
316 }
317 //printf ("\n");
318 }
319 break;
320
321 case 'k':
322 {
323 if( !tag.ReadFromCommaSeparatedString(optarg) )
324 {
325 std::cerr << "Could not read Tag: " << optarg << std::endl;
326 return 1;
327 }
328 std::stringstream ss;
329 ss.str( optarg );
330 uint16_t dummy;
331 char cdummy; // comma
332 ss >> std::hex >> dummy;
333 assert( tag.GetGroup() == dummy );
334 ss >> cdummy;
335 assert( cdummy == ',' );
336 ss >> std::hex >> dummy;
337 assert( tag.GetElement() == dummy );
338 ss >> cdummy;
339 assert( cdummy == ',' || cdummy == '=' );
340 std::string str;
341 std::getline(ss, str); // do not skip whitespace
342 keys.emplace_back(tag, str );
343 }
344 break;
345
346 case 'i':
347 //printf ("option i with value '%s'\n", optarg);
348 filenames.push_back( optarg );
349 break;
350
351 case 'r':
352 recursive = 1;
353 break;
354
355 case 'o':
356 assert( outputdir.empty() );
357 outputdir = optarg;
358 break;
359
360 case 'H':
361 shostname = optarg;
362 break;
363
364 case 'p':
365 port = atoi( optarg );
366 break;
367
368 case 'L':
369 logfile = 1;
370 logfilename = optarg;
371 break;
372
373 case 'V':
374 verbose = 1;
375 break;
376
377 case 'W':
378 warning = 1;
379 break;
380
381 case 'D':
382 debug = 1;
383 break;
384
385 case 'E':
386 error = 1;
387 break;
388
389 case 'h':
390 help = 1;
391 break;
392
393 case 'q':
394 queryhelp = 1;
395 break;
396
397 case 'v':
398 version = 1;
399 break;
400
401 case '?':
402 break;
403
404 default:
405 printf ("?? getopt returned character code 0%o ??\n", c);
406 }
407 }
408
409 if (optind < argc)
410 {
411 int v = argc - optind;
412 // hostname port filename
413 if( v == 1 )
414 {
415 shostname = argv[optind++];
416 }
417 else if( v == 2 )
418 {
419 shostname = argv[optind++];
420 port = atoi( argv[optind++] );
421 }
422 else if( v >= 3 )
423 {
424 shostname = argv[optind++];
425 port = atoi( argv[optind++] );
426 std::vector<std::string> files;
427 while (optind < argc)
428 {
429 files.emplace_back(argv[optind++] );
430 }
431 filenames = files;
432 }
433 else
434 {
435 return 1;
436 }
437 assert( optind == argc );
438 }
439
440 if( version )
441 {
442 PrintVersion();
443 return 0;
444 }
445
446 if( help )
447 {
448 PrintHelp();
449 return 0;
450 }
451 if(queryhelp)
452 {
453 PrintQueryHelp(findpatientroot);
454 return 0;
455 }
456 const bool theDebug = debug != 0;
457 const bool theWarning = warning != 0;
458 const bool theError = error != 0;
459 const bool theVerbose = verbose != 0;
460 const bool theRecursive = recursive != 0;
461 // Debug is a little too verbose
462 gdcm::Trace::SetDebug( theDebug );
463 gdcm::Trace::SetWarning( theWarning );
464 gdcm::Trace::SetError( theError );
465 // when verbose is true, make sure warning+error are turned on:
466 if( verbose )
467 {
468 gdcm::Trace::SetWarning( theVerbose );
469 gdcm::Trace::SetError( theVerbose);
470 }
471 if( logfile )
472 {
473 gdcm::Trace::SetStreamToFile( logfilename.c_str() );
474 }
475 gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( callaetitle.c_str() );
476 if( !rootuid )
477 {
478 // only read the env var if no explicit cmd line option
479 // maybe there is an env var defined... let's check
480 const char *rootuid_env = getenv("GDCM_ROOT_UID");
481 if( rootuid_env )
482 {
483 rootuid = 1;
484 root = rootuid_env;
485 }
486 }
487 if( rootuid )
488 {
489 // root is set either by the cmd line option or the env var
490 if( !gdcm::UIDGenerator::IsValid( root.c_str() ) )
491 {
492 std::cerr << "specified Root UID is not valid: " << root << std::endl;
493 return 1;
494 }
495 gdcm::UIDGenerator::SetRoot( root.c_str() );
496 }
497
498 if( shostname.empty() )
499 {
500 //std::cerr << "Hostname missing" << std::endl;
501 PrintHelp(); // needed to display help message when no arg
502 return 1;
503 }
504 if( port == 0 )
505 {
506 std::cerr << "Problem with port number" << std::endl;
507 return 1;
508 }
509 // checkout outputdir opt:
510 if( outputopt )
511 {
512 if( !gdcm::System::FileIsDirectory( outputdir.c_str()) )
513 {
514 if( !gdcm::System::MakeDirectory( outputdir.c_str() ) )
515 {
516 std::cerr << "Sorry: " << outputdir << " is not a valid directory.";
517 std::cerr << std::endl;
518 std::cerr << "and I could not create it.";
519 std::cerr << std::endl;
520 return 1;
521 }
522 }
523 }
524
525 const char *hostname = shostname.c_str();
526 std::string mode = "echo";
527 if ( echomode )
528 {
529 mode = "echo";
530 }
531 else if ( storemode )
532 {
533 mode = "store";
534 }
535 else if ( findmode )
536 {
537 mode = "find";
538 }
539 else if ( movemode )
540 {
541 mode = "move";
542 }
543 else if ( getmode )
544 {
545 mode = "get";
546 }
547 else if ( findworklist )
548 {
549 mode = "worklist";
550 }
551
552 //this class contains the networking calls
553
554 if ( mode == "server" ) // C-STORE SCP
555 {
556 // MM: Do not expose that to user for now (2010/10/11).
557 //CStoreServer( port );
558 return 1;
559 }
560 else if ( mode == "echo" ) // C-ECHO SCU
561 {
562 // ./bin/gdcmscu mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2
563 // ./bin/gdcmscu --echo mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2
564 bool didItWork = gdcm::CompositeNetworkFunctions::CEcho( hostname, (uint16_t)port,
565 callingaetitle.c_str(), callaetitle.c_str() );
566 gdcmDebugMacro( (didItWork ? "Echo succeeded." : "Echo failed.") );
567 return didItWork ? 0 : 1;
568 }
569 else if ( mode == "move" ) // C-FIND SCU
570 {
571 // ./bin/gdcmscu --move --patient dhcp-67-183 5678 move
572 // ./bin/gdcmscu --move --patient mi2b2.slicer.org 11112 move
573 gdcm::ERootType theRoot = gdcm::eStudyRootType;
574 if (findpatientroot)
575 theRoot = gdcm::ePatientRootType;
576 gdcm::EQueryLevel theLevel = gdcm::eStudy;
577 if (patientquery)
578 theLevel = gdcm::ePatient;
579 if (seriesquery)
580 theLevel = gdcm::eSeries;
581 if (imagequery)
582 theLevel = gdcm::eImage;
583
584 gdcm::SmartPointer<gdcm::BaseRootQuery> theQuery =
585 gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys, gdcm::eMove );
586
587 if (findstudyroot == 0 && findpatientroot == 0)
588 {
589 if (gdcm::Trace::GetErrorFlag())
590 {
591 std::cerr << "Need to explicitly choose query retrieve level, --patientroot or --studyroot" << std::endl;
592 }
593 std::cerr << "Move failed." << std::endl;
594 return 1;
595 }
596
597 if( !portscp )
598 {
599 std::cerr << "Need to set explicitly port number for SCP association"
600 " --port-scp" << std::endl;
601 //std::cerr << "Move failed." << std::endl;
602 return 1;
603 }
604
605 if( storequery )
606 {
607 if (!theQuery->WriteQuery(queryfile))
608 {
609 std::cerr << "Could not write out query to: " << queryfile << std::endl;
610 std::cerr << "Move failed." << std::endl;
611 return 1;
612 }
613 }
614
615 if (!theQuery->ValidateQuery(false))
616 {
617 std::cerr << "You have not constructed a valid find query."
618 " Please try again." << std::endl;
619 return 1;
620 }
621
622 //!!! added the boolean to 'interleave writing', which basically writes
623 //each file out as it comes across, rather than all at once at the end.
624 //Turn off the boolean to have it written all at once at the end.
625 bool didItWork = gdcm::CompositeNetworkFunctions::CMove( hostname, (uint16_t)port,
626 theQuery, (uint16_t)portscpnum,
627 callingaetitle.c_str(), callaetitle.c_str(), outputdir.c_str() );
628 gdcmDebugMacro( (didItWork ? "Move succeeded." : "Move failed.") );
629 return didItWork ? 0 : 1;
630 }
631 else if ( mode == "worklist" )
632 {
633 gdcm::ERootType theRoot = gdcm::ePatientRootType;
634 gdcm::EQueryLevel theLevel = gdcm::eSeries;
635 gdcm::SmartPointer<gdcm::BaseRootQuery> theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery( theRoot, theLevel ,keys, gdcm::eWLMFind );
636 if (!theQuery->ValidateQuery(false))
637 {
638 //issue
639 }
640 std::vector<gdcm::DataSet> theDataSet;
641 if( !gdcm::CompositeNetworkFunctions::CFind(hostname, (uint16_t)port, theQuery, theDataSet,
642 callingaetitle.c_str(), callaetitle.c_str()) )
643 {
644 }
645 gdcm::Printer p;
646 std::ostream &os = gdcm::Trace::GetStream();
647 for( std::vector<gdcm::DataSet>::iterator itor
648 = theDataSet.begin(); itor != theDataSet.end(); itor++)
649 {
650 os << "WL Find Response: " << (itor - theDataSet.begin() + 1) << std::endl;
651 p.PrintDataSet( *itor, os );
652 os << std::endl;
653 }
654
655 if( gdcm::Trace::GetWarningFlag() ) // == verbose flag
656 {
657 os << "WL Find was successful." << std::endl;
658 }
659 }
660 else if ( mode == "find" ) // C-FIND SCU
661 {
662 // Construct C-FIND DataSet:
663 // ./bin/gdcmscu --find --patient dhcp-67-183 5678
664 // ./bin/gdcmscu --find --patient mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2
665 // findscu -aec MI2B2 -P -k 0010,0010=F* mi2b2.slicer.org 11112 patqry.dcm
666
667 // PATIENT query:
668 // ./bin/gdcmscu --find --patient mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2 --key 10,10="F*" -V
669 gdcm::ERootType theRoot = gdcm::eStudyRootType;
670 if (findpatientroot)
671 theRoot = gdcm::ePatientRootType;
672 gdcm::EQueryLevel theLevel = gdcm::eStudy;
673 if (patientquery)
674 theLevel = gdcm::ePatient;
675 if (seriesquery)
676 theLevel = gdcm::eSeries;
677 if (imagequery)
678 theLevel = gdcm::eImage;
679
680 gdcm::SmartPointer<gdcm::BaseRootQuery> theQuery =
681 gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys);
682
683 if (findstudyroot == 0 && findpatientroot == 0)
684 {
685 if (gdcm::Trace::GetErrorFlag())
686 {
687 std::cerr << "Need to explicitly choose query retrieve level, --patientroot or --studyroot" << std::endl;
688 }
689 std::cerr << "Find failed." << std::endl;
690 return 1;
691 }
692 if (!theQuery)
693 {
694 std::cerr << "Query construction failed." <<std::endl;
695 return 1;
696 }
697
698 if( storequery )
699 {
700 if (!theQuery->WriteQuery(queryfile))
701 {
702 std::cerr << "Could not write out query to: " << queryfile << std::endl;
703 return 1;
704 }
705 }
706
707 //doing a non-strict query, the second parameter there.
708 //look at the base query comments
709 if (!theQuery->ValidateQuery(false))
710 {
711 std::cerr << "You have not constructed a valid find query."
712 " Please try again." << std::endl;
713 return 1;
714 }
715 //the value in that tag corresponds to the query type
716 std::vector<gdcm::DataSet> theDataSet;
717 if( !gdcm::CompositeNetworkFunctions::CFind(hostname, (uint16_t)port, theQuery, theDataSet,
718 callingaetitle.c_str(), callaetitle.c_str()) )
719 {
720 gdcmDebugMacro( "Problem in CFind." );
721 return 1;
722 }
723
724 gdcm::Printer p;
725 std::ostream &os = gdcm::Trace::GetStream();
726 for( std::vector<gdcm::DataSet>::iterator itor
727 = theDataSet.begin(); itor != theDataSet.end(); itor++)
728 {
729 os << "Find Response: " << (itor - theDataSet.begin() + 1) << std::endl;
730 p.PrintDataSet( *itor, os );
731 os << std::endl;
732 }
733
734 if( gdcm::Trace::GetWarningFlag() ) // == verbose flag
735 {
736 os << "Find was successful." << std::endl;
737 }
738 return 0;
739 }
740 else if ( mode == "store" ) // C-STORE SCU
741 {
742 // mode == directory
743 gdcm::Directory::FilenamesType thefiles;
744 for( gdcm::Directory::FilenamesType::const_iterator file = filenames.begin();
745 file != filenames.end(); ++file )
746 {
747 if( gdcm::System::FileIsDirectory(file->c_str()) )
748 {
749 gdcm::Directory::FilenamesType files;
750 gdcm::Directory dir;
751 dir.Load(*file, theRecursive);
752 files = dir.GetFilenames();
753 thefiles.insert(thefiles.end(), files.begin(), files.end());
754 }
755 else
756 {
757 // This is a file simply add it
758 thefiles.push_back(*file);
759 }
760 }
761 bool didItWork =
762 gdcm::CompositeNetworkFunctions::CStore(hostname, (uint16_t)port, thefiles,
763 callingaetitle.c_str(), callaetitle.c_str());
764
765 gdcmDebugMacro( (didItWork ? "Store was successful." : "Store failed.") );
766 return didItWork ? 0 : 1;
767 }
768 else if ( mode == "get" ) // C-GET SCU
769 {
770 return 1;
771 }
772 else
773 {
774 assert( 0 );
775 return 1;
776 }
777
778 return 0;
779 }
780