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.sourcegen;
31
32 import java.io.BufferedWriter;
33 import java.io.File;
34 import java.io.FileOutputStream;
35 import java.io.OutputStreamWriter;
36 import java.util.Arrays;
37 import java.util.List;
38
39 import org.apache.velocity.Template;
40 import org.apache.velocity.VelocityContext;
41 import org.apache.velocity.context.Context;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import ca.uhn.hl7v2.HL7Exception;
46 import ca.uhn.hl7v2.Version;
47 import ca.uhn.hl7v2.parser.DefaultModelClassFactory;
48 import ca.uhn.hl7v2.sourcegen.util.VelocityFactory;
49
50
51
52
53
54
55
56
57
58 public class GroupGenerator {
59
60 private static final Logger log = LoggerFactory.getLogger(GroupGenerator.class);
61
62
63 public static void writeGroup(String groupName, String fileName, GroupDef group, String version, String basePackageName, String theTemplatePackage, String theDescription) throws Exception {
64
65 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName, false), SourceGenerator.ENCODING));
66
67 theTemplatePackage = theTemplatePackage.replace(".", "/");
68 Template template = VelocityFactory.getClasspathTemplateInstance(theTemplatePackage + "/group.vsm");
69 Context ctx = new VelocityContext();
70 ctx.put("groupName", groupName);
71 ctx.put("specVersion", version);
72 ctx.put("typeDescription", theDescription);
73 ctx.put("basePackageName", basePackageName);
74 ctx.put("groups", Arrays.asList(group.getStructures()));
75 ctx.put("chapter", "");
76
77 template.merge(ctx, out);
78
79 out.flush();
80 out.close();
81
82
83
84
85
86
87
88
89
90
91
92 }
93
94
95
96 public GroupGenerator() {
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 public static GroupDef writeGroup(StructureDef[] structures, String groupName, String baseDirectory, String version, String message, String theTemplatePackage, String theFileExt) throws Exception {
128
129
130 if (!(baseDirectory.endsWith("\\") || baseDirectory.endsWith("/"))) {
131 baseDirectory = baseDirectory + "/";
132 }
133 File targetDir = SourceGenerator.makeDirectory(baseDirectory + DefaultModelClassFactory.getVersionPackagePath(version) + "group");
134
135 GroupDef group = getGroupDef(structures, groupName, baseDirectory, version, message, theTemplatePackage, theFileExt);
136
137 String fileName = targetDir.getPath() + "/" + group.getName() + "." + theFileExt;
138 writeGroup(group.getName(), fileName, group, version, DefaultModelClassFactory.getVersionPackageName(version), theTemplatePackage, group.getDescription());
139
140 return group;
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public static GroupDef getGroupDef(StructureDef[] structures, String groupName, String baseDirectory, String version, String message, String theTemplatePackage, String theFileExt) throws Exception {
164 GroupDef ret;
165 boolean required = true;
166 boolean repeating = false;
167 boolean rep_opt = false;
168
169
170
171
172
173
174 if (null == (groupName) && "2.5".equals(version) && "ORL_O34".equals(message) && !structuresContainsSegmentWithGroupName(structures, "RESPONSE")) {
175 List<StructureDef> tmpStructures = new java.util.ArrayList<>(java.util.Arrays.asList(structures));
176 tmpStructures.add(new SegmentDef("]", "RESPONSE", false, false, false, ""));
177 tmpStructures.add(5, new SegmentDef("[", "RESPONSE", false, false, false, ""));
178 structures = tmpStructures.toArray(new StructureDef[structures.length]);
179 }
180
181 int len = structures.length;
182 StructureDefl#StructureDef">StructureDef[] shortList = new StructureDef[len];
183
184
185
186 int currShortListPos = 0;
187 int currLongListPos;
188
189 try {
190
191
192
193
194
195 String struct0name = structures[0].getName();
196 String struct1name = structures[1].getName();
197 String structLastName = structures[len - 1].getName();
198 String structSecondLastName = structures[len - 2].getName();
199
200 if (optMarkers(struct0name, structLastName) && (findGroupEnd(message, structures, 0) == len - 1))
201 required = false;
202 if (repMarkers(struct0name, structLastName) && (findGroupEnd(message, structures, 0) == len - 1))
203 repeating = true;
204 if (repoptMarkers(struct0name, structLastName) && (findGroupEnd(message, structures, 0) == len - 1))
205 rep_opt = true;
206
207 if (repeating || !required) {
208 if (optMarkers(struct1name, structSecondLastName) && (findGroupEnd(message, structures, 1) == len - 2))
209 required = false;
210 if (repMarkers(struct1name, structSecondLastName) && (findGroupEnd(message, structures, 1) == len - 2))
211 repeating = true;
212 }
213
214
215
216 int skip = 0;
217 if (!required)
218 skip++;
219 if (repeating)
220 skip++;
221 if (rep_opt)
222 skip++;
223 currLongListPos = skip;
224 while (currLongListPos < len - skip) {
225 String currSegName = structures[currLongListPos].getName();
226 if (currSegName.equals("[") || currSegName.equals("{") || currSegName.equals("[{")) {
227
228 String name = ((SegmentDef) structures[currLongListPos]).getGroupName();
229
230
231 if (name != null) {
232 name = name.replace("TIIMING", "TIMING");
233
234 if ("OBSERVATION_REQUEST".equals(groupName)) {
235 if ("ORL_O34".equals(message)) {
236 if ("SPECIMEN".equals(name))
237 if (Version.versionOf(version) == Version.V251) {
238 name = "OBSERVATION_REQUEST_SPECIMEN";
239 }
240 }
241 }
242
243 }
244
245
246
247
248 int endOfNewGroup = findGroupEnd(message, structures, currLongListPos);
249 StructureDefreDef">StructureDef[] newGroupStructures = new StructureDef[endOfNewGroup - currLongListPos + 1];
250 System.arraycopy(structures, currLongListPos, newGroupStructures, 0, newGroupStructures.length);
251 shortList[currShortListPos] = writeGroup(newGroupStructures, name, baseDirectory, version, message, theTemplatePackage, theFileExt);
252 currLongListPos = endOfNewGroup + 1;
253 } else {
254
255 shortList[currShortListPos] = structures[currLongListPos];
256 currLongListPos++;
257 }
258 currShortListPos++;
259 }
260 } catch (IllegalArgumentException e) {
261 throw new HL7Exception("Problem creating nested group: " + e.getClass().getName() + ": " + e.getMessage());
262 }
263
264 if (rep_opt) {
265 ret = new GroupDef(message, groupName, false, true, "a Group object");
266 } else {
267 ret = new GroupDef(message, groupName, required, repeating, "a Group object");
268 }
269
270 StructureDefl#StructureDef">StructureDef[] finalList = new StructureDef[currShortListPos];
271
272
273
274
275 System.arraycopy(shortList, 0, finalList, 0, currShortListPos);
276 for (StructureDef nextStruct : finalList) {
277
278 if (nextStruct.getUnqualifiedName().equals("ED")) {
279 continue;
280 }
281 if (nextStruct instanceof GroupDef/.GroupDefuhn/hl7v2/sourcegen/GroupDef.html#GroupDef">GroupDef && ((GroupDef) GroupDefct).getRawGroupName() != null && ((GroupDef) nextStruct).getRawGroupName().contains("TIIMING")) {
282 ((GroupDef2/sourcegen/GroupDef.html#GroupDef">GroupDef) nextStruct).setRawGroupName(((GroupDef) nextStruct).getRawGroupName().replace("TIIMING", "TIMING"));
283 }
284
285
286
287
288
289
290
291
292 String nextName = nextStruct.getUnqualifiedName();
293 if ("QUERY_RESPONSE".equals(nextName)) {
294 if ("RSP_K21".equals(message)) {
295 if (Version.versionOf(version) == Version.V25 || Version.versionOf(version) == Version.V251
296 || Version.versionOf(version) == Version.V26) {
297 log.info("Forcing repeatable group");
298 ((GroupDef) nextStruct).setRepeating(true);
299 }
300 }
301 }
302
303
304
305
306
307
308
309
310 if ("OBSERVATION_REQUEST".equals(ret.getUnqualifiedName())) {
311 if ("ORL_O34".equals(message)) {
312 if ("SPECIMEN".equals(nextName))
313 if (Version.versionOf(version) == Version.V251) {
314 ((GroupDef) nextStruct).setRawGroupName("OBSERVATION_REQUEST_SPECIMEN");
315 log.info("Forcing name to " + ((GroupDef) nextStruct).getRawGroupName());
316 }
317 }
318 }
319
320 ret.addStructure(nextStruct);
321 }
322
323 return ret;
324 }
325
326
327 private static boolean structuresContainsSegmentWithGroupName(StructureDef[] theStructures, String theString) {
328 for (StructureDef structureDef : theStructures) {
329 if (theString.equals(((SegmentDef)structureDef).getGroupName())) {
330 return true;
331 }
332 }
333 return false;
334 }
335
336
337
338
339
340 private static boolean repoptMarkers(String opening, String closing) {
341 boolean ret = false;
342 if (opening.equals("[{") && closing.equals("}]")) {
343 ret = true;
344 }
345 return ret;
346 }
347
348
349
350
351
352 private static boolean optMarkers(String opening, String closing) {
353 boolean ret = false;
354 if (opening.equals("[") && closing.equals("]")) {
355 ret = true;
356 }
357 return ret;
358 }
359
360
361
362
363
364 private static boolean repMarkers(String opening, String closing) {
365 boolean ret = false;
366 if (opening.equals("{") && closing.equals("}")) {
367 ret = true;
368 }
369 return ret;
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 public static int findGroupEnd(String message, StructureDef[] structures, int groupStart) throws IllegalArgumentException, HL7Exception {
388
389
390 String endMarker;
391 String startMarker;
392 try {
393 startMarker = structures[groupStart].getName();
394 switch (startMarker) {
395 case "[":
396 endMarker = "]";
397 break;
398 case "{":
399 endMarker = "}";
400 break;
401 case "[{":
402 endMarker = "}]";
403 break;
404 default:
405 log.error("Problem starting at {}", groupStart);
406 for (int i = 0; i < structures.length; i++) {
407 log.error("Structure at index {}: {}", i, structures[i].getName());
408 }
409 throw new IllegalArgumentException("The segment " + startMarker + " does not begin a group - must be [ or {");
410 }
411 } catch (IndexOutOfBoundsException e) {
412 throw new IllegalArgumentException("The given start location is out of bounds");
413 }
414
415
416
417 String segName = null;
418 int offset = 0;
419 try {
420 int nestedInside = 1;
421 while (nestedInside > 0) {
422 offset++;
423 segName = structures[groupStart + offset].getName();
424 if (segName.equals("{") || segName.equals("[") || segName.equals("[{")) {
425 nestedInside++;
426 } else if (segName.equals("}") || segName.equals("]") || segName.equals("}]")) {
427 nestedInside--;
428 }
429 }
430 } catch (IndexOutOfBoundsException e) {
431 throw new HL7Exception("Couldn't find end of group index " + groupStart + " for msg " + message);
432 }
433 if (!endMarker.equals(segName)) {
434 StringBuilder buf = new StringBuilder();
435 for (int i = 0; i < structures.length; i++) {
436 buf.append("\r\n").append(i).append(" - ").append(structures[i].toString());
437 }
438 String msg = "Group markers for group indexes " + groupStart + "-" + (groupStart + offset) + " are not nested properly for message " + message + ": " + buf.toString();
439 throw new HL7Exception(msg);
440 }
441 return groupStart + offset;
442 }
443
444 }