1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package ca.uhn.hl7v2.model;
31
32 import java.lang.reflect.InvocationTargetException;
33 import java.util.ArrayList;
34 import java.util.List;
35
36 import ca.uhn.hl7v2.HL7Exception;
37 import ca.uhn.hl7v2.Location;
38 import ca.uhn.hl7v2.parser.EncodingCharacters;
39 import ca.uhn.hl7v2.parser.ModelClassFactory;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public abstract class AbstractSegment extends AbstractStructure implements
60 Segment {
61
62
63
64
65 static final String ERROR_MSH_1_OR_2_NOT_SET = "Can not invoke parse(String) on a segment if the encoding characters (MSH-1 and MSH-2) are not already correctly set on the message";
66
67 private static final long serialVersionUID = -6686329916234746948L;
68
69 private final List<List<Type>> fields;
70 private final List<Class<? extends Type>> types;
71 private final List<Boolean> required;
72 private final List<Integer> length;
73 private final List<Object> args;
74 private final List<Integer> maxReps;
75 private final List<String> names;
76
77
78
79
80
81
82
83
84
85
86
87 public AbstractSegment(Group parent, ModelClassFactory factory) {
88 super(parent);
89 this.fields = new ArrayList<>();
90 this.types = new ArrayList<>();
91 this.required = new ArrayList<>();
92 this.length = new ArrayList<>();
93 this.args = new ArrayList<>();
94 this.maxReps = new ArrayList<>();
95 this.names = new ArrayList<>();
96 }
97
98
99
100
101
102
103
104
105
106
107 public boolean accept(MessageVisitor visitor, Location location) throws HL7Exception {
108 if (visitor.start(this, location)) {
109 String[] names = getNames();
110 for (int i = 1; i <= names.length; i++) {
111 Fieldld.html#Field">Field f = new Field(getField(i), getMaxCardinality(i));
112 Location nextLocation = f.provideLocation(location, i, -1);
113 if (!f.accept(visitor, nextLocation))
114 break;
115 }
116 }
117 return visitor.end(this, location);
118 }
119
120 public Location/../ca/uhn/hl7v2/Location.html#Location">Location provideLocation(Location location, int index, int repetition) {
121 return new Location(location)
122 .withSegmentName(getName())
123 .withSegmentRepetition(repetition);
124 }
125
126
127
128
129
130
131 public Type[] getField(int number) throws HL7Exception {
132 List<Type> retVal = getFieldAsList(number);
133 return retVal.toArray(new Type[0]);
134
135
136
137 }
138
139
140
141
142 public boolean isEmpty() throws HL7Exception {
143 for (int i = 1; i <= numFields(); i++) {
144 Type[] types = getField(i);
145 for (Type type : types) {
146 if (!type.isEmpty()) return false;
147 }
148 }
149 return true;
150 }
151
152
153
154
155 protected <T extends Type> T[] getTypedField(int number, T[] array) {
156 try {
157 List<Type> retVal = getFieldAsList(number);
158 @SuppressWarnings("unchecked")
159 List<T> cast = (List<T>) retVal;
160 return cast.toArray(array);
161 } catch (ClassCastException | HL7Exception cce) {
162 log.error("Unexpected problem obtaining field value. This is a bug.", cce);
163 throw new RuntimeException(cce);
164 }
165 }
166
167
168 protected int getReps(int number) {
169 try {
170 return getFieldAsList(number).size();
171 } catch (HL7Exception he) {
172 log.error("Unexpected problem obtaining field value. This is a bug.", he);
173 throw new RuntimeException(he);
174 }
175 }
176
177 private List<Type> getFieldAsList(int number) throws HL7Exception {
178 ensureEnoughFields(number);
179
180 if (number < 1 || number > fields.size()) {
181 throw new HL7Exception("Can't retrieve field " + number
182 + " from segment " + this.getClass().getName()
183 + " - there are only " + fields.size() + " fields.");
184 }
185
186 return fields.get(number - 1);
187
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 public Type getField(int number, int rep) throws HL7Exception {
209
210 ensureEnoughFields(number);
211
212 if (number < 1 || number > fields.size()) {
213 throw new HL7Exception("Can't get field " + number + " in segment "
214 + getName() + " - there are currently only "
215 + fields.size() + " reps.");
216 }
217
218 List<Type> arr = fields.get(number - 1);
219
220
221 if (rep > arr.size())
222 throw new HL7Exception("Can't get repetition " + rep
223 + " from field " + number + " - there are currently only "
224 + arr.size() + " reps.");
225
226
227 if (rep == arr.size()) {
228 Type newType = createNewType(number);
229 arr.add(newType);
230 }
231
232 return arr.get(rep);
233 }
234
235
236
237
238 protected <T extends Type> T getTypedField(int number, int rep) {
239 try {
240 @SuppressWarnings("unchecked") T retVal = (T)getField(number, rep);
241 return retVal;
242 } catch (ClassCastException | HL7Exception cce) {
243 log.error("Unexpected problem obtaining field value. This is a bug.", cce);
244 throw new RuntimeException(cce);
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 protected Type createNewTypeWithoutReflection(int field) {
267 return null;
268 }
269
270
271
272
273
274 private Type createNewType(int field) throws HL7Exception {
275 Type retVal = createNewTypeWithoutReflection(field - 1);
276 if (retVal != null) {
277 return retVal;
278 }
279
280 int number = field - 1;
281 Class<? extends Type> c = this.types.get(number);
282
283 Type newType;
284 try {
285 Object[] args = getArgs(number);
286 Class<?>[] argClasses = new Class[args.length];
287 for (int i = 0; i < args.length; i++) {
288 if (args[i] instanceof Message) {
289 argClasses[i] = Message.class;
290 } else {
291 argClasses[i] = args[i].getClass();
292 }
293 }
294 newType = c.getConstructor(argClasses).newInstance(args);
295 } catch (IllegalAccessException iae) {
296 throw new HL7Exception("Can't access class " + c.getName() + " ("
297 + iae.getClass().getName() + "): " + iae.getMessage());
298 } catch (InstantiationException | NoSuchMethodException | InvocationTargetException ie) {
299 throw new HL7Exception("Can't instantiate class " + c.getName()
300 + " (" + ie.getClass().getName() + "): " + ie.getMessage());
301 }
302 return newType;
303 }
304
305
306 private Object[] getArgs(int fieldNum) {
307 Object[] result;
308
309 Object o = this.args.get(fieldNum);
310 if (o instanceof Object[]) {
311 result = (Object[]) o;
312 } else {
313 result = new Object[] { getMessage() };
314 }
315
316 return result;
317 }
318
319
320
321
322
323
324
325
326 public boolean isRequired(int number) throws HL7Exception {
327 if (number < 1 || number > required.size()) {
328 throw new HL7Exception("Can't retrieve optionality of field "
329 + number + " from segment " + this.getClass().getName()
330 + " - there are only " + fields.size() + " fields.");
331 }
332
333 try {
334 return required.get(number - 1);
335 } catch (Exception e) {
336 throw new HL7Exception("Can't retrieve optionality of field "
337 + number + ": " + e.getMessage());
338 }
339 }
340
341
342
343
344
345
346
347
348 public int getLength(int number) throws HL7Exception {
349 if (number < 1 || number > length.size()) {
350 throw new HL7Exception("Can't retrieve max length of field "
351 + number + " from segment " + this.getClass().getName()
352 + " - there are only " + fields.size() + " fields.");
353 }
354
355 try {
356 return length.get(number - 1);
357 } catch (Exception e) {
358 throw new HL7Exception("Can't retrieve max length of field "
359 + number + ": " + e.getMessage());
360 }
361
362 }
363
364
365
366
367
368
369
370 public int getMaxCardinality(int number) throws HL7Exception {
371 if (number < 1 || number > length.size()) {
372 throw new HL7Exception("Can't retrieve cardinality of field "
373 + number + " from segment " + this.getClass().getName()
374 + " - there are only " + fields.size() + " fields.");
375 }
376
377 try {
378 return maxReps.get(number - 1);
379 } catch (Exception e) {
380 throw new HL7Exception("Can't retrieve max repetitions of field "
381 + number + ": " + e.getMessage());
382 }
383 }
384
385
386
387
388 protected void add(Class<? extends Type> c, boolean required, int maxReps,
389 int length, Object[] constructorArgs) throws HL7Exception {
390 add(c, required, maxReps, length, constructorArgs, null);
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425 protected void add(Class<? extends Type> c, boolean required, int maxReps,
426 int length, Object[] constructorArgs, String name)
427 throws HL7Exception {
428 List<Type> arr = new ArrayList<>();
429 this.types.add(c);
430 this.fields.add(arr);
431 this.required.add(required);
432 this.length.add(length);
433 this.args.add(constructorArgs);
434 this.maxReps.add(maxReps);
435 this.names.add(name);
436 }
437
438
439
440
441
442
443 private void ensureEnoughFields(int fieldRequested) {
444 int fieldsToAdd = fieldRequested - this.numFields();
445 if (fieldsToAdd < 0) {
446 fieldsToAdd = 0;
447 }
448
449 try {
450 for (int i = 0; i < fieldsToAdd; i++) {
451 this.add(Varies.class, false, 0, 65536, null);
452
453
454
455 }
456 } catch (HL7Exception e) {
457 log.error(
458 "Can't create additional generic fields to handle request for field "
459 + fieldRequested, e);
460 }
461 }
462
463 public static void main(String[] args) {
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500 }
501
502
503
504
505
506 public int numFields() {
507 return this.fields.size();
508 }
509
510
511
512
513
514
515 public String getName() {
516 String fullName = this.getClass().getName();
517 return fullName.substring(fullName.lastIndexOf('.') + 1
518 );
519 }
520
521
522
523
524
525
526
527
528
529
530
531 public String[] getNames() {
532 return names.toArray(new String[0]);
533 }
534
535
536
537
538
539
540
541
542
543
544 public void parse(String string) throws HL7Exception {
545 if (string == null) {
546 throw new NullPointerException("String can not be null");
547 }
548
549 EncodingCharacters encodingCharacters;
550 try {
551 encodingCharacters = EncodingCharacters.getInstance(getMessage());
552 } catch (HL7Exception e) {
553 throw new HL7Exception(ERROR_MSH_1_OR_2_NOT_SET);
554 }
555 clear();
556 getMessage().getParser().parse(this, string, encodingCharacters);
557 }
558
559
560
561
562 public String encode() throws HL7Exception {
563 return getMessage().getParser().doEncode(this,
564 EncodingCharacters.getInstance(getMessage()));
565 }
566
567
568
569
570
571
572
573
574
575
576
577 public Type removeRepetition(int fieldNum, int index)
578 throws HL7Exception {
579 if (fieldNum < 1 || fieldNum > fields.size()) {
580 throw new HL7Exception("The field " + fieldNum
581 + " does not exist in the segment "
582 + this.getClass().getName());
583 }
584
585 String name = names.get(fieldNum - 1);
586 List<Type> list = fields.get(fieldNum - 1);
587 if (list.size() == 0) {
588 throw new HL7Exception("Invalid index: " + index + ", structure "
589 + name + " has no repetitions");
590 }
591 if (list.size() <= index) {
592 throw new HL7Exception("Invalid index: " + index + ", structure "
593 + name + " must be between 0 and " + (list.size() - 1));
594 }
595
596 return list.remove(index);
597 }
598
599
600
601
602
603
604
605
606
607 public Type insertRepetition(int fieldNum, int index)
608 throws HL7Exception {
609 if (fieldNum < 1 || fieldNum > fields.size()) {
610 throw new HL7Exception("The field " + fieldNum
611 + " does not exist in the segment "
612 + this.getClass().getName());
613 }
614
615 List<Type> list = fields.get(fieldNum - 1);
616 Type newType = createNewType(fieldNum);
617
618 list.add(index, newType);
619
620 return newType;
621 }
622
623
624
625
626 public void clear() {
627 for (List<Type> next : fields) {
628 next.clear();
629 }
630 }
631
632 }