1 package ca.uhn.hl7v2.util;
2
3 import java.util.NoSuchElementException;
4
5 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory;
7
8 import ca.uhn.hl7v2.HL7Exception;
9 import ca.uhn.hl7v2.model.Group;
10 import ca.uhn.hl7v2.model.Message;
11 import ca.uhn.hl7v2.model.Segment;
12 import ca.uhn.hl7v2.model.Structure;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 public class MessageIterator implements java.util.Iterator<Structure> {
30
31 private Structure currentStructure;
32 private String direction;
33 private Position next;
34 private final boolean handleUnexpectedSegments;
35
36 private static final Logger log = LoggerFactory.getLogger(MessageIterator.class);
37
38
39
40
41
42
43
44
45
46
47
48 public MessageIterator(Structure start, String direction, boolean handleUnexpectedSegments) {
49 this.currentStructure = start;
50 this.direction = direction;
51 this.handleUnexpectedSegments = handleUnexpectedSegments;
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public boolean hasNext() {
86 boolean has = true;
87 if (next == null) {
88 if (Group.class.isAssignableFrom(currentStructure.getClass())) {
89 groupNext((Group) currentStructure);
90 } else {
91 Group parent = currentStructure.getParent();
92 Index i = getIndex(parent, currentStructure);
93 Position currentPosition = new Position(parent, i);
94
95 try {
96 if (parent.isRepeating(i.name) && currentStructure.getName().equals(direction)) {
97 nextRep(currentPosition);
98 } else {
99 has = nextPosition(currentPosition, this.direction, this.handleUnexpectedSegments);
100 }
101 } catch (HL7Exception e) {
102 throw new Error("HL7Exception arising from bad index: " + e.getMessage());
103 }
104 }
105 }
106 log.debug("MessageIterator.hasNext() in direction {}? {}", direction, has);
107 return has;
108 }
109
110
111
112
113
114 private void groupNext(Group current) {
115 next = new Position(current, current.getNames()[0], 0);
116 }
117
118
119
120
121 private void nextRep(Position current) {
122 next = new Position(current.parent, current.index.name, current.index.rep + 1);
123 }
124
125
126
127
128
129
130 private boolean nextPosition(Position currPos, String direction, boolean makeNewSegmentIfNeeded) throws HL7Exception {
131 boolean nextExists = true;
132 if (isLast(currPos)) {
133 nextExists = nextFromGroupEnd(currPos, direction, makeNewSegmentIfNeeded);
134 } else {
135 nextSibling(currPos);
136 }
137 return nextExists;
138 }
139
140
141 private boolean nextFromGroupEnd(Position currPos, String direction, boolean makeNewSegmentIfNeeded) throws HL7Exception {
142 assert isLast(currPos);
143 boolean nextExists = true;
144
145
146
147
148 if (!makeNewSegmentIfNeeded && Message.class.isAssignableFrom(currPos.parent.getClass())) {
149 nextExists = false;
150 } else if (!makeNewSegmentIfNeeded || matchExistsAfterPosition(currPos, direction, false, true)) {
151 Group grandparent = currPos.parent.getParent();
152 Index parentIndex = getIndex(grandparent, currPos.parent);
153 Position parentPos = new Position(grandparent, parentIndex);
154
155 try {
156 boolean parentRepeats = parentPos.parent.isRepeating(parentPos.index.name);
157 if (parentRepeats && contains(parentPos.parent.get(parentPos.index.name, 0), direction, false, true)) {
158 nextRep(parentPos);
159 } else {
160 nextExists = nextPosition(parentPos, direction, makeNewSegmentIfNeeded);
161 }
162 } catch (HL7Exception e) {
163 throw new Error("HL7Exception arising from bad index: " + e.getMessage());
164 }
165 } else {
166 newSegment(currPos.parent, direction);
167 }
168 return nextExists;
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 public static boolean matchExistsAfterPosition(Position pos, String name, boolean firstDescendentsOnly, boolean upToFirstRequired) throws HL7Exception {
185 boolean matchExists = false;
186
187
188 if (pos.parent.isRepeating(pos.index.name)) {
189 Structure s = pos.parent.get(pos.index.name, pos.index.rep);
190 matchExists = contains(s, name, firstDescendentsOnly, upToFirstRequired);
191 }
192
193
194 if (!matchExists) {
195 String[] siblings = pos.parent.getNames();
196 boolean after = false;
197 for (int i = 0; i < siblings.length && !matchExists; i++) {
198 if (after) {
199 matchExists = contains(pos.parent.get(siblings[i]), name, firstDescendentsOnly, upToFirstRequired);
200 if (upToFirstRequired && pos.parent.isRequired(siblings[i])) break;
201 }
202 if (pos.index.name.equals(siblings[i])) after = true;
203 }
204 }
205
206
207 if (!matchExists && !Message.class.isAssignableFrom(pos.parent.getClass())) {
208 Group grandparent = pos.parent.getParent();
209 Position parentPos = new Position(grandparent, getIndex(grandparent, pos.parent));
210 matchExists = matchExistsAfterPosition(parentPos, name, firstDescendentsOnly, upToFirstRequired);
211 }
212 log.debug("Match exists after position {} for {}? {}", pos, name, matchExists);
213 return matchExists;
214 }
215
216
217
218
219
220 private void newSegment(Group parent, String name) throws HL7Exception {
221 log.info("MessageIterator creating new segment: {}", name);
222 parent.addNonstandardSegment(name);
223 next = new Position(parent, parent.getNames()[parent.getNames().length-1], 0);
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 public static boolean contains(Structure s, String name, boolean firstDescendentsOnly, boolean upToFirstRequired) {
241 boolean contains = false;
242 if (Segment.class.isAssignableFrom(s.getClass())) {
243 if (s.getName().equals(name)) contains = true;
244 } else {
245 Grouphref="../../../../ca/uhn/hl7v2/model/Group.html#Group">Group g = (Group) s;
246 String[] names = g.getNames();
247 for (int i = 0; i < names.length && !contains; i++) {
248 try {
249 contains = contains(g.get(names[i], 0), name, firstDescendentsOnly, upToFirstRequired);
250 if (firstDescendentsOnly) break;
251 if (upToFirstRequired && g.isRequired(names[i])) break;
252 } catch (HL7Exception e) {
253 throw new Error("HL7Exception due to bad index: " + e.getMessage());
254 }
255 }
256 }
257 return contains;
258 }
259
260
261
262
263
264 public static boolean isLast(Position p) {
265 String[] names = p.parent.getNames();
266 return names[names.length-1].equals(p.index.name);
267 }
268
269
270
271
272
273 private void nextSibling(Position pos) {
274 String[] names = pos.parent.getNames();
275 int i = 0;
276 for (; i < names.length && !names[i].equals(pos.index.name); i++) {}
277 String nextName = names[i+1];
278
279 this.next = new Position(pos.parent, nextName, 0);
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 public Structure next() {
307 if (!hasNext()) {
308 throw new NoSuchElementException("No more nodes in message");
309 }
310 try {
311 this.currentStructure = next.parent.get(next.index.name, next.index.rep);
312 } catch (HL7Exception e) {
313 throw new NoSuchElementException("HL7Exception: " + e.getMessage());
314 }
315 clearNext();
316 return this.currentStructure;
317 }
318
319
320 public void remove() {
321 throw new UnsupportedOperationException("Can't remove a node from a message");
322 }
323
324 public String getDirection() {
325 return this.direction;
326 }
327
328 public void setDirection(String direction) {
329 clearNext();
330 this.direction = direction;
331 }
332
333 private void clearNext() {
334 next = null;
335 }
336
337
338
339
340
341 public static Index getIndex(Group parent, Structure child) {
342 Index index = null;
343 String[] names = parent.getNames();
344 findChild :
345 for (String name : names) {
346 if (name.startsWith(child.getName())) {
347 try {
348 Structure[] reps = parent.getAll(name);
349 for (int j = 0; j < reps.length; j++) {
350 if (child.equals(reps[j])) {
351 index = new Index(name, j);
352 break findChild;
353 }
354 }
355 } catch (HL7Exception e) {
356 log.error(e.getMessage(), e);
357 throw new Error("Internal HL7Exception finding structure index: " + e.getMessage());
358 }
359 }
360 }
361 return index;
362 }
363
364
365
366
367
368 public static class Index {
369 public final String name;
370 public final int rep;
371 public Index(String name, int rep) {
372 this.name = name;
373 this.rep = rep;
374 }
375
376
377 public boolean equals(Object o) {
378 boolean equals = false;
379 if (o instanceof Index) {
380 Index i = (Index) o;
381 if (i.rep == rep && i.name.equals(name)) equals = true;
382 }
383 return equals;
384 }
385
386
387 public int hashCode() {
388 return name.hashCode() + 700 * rep;
389 }
390
391
392 public String toString() {
393 return this.name + ":" + this.rep;
394 }
395 }
396
397
398
399
400 public static class Position {
401 public final Group parent;
402 public final Index index;
403 public Position(Group parent, String name, int rep) {
404 this.parent = parent;
405 this.index = new Index(name, rep);
406 }
407 public Position(Group parent, Index i) {
408 this.parent = parent;
409 this.index = i;
410 }
411
412
413 public boolean equals(Object o) {
414 boolean equals = false;
415 if (o instanceof Position) {
416 Position p = (Position) o;
417 if (p.parent.equals(parent) && p.index.equals(index)) equals = true;
418 }
419 return equals;
420 }
421
422
423 public int hashCode() {
424 return parent.hashCode() + index.hashCode();
425 }
426
427 public String toString() {
428 return parent.getName() + ":" +
429 index.name +
430 "(" +
431 index.rep +
432 ")";
433 }
434 }
435 }