1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.commons.ihe.xds.core.transform.requests.query;
17
18 import ca.uhn.hl7v2.model.Composite;
19 import org.apache.commons.lang3.StringUtils;
20 import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLAdhocQueryRequest;
21 import org.openehealth.ipf.commons.ihe.xds.core.ebxml.EbXMLSlot;
22 import org.openehealth.ipf.commons.ihe.xds.core.metadata.*;
23 import org.openehealth.ipf.commons.ihe.xds.core.requests.query.QueryList;
24 import org.openehealth.ipf.commons.ihe.xds.core.transform.requests.QueryParameter;
25 import org.openehealth.ipf.commons.ihe.xds.core.validate.ValidationMessage;
26 import org.openehealth.ipf.commons.ihe.xds.core.validate.XDSMetaDataException;
27
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.stream.Collectors;
31
32 import static org.apache.commons.lang3.StringUtils.isEmpty;
33 import static org.apache.commons.lang3.StringUtils.isNotBlank;
34 import static org.apache.commons.lang3.Validate.notNull;
35 import static org.apache.commons.lang3.Validate.noNullElements;
36
37
38
39
40
41
42
43
44
45
46
47 public class QuerySlotHelper {
48
49 private final EbXMLAdhocQueryRequest ebXML;
50
51
52
53
54
55
56 public QuerySlotHelper(EbXMLAdhocQueryRequest ebXML) {
57 notNull(ebXML, "ebXML cannot be null");
58 this.ebXML = ebXML;
59 }
60
61
62
63
64
65
66
67 public String toString(QueryParameter param) {
68 String value = ebXML.getSingleSlotValue(param.getSlotName());
69 return decodeString(value);
70 }
71
72
73
74
75
76
77
78
79 public void fromString(QueryParameter param, String value) {
80 if (value != null) {
81 ebXML.addSlot(param.getSlotName(), encodeAsString(value));
82 }
83 }
84
85
86
87
88
89
90
91
92 public void fromCode(QueryParameter param, List<Code> codes) {
93 if (codes == null) {
94 return;
95 }
96
97 List<String> slotValues = new ArrayList<>();
98 for (Code code : codes) {
99 String hl7CE = Hl7v2Based.render(code);
100 slotValues.add(encodeAsStringList(hl7CE));
101 }
102 ebXML.addSlot(param.getSlotName(), slotValues.toArray(new String[slotValues.size()]));
103 }
104
105
106
107
108
109
110
111
112 public void fromCode(QueryParameter param, QueryList<Code> queryList) {
113 if (queryList == null) {
114 return;
115 }
116
117 for (List<Code> codes : queryList.getOuterList()) {
118 fromCode(param, codes);
119 }
120 }
121
122 private QueryList<Code> toCodeQueryList(QueryParameter param) {
123 List<EbXMLSlot> slots = ebXML.getSlots(param.getSlotName());
124 if (slots.isEmpty()) {
125 return null;
126 }
127
128 QueryList<Code> queryList = new QueryList<>();
129 for (EbXMLSlot slot : slots) {
130 List<Code> innerList = toCode(slot.getValueList());
131 queryList.getOuterList().add(innerList);
132 }
133 return queryList;
134 }
135
136
137
138
139
140
141
142 public QueryList<String> toStringQueryList(QueryParameter param) {
143 return toStringQueryList(param.getSlotName());
144 }
145
146
147
148
149
150
151
152
153 public QueryList<String> toStringQueryList(String slotName) {
154 if (isEmpty(slotName)) {
155 return null;
156 }
157
158 List<EbXMLSlot> slots = ebXML.getSlots(slotName);
159 if (slots.isEmpty()) {
160 return null;
161 }
162
163 QueryList<String> queryList = new QueryList<>();
164 for (EbXMLSlot slot : slots) {
165 List<String> innerList = new ArrayList<>();
166 for (String slotValue : slot.getValueList()) {
167 innerList.addAll(decodeStringList(slotValue));
168 }
169 queryList.getOuterList().add(innerList);
170 }
171 return queryList;
172 }
173
174
175
176
177
178
179
180
181 public void fromStringList(QueryParameter param, List<String> values) {
182 fromStringList(param.getSlotName(), values);
183 }
184
185
186
187
188
189
190
191
192
193 public void fromStringList(String slotName, List<String> values) {
194 if (isEmpty(slotName) || (values == null)) {
195 return;
196 }
197
198 String[] slotValues = values.stream()
199 .map(QuerySlotHelper::encodeAsStringList)
200 .toArray(String[]::new);
201 ebXML.addSlot(slotName, slotValues);
202 }
203
204
205
206
207
208
209
210
211 public void fromStringList(QueryParameter param, QueryList<String> queryList) {
212 fromStringList(param.getSlotName(), queryList);
213 }
214
215
216
217
218
219
220
221
222
223 public void fromStringList(String slotName, QueryList<String> queryList) {
224 if (isEmpty(slotName) || (queryList == null)) {
225 return;
226 }
227
228 for (List<String> list : queryList.getOuterList()) {
229 fromStringList(slotName, list);
230 }
231 }
232
233
234
235
236
237
238
239 public List<String> toStringList(QueryParameter param) {
240 List<String> slotValues = ebXML.getSlotValues(param.getSlotName());
241 if (slotValues.isEmpty()) {
242 return null;
243 }
244
245 List<String> values = new ArrayList<>();
246 for (String slotValue : slotValues) {
247 values.addAll(decodeStringList(slotValue));
248 }
249 return values;
250 }
251
252
253
254
255
256
257
258
259
260 public void fromPatientIdList(QueryParameter param, List<Identifiable> values) {
261 if (values == null) {
262 return;
263 }
264
265 String[] slotValues = values.stream()
266 .map(value -> encodeAsStringList(Hl7v2Based.render(value)))
267 .toArray(String[]::new);
268 ebXML.addSlot(param.getSlotName(), slotValues);
269 }
270
271
272
273
274
275
276
277 public List<Identifiable> toPatientIdList(QueryParameter param) {
278 List<String> values = toStringList(param);
279 if (values == null) {
280 return null;
281 }
282
283 List<Identifiable> patientIds = new ArrayList<>();
284 for (String value : values) {
285 patientIds.add(Hl7v2Based.parse(value, Identifiable.class));
286 }
287 return patientIds;
288 }
289
290
291
292
293
294
295
296 public List<Code> toCodeList(QueryParameter param) {
297 return toCode(ebXML.getSlotValues(param.getSlotName()));
298 }
299
300
301
302
303
304
305
306
307
308 public QueryList<Code> toCodeQueryList(QueryParameter param, QueryParameter schemeParam) {
309 QueryList<Code> codes = toCodeQueryList(param);
310 if (codes == null) {
311 return null;
312 }
313
314 QueryList<String> schemes = toStringQueryList(schemeParam);
315 if (schemes != null) {
316 List<List<String>> schemesOuter = schemes.getOuterList();
317 List<List<Code>> codesOuter = codes.getOuterList();
318 for (int outer = 0; outer < schemesOuter.size() && outer < codesOuter.size(); ++outer) {
319 List<String> schemesInner = schemesOuter.get(outer);
320 List<Code> codesInner = codesOuter.get(outer);
321 for (int inner = 0; inner < schemesInner.size() && inner < codesInner.size(); ++inner) {
322 codesInner.get(inner).setSchemeName(schemesInner.get(inner));
323 }
324 }
325 }
326 return codes;
327 }
328
329
330
331
332
333
334
335
336 public void fromNumber(QueryParameter param, String value) {
337 ebXML.addSlot(param.getSlotName(), value);
338 }
339
340
341
342
343
344
345
346 public String toNumber(QueryParameter param) {
347 return ebXML.getSingleSlotValue(param.getSlotName());
348 }
349
350
351
352
353
354
355
356
357 public void fromStatus(QueryParameter param, List<AvailabilityStatus> status) {
358 if (status == null) {
359 return;
360 }
361 List<String> opcodes = status.stream()
362 .map(AvailabilityStatus::toQueryOpcode)
363 .collect(Collectors.toList());
364 fromStringList(param, opcodes);
365 }
366
367
368
369
370
371
372
373 public List<AvailabilityStatus> toStatus(QueryParameter param) {
374 List<String> opcodes = toStringList(param);
375 if (opcodes == null) {
376 return null;
377 }
378
379 List<AvailabilityStatus> list = new ArrayList<>();
380 for (String opcode : opcodes) {
381 AvailabilityStatus status = AvailabilityStatus.valueOfOpcode(opcode);
382 if (status != null) {
383 list.add(status);
384 }
385 }
386 return list;
387 }
388
389
390
391
392
393
394
395
396 public void fromAssociationType(QueryParameter param, List<AssociationType> associationTypes) {
397 if (associationTypes == null) {
398 return;
399 }
400
401 List<String> opcodes = associationTypes.stream()
402 .map(type -> AssociationType.getOpcode30(type))
403 .collect(Collectors.toList());
404 fromStringList(param, opcodes);
405 }
406
407
408
409
410
411
412
413 public List<AssociationType> toAssociationType(QueryParameter param) {
414 List<String> opcodes = toStringList(param);
415 if (opcodes == null) {
416 return null;
417 }
418
419 return opcodes.stream()
420 .map(AssociationType::valueOfOpcode30)
421 .collect(Collectors.toList());
422 }
423
424 public void fromDocumentEntryType(QueryParameter param, List<DocumentEntryType> documentEntryTypes) {
425 if (documentEntryTypes == null) {
426 return;
427 }
428
429 List<String> uuids = documentEntryTypes.stream()
430 .map(DocumentEntryType::toUuid)
431 .collect(Collectors.toList());
432 fromStringList(param, uuids);
433 }
434
435 public List<DocumentEntryType> toDocumentEntryType(QueryParameter param) {
436 List<String> uuids = toStringList(param);
437 if (uuids == null) {
438 return null;
439 }
440
441 return uuids.stream()
442 .map(DocumentEntryType::valueOfUuid)
443 .collect(Collectors.toList());
444 }
445
446 public static List<Code> toCode(List<String> slotValues) {
447 if (slotValues.isEmpty()) {
448 return null;
449 }
450
451 List<Code> codes = new ArrayList<>();
452 for (String slotValue : slotValues) {
453 for (String hl7CE : decodeStringList(slotValue)) {
454 Code code = Hl7v2Based.parse(hl7CE, Code.class);
455 if (code == null || StringUtils.isEmpty(code.getCode()) || StringUtils.isEmpty(code.getSchemeName())) {
456 throw new XDSMetaDataException(ValidationMessage.INVALID_QUERY_PARAMETER_VALUE, hl7CE);
457 }
458 codes.add(code);
459 }
460 }
461 return codes;
462 }
463
464
465
466
467
468
469
470
471
472 public void fromDocumentAvailability(QueryParameter param, List<DocumentAvailability> status) {
473 if (status == null) {
474 return;
475 }
476
477 List<String> opcodes = status.stream()
478 .map(DocumentAvailability::toFullQualifiedOpcode)
479 .collect(Collectors.toList());
480 fromStringList(param, opcodes);
481 }
482
483
484
485
486
487
488
489 public List<DocumentAvailability> toDocumentAvailability(QueryParameter param) {
490 List<String> opcodes = toStringList(param);
491 if (opcodes == null) {
492 return null;
493 }
494
495 List<DocumentAvailability> list = new ArrayList<>();
496 for (String opcode : opcodes) {
497 DocumentAvailability availability = DocumentAvailability.valueOfOpcode(opcode);
498 if (availability != null) {
499 list.add(availability);
500 }
501 }
502 return list;
503 }
504
505
506
507
508
509
510
511
512 public void fromInteger(QueryParameter param, Integer value) {
513 if (value == null){
514 return;
515 }
516 ebXML.addSlot(param.getSlotName(), String.valueOf(value));
517 }
518
519
520
521
522
523
524
525 public Integer toInteger(QueryParameter param) {
526 Integer result = null;
527 try {
528 String slotValue = ebXML.getSingleSlotValue(param.getSlotName());
529 if (StringUtils.isNotBlank(slotValue)) {
530 result = Integer.valueOf(slotValue);
531 }
532 } catch (NumberFormatException nfe){
533
534 }
535 return result;
536 }
537
538 public static String encodeAsString(String value) {
539 if (value == null) {
540 return null;
541 }
542 return "'" + value.replace("'", "''") + "'";
543 }
544
545 public static String decodeString(String value) {
546 if (value == null) {
547 return null;
548 }
549
550 if (value.startsWith("'") && value.endsWith("'")) {
551 value = value.substring(1, value.length() - 1);
552 }
553 return value.replaceAll("''", "'");
554 }
555
556 public static String encodeAsStringList(String value) {
557 if (value == null) {
558 return null;
559 }
560 return "('" + value.replace("'", "''") + "')";
561 }
562
563 public static List<String> decodeStringList(String list) {
564 if (list == null) {
565 return null;
566 }
567
568 list = list.trim();
569 if (list.startsWith("(")) {
570 list = list.substring(1);
571 }
572 if (list.endsWith(")")) {
573 list = list.substring(0, list.length() - 1);
574 }
575
576 List<String> values = new ArrayList<>();
577 for (String value: list.split(",")){
578 String decodedValue = isNotBlank(value)? decodeString(value.trim()): "";
579 values.add(decodedValue);
580 }
581 return values;
582 }
583
584 public static <T extends Hl7v2Based> QueryList<String> render(QueryList<T> source) {
585 if (source == null) {
586 return null;
587 }
588 noNullElements(source.getOuterList(), "outer list cannot contain NULL elements");
589 QueryList<String> target = new QueryList<>();
590 source.getOuterList().forEach(list -> target.getOuterList().add(render(list)));
591 return target;
592 }
593
594 public static <T extends Hl7v2Based> List<String> render(List<T> source) {
595 if (source == null) {
596 return null;
597 }
598 noNullElements(source, "list cannot contain NULL elements");
599 return source.stream()
600 .map(Hl7v2Based::render)
601 .collect(Collectors.toList());
602 }
603
604 public static <C extends Composite, T extends Hl7v2Based<C>> QueryList<T> parse(
605 QueryList<String> source,
606 Class<T> targetClass)
607 {
608 if (source == null) {
609 return null;
610 }
611 noNullElements(source.getOuterList(), "outer list cannot contain NULL elements");
612 QueryList<T> target = new QueryList<>();
613 source.getOuterList().forEach(list -> target.getOuterList().add(parse(list, targetClass)));
614 return target;
615 }
616
617 public static <C extends Composite, T extends Hl7v2Based<C>> List<T> parse(
618 List<String> source,
619 Class<T> targetClass)
620 {
621 if (source == null) {
622 return null;
623 }
624 noNullElements(source, "list cannot contain NULL elements");
625 return source.stream()
626 .map(value -> Hl7v2Based.parse(value, targetClass))
627 .collect(Collectors.toList());
628 }
629
630 }