View Javadoc
1   /**
2    * The contents of this file are subject to the Mozilla Public License Version 1.1
3    * (the "License"); you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
5    * Software distributed under the License is distributed on an "AS IS" basis,
6    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
7    * specific language governing rights and limitations under the License.
8    *
9    * The Original Code is ""  Description:
10   * ""
11   *
12   * The Initial Developer of the Original Code is University Health Network. Copyright (C)
13   * 2001.  All Rights Reserved.
14   *
15   * Contributor(s): ______________________________________.
16   *
17   * Alternatively, the contents of this file may be used under the terms of the
18   * GNU General Public License (the  "GPL"), in which case the provisions of the GPL are
19   * applicable instead of those above.  If you wish to allow use of your version of this
20   * file only under the terms of the GPL and not to allow others to use your version
21   * of this file under the MPL, indicate your decision by deleting  the provisions above
22   * and replace  them with the notice and other provisions required by the GPL License.
23   * If you do not delete the provisions above, a recipient may use your version of
24   * this file under either the MPL or the GPL.
25   */
26  package ca.uhn.hl7v2.testpanel.model.msg;
27  
28  import java.beans.PropertyVetoException;
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.Collections;
32  import java.util.List;
33  
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  import ca.uhn.hl7v2.HL7Exception;
38  import ca.uhn.hl7v2.model.Composite;
39  import ca.uhn.hl7v2.model.Group;
40  import ca.uhn.hl7v2.model.Message;
41  import ca.uhn.hl7v2.model.Primitive;
42  import ca.uhn.hl7v2.model.Segment;
43  import ca.uhn.hl7v2.model.Structure;
44  import ca.uhn.hl7v2.model.Type;
45  import ca.uhn.hl7v2.model.Varies;
46  import ca.uhn.hl7v2.parser.DefaultXMLParser;
47  import ca.uhn.hl7v2.parser.EncodingCharacters;
48  import ca.uhn.hl7v2.testpanel.util.CharCountingStringIteratorDecorator;
49  import ca.uhn.hl7v2.testpanel.util.Range;
50  import ca.uhn.hl7v2.testpanel.util.SegmentAndComponentPath;
51  import ca.uhn.hl7v2.testpanel.xsd.Hl7V2EncodingTypeEnum;
52  
53  public class Hl7V2MessageEr7 extends Hl7V2MessageBase {
54  	private static final Logger ourLog = LoggerFactory.getLogger(Hl7V2MessageEr7.class);
55  	private String myHighlitedPath;
56  	private Range myHighlitedRange;
57  	private ArrayList<Segment> mySegmentIndexes = new ArrayList<Segment>();
58  	private ArrayList<Range> mySegmentRanges = new ArrayList<Range>();
59  	private ArrayList<String> mySegmentTerserPaths = new ArrayList<String>();
60  
61  	public Hl7V2MessageEr7() {
62  		super();
63  	}
64  
65  	public Hl7V2MessageEr7(int theIndexWithinCollection) throws PropertyVetoException {
66  		this();
67  
68  		setIndexWithinCollection(theIndexWithinCollection);
69  	}
70  
71  	@Override
72  	public Hl7V2MessageBase asEncoding(Hl7V2EncodingTypeEnum theEncoding) {
73  		switch (theEncoding) {
74  		case ER_7:
75  			return this;
76  		case XML:
77  		default:
78  			Hl7V2MessageXml retVal = new Hl7V2MessageXml();
79  			try {
80  				retVal.setSourceMessage(new DefaultXMLParser().encode(getParsedMessage()));
81  			} catch (PropertyVetoException e) {
82  				ourLog.error("Failed to create XML message", e);
83  			} catch (HL7Exception e) {
84  				ourLog.error("Failed to create XML message", e);
85  			}
86  
87  			return retVal;
88  		}
89  
90  	}
91  
92  	public void clearHighlight() {
93  		setHighlitedRangeBasedOnSegment((Segment[])null);
94  		setHighlitedPathBasedOnRange(null);
95  	}
96  
97  	/**
98  	 * @return the highlitedPath
99  	 */
100 	public String getHighlitedPath() {
101 		return myHighlitedPath;
102 	}
103 
104 	public Range getHighlitedRange() {
105 		return myHighlitedRange;
106 	}
107 
108 	public int getLineIndex(Segment theSegment) {
109 		int index = 0;
110 		for (Segment next : mySegmentIndexes) {
111 			if (next == theSegment) {
112 				return index;
113 			} else {
114 				index++;
115 			}
116 		}
117 
118 		return -1;
119 	}
120 
121 	List<Range> getSegmentRanges() {
122 		return Collections.unmodifiableList(mySegmentRanges);
123 	}
124 
125 	protected void recalculateIndexes() {
126 		String[] lines = getSourceMessage().split("\\r");
127 		CharCountingStringIteratorDecorator iter = new CharCountingStringIteratorDecorator(Arrays.asList(lines).iterator());
128 		mySegmentIndexes.clear();
129 		mySegmentRanges.clear();
130 		mySegmentTerserPaths.clear();
131 
132 		try {
133 			// Integer.toString(getIndexWithinCollection())
134 			recalculateIndexes(iter, getParsedMessage(), null, "");
135 		} catch (HL7Exception e) {
136 			ourLog.error("Failed to calculate message segment indexes", e);
137 		}
138 	}
139 
140 	private String recalculateIndexes(CharCountingStringIteratorDecorator theIter, Group theGroup, String theNameToSearchFor, String thePath) throws HL7Exception {
141 		for (String nextName : theGroup.getNames()) {
142 
143 			if (theNameToSearchFor == null && theIter.hasNext()) {
144 				do {
145 					theNameToSearchFor = theIter.next();
146 
147 					// Account for \r
148 					theIter.setNumCharsReturned(theIter.getNumCharsReturned() + 1);
149 
150 					if (theNameToSearchFor.length() < 3) {
151 						mySegmentIndexes.add(null);
152 						mySegmentRanges.add(null);
153 					} else {
154 						theNameToSearchFor = theNameToSearchFor.substring(0, 3);
155 					}
156 				} while (theNameToSearchFor == null);
157 			}
158 
159 			if (theNameToSearchFor == null && theIter.hasNext() == false) {
160 				return null;
161 			}
162 
163 			Structure[] reps = theGroup.getAll(nextName);
164 			if (theGroup.isGroup(nextName)) {
165 				int repIndex = 1;
166 				for (Structure structure : reps) {
167 					String nextPath = thePath + "/" + nextName + (repIndex > 1 ? "(" + repIndex + ")" : "");
168 					repIndex++;
169 					theNameToSearchFor = recalculateIndexes(theIter, (Group) structure, theNameToSearchFor, nextPath);
170 				}
171 				continue;
172 			}
173 
174 			if (!theNameToSearchFor.equals(nextName)) {
175 				continue;
176 			}
177 
178 			int repIndex = 1;
179 			ER7_STRUCTURE_REPS: for (Structure structure : reps) {
180 
181 				String nextPath = thePath + "/" + nextName + (repIndex > 1 ? "(" + repIndex + ")" : "");
182 				mySegmentTerserPaths.add(nextPath);
183 				repIndex++;
184 
185 				mySegmentIndexes.add((Segment) structure);
186 
187 				int start = 0;
188 				if (mySegmentRanges.size() > 0) {
189 					start = mySegmentRanges.get(mySegmentRanges.size() - 1).getEnd() + 1;
190 				}
191 
192 				int end = theIter.getNumCharsReturned();
193 				mySegmentRanges.add(new Range(start, end - 1));
194 
195 				if (theIter.hasNext() == false) {
196 					return null;
197 				}
198 
199 				do {
200 					theNameToSearchFor = theIter.next();
201 
202 					// Account for \r
203 					theIter.setNumCharsReturned(theIter.getNumCharsReturned() + 1);
204 
205 					if (theNameToSearchFor.length() < 3) {
206 						mySegmentIndexes.add(null);
207 						mySegmentRanges.add(null);
208 					} else {
209 						theNameToSearchFor = theNameToSearchFor.substring(0, 3);
210 					}
211 				} while (theNameToSearchFor == null);
212 
213 				if (!theNameToSearchFor.equals(nextName)) {
214 					break ER7_STRUCTURE_REPS;
215 				}
216 
217 			}
218 
219 		} // for
220 
221 		return theNameToSearchFor;
222 
223 	}
224 
225 	public void setHighlitedField(SegmentAndComponentPath theField) {
226 
227 		if (theField == null) {
228 			setHighlitedPathBasedOnRange(null);
229 			return;
230 		}
231 
232 		int lineIndex = getLineIndex(theField.getSegment());
233 		if (lineIndex == -1) {
234 			setHighlitedPathBasedOnRange(null);
235 			return;
236 		}
237 
238 		Range segmentRange = mySegmentRanges.get(lineIndex);
239 		String sourceMessage = getSourceMessage();
240 		Message parsedMessage = getParsedMessage();
241 
242 		Range currentRange = findFieldRange(theField.getComponentPath(), theField.getRepNum(), segmentRange, sourceMessage, parsedMessage);
243 		setHighlitedPathBasedOnRange(currentRange);
244 		myHighlitedRange = currentRange;
245 
246 	}
247 
248 	public void setHighlitedPathBasedOnRange(Range theRange) {
249 
250 		if (theRange == null) {
251 			myHighlitedPath = null;
252 			return;
253 		}
254 
255 		int dot = theRange.getStart();
256 
257 		int dotIndex = -1;
258 		Range segmentRange = null;
259 		for (int i = 0; i < mySegmentRanges.size(); i++) {
260 			segmentRange = mySegmentRanges.get(i);
261 			if (segmentRange != null && segmentRange.contains(dot)) {
262 				dotIndex = i;
263 				break;
264 			}
265 		}
266 
267 		if (dotIndex == -1) {
268 			return;
269 		}
270 
271 		EncodingCharacters enc;
272 		try {
273 			enc = EncodingCharacters.getInstance(getParsedMessage());
274 		} catch (HL7Exception e) {
275 			ourLog.error("Failed to find field", e);
276 			return;
277 		}
278 
279 		int fieldIndex = 0;
280 		int cmpIndex = 0;
281 		int subCmpIndex = 0;
282 		int repIndex = 0;
283 		for (int i = segmentRange.getStart() + 1; i <= segmentRange.getEnd() && i <= dot && i <= getSourceMessage().length(); i++) {
284 			char nextChar = getSourceMessage().charAt(i - 1);
285 			if (nextChar == enc.getRepetitionSeparator()) {
286 				repIndex++;
287 				cmpIndex = 1;
288 				subCmpIndex = 1;
289 			} else if (nextChar == enc.getFieldSeparator()) {
290 				fieldIndex++;
291 				repIndex = 0;
292 				cmpIndex = 1;
293 				subCmpIndex = 1;
294 			} else if (nextChar == enc.getComponentSeparator()) {
295 				cmpIndex++;
296 				subCmpIndex = 1;
297 			} else if (nextChar == enc.getSubcomponentSeparator()) {
298 				subCmpIndex++;
299 			}
300 		}
301 
302 		Segment segment = mySegmentIndexes.get(dotIndex);
303 		if (segment.getName().equals("MSH")) {
304 			fieldIndex++;
305 			if (fieldIndex == 2) {
306 				cmpIndex = 1;
307 				subCmpIndex = 1;
308 				repIndex = 0;
309 			}
310 		}
311 
312 		try {
313 			if (fieldIndex > 0) {
314 				Type type = segment.getField(fieldIndex, 0);
315 				if (type instanceof Varies) {
316 					type = ((Varies) type).getData();
317 				}
318 				if (type instanceof Composite) {
319 					Composite composite = (Composite) type;
320 					if (subCmpIndex == 1) {
321 						Type subComponent = composite.getComponent(1);
322 						if (subComponent instanceof Varies) {
323 							subComponent = ((Varies) subComponent).getData();
324 						}
325 						if (subComponent instanceof Primitive) {
326 							subCmpIndex = 0;
327 						}
328 					}
329 				} else if (cmpIndex == 1) {
330 					cmpIndex = 0;
331 				}
332 			}
333 
334 		} catch (HL7Exception e) {
335 			ourLog.error("Failed to retrieve field", e);
336 		}
337 
338 		String basePath = mySegmentTerserPaths.get(dotIndex);
339 		StringBuilder fullPathB = new StringBuilder(basePath);
340 		if (fieldIndex >= 1) {
341 			fullPathB.append('-').append(fieldIndex);
342 			if (repIndex > 0) {
343 				fullPathB.append('(');
344 				fullPathB.append(repIndex + 1);
345 				fullPathB.append(')');
346 			}
347 			if (cmpIndex >= 1) {
348 				fullPathB.append('-').append(cmpIndex);
349 				if (subCmpIndex >= 1) {
350 					fullPathB.append('-').append(subCmpIndex);
351 				}
352 			}
353 		}
354 		String fullPath = fullPathB.toString();
355 		
356 //		/*
357 //		 * The encoding characters in MSH-2 make this think that we're in subcomponents
358 //		 * and repetitions
359 //		 */
360 //		if (fullPath.startsWith("MSH-2")) {
361 //			fullPath = "MSH-2";
362 //		}
363 
364 		ourLog.info("Highlited path is now: " + fullPath);
365 
366 		myHighlitedPath = fullPath;
367 	}
368 
369 	public void setHighlitedRangeBasedOnSegment(Segment... theSegment) {
370 		if (theSegment == null || theSegment.length == 0) {
371 			myHighlitedRange = null;
372 		} else {
373 
374 			myHighlitedRange = null;
375 			for (Segment segment : theSegment) {
376 				int newSelectedIndex = theSegment != null ? getLineIndex(segment) : -1;
377 				if (newSelectedIndex != -1) {
378 					Range nextRange = mySegmentRanges.get(newSelectedIndex);
379 					if (nextRange == null) {
380 						// nothing
381 					} else if (myHighlitedRange == null) {
382 						myHighlitedRange = nextRange;
383 					} else {
384 						myHighlitedRange = myHighlitedRange.overlay(nextRange);
385 					}
386 				}
387 			}
388 
389 		}
390 
391 	}
392 
393 }