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 package ca.uhn.hl7v2.model;
29
30 import java.io.IOException;
31 import java.util.Arrays;
32 import java.util.Date;
33 import java.util.GregorianCalendar;
34 import java.util.Map;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37
38 import ca.uhn.hl7v2.AcknowledgmentCode;
39 import ca.uhn.hl7v2.HL7Exception;
40 import ca.uhn.hl7v2.Location;
41 import ca.uhn.hl7v2.Version;
42 import ca.uhn.hl7v2.model.primitive.CommonTS;
43 import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
44 import ca.uhn.hl7v2.parser.ModelClassFactory;
45 import ca.uhn.hl7v2.parser.Parser;
46 import ca.uhn.hl7v2.parser.PipeParser;
47 import ca.uhn.hl7v2.util.ArrayUtil;
48 import ca.uhn.hl7v2.util.ReflectionUtil;
49 import ca.uhn.hl7v2.util.StringUtil;
50 import ca.uhn.hl7v2.util.Terser;
51 import ca.uhn.hl7v2.validation.ValidationContext;
52
53
54
55
56
57 @SuppressWarnings("serial")
58 public abstract class AbstractMessage extends AbstractGroup implements Message {
59
60 private static final Pattern ourVersionPattern = Pattern.compile("\\.(v2[0-9][0-9]?)\\.");
61 private String myVersion;
62 private transient Parser myParser;
63
64
65
66
67 public AbstractMessage(ModelClassFactory theFactory) {
68 super(null, theFactory);
69 }
70
71
72
73
74 public Message getMessage() {
75 return this;
76 }
77
78 public Group getParent() {
79 return this;
80 }
81
82
83
84
85
86
87
88
89
90 public String getVersion() {
91 if (myVersion != null) {
92 return myVersion;
93 }
94
95 String version = null;
96 Matcher m = ourVersionPattern.matcher(this.getClass().getName());
97 if (m.find()) {
98 String verFolder = m.group(1);
99 if (verFolder.length() > 0) {
100 char[] chars = verFolder.toCharArray();
101 StringBuilder buf = new StringBuilder();
102 for (int i = 1; i < chars.length; i++) {
103 buf.append(chars[i]);
104 if (i < chars.length - 1) buf.append('.');
105 }
106 version = buf.toString();
107 }
108 }
109
110 if (version == null)
111 version = Version.lowestAvailableVersion().getVersion();
112
113 myVersion = version;
114 return version;
115 }
116
117
118
119
120
121
122
123 public ValidationContext getValidationContext() {
124 if (getParser() == null || !getParser().getParserConfiguration().isValidating()) return null;
125 return getParser().getHapiContext().getValidationContext();
126 }
127
128
129
130
131
132 public Character getFieldSeparatorValue() throws HL7Exception {
133 Segment./../ca/uhn/hl7v2/model/Segment.html#Segment">Segment firstSegment = (Segment) get(getNames()[0]);
134 Primitive/../../../ca/uhn/hl7v2/model/Primitive.html#Primitive">Primitive value = (Primitive) firstSegment.getField(1, 0);
135 String valueString = value.getValue();
136 if (valueString == null || valueString.length() == 0) {
137 return null;
138 }
139 return valueString.charAt(0);
140 }
141
142
143
144
145
146 public String getEncodingCharactersValue() throws HL7Exception {
147 Segment./../ca/uhn/hl7v2/model/Segment.html#Segment">Segment firstSegment = (Segment) get(getNames()[0]);
148 Primitive/../../../ca/uhn/hl7v2/model/Primitive.html#Primitive">Primitive value = (Primitive) firstSegment.getField(2, 0);
149 return value.getValue();
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 public void setParser(Parser parser) {
167 if (parser == null) {
168 throw new NullPointerException("Value may not be null");
169 }
170
171 myParser = parser;
172 }
173
174
175
176
177
178
179
180
181
182 public Parser getParser() {
183 if (myParser == null) {
184 myParser = new PipeParser();
185 }
186
187 return myParser;
188 }
189
190
191
192
193
194 public void parse(String string) throws HL7Exception {
195 clear();
196 getParser().parse(this, string);
197 }
198
199
200
201
202
203 public String encode() throws HL7Exception {
204 return getParser().encode(this);
205 }
206
207
208
209
210 public Message generateACK() throws HL7Exception, IOException {
211 return generateACK(AcknowledgmentCode.AA, null);
212 }
213
214
215
216
217
218 public Message generateACK(String theAcknowledgementCode, HL7Exception theException) throws HL7Exception, IOException {
219 AcknowledgmentCode theCode = theAcknowledgementCode == null ?
220 AcknowledgmentCode.AA :
221 AcknowledgmentCode.valueOf(theAcknowledgementCode);
222 return generateACK(theCode, theException);
223 }
224
225
226
227
228 public Message generateACK(AcknowledgmentCode theAcknowledgementCode, HL7Exception theException) throws HL7Exception, IOException {
229 if (theException != null && theException.getResponseMessage() != null) {
230 return theException.getResponseMessage();
231 }
232 Message out = instantiateACK();
233 out.setParser(getParser());
234 fillResponseHeader(out, theAcknowledgementCode);
235 if (theException != null) {
236 theException.populateResponse(out, theAcknowledgementCode, 0);
237 }
238 return out;
239 }
240
241 private Message instantiateACK() throws HL7Exception {
242 ModelClassFactory mcf = getParser() != null ?
243 getParser().getFactory() :
244 new DefaultModelClassFactory();
245 Version version = Version.versionOf(getVersion());
246 Message out = null;
247 if (version != null && version.available()) {
248 Class<? extends Message> clazz = mcf.getMessageClass("ACK", version.getVersion(), false);
249 if (clazz != null) {
250 out = ReflectionUtil.instantiateMessage(clazz, mcf);
251 }
252 }
253 if (out == null) {
254 out = new GenericMessage.UnknownVersion(mcf);
255 }
256
257 if (out instanceof GenericMessage) {
258 if (!ArrayUtil.contains(out.getNames(), "MSA")) {
259 out.addNonstandardSegment("MSA");
260 }
261 if (!ArrayUtil.contains(out.getNames(), "ERR")) {
262 out.addNonstandardSegment("ERR");
263 }
264 }
265
266 return out;
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282 public Message./ca/uhn/hl7v2/model/Message.html#Message">Message fillResponseHeader(Message out, AcknowledgmentCode code)
283 throws HL7Exception, IOException {
284 Segment mshIn = (Segment) get("MSH");
285 Segment mshOut = (Segment) out.get("MSH");
286
287
288 String fieldSep = Terser.get(mshIn, 1, 0, 1, 1);
289 String encChars = Terser.get(mshIn, 2, 0, 1, 1);
290 String procID = Terser.get(mshIn, 11, 0, 1, 1);
291
292
293 Terser.set(mshOut, 1, 0, 1, 1, fieldSep);
294 Terser.set(mshOut, 2, 0, 1, 1, encChars);
295 GregorianCalendar now = new GregorianCalendar();
296 now.setTime(new Date());
297 Terser.set(mshOut, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now));
298 Terser.set(mshOut, 9, 0, 1, 1, "ACK");
299 Terser.set(mshOut, 9, 0, 2, 1, Terser.get(mshIn, 9, 0, 2, 1));
300 String v = mshOut.getMessage().getVersion();
301 if (v != null) {
302 Version version = Version.versionOf(v);
303 if (version != null && !Version.V25.isGreaterThan(version)) {
304 Terser.set(mshOut, 9, 0, 3, 1, "ACK");
305 }
306 }
307 Terser.set(mshOut, 10, 0, 1, 1, mshIn.getMessage().getParser().getParserConfiguration().getIdGenerator().getID());
308 Terser.set(mshOut, 11, 0, 1, 1, procID);
309
310 String versionId = Terser.get(mshIn, 12, 0, 1, 1);
311 if (StringUtil.isBlank(versionId)) {
312 versionId = Version.highestAvailableVersionOrDefault().getVersion();
313 }
314 Terser.set(mshOut, 12, 0, 1, 1, versionId);
315
316
317 Terser.set(mshOut, 3, 0, 1, 1, Terser.get(mshIn, 5, 0, 1, 1));
318 Terser.set(mshOut, 4, 0, 1, 1, Terser.get(mshIn, 6, 0, 1, 1));
319 Terser.set(mshOut, 5, 0, 1, 1, Terser.get(mshIn, 3, 0, 1, 1));
320 Terser.set(mshOut, 6, 0, 1, 1, Terser.get(mshIn, 4, 0, 1, 1));
321
322
323 Segment msaOut = (Segment) out.get("MSA");
324 Terser.set(msaOut, 1, 0, 1, 1, code.name());
325 Terser.set(msaOut, 2, 0, 1, 1, Terser.get(mshIn, 10, 0, 1, 1));
326 return out;
327 }
328
329
330
331
332
333 @Override
334 public String toString() {
335 try {
336 return encode();
337 } catch (HL7Exception e) {
338 return (getClass().getName() + " - Failed to create toString(): " + e.getMessage());
339 }
340 }
341
342
343
344
345 public String printStructure() throws HL7Exception {
346 StringBuilder builder = new StringBuilder();
347 appendStructureDescription(builder, 0, false, false, true, true, true);
348 return builder.toString();
349 }
350
351
352
353
354
355 public String printStructure(boolean includeEmptyElements) throws HL7Exception {
356 StringBuilder builder = new StringBuilder();
357 appendStructureDescription(builder, 0, false, false, true, true, includeEmptyElements);
358 return builder.toString();
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 public void initQuickstart(String messageCode, String messageTriggerEvent, String processingId) throws HL7Exception, IOException {
383 Segment msh = (Segment) get("MSH");
384 Version version = Version.versionOf(getVersion());
385 Terser.set(msh, 1, 0, 1, 1, "|");
386 Terser.set(msh, 2, 0, 1, 1, Version.V27.isGreaterThan(version) ?
387 "^~\\&" : "^~\\&#");
388 GregorianCalendar now = new GregorianCalendar();
389 Terser.set(msh, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now));
390 Terser.set(msh, 9, 0, 1, 1, messageCode);
391 Terser.set(msh, 9, 0, 2, 1, messageTriggerEvent);
392 Terser.set(msh, 10, 0, 1, 1, getParser().getParserConfiguration().getIdGenerator().getID());
393 Terser.set(msh, 11, 0, 1, 1, processingId);
394 Terser.set(msh, 12, 0, 1, 1, getVersion());
395
396
397 if (!Version.V24.isGreaterThan(version)) {
398 if (this instanceof SuperStructure) {
399 Map<String, String> eventMap = new DefaultModelClassFactory().getEventMapForVersion(version);
400 if (StringUtil.isNotBlank(messageCode) && StringUtil.isNotBlank(messageTriggerEvent)) {
401 String structure = eventMap.get(messageCode + "_" + messageTriggerEvent);
402 Terser.set(msh, 9, 0, 3, 1, structure);
403 }
404 } else {
405 String className = getClass().getName();
406 int lastIndexOf = className.lastIndexOf('.');
407 className = className.substring(lastIndexOf + 1);
408 if (className.matches("[A-Z]{3}_[A-Z0-9]{3}")) {
409 Terser.set(msh, 9, 0, 3, 1, className);
410 }
411 }
412 }
413
414 }
415
416 @Override
417 public boolean accept(MessageVisitor visitor, Location location) throws HL7Exception {
418 if (visitor.start(this)) {
419 visitNestedStructures(visitor, location);
420 }
421 return visitor.end(this);
422 }
423
424
425
426
427
428
429
430
431
432
433 public AbstractMessage copy() throws HL7Exception{
434 AbstractMessage clonedMessage = ReflectionUtil.instantiateMessage(this.getClass(), this.getModelClassFactory());
435 clonedMessage.setParser(this.getParser());
436
437 copyParserRequiredMshFields(this, clonedMessage);
438 copyGroup(this, clonedMessage);
439 return clonedMessage;
440 }
441
442 private void copyParserRequiredMshFields(AbstractMessage./ca/uhn/hl7v2/model/AbstractMessage.html#AbstractMessage">AbstractMessage theSource, AbstractMessage theTarget) throws HL7Exception {
443 String mshField = "MSH";
444 AbstractSegmentca/uhn/hl7v2/model/AbstractSegment.html#AbstractSegment">AbstractSegment sourceMsh = (AbstractSegment) theSource.get(mshField);
445 AbstractSegmentca/uhn/hl7v2/model/AbstractSegment.html#AbstractSegment">AbstractSegment targetMsh = (AbstractSegment) theTarget.get(mshField);
446
447 String msh1 = Terser.get(sourceMsh, 1, 0, 1, 1);
448 Terser.set(targetMsh, 1, 0, 1, 1, msh1);
449
450 String msh2 = Terser.get(sourceMsh, 2, 0, 1, 1);
451 Terser.set(targetMsh, 2, 0, 1, 1, msh2);
452 }
453
454 private void copyGroup(AbstractGroup/../ca/uhn/hl7v2/model/AbstractGroup.html#AbstractGroup">AbstractGroup theSource, AbstractGroup theTarget) throws HL7Exception {
455 String[] sourceNames = theSource.getNames();
456
457 for (String sourceName : sourceNames) {
458
459 Structure[] sourceStructures = theSource.getAll(sourceName);
460 for (int i = 0; i < sourceStructures.length; i++) {
461
462 Structure sourceStructure = sourceStructures[i];
463
464 if (sourceStructure instanceof AbstractGroup) {
465 Structure targetGroup = theTarget.get(sourceName, i);
466 copyGroup((AbstractGroupuhn/hl7v2/model/AbstractGroup.html#AbstractGroup">AbstractGroup)sourceStructure, (AbstractGroup)targetGroup);
467
468 } else if (sourceStructure instanceof AbstractSegment) {
469
470 boolean isNonStandardSegment = theSource.getNonStandardNames().contains(sourceName);
471 if (isNonStandardSegment) {
472 insertNonStandardSegment(theSource, theTarget, sourceName);
473 }
474
475 AbstractSegmenthn/hl7v2/model/AbstractSegment.html#AbstractSegment">AbstractSegment sourceSegment = (AbstractSegment) sourceStructure;
476 AbstractSegmenthn/hl7v2/model/AbstractSegment.html#AbstractSegment">AbstractSegment targetSegment = (AbstractSegment) theTarget.get(sourceName, i);
477 String segmentContents = sourceSegment.encode();
478 targetSegment.parse(segmentContents);
479 }
480 }
481 }
482 }
483
484 private void insertNonStandardSegment(AbstractGroup/../ca/uhn/hl7v2/model/AbstractGroup.html#AbstractGroup">AbstractGroup theSource, AbstractGroup theTarget, String theNonStandardSegmentName) throws HL7Exception {
485 String[] sourceNames = theSource.getNames();
486 int sourceIndex = Arrays.asList(sourceNames).indexOf(theNonStandardSegmentName);
487
488 String[] targetNames = theTarget.getNames();
489 boolean shouldInsertAtEnd = sourceIndex >= targetNames.length;
490
491 if (shouldInsertAtEnd) {
492 theTarget.addNonstandardSegment(theNonStandardSegmentName);
493 } else {
494 theTarget.addNonstandardSegment(theNonStandardSegmentName, sourceIndex);
495 }
496 }
497 }