1 package ca.uhn.hl7v2.preparser;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Properties;
8 import java.util.SortedMap;
9 import java.util.StringTokenizer;
10 import java.util.TreeMap;
11
12 import ca.uhn.hl7v2.parser.EncodingCharacters;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public class ER7 {
36
37 private ER7() {}
38
39
40
41
42 static final String segmentSeparators = "\r\n\f";
43
44
45
46
47 public static boolean parseMessage( Properties props,
48 List<DatumPath> msgMask, String message)
49 {
50 boolean ok = false;
51 if(message != null) {
52 if(props == null)
53 props = new Properties();
54
55 StringTokenizer messageTokenizer
56 = new StringTokenizer(message, segmentSeparators);
57 if(messageTokenizer.hasMoreTokens()) {
58 String firstSegment = messageTokenizer.nextToken();
59 EncodingCharacters encodingChars = new EncodingCharacters('0', "0000");
60 if(parseMSHSegmentWhole(props, msgMask, encodingChars, firstSegment)) {
61 ok = true;
62 SortedMap<String, Integer> segmentId2nextRepIdx = new TreeMap<>();
63 segmentId2nextRepIdx.put("MSH", 1);
64
65 while(messageTokenizer.hasMoreTokens()) {
66 parseSegmentWhole(props, segmentId2nextRepIdx,
67 msgMask, encodingChars, messageTokenizer.nextToken());
68 }
69 }
70 }
71 }
72 return ok;
73 }
74
75
76
77
78 protected static boolean parseMSHSegmentWhole( Properties props,
79 List<DatumPath> msgMask, EncodingCharacters encodingChars,
80 String segment)
81 {
82 boolean ret = false;
83 try {
84 ER7SegmentHandler handler = new ER7SegmentHandler();
85 handler.m_props = props;
86 handler.m_encodingChars = encodingChars;
87 handler.m_segmentId = "MSH";
88 handler.m_segmentRepIdx = 0;
89 if(msgMask != null)
90 handler.m_msgMask = msgMask;
91 else {
92 handler.m_msgMask = new ArrayList<>();
93 handler.m_msgMask.add(new DatumPath());
94
95 }
96
97 encodingChars.setFieldSeparator(segment.charAt(3));
98 List<Integer> nodeKey = new ArrayList<>();
99 nodeKey.add(0);
100 handler.putDatum(nodeKey, String.valueOf(encodingChars.getFieldSeparator()));
101 encodingChars.setComponentSeparator(segment.charAt(4));
102 encodingChars.setRepetitionSeparator(segment.charAt(5));
103 encodingChars.setEscapeCharacter(segment.charAt(6));
104 encodingChars.setSubcomponentSeparator(segment.charAt(7));
105 nodeKey.set(0, 1);
106 handler.putDatum(nodeKey, encodingChars.toString());
107
108 if(segment.charAt(8) == encodingChars.getFieldSeparator()) {
109 ret = true;
110
111
112 nodeKey.clear();
113 nodeKey.add(2);
114 parseSegmentGuts(handler, segment.substring(9), nodeKey);
115 }
116 }
117 catch(IndexOutOfBoundsException | NullPointerException ignored) {}
118
119 return ret;
120 }
121
122
123
124
125 protected static void parseSegmentWhole( Properties props,
126 Map<String, Integer> segmentId2nextRepIdx,
127 List<DatumPath> msgMask, EncodingCharacters encodingChars,
128 String segment)
129 {
130 try {
131 String segmentId = segment.substring(0, 3);
132
133 int currentSegmentRepIdx;
134 if(segmentId2nextRepIdx.containsKey(segmentId))
135 currentSegmentRepIdx = segmentId2nextRepIdx.get(segmentId);
136 else
137 currentSegmentRepIdx = 0;
138 segmentId2nextRepIdx.put(segmentId, currentSegmentRepIdx + 1);
139
140
141
142 boolean parseThisSegment = false;
143 DatumPath segmentIdAsDatumPath = new DatumPath().add(segmentId);
144 for(Iterator<DatumPath> maskIt = msgMask.iterator(); !parseThisSegment && maskIt.hasNext(); )
145 parseThisSegment = segmentIdAsDatumPath.startsWith(maskIt.next());
146 for(Iterator<DatumPath> maskIt = msgMask.iterator(); !parseThisSegment && maskIt.hasNext(); )
147 parseThisSegment = maskIt.next().startsWith(segmentIdAsDatumPath);
148
149 if(parseThisSegment && (segment.charAt(3) == encodingChars.getFieldSeparator())) {
150 ER7SegmentHandler handler = new ER7SegmentHandler();
151 handler.m_props = props;
152 handler.m_encodingChars = encodingChars;
153 handler.m_segmentId = segmentId;
154 handler.m_msgMask = msgMask;
155 handler.m_segmentRepIdx = currentSegmentRepIdx;
156
157 List<Integer> nodeKey = new ArrayList<>();
158 nodeKey.add(0);
159 parseSegmentGuts(handler, segment.substring(4), nodeKey);
160 }
161 }
162 catch(NullPointerException | IndexOutOfBoundsException ignored) {}
163 }
164
165 protected interface Handler
166 {
167 int specDepth();
168 char delim(int level);
169
170 void putDatum(List<Integer> nodeKey, String value);
171 }
172
173 static protected class ER7SegmentHandler implements Handler
174 {
175 Properties m_props;
176
177 EncodingCharacters m_encodingChars;
178
179 String m_segmentId;
180 int m_segmentRepIdx;
181
182 List<DatumPath> m_msgMask;
183
184 public int specDepth() {return 4;}
185
186 public char delim(int level)
187 {
188 if(level == 0)
189 return m_encodingChars.getFieldSeparator();
190 else if(level == 1)
191 return m_encodingChars.getRepetitionSeparator();
192 else if(level == 2)
193 return m_encodingChars.getComponentSeparator();
194 else if(level == 3)
195 return m_encodingChars.getSubcomponentSeparator();
196 else if(level == 4)
197 return m_encodingChars.getTruncationCharacter();
198 else
199 throw new java.lang.Error();
200 }
201
202 public void putDatum(List<Integer> valNodeKey, String value)
203 {
204
205 DatumPath valDatumPath = new DatumPath();
206 valDatumPath.add(m_segmentId).add(m_segmentRepIdx);
207 for(int i=0; i<valNodeKey.size(); ++i) {
208
209 int itval = valNodeKey.get(i);
210 valDatumPath.add(Integer.valueOf(i == 1 ? itval : itval + 1));
211 }
212
213
214 boolean valDatumPathPassesMask = false;
215 for(Iterator<DatumPath> maskIt = m_msgMask.iterator();
216 !valDatumPathPassesMask && maskIt.hasNext(); )
217 {
218 valDatumPathPassesMask = valDatumPath.startsWith(maskIt.next());
219 }
220
221 if(valDatumPathPassesMask)
222 m_props.setProperty(valDatumPath.toString(), value);
223 }
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237 protected static void parseSegmentGuts( Handler handler,
238 String guts, List<Integer> nodeKey)
239 {
240 char thisDepthsDelim = handler.delim(nodeKey.size()-1);
241
242
243 StringTokenizer gutsTokenizer
244 = new StringTokenizer(guts, String.valueOf(thisDepthsDelim), true);
245 while(gutsTokenizer.hasMoreTokens()) {
246 String gutsToken = gutsTokenizer.nextToken();
247
248 if(gutsToken.charAt(0) == thisDepthsDelim) {
249
250
251 int oldvalue = nodeKey.get(nodeKey.size() - 1);
252 nodeKey.set(nodeKey.size()-1, oldvalue + gutsToken.length());
253 }
254 else {
255 if(nodeKey.size() < handler.specDepth()) {
256 nodeKey.add(0);
257 parseSegmentGuts(handler, gutsToken, nodeKey);
258 nodeKey.remove(nodeKey.size()-1);
259 }
260 else
261 handler.putDatum(nodeKey, gutsToken);
262 }
263 }
264
265 }
266
267 public static void main(String[] args)
268 {
269 if(args.length >= 1) {
270
271 System.out.println(args[0]);
272
273 Properties props = new Properties();
274
275 List<DatumPath> msgMask = new ArrayList<>();
276 msgMask.add(new DatumPath());
277
278 System.err.println("ER7.parseMessage returned " + parseMessage(props, msgMask, args[0]));
279 props.list(System.out);
280 }
281 }
282
283 }
284