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.Date; |
32 | |
import java.util.GregorianCalendar; |
33 | |
import java.util.Map; |
34 | |
import java.util.regex.Matcher; |
35 | |
import java.util.regex.Pattern; |
36 | |
|
37 | |
import ca.uhn.hl7v2.AcknowledgmentCode; |
38 | |
import ca.uhn.hl7v2.HL7Exception; |
39 | |
import ca.uhn.hl7v2.Location; |
40 | |
import ca.uhn.hl7v2.Version; |
41 | |
import ca.uhn.hl7v2.model.primitive.CommonTS; |
42 | |
import ca.uhn.hl7v2.parser.DefaultModelClassFactory; |
43 | |
import ca.uhn.hl7v2.parser.ModelClassFactory; |
44 | |
import ca.uhn.hl7v2.parser.Parser; |
45 | |
import ca.uhn.hl7v2.parser.PipeParser; |
46 | |
import ca.uhn.hl7v2.util.ArrayUtil; |
47 | |
import ca.uhn.hl7v2.util.ReflectionUtil; |
48 | |
import ca.uhn.hl7v2.util.StringUtil; |
49 | |
import ca.uhn.hl7v2.util.Terser; |
50 | |
import ca.uhn.hl7v2.validation.ValidationContext; |
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
@SuppressWarnings("serial") |
57 | |
public abstract class AbstractMessage extends AbstractGroup implements Message { |
58 | |
|
59 | 5 | private static final Pattern ourVersionPattern = Pattern.compile("\\.(v2[0-9][0-9]?)\\."); |
60 | |
private String myVersion; |
61 | |
private transient Parser myParser; |
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
public AbstractMessage(ModelClassFactory theFactory) { |
67 | 21252 | super(null, theFactory); |
68 | 21252 | } |
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
public Message getMessage() { |
74 | 3866423 | return this; |
75 | |
} |
76 | |
|
77 | |
public Group getParent() { |
78 | 0 | return this; |
79 | |
} |
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
public String getVersion() { |
90 | 0 | if (myVersion != null) { |
91 | 0 | return myVersion; |
92 | |
} |
93 | |
|
94 | 0 | String version = null; |
95 | 0 | Pattern p = ourVersionPattern; |
96 | 0 | Matcher m = p.matcher(this.getClass().getName()); |
97 | 0 | if (m.find()) { |
98 | 0 | String verFolder = m.group(1); |
99 | 0 | if (verFolder.length() > 0) { |
100 | 0 | char[] chars = verFolder.toCharArray(); |
101 | 0 | StringBuilder buf = new StringBuilder(); |
102 | 0 | for (int i = 1; i < chars.length; i++) { |
103 | 0 | buf.append(chars[i]); |
104 | 0 | if (i < chars.length - 1) buf.append('.'); |
105 | |
} |
106 | 0 | version = buf.toString(); |
107 | |
} |
108 | |
} |
109 | |
|
110 | 0 | if (version == null) |
111 | 0 | version = Version.lowestAvailableVersion().getVersion(); |
112 | |
|
113 | 0 | myVersion = version; |
114 | 0 | return version; |
115 | |
} |
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | |
public ValidationContext getValidationContext() { |
124 | 0 | if (getParser() == null || !getParser().getParserConfiguration().isValidating()) return null; |
125 | 0 | return getParser().getHapiContext().getValidationContext(); |
126 | |
} |
127 | |
|
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | |
public Character getFieldSeparatorValue() throws HL7Exception { |
133 | 9800 | Segment firstSegment = (Segment) get(getNames()[0]); |
134 | 9800 | Primitive value = (Primitive) firstSegment.getField(1, 0); |
135 | 9800 | String valueString = value.getValue(); |
136 | 9800 | if (valueString == null || valueString.length() == 0) { |
137 | 0 | return null; |
138 | |
} |
139 | 9800 | return valueString.charAt(0); |
140 | |
} |
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
public String getEncodingCharactersValue() throws HL7Exception { |
147 | 9805 | Segment firstSegment = (Segment) get(getNames()[0]); |
148 | 9805 | Primitive value = (Primitive) firstSegment.getField(2, 0); |
149 | 9805 | 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 | 7873 | if (parser == null) { |
168 | 0 | throw new NullPointerException("Value may not be null"); |
169 | |
} |
170 | |
|
171 | 7873 | myParser = parser; |
172 | 7873 | } |
173 | |
|
174 | |
|
175 | |
|
176 | |
|
177 | |
|
178 | |
|
179 | |
|
180 | |
|
181 | |
|
182 | |
public Parser getParser() { |
183 | 186180 | if (myParser == null) { |
184 | 1455 | myParser = new PipeParser(); |
185 | |
} |
186 | |
|
187 | 186180 | return myParser; |
188 | |
} |
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
public void parse(String string) throws HL7Exception { |
195 | 605 | clear(); |
196 | 605 | getParser().parse(this, string); |
197 | 545 | } |
198 | |
|
199 | |
|
200 | |
|
201 | |
|
202 | |
|
203 | |
public String encode() throws HL7Exception { |
204 | 890 | return getParser().encode(this); |
205 | |
} |
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
public Message generateACK() throws HL7Exception, IOException { |
211 | 413 | return generateACK(AcknowledgmentCode.AA, null); |
212 | |
} |
213 | |
|
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
public Message generateACK(String theAcknowledgementCode, HL7Exception theException) throws HL7Exception, IOException { |
219 | 0 | AcknowledgmentCode theCode = theAcknowledgementCode == null ? |
220 | |
AcknowledgmentCode.AA : |
221 | 0 | AcknowledgmentCode.valueOf(theAcknowledgementCode); |
222 | 0 | return generateACK(theCode, theException); |
223 | |
} |
224 | |
|
225 | |
|
226 | |
|
227 | |
|
228 | |
public Message generateACK(AcknowledgmentCode theAcknowledgementCode, HL7Exception theException) throws HL7Exception, IOException { |
229 | 803 | if (theException != null && theException.getResponseMessage() != null) { |
230 | 0 | return theException.getResponseMessage(); |
231 | |
} |
232 | 803 | Message out = instantiateACK(); |
233 | 803 | out.setParser(getParser()); |
234 | 803 | fillResponseHeader(out, theAcknowledgementCode); |
235 | 803 | if (theException != null) { |
236 | 330 | theException.populateResponse(out, theAcknowledgementCode, 0); |
237 | |
} |
238 | 803 | return out; |
239 | |
} |
240 | |
|
241 | |
private Message instantiateACK() throws HL7Exception { |
242 | 803 | ModelClassFactory mcf = getParser() != null ? |
243 | 803 | getParser().getFactory() : |
244 | |
new DefaultModelClassFactory(); |
245 | 803 | Version version = Version.versionOf(getVersion()); |
246 | 803 | Message out = null; |
247 | 803 | if (version != null && version.available()) { |
248 | 803 | Class<? extends Message> clazz = mcf.getMessageClass("ACK", version.getVersion(), false); |
249 | 803 | if (clazz != null) { |
250 | 803 | out = ReflectionUtil.instantiateMessage(clazz, mcf); |
251 | |
} |
252 | |
} |
253 | 803 | if (out == null) { |
254 | 0 | out = new GenericMessage.UnknownVersion(mcf); |
255 | |
} |
256 | |
|
257 | 803 | if (out instanceof GenericMessage) { |
258 | 0 | if (!ArrayUtil.contains(out.getNames(), "MSA")) { |
259 | 0 | out.addNonstandardSegment("MSA"); |
260 | |
} |
261 | 0 | if (!ArrayUtil.contains(out.getNames(), "ERR")) { |
262 | 0 | out.addNonstandardSegment("ERR"); |
263 | |
} |
264 | |
} |
265 | |
|
266 | 803 | return out; |
267 | |
} |
268 | |
|
269 | |
|
270 | |
|
271 | |
|
272 | |
|
273 | |
|
274 | |
|
275 | |
|
276 | |
|
277 | |
|
278 | |
|
279 | |
|
280 | |
|
281 | |
|
282 | |
public Message fillResponseHeader(Message out, AcknowledgmentCode code) |
283 | |
throws HL7Exception, IOException { |
284 | 803 | Segment mshIn = (Segment) get("MSH"); |
285 | 803 | Segment mshOut = (Segment) out.get("MSH"); |
286 | |
|
287 | |
|
288 | 803 | String fieldSep = Terser.get(mshIn, 1, 0, 1, 1); |
289 | 803 | String encChars = Terser.get(mshIn, 2, 0, 1, 1); |
290 | 803 | String procID = Terser.get(mshIn, 11, 0, 1, 1); |
291 | |
|
292 | |
|
293 | 803 | Terser.set(mshOut, 1, 0, 1, 1, fieldSep); |
294 | 803 | Terser.set(mshOut, 2, 0, 1, 1, encChars); |
295 | 803 | GregorianCalendar now = new GregorianCalendar(); |
296 | 803 | now.setTime(new Date()); |
297 | 803 | Terser.set(mshOut, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now)); |
298 | 803 | Terser.set(mshOut, 9, 0, 1, 1, "ACK"); |
299 | 803 | Terser.set(mshOut, 9, 0, 2, 1, Terser.get(mshIn, 9, 0, 2, 1)); |
300 | 803 | String v = mshOut.getMessage().getVersion(); |
301 | 803 | if (v != null) { |
302 | 803 | Version version = Version.versionOf(v); |
303 | 803 | if (version != null && !Version.V25.isGreaterThan(version)) { |
304 | 195 | Terser.set(mshOut, 9, 0, 3, 1, "ACK"); |
305 | |
} |
306 | |
} |
307 | 803 | Terser.set(mshOut, 10, 0, 1, 1, mshIn.getMessage().getParser().getParserConfiguration().getIdGenerator().getID()); |
308 | 803 | Terser.set(mshOut, 11, 0, 1, 1, procID); |
309 | |
|
310 | 803 | String versionId = Terser.get(mshIn, 12, 0, 1, 1); |
311 | 803 | if (StringUtil.isBlank(versionId)) { |
312 | 10 | versionId = Version.highestAvailableVersionOrDefault().getVersion(); |
313 | |
} |
314 | 803 | Terser.set(mshOut, 12, 0, 1, 1, versionId); |
315 | |
|
316 | |
|
317 | 803 | Terser.set(mshOut, 3, 0, 1, 1, Terser.get(mshIn, 5, 0, 1, 1)); |
318 | 803 | Terser.set(mshOut, 4, 0, 1, 1, Terser.get(mshIn, 6, 0, 1, 1)); |
319 | 803 | Terser.set(mshOut, 5, 0, 1, 1, Terser.get(mshIn, 3, 0, 1, 1)); |
320 | 803 | Terser.set(mshOut, 6, 0, 1, 1, Terser.get(mshIn, 4, 0, 1, 1)); |
321 | |
|
322 | |
|
323 | 803 | Segment msaOut = (Segment) out.get("MSA"); |
324 | 803 | Terser.set(msaOut, 1, 0, 1, 1, code.name()); |
325 | 803 | Terser.set(msaOut, 2, 0, 1, 1, Terser.get(mshIn, 10, 0, 1, 1)); |
326 | 803 | return out; |
327 | |
} |
328 | |
|
329 | |
|
330 | |
|
331 | |
|
332 | |
|
333 | |
@Override |
334 | |
public String toString() { |
335 | |
try { |
336 | 85 | return encode(); |
337 | 0 | } catch (HL7Exception e) { |
338 | 0 | return (getClass().getName() + " - Failed to create toString(): " + e.getMessage()); |
339 | |
} |
340 | |
} |
341 | |
|
342 | |
|
343 | |
|
344 | |
|
345 | |
public String printStructure() throws HL7Exception { |
346 | 485 | StringBuilder builder = new StringBuilder(); |
347 | 485 | appendStructureDescription(builder, 0, false, false, true, true, true); |
348 | 485 | return builder.toString(); |
349 | |
} |
350 | |
|
351 | |
|
352 | |
|
353 | |
|
354 | |
|
355 | |
public String printStructure(boolean includeEmptyElements) throws HL7Exception { |
356 | 5 | StringBuilder builder = new StringBuilder(); |
357 | 5 | appendStructureDescription(builder, 0, false, false, true, true, includeEmptyElements); |
358 | 5 | 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 | 630 | Segment msh = (Segment) get("MSH"); |
384 | 630 | Version version = Version.versionOf(getVersion()); |
385 | 630 | Terser.set(msh, 1, 0, 1, 1, "|"); |
386 | 630 | Terser.set(msh, 2, 0, 1, 1, Version.V27.isGreaterThan(version) ? |
387 | |
"^~\\&" : "^~\\&#"); |
388 | 630 | GregorianCalendar now = new GregorianCalendar(); |
389 | 630 | Terser.set(msh, 7, 0, 1, 1, CommonTS.toHl7TSFormat(now)); |
390 | 630 | Terser.set(msh, 9, 0, 1, 1, messageCode); |
391 | 630 | Terser.set(msh, 9, 0, 2, 1, messageTriggerEvent); |
392 | 630 | Terser.set(msh, 10, 0, 1, 1, getParser().getParserConfiguration().getIdGenerator().getID()); |
393 | 630 | Terser.set(msh, 11, 0, 1, 1, processingId); |
394 | 630 | Terser.set(msh, 12, 0, 1, 1, getVersion()); |
395 | |
|
396 | |
|
397 | 630 | if (!Version.V24.isGreaterThan(version)) { |
398 | 600 | if (this instanceof SuperStructure) { |
399 | 5 | Map<String, String> eventMap = new DefaultModelClassFactory().getEventMapForVersion(version); |
400 | 5 | if (StringUtil.isNotBlank(messageCode) && StringUtil.isNotBlank(messageTriggerEvent)) { |
401 | 5 | String structure = eventMap.get(messageCode + "_" + messageTriggerEvent); |
402 | 5 | Terser.set(msh, 9, 0, 3, 1, structure); |
403 | |
} |
404 | 5 | } else { |
405 | 595 | String className = getClass().getName(); |
406 | 595 | int lastIndexOf = className.lastIndexOf('.'); |
407 | 595 | className = className.substring(lastIndexOf + 1); |
408 | 595 | if (className.matches("[A-Z]{3}_[A-Z0-9]{3}")) { |
409 | 575 | Terser.set(msh, 9, 0, 3, 1, className); |
410 | |
} |
411 | |
} |
412 | |
} |
413 | |
|
414 | 630 | } |
415 | |
|
416 | |
@Override |
417 | |
public boolean accept(MessageVisitor visitor, Location location) throws HL7Exception { |
418 | 10 | if (visitor.start(this)) { |
419 | 10 | visitNestedStructures(visitor, location); |
420 | |
} |
421 | 10 | return visitor.end(this); |
422 | |
} |
423 | |
|
424 | |
|
425 | |
} |