PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
worklist_cli::worklist_result_formatter Class Reference

Result formatter for worklist query results. More...

#include <worklist_result_formatter.h>

Collaboration diagram for worklist_cli::worklist_result_formatter:
Collaboration graph

Classes

struct  worklist_item
 Worklist item data extracted for display. More...
 

Public Member Functions

 worklist_result_formatter (output_format format)
 Construct formatter with output format.
 
std::string format (const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
 Format worklist results.
 

Private Member Functions

worklist_item extract_item (const kcenon::pacs::core::dicom_dataset &ds) const
 Extract worklist item data from dataset.
 
std::string format_table (const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
 Format results as a human-readable table.
 
std::string format_json (const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
 Format results as JSON.
 
std::string format_csv (const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
 Format results as CSV.
 
std::string format_xml (const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
 Format results as XML.
 

Static Private Member Functions

static std::string truncate (const std::string &s, size_t max_len)
 Truncate string to max length.
 
static std::string format_date (const std::string &date)
 Format DICOM date (YYYYMMDD) for display.
 
static std::string format_time (const std::string &time)
 Format DICOM time (HHMMSS) for display.
 
static std::string escape_json (const std::string &s)
 Escape string for JSON output.
 
static std::string escape_csv (const std::string &s)
 Escape string for CSV output.
 
static std::string escape_xml (const std::string &s)
 Escape string for XML output.
 

Private Attributes

output_format format_
 

Detailed Description

Result formatter for worklist query results.

Formats MWL C-FIND query results for display in different output formats. Handles the complexity of extracting data from the Scheduled Procedure Step Sequence.

Examples
worklist_scu/main.cpp.

Definition at line 55 of file worklist_result_formatter.h.

Constructor & Destructor Documentation

◆ worklist_result_formatter()

worklist_cli::worklist_result_formatter::worklist_result_formatter ( output_format format)
inlineexplicit

Construct formatter with output format.

Parameters
formatThe output format to use

Definition at line 61 of file worklist_result_formatter.h.

Member Function Documentation

◆ escape_csv()

static std::string worklist_cli::worklist_result_formatter::escape_csv ( const std::string & s)
inlinestaticnodiscardprivate

Escape string for CSV output.

Definition at line 411 of file worklist_result_formatter.h.

411 {
412 if (s.find_first_of(",\"\n\r") == std::string::npos) {
413 return s;
414 }
415
416 std::string result = "\"";
417 for (char c : s) {
418 if (c == '"') {
419 result += "\"\"";
420 } else {
421 result += c;
422 }
423 }
424 result += "\"";
425 return result;
426 }

Referenced by format_csv().

Here is the caller graph for this function:

◆ escape_json()

static std::string worklist_cli::worklist_result_formatter::escape_json ( const std::string & s)
inlinestaticnodiscardprivate

Escape string for JSON output.

Definition at line 381 of file worklist_result_formatter.h.

381 {
382 std::string result;
383 result.reserve(s.length());
384 for (char c : s) {
385 switch (c) {
386 case '"': result += "\\\""; break;
387 case '\\': result += "\\\\"; break;
388 case '\b': result += "\\b"; break;
389 case '\f': result += "\\f"; break;
390 case '\n': result += "\\n"; break;
391 case '\r': result += "\\r"; break;
392 case '\t': result += "\\t"; break;
393 default:
394 if (static_cast<unsigned char>(c) < 0x20) {
395 result += "\\u";
396 char buf[5];
397 std::snprintf(buf, sizeof(buf), "%04X",
398 static_cast<unsigned char>(c));
399 result += buf;
400 } else {
401 result += c;
402 }
403 }
404 }
405 return result;
406 }

Referenced by format_json().

Here is the caller graph for this function:

◆ escape_xml()

static std::string worklist_cli::worklist_result_formatter::escape_xml ( const std::string & s)
inlinestaticnodiscardprivate

Escape string for XML output.

Definition at line 431 of file worklist_result_formatter.h.

431 {
432 std::string result;
433 result.reserve(s.length());
434 for (char c : s) {
435 switch (c) {
436 case '&': result += "&amp;"; break;
437 case '<': result += "&lt;"; break;
438 case '>': result += "&gt;"; break;
439 case '"': result += "&quot;"; break;
440 case '\'': result += "&apos;"; break;
441 default: result += c;
442 }
443 }
444 return result;
445 }

Referenced by format_xml().

Here is the caller graph for this function:

◆ extract_item()

worklist_item worklist_cli::worklist_result_formatter::extract_item ( const kcenon::pacs::core::dicom_dataset & ds) const
inlinenodiscardprivate

Extract worklist item data from dataset.

Note
This implementation uses a flat dataset structure without nested sequences. The Scheduled Procedure Step attributes are extracted directly from the main dataset.

Definition at line 116 of file worklist_result_formatter.h.

117 {
118 using namespace kcenon::pacs::core;
119
120 worklist_item item;
121
122 // Patient demographics
123 item.patient_name = ds.get_string(tags::patient_name);
124 item.patient_id = ds.get_string(tags::patient_id);
125 item.patient_birth_date = ds.get_string(tags::patient_birth_date);
126 item.patient_sex = ds.get_string(tags::patient_sex);
127
128 // Study-level attributes
129 item.accession_number = ds.get_string(tags::accession_number);
130 item.study_uid = ds.get_string(tags::study_instance_uid);
131 item.requested_procedure_id = ds.get_string(tags::requested_procedure_id);
132
133 // Scheduled Procedure Step attributes (flat structure)
134 item.scheduled_date = ds.get_string(tags::scheduled_procedure_step_start_date);
135 item.scheduled_time = ds.get_string(tags::scheduled_procedure_step_start_time);
136 item.modality = ds.get_string(tags::modality);
137 item.station_ae = ds.get_string(tags::scheduled_station_ae_title);
138 item.step_id = ds.get_string(tags::scheduled_procedure_step_id);
139 item.step_description = ds.get_string(tags::scheduled_procedure_step_description);
140
141 return item;
142 }
auto get_string(dicom_tag tag, std::string_view default_value="") const -> std::string
Get the string value of an element.
constexpr dicom_tag item
Item.

References kcenon::pacs::core::dicom_dataset::get_string().

Referenced by format_csv(), format_json(), format_table(), and format_xml().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format()

std::string worklist_cli::worklist_result_formatter::format ( const std::vector< kcenon::pacs::core::dicom_dataset > & results) const
inlinenodiscard

Format worklist results.

Parameters
resultsVector of result datasets
Returns
Formatted string output
Examples
worklist_scu/main.cpp.

Definition at line 69 of file worklist_result_formatter.h.

70 {
71 switch (format_) {
73 return format_json(results);
75 return format_csv(results);
77 return format_xml(results);
79 default:
80 return format_table(results);
81 }
82 }
std::string format_xml(const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
Format results as XML.
std::string format_table(const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
Format results as a human-readable table.
std::string format_json(const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
Format results as JSON.
std::string format_csv(const std::vector< kcenon::pacs::core::dicom_dataset > &results) const
Format results as CSV.
@ xml
XML format for integration.
@ json
JSON format for integration.
@ csv
CSV format for export.
@ table
Human-readable table format (alias: text)

References worklist_cli::csv, format_, format_csv(), format_json(), format_table(), format_xml(), worklist_cli::json, worklist_cli::table, and worklist_cli::xml.

Here is the call graph for this function:

◆ format_csv()

std::string worklist_cli::worklist_result_formatter::format_csv ( const std::vector< kcenon::pacs::core::dicom_dataset > & results) const
inlinenodiscardprivate

Format results as CSV.

Definition at line 268 of file worklist_result_formatter.h.

269 {
270 std::ostringstream oss;
271
272 // Header row
273 oss << "PatientName,PatientID,BirthDate,Sex,"
274 << "ScheduledDate,ScheduledTime,Modality,StationAE,"
275 << "StepID,StepDescription,AccessionNumber,StudyUID,RequestedProcedureID\n";
276
277 // Data rows
278 for (const auto& r : results) {
279 auto item = extract_item(r);
280
281 oss << escape_csv(item.patient_name) << ","
282 << escape_csv(item.patient_id) << ","
283 << item.patient_birth_date << ","
284 << item.patient_sex << ","
285 << item.scheduled_date << ","
286 << item.scheduled_time << ","
287 << item.modality << ","
288 << escape_csv(item.station_ae) << ","
289 << escape_csv(item.step_id) << ","
290 << escape_csv(item.step_description) << ","
291 << escape_csv(item.accession_number) << ","
292 << item.study_uid << ","
293 << escape_csv(item.requested_procedure_id) << "\n";
294 }
295
296 return oss.str();
297 }
static std::string escape_csv(const std::string &s)
Escape string for CSV output.
worklist_item extract_item(const kcenon::pacs::core::dicom_dataset &ds) const
Extract worklist item data from dataset.

References escape_csv(), and extract_item().

Referenced by format().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_date()

static std::string worklist_cli::worklist_result_formatter::format_date ( const std::string & date)
inlinestaticnodiscardprivate

Format DICOM date (YYYYMMDD) for display.

Definition at line 361 of file worklist_result_formatter.h.

361 {
362 if (date.length() == 8) {
363 return date.substr(0, 4) + "-" + date.substr(4, 2) + "-" + date.substr(6, 2);
364 }
365 return date;
366 }

Referenced by format_table().

Here is the caller graph for this function:

◆ format_json()

std::string worklist_cli::worklist_result_formatter::format_json ( const std::vector< kcenon::pacs::core::dicom_dataset > & results) const
inlinenodiscardprivate

Format results as JSON.

Definition at line 222 of file worklist_result_formatter.h.

223 {
224 std::ostringstream oss;
225
226 oss << "{\n";
227 oss << " \"resultCount\": " << results.size() << ",\n";
228 oss << " \"worklistItems\": [\n";
229
230 for (size_t i = 0; i < results.size(); ++i) {
231 auto item = extract_item(results[i]);
232
233 oss << " {\n";
234 oss << " \"patient\": {\n";
235 oss << " \"name\": \"" << escape_json(item.patient_name) << "\",\n";
236 oss << " \"id\": \"" << escape_json(item.patient_id) << "\",\n";
237 oss << " \"birthDate\": \"" << item.patient_birth_date << "\",\n";
238 oss << " \"sex\": \"" << item.patient_sex << "\"\n";
239 oss << " },\n";
240 oss << " \"scheduledProcedureStep\": {\n";
241 oss << " \"startDate\": \"" << item.scheduled_date << "\",\n";
242 oss << " \"startTime\": \"" << item.scheduled_time << "\",\n";
243 oss << " \"modality\": \"" << item.modality << "\",\n";
244 oss << " \"stationAETitle\": \"" << escape_json(item.station_ae) << "\",\n";
245 oss << " \"stepId\": \"" << escape_json(item.step_id) << "\",\n";
246 oss << " \"description\": \"" << escape_json(item.step_description) << "\"\n";
247 oss << " },\n";
248 oss << " \"accessionNumber\": \"" << escape_json(item.accession_number) << "\",\n";
249 oss << " \"studyInstanceUid\": \"" << item.study_uid << "\",\n";
250 oss << " \"requestedProcedureId\": \"" << escape_json(item.requested_procedure_id) << "\"\n";
251 oss << " }";
252
253 if (i < results.size() - 1) {
254 oss << ",";
255 }
256 oss << "\n";
257 }
258
259 oss << " ]\n";
260 oss << "}\n";
261
262 return oss.str();
263 }
static std::string escape_json(const std::string &s)
Escape string for JSON output.

References escape_json(), and extract_item().

Referenced by format().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_table()

std::string worklist_cli::worklist_result_formatter::format_table ( const std::vector< kcenon::pacs::core::dicom_dataset > & results) const
inlinenodiscardprivate

Format results as a human-readable table.

Definition at line 147 of file worklist_result_formatter.h.

148 {
149 std::ostringstream oss;
150
151 if (results.empty()) {
152 oss << "No worklist items found.\n";
153 return oss.str();
154 }
155
156 // Extract all items
157 std::vector<worklist_item> items;
158 items.reserve(results.size());
159 for (const auto& r : results) {
160 items.push_back(extract_item(r));
161 }
162
163 // Define column widths
164 size_t w_name = 20, w_id = 12, w_date = 10, w_time = 8;
165 size_t w_mod = 6, w_station = 16, w_accession = 12, w_step = 12;
166
167 // Update widths based on data
168 for (const auto& item : items) {
169 w_name = std::min(size_t(30), std::max(w_name, item.patient_name.length()));
170 w_id = std::min(size_t(20), std::max(w_id, item.patient_id.length()));
171 w_station = std::min(size_t(20), std::max(w_station, item.station_ae.length()));
172 w_accession = std::min(size_t(20), std::max(w_accession, item.accession_number.length()));
173 w_step = std::min(size_t(20), std::max(w_step, item.step_id.length()));
174 }
175
176 // Print header
177 oss << "\n=== Worklist Results (" << results.size() << " scheduled procedure(s)) ===\n\n";
178
179 // Print column headers
180 oss << std::left
181 << std::setw(static_cast<int>(w_name + 2)) << "Patient Name"
182 << std::setw(static_cast<int>(w_id + 2)) << "Patient ID"
183 << std::setw(static_cast<int>(w_date + 2)) << "Sched Date"
184 << std::setw(static_cast<int>(w_time + 2)) << "Time"
185 << std::setw(static_cast<int>(w_mod + 2)) << "Mod"
186 << std::setw(static_cast<int>(w_station + 2)) << "Station AE"
187 << std::setw(static_cast<int>(w_accession + 2)) << "Accession#"
188 << std::setw(static_cast<int>(w_step + 2)) << "Step ID"
189 << "\n";
190
191 // Print separator
192 oss << std::string(w_name, '-') << " "
193 << std::string(w_id, '-') << " "
194 << std::string(w_date, '-') << " "
195 << std::string(w_time, '-') << " "
196 << std::string(w_mod, '-') << " "
197 << std::string(w_station, '-') << " "
198 << std::string(w_accession, '-') << " "
199 << std::string(w_step, '-') << " "
200 << "\n";
201
202 // Print data rows
203 for (const auto& item : items) {
204 oss << std::left
205 << std::setw(static_cast<int>(w_name + 2)) << truncate(item.patient_name, w_name)
206 << std::setw(static_cast<int>(w_id + 2)) << truncate(item.patient_id, w_id)
207 << std::setw(static_cast<int>(w_date + 2)) << format_date(item.scheduled_date)
208 << std::setw(static_cast<int>(w_time + 2)) << format_time(item.scheduled_time)
209 << std::setw(static_cast<int>(w_mod + 2)) << item.modality
210 << std::setw(static_cast<int>(w_station + 2)) << truncate(item.station_ae, w_station)
211 << std::setw(static_cast<int>(w_accession + 2)) << truncate(item.accession_number, w_accession)
212 << std::setw(static_cast<int>(w_step + 2)) << truncate(item.step_id, w_step)
213 << "\n";
214 }
215
216 return oss.str();
217 }
static std::string truncate(const std::string &s, size_t max_len)
Truncate string to max length.
static std::string format_time(const std::string &time)
Format DICOM time (HHMMSS) for display.
static std::string format_date(const std::string &date)
Format DICOM date (YYYYMMDD) for display.

References extract_item(), format_date(), format_time(), and truncate().

Referenced by format().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ format_time()

static std::string worklist_cli::worklist_result_formatter::format_time ( const std::string & time)
inlinestaticnodiscardprivate

Format DICOM time (HHMMSS) for display.

Definition at line 371 of file worklist_result_formatter.h.

371 {
372 if (time.length() >= 4) {
373 return time.substr(0, 2) + ":" + time.substr(2, 2);
374 }
375 return time;
376 }

Referenced by format_table().

Here is the caller graph for this function:

◆ format_xml()

std::string worklist_cli::worklist_result_formatter::format_xml ( const std::vector< kcenon::pacs::core::dicom_dataset > & results) const
inlinenodiscardprivate

Format results as XML.

Definition at line 302 of file worklist_result_formatter.h.

303 {
304 std::ostringstream oss;
305
306 oss << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
307 oss << "<WorklistQueryResult>\n";
308 oss << " <ResultCount>" << results.size() << "</ResultCount>\n";
309 oss << " <WorklistItems>\n";
310
311 for (size_t i = 0; i < results.size(); ++i) {
312 auto item = extract_item(results[i]);
313
314 oss << " <WorklistItem index=\"" << (i + 1) << "\">\n";
315
316 // Patient information
317 oss << " <Patient>\n";
318 oss << " <Name>" << escape_xml(item.patient_name) << "</Name>\n";
319 oss << " <ID>" << escape_xml(item.patient_id) << "</ID>\n";
320 oss << " <BirthDate>" << item.patient_birth_date << "</BirthDate>\n";
321 oss << " <Sex>" << item.patient_sex << "</Sex>\n";
322 oss << " </Patient>\n";
323
324 // Scheduled Procedure Step
325 oss << " <ScheduledProcedureStep>\n";
326 oss << " <StartDate>" << item.scheduled_date << "</StartDate>\n";
327 oss << " <StartTime>" << item.scheduled_time << "</StartTime>\n";
328 oss << " <Modality>" << item.modality << "</Modality>\n";
329 oss << " <StationAETitle>" << escape_xml(item.station_ae) << "</StationAETitle>\n";
330 oss << " <StepID>" << escape_xml(item.step_id) << "</StepID>\n";
331 oss << " <Description>" << escape_xml(item.step_description) << "</Description>\n";
332 oss << " </ScheduledProcedureStep>\n";
333
334 // Study information
335 oss << " <AccessionNumber>" << escape_xml(item.accession_number) << "</AccessionNumber>\n";
336 oss << " <StudyInstanceUID>" << item.study_uid << "</StudyInstanceUID>\n";
337 oss << " <RequestedProcedureID>" << escape_xml(item.requested_procedure_id) << "</RequestedProcedureID>\n";
338
339 oss << " </WorklistItem>\n";
340 }
341
342 oss << " </WorklistItems>\n";
343 oss << "</WorklistQueryResult>\n";
344
345 return oss.str();
346 }
static std::string escape_xml(const std::string &s)
Escape string for XML output.

References escape_xml(), and extract_item().

Referenced by format().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ truncate()

static std::string worklist_cli::worklist_result_formatter::truncate ( const std::string & s,
size_t max_len )
inlinestaticnodiscardprivate

Truncate string to max length.

Definition at line 351 of file worklist_result_formatter.h.

351 {
352 if (s.length() <= max_len) {
353 return s;
354 }
355 return s.substr(0, max_len - 3) + "...";
356 }

Referenced by format_table().

Here is the caller graph for this function:

Member Data Documentation

◆ format_

output_format worklist_cli::worklist_result_formatter::format_
private

Definition at line 447 of file worklist_result_formatter.h.

Referenced by format().


The documentation for this class was generated from the following file: