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  package ca.uhn.hl7v2.testpanel.ui;
27  
28  import java.awt.Color;
29  import java.awt.Component;
30  import java.awt.EventQueue;
31  import java.awt.Font;
32  
33  import javax.swing.JScrollBar;
34  import javax.swing.JTable;
35  
36  import org.apache.commons.lang.StringUtils;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import ca.uhn.hl7v2.HL7Exception;
41  import ca.uhn.hl7v2.testpanel.model.ActivityBytesBase;
42  import ca.uhn.hl7v2.testpanel.model.ActivityInfo;
43  import ca.uhn.hl7v2.testpanel.model.ActivityInfoError;
44  import ca.uhn.hl7v2.testpanel.model.ActivityMessage;
45  import ca.uhn.hl7v2.testpanel.model.ActivityValidationOutcome;
46  import ca.uhn.hl7v2.testpanel.util.FormatUtil;
47  import ca.uhn.hl7v2.testpanel.xsd.Hl7V2EncodingTypeEnum;
48  
49  public class ActivityDetailsCellRenderer extends ActivityCellRendererBase {
50  
51  	private static final Logger ourLog = LoggerFactory.getLogger(ActivityDetailsCellRenderer.class);
52  
53  	private Font myFixedWidthFont;
54  	private Font myVarWidthFont;
55  
56  	private boolean myScrollToBottom;
57  
58  	public ActivityDetailsCellRenderer(ActivityTable theTablePanel) {
59  		super(theTablePanel);
60  
61  		myFixedWidthFont = new Font("Lucida Console", Font.PLAIN, 12);
62  		myVarWidthFont = new Font("Lucida", Font.PLAIN, 12);
63  	}
64  
65  	@Override
66  	public Component getTableCellRendererComponent(final JTable theTable, Object theValue, boolean theIsSelected, boolean theHasFocus, final int theRow, int theColumn) {
67  		super.getTableCellRendererComponent(theTable, theValue, theIsSelected, theHasFocus, theRow, theColumn);
68  
69  		if (theValue instanceof ActivityInfo) {
70  
71  			renderInfo(theTable, theValue, theRow);
72  
73  		} else if (theValue instanceof ActivityMessage) {
74  
75  			renderMessage(theTable, theValue, theRow, theIsSelected);
76  
77  		} else if (theValue instanceof ActivityBytesBase) {
78  
79  			renderBytes(theTable, theValue, theRow);
80  
81  		} else if (theValue instanceof ActivityValidationOutcome) {
82  
83  			renderValidation(theTable, (ActivityValidationOutcome) theValue, theRow);
84  
85  		}
86  
87  		
88  		
89  		
90  		
91  		
92  		
93  
94  		
95  		
96  		
97  		
98  		
99  		
100 		
101 		
102 		
103 		
104 
105 		
106 
107 		
108 		
109 		
110 		
111 		
112 		
113 		
114 		
115 		if (myScrollToBottom) {
116 			EventQueue.invokeLater(new Runnable() {
117 				public void run() {
118 					JScrollBar vsb = getTablePanel().getScrollPane().getVerticalScrollBar();
119 					int newValue = vsb.getMaximum();
120 					int existingValue = vsb.getValue();
121 					if (newValue != existingValue) {
122 						vsb.setValue(newValue);
123 						ourLog.debug("Setting scrollbar to bottom, from {} to {}", existingValue, newValue);
124 					}
125 
126 					if (theRow == getTablePanel().getTableModel().getRowCount() - 1) {
127 						myScrollToBottom = false;
128 					}
129 				}
130 			});
131 
132 		}
133 
134 		return this;
135 	}
136 
137 	private void renderValidation(JTable theTable, ActivityValidationOutcome theValue, int theRow) {
138 		if (theValue.isValidated()) {
139 
140 			setText("No Errors");
141 
142 		} else {
143 
144 			StringBuilder b = new StringBuilder("<html>");
145 
146 			b.append("<font color=\"#800000\">");
147 			b.append("<ul>");
148 
149 			for (HL7Exception next : theValue.getIssues()) {
150 				b.append("<li>");
151 				if (StringUtils.isNotBlank(next.getLocation().getSegmentName())) {
152 					b.append("<b>");
153 					b.append(next.getLocation().getSegmentName());
154 					if (next.getLocation().getSegmentRepetition() > 1) {
155 						b.append("(").append(next.getLocation().getSegmentRepetition()).append(")");
156 					}
157 					if (next.getLocation().getField() > 0) {
158 						b.append("-");
159 						b.append(next.getLocation().getField());
160 					}
161 					b.append("</b>: ");
162 				}
163 				b.append("<nobr>").append(next.getMessage()).append("</nobr>");
164 				b.append("</li>");
165 			}
166 
167 			b.append("</ul>");
168 			b.append("</font>");
169 			b.append("</html>");
170 			setText(b.toString());
171 
172 		}
173 
174 		updatePreferredHeight(theTable, theRow);
175 
176 	}
177 
178 	private void renderBytes(final JTable theTable, Object theValue, final int theRow) {
179 		ActivityBytesBase msg = (ActivityBytesBase) theValue;
180 
181 		StringBuilder b = new StringBuilder();
182 		b.append("<html>");
183 		b.append("<table>");
184 
185 		StringBuilder charsB = new StringBuilder();
186 		StringBuilder bytesB = new StringBuilder();
187 
188 		byte[] bytes = msg.getBytes();
189 		for (int i = 0; i < bytes.length; i++) {
190 
191 			if (i == 0) {
192 				b.append("<tr>");
193 			} else if (i % 20 == 0) {
194 				b.append("<td><nobr>");
195 				b.append(charsB.toString());
196 				for (int j = charsB.toString().length(); j < 20; j++) {
197 					b.append(" ");
198 				}
199 				b.append("</nobr></td><td><nobr>");
200 				b.append(bytesB.toString());
201 				b.append("</nobr></td></tr><tr>");
202 				charsB.setLength(0);
203 				bytesB.setLength(0);
204 			}
205 
206 			byte nextByte = bytes[i];
207 			if (nextByte < 32) {
208 				charsB.append(" ");
209 			} else if ((char)nextByte == '<') {
210 				charsB.append("<");
211 			} else {
212 				charsB.append(new String(new byte[] { nextByte }));
213 			}
214 
215 			String byteToString = Integer.toString(nextByte);
216 			if (nextByte < 32) {
217 				byteToString = "<font color=\"#FF0000\">" + byteToString + "</font>";
218 			}
219 
220 			if (nextByte < 100) {
221 				bytesB.append(" ");
222 			}
223 			bytesB.append(byteToString).append(" ");
224 
225 		}
226 
227 		b.append("<td><nobr>");
228 		b.append(charsB.toString());
229 		for (int j = charsB.toString().length(); j < 20; j++) {
230 			b.append(" ");
231 		}
232 		b.append("</nobr></td><td><nobr>");
233 		b.append(bytesB.toString());
234 		b.append("</nobr></td></tr><tr>");
235 		b.append("</tr>");
236 		b.append("</table>");
237 		b.append("</html>");
238 
239 		String rawMessage = b.toString();
240 		setText(rawMessage);
241 		setFont(myFixedWidthFont);
242 		setForeground(Color.black);
243 
244 		updatePreferredHeight(theTable, theRow);
245 
246 	}
247 
248 	private void renderInfo(final JTable theTable, Object theValue, final int theRow) {
249 		if (theValue instanceof ActivityInfoError) {
250 			setForeground(Color.red);
251 		} else {
252 			setForeground(Color.black);
253 		}
254 
255 		String message = ((ActivityInfo) theValue).getMessage();
256 		setText(message);
257 		
258 
259 		setFont(myVarWidthFont);
260 
261 		if (theTable.getRowHeight(theRow) != theTable.getRowHeight()) {
262 			EventQueue.invokeLater(new Runnable() {
263 				public void run() {
264 					theTable.setRowHeight(theRow, theTable.getRowHeight());
265 				}
266 			});
267 		}
268 	}
269 
270 	private void renderMessage(final JTable theTable, Object theValue, final int theRow, boolean theSelected) {
271 		ActivityMessage msg = (ActivityMessage) theValue;
272 
273 		if (theSelected) {
274 
275 			String rawMessage;
276 			if (msg.getEncoding() == Hl7V2EncodingTypeEnum.XML) {
277 				StringBuilder b = new StringBuilder();
278 				b.append("<html>");
279 
280 				String raw = msg.getRawMessage();
281 				for (int c = 0; c < raw.length(); c++) {
282 					char nextChar = raw.charAt(c);
283 					boolean isSpecial = nextChar == msg.getEncodingCharacters().getComponentSeparator();
284 					isSpecial |= nextChar == msg.getEncodingCharacters().getFieldSeparator();
285 					isSpecial |= nextChar == msg.getEncodingCharacters().getEscapeCharacter();
286 					isSpecial |= nextChar == msg.getEncodingCharacters().getRepetitionSeparator();
287 					isSpecial |= nextChar == msg.getEncodingCharacters().getSubcomponentSeparator();
288 
289 					if (isSpecial) {
290 						b.append("<font color=\"#48A0A0\">");
291 					}
292 
293 					switch (nextChar) {
294 					case '\r':
295 					case '\n':
296 						b.append("<br>");
297 						break;
298 					case ' ':
299 						b.append(" ");
300 						break;
301 					case '&':
302 						b.append("&");
303 						break;
304 					case '<':
305 						b.append("<");
306 						break;
307 					case '>':
308 						b.append(">");
309 						break;
310 					default:
311 						b.append(nextChar);
312 					}
313 
314 					if (isSpecial) {
315 						b.append("</font>");
316 					}
317 
318 				}
319 
320 				b.append("</html>");
321 
322 				rawMessage = b.toString();
323 
324 			} else {
325 
326 				rawMessage = FormatUtil.formatEr7(msg.getRawMessage(), false).replace("\r", "<br>");
327 
328 			}
329 
330 			setText(rawMessage);
331 
332 		} else {
333 
334 			setText("<html>" + msg.getRawMessage().replace("\r", "<br>") + "</html>");
335 		}
336 
337 
338 		setForeground(Color.black);
339 		setFont(myFixedWidthFont);
340 
341 		updatePreferredHeight(theTable, theRow);
342 		
343 	}
344 
345 	private void updatePreferredHeight(final JTable theTable, final int theRow) {
346 		final int newHeight = (int) getPreferredSize().getHeight();
347 		if (theTable.getRowHeight(theRow) != newHeight) {
348 			EventQueue.invokeLater(new Runnable() {
349 				public void run() {
350 					theTable.setRowHeight(theRow, newHeight);
351 
352 				}
353 			});
354 		}
355 	}
356 
357 	public void markScrollToBottom() {
358 		myScrollToBottom = true;
359 	}
360 }