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 | 0 | 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 | 385 | boolean ok = false; |
51 | 385 | if(message != null) { |
52 | 385 | if(props == null) |
53 | 0 | props = new Properties(); |
54 | |
|
55 | 385 | StringTokenizer messageTokenizer |
56 | |
= new StringTokenizer(message, segmentSeparators); |
57 | 385 | if(messageTokenizer.hasMoreTokens()) { |
58 | 385 | String firstSegment = messageTokenizer.nextToken(); |
59 | 385 | EncodingCharacters encodingChars = new EncodingCharacters('0', "0000"); |
60 | 385 | if(parseMSHSegmentWhole(props, msgMask, encodingChars, firstSegment)) { |
61 | 380 | ok = true; |
62 | 380 | SortedMap<String, Integer> segmentId2nextRepIdx = new TreeMap<String, Integer>(); |
63 | 380 | segmentId2nextRepIdx.put(new String("MSH"), 1); |
64 | |
|
65 | 810 | while(messageTokenizer.hasMoreTokens()) { |
66 | 860 | parseSegmentWhole(props, segmentId2nextRepIdx, |
67 | 430 | msgMask, encodingChars, messageTokenizer.nextToken()); |
68 | |
} |
69 | |
} |
70 | |
} |
71 | |
} |
72 | 385 | 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 | 385 | boolean ret = false; |
83 | |
try { |
84 | 385 | ER7SegmentHandler handler = new ER7SegmentHandler(); |
85 | 385 | handler.m_props = props; |
86 | 385 | handler.m_encodingChars = encodingChars; |
87 | 385 | handler.m_segmentId = "MSH"; |
88 | 385 | handler.m_segmentRepIdx = 0; |
89 | 385 | if(msgMask != null) |
90 | 385 | handler.m_msgMask = msgMask; |
91 | |
else { |
92 | 0 | handler.m_msgMask = new ArrayList<DatumPath>(); |
93 | 0 | handler.m_msgMask.add(new DatumPath()); |
94 | |
|
95 | |
} |
96 | |
|
97 | 385 | encodingChars.setFieldSeparator(segment.charAt(3)); |
98 | 385 | List<Integer> nodeKey = new ArrayList<Integer>(); |
99 | 385 | nodeKey.add(new Integer(0)); |
100 | 385 | handler.putDatum(nodeKey, String.valueOf(encodingChars.getFieldSeparator())); |
101 | 385 | encodingChars.setComponentSeparator(segment.charAt(4)); |
102 | 385 | encodingChars.setRepetitionSeparator(segment.charAt(5)); |
103 | 385 | encodingChars.setEscapeCharacter(segment.charAt(6)); |
104 | 385 | encodingChars.setSubcomponentSeparator(segment.charAt(7)); |
105 | 385 | nodeKey.set(0, new Integer(1)); |
106 | 385 | handler.putDatum(nodeKey, encodingChars.toString()); |
107 | |
|
108 | 385 | if(segment.charAt(8) == encodingChars.getFieldSeparator()) { |
109 | 380 | ret = true; |
110 | |
|
111 | |
|
112 | 380 | nodeKey.clear(); |
113 | 380 | nodeKey.add(new Integer(2)); |
114 | 380 | parseSegmentGuts(handler, segment.substring(9), nodeKey); |
115 | |
} |
116 | |
} |
117 | 0 | catch(IndexOutOfBoundsException e) {} |
118 | 385 | catch(NullPointerException e) {} |
119 | |
|
120 | 385 | return ret; |
121 | |
} |
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
protected static void parseSegmentWhole( Properties props, |
127 | |
Map<String, Integer> segmentId2nextRepIdx, |
128 | |
List<DatumPath> msgMask, EncodingCharacters encodingChars, |
129 | |
String segment) |
130 | |
{ |
131 | |
try { |
132 | 430 | String segmentId = segment.substring(0, 3); |
133 | |
|
134 | 430 | int currentSegmentRepIdx = 0; |
135 | 430 | if(segmentId2nextRepIdx.containsKey(segmentId)) |
136 | 40 | currentSegmentRepIdx = ((Integer)segmentId2nextRepIdx.get(segmentId)).intValue(); |
137 | |
else |
138 | 390 | currentSegmentRepIdx = 0; |
139 | 430 | segmentId2nextRepIdx.put(segmentId, new Integer(currentSegmentRepIdx+1)); |
140 | |
|
141 | |
|
142 | |
|
143 | 430 | boolean parseThisSegment = false; |
144 | 430 | DatumPath segmentIdAsDatumPath = new DatumPath().add(segmentId); |
145 | 430 | for(Iterator<DatumPath> maskIt = msgMask.iterator(); !parseThisSegment && maskIt.hasNext(); ) |
146 | 685 | parseThisSegment = segmentIdAsDatumPath.startsWith(maskIt.next()); |
147 | 430 | for(Iterator<DatumPath> maskIt = msgMask.iterator(); !parseThisSegment && maskIt.hasNext(); ) |
148 | 645 | parseThisSegment = maskIt.next().startsWith(segmentIdAsDatumPath); |
149 | |
|
150 | 430 | if(parseThisSegment && (segment.charAt(3) == encodingChars.getFieldSeparator())) { |
151 | 160 | ER7SegmentHandler handler = new ER7SegmentHandler(); |
152 | 160 | handler.m_props = props; |
153 | 160 | handler.m_encodingChars = encodingChars; |
154 | 160 | handler.m_segmentId = segmentId; |
155 | 160 | handler.m_msgMask = msgMask; |
156 | 160 | handler.m_segmentRepIdx = currentSegmentRepIdx; |
157 | |
|
158 | 160 | List<Integer> nodeKey = new ArrayList<Integer>(); |
159 | 160 | nodeKey.add(new Integer(0)); |
160 | 160 | parseSegmentGuts(handler, segment.substring(4), nodeKey); |
161 | |
} |
162 | |
} |
163 | 0 | catch(NullPointerException e) {} |
164 | 430 | catch(IndexOutOfBoundsException e) {} |
165 | 430 | } |
166 | |
|
167 | |
static protected interface Handler |
168 | |
{ |
169 | |
public int specDepth(); |
170 | |
public char delim(int level); |
171 | |
|
172 | |
public void putDatum(List<Integer> nodeKey, String value); |
173 | |
} |
174 | |
|
175 | 545 | static protected class ER7SegmentHandler implements Handler |
176 | |
{ |
177 | |
Properties m_props; |
178 | |
|
179 | |
EncodingCharacters m_encodingChars; |
180 | |
|
181 | |
String m_segmentId; |
182 | |
int m_segmentRepIdx; |
183 | |
|
184 | |
List<DatumPath> m_msgMask; |
185 | |
|
186 | 15240 | public int specDepth() {return 4;} |
187 | |
|
188 | |
public char delim(int level) |
189 | |
{ |
190 | 11400 | if(level == 0) |
191 | 540 | return m_encodingChars.getFieldSeparator(); |
192 | 10860 | else if(level == 1) |
193 | 3230 | return m_encodingChars.getRepetitionSeparator(); |
194 | 7630 | else if(level == 2) |
195 | 3280 | return m_encodingChars.getComponentSeparator(); |
196 | 4350 | else if(level == 3) |
197 | 4350 | return m_encodingChars.getSubcomponentSeparator(); |
198 | 0 | else if(level == 4) |
199 | 0 | return m_encodingChars.getTruncationCharacter(); |
200 | |
else |
201 | 0 | throw new java.lang.Error(); |
202 | |
} |
203 | |
|
204 | |
public void putDatum(List<Integer> valNodeKey, String value) |
205 | |
{ |
206 | |
|
207 | 5150 | DatumPath valDatumPath = new DatumPath(); |
208 | 5150 | valDatumPath.add(m_segmentId).add(m_segmentRepIdx); |
209 | 23440 | for(int i=0; i<valNodeKey.size(); ++i) { |
210 | |
|
211 | 18290 | int itval = ((Integer)valNodeKey.get(i)).intValue(); |
212 | 18290 | valDatumPath.add(new Integer(i == 1 ? itval : itval+1)); |
213 | |
} |
214 | |
|
215 | |
|
216 | 5150 | boolean valDatumPathPassesMask = false; |
217 | 5150 | for(Iterator<DatumPath> maskIt = m_msgMask.iterator(); |
218 | 13250 | !valDatumPathPassesMask && maskIt.hasNext(); ) |
219 | |
{ |
220 | 8100 | valDatumPathPassesMask = valDatumPath.startsWith(maskIt.next()); |
221 | |
} |
222 | |
|
223 | 5150 | if(valDatumPathPassesMask) |
224 | 330 | m_props.setProperty(valDatumPath.toString(), value); |
225 | 5150 | } |
226 | |
} |
227 | |
|
228 | |
|
229 | |
|
230 | |
|
231 | |
|
232 | |
|
233 | |
|
234 | |
|
235 | |
|
236 | |
|
237 | |
|
238 | |
|
239 | |
protected static void parseSegmentGuts( Handler handler, |
240 | |
String guts, List<Integer> nodeKey) |
241 | |
{ |
242 | 11400 | char thisDepthsDelim = handler.delim(nodeKey.size()-1); |
243 | |
|
244 | |
|
245 | 11400 | StringTokenizer gutsTokenizer |
246 | 11400 | = new StringTokenizer(guts, String.valueOf(thisDepthsDelim), true); |
247 | 34560 | while(gutsTokenizer.hasMoreTokens()) { |
248 | 23160 | String gutsToken = gutsTokenizer.nextToken(); |
249 | |
|
250 | 23160 | if(gutsToken.charAt(0) == thisDepthsDelim) { |
251 | |
|
252 | |
|
253 | 7920 | int oldvalue = ((Integer)nodeKey.get(nodeKey.size()-1)).intValue(); |
254 | 7920 | nodeKey.set(nodeKey.size()-1, new Integer(oldvalue + gutsToken.length())); |
255 | 7920 | } |
256 | |
else { |
257 | 15240 | if(nodeKey.size() < handler.specDepth()) { |
258 | 10860 | nodeKey.add(new Integer(0)); |
259 | 10860 | parseSegmentGuts(handler, gutsToken, nodeKey); |
260 | 10860 | nodeKey.remove(nodeKey.size()-1); |
261 | |
} |
262 | |
else |
263 | 4380 | handler.putDatum(nodeKey, gutsToken); |
264 | |
} |
265 | 23160 | } |
266 | |
|
267 | 11400 | } |
268 | |
|
269 | |
public static void main(String args[]) |
270 | |
{ |
271 | 0 | if(args.length >= 1) { |
272 | |
|
273 | 0 | System.out.println(args[0]); |
274 | |
|
275 | 0 | Properties props = new Properties(); |
276 | |
|
277 | 0 | List<DatumPath> msgMask = new ArrayList<DatumPath>(); |
278 | 0 | msgMask.add(new DatumPath()); |
279 | |
|
280 | 0 | System.err.println("ER7.parseMessage returned " + parseMessage(props, msgMask, args[0])); |
281 | 0 | props.list(System.out); |
282 | |
} |
283 | 0 | } |
284 | |
|
285 | |
} |
286 | |
|