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.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  		// int prefHeight = getPreferredSize().height;
88  		// prefHeight = Math.max(prefHeight, 10);
89  		// if (prefHeight != theTable.getRowHeight(theRow)) {
90  		// ourLog.trace("Setting height of row {} to {}", theRow, prefHeight);
91  		// theTable.setRowHeight(theRow, prefHeight);
92  		// }
93  
94  		// EventQueue.invokeLater(new Runnable() {
95  		// public void run() {
96  		// int minWidth = getPreferredSize().width + 200;
97  		//
98  		// if (minWidth > theTable.getColumnModel().getColumn(2).getWidth()) {
99  		// theTable.getColumnModel().getColumn(2).setMinWidth(getPreferredSize().width);
100 		// theTable.getColumnModel().getColumn(2).setMaxWidth(getPreferredSize().width);
101 		// theTable.getColumnModel().getColumn(2).setPreferredWidth(getPreferredSize().width);
102 		// }
103 		// }});
104 
105 		// ourLog.info("Rendering row {}", theRow);
106 
107 		// EventQueue.invokeLater(new Runnable() {
108 		// public void run() {
109 		// getTablePanel().
110 		// JScrollBar vsb = myscrollPane.getVerticalScrollBar();
111 		// vsb.setValue(vsb.getMaximum());
112 		// ourLog.info("Setting scrollbar to bottom: {}", vsb.getMaximum());
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("&nbsp;");
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("&nbsp;");
209 			} else if ((char)nextByte == '<') {
210 				charsB.append("&lt;");
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("&nbsp;");
222 			}
223 			bytesB.append(byteToString).append("&nbsp;");
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("&nbsp;");
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 //		updateHeight(theTable, theRow);
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 		// setText(text);
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("&nbsp;");
300 						break;
301 					case '&':
302 						b.append("&amp;");
303 						break;
304 					case '<':
305 						b.append("&lt;");
306 						break;
307 					case '>':
308 						b.append("&gt;");
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 //		setBackground(Color.white);
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 //					theTable.getColumnModel().getColumn(2).setWidth(5000);
352 				}
353 			});
354 		}
355 	}
356 
357 	public void markScrollToBottom() {
358 		myScrollToBottom = true;
359 	}
360 }