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().replace("<", "&lt;"));
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 {
210 				charsB.append(new String(new byte[] { nextByte }));
211 			}
212 
213 			String byteToString = Integer.toString(nextByte);
214 			if (nextByte < 32) {
215 				byteToString = "<font color=\"#FF0000\">" + byteToString + "</font>";
216 			}
217 
218 			if (nextByte < 100) {
219 				bytesB.append("&nbsp;");
220 			}
221 			bytesB.append(byteToString).append("&nbsp;");
222 
223 		}
224 
225 		b.append("<td><nobr>");
226 		b.append(charsB.toString());
227 		for (int j = charsB.toString().length(); j < 20; j++) {
228 			b.append("&nbsp;");
229 		}
230 		b.append("</nobr></td><td><nobr>");
231 		b.append(bytesB.toString());
232 		b.append("</nobr></td></tr><tr>");
233 		b.append("</tr>");
234 		b.append("</table>");
235 		b.append("</html>");
236 
237 		String rawMessage = b.toString();
238 		setText(rawMessage);
239 		setFont(myFixedWidthFont);
240 		setForeground(Color.black);
241 
242 		updatePreferredHeight(theTable, theRow);
243 //		updateHeight(theTable, theRow);
244 	}
245 
246 	private void renderInfo(final JTable theTable, Object theValue, final int theRow) {
247 		if (theValue instanceof ActivityInfoError) {
248 			setForeground(Color.red);
249 		} else {
250 			setForeground(Color.black);
251 		}
252 
253 		String message = ((ActivityInfo) theValue).getMessage();
254 		setText(message);
255 		// setText(text);
256 
257 		setFont(myVarWidthFont);
258 
259 		if (theTable.getRowHeight(theRow) != theTable.getRowHeight()) {
260 			EventQueue.invokeLater(new Runnable() {
261 				public void run() {
262 					theTable.setRowHeight(theRow, theTable.getRowHeight());
263 				}
264 			});
265 		}
266 	}
267 
268 	private void renderMessage(final JTable theTable, Object theValue, final int theRow, boolean theSelected) {
269 		ActivityMessage msg = (ActivityMessage) theValue;
270 
271 		if (theSelected) {
272 
273 			String rawMessage;
274 			if (msg.getEncoding() == Hl7V2EncodingTypeEnum.XML) {
275 				StringBuilder b = new StringBuilder();
276 				b.append("<html>");
277 
278 				String raw = msg.getRawMessage();
279 				for (int c = 0; c < raw.length(); c++) {
280 					char nextChar = raw.charAt(c);
281 					boolean isSpecial = nextChar == msg.getEncodingCharacters().getComponentSeparator();
282 					isSpecial |= nextChar == msg.getEncodingCharacters().getFieldSeparator();
283 					isSpecial |= nextChar == msg.getEncodingCharacters().getEscapeCharacter();
284 					isSpecial |= nextChar == msg.getEncodingCharacters().getRepetitionSeparator();
285 					isSpecial |= nextChar == msg.getEncodingCharacters().getSubcomponentSeparator();
286 
287 					if (isSpecial) {
288 						b.append("<font color=\"#48A0A0\">");
289 					}
290 
291 					switch (nextChar) {
292 					case '\r':
293 					case '\n':
294 						b.append("<br>");
295 						break;
296 					case ' ':
297 						b.append("&nbsp;");
298 						break;
299 					case '&':
300 						b.append("&amp;");
301 						break;
302 					case '<':
303 						b.append("&lt;");
304 						break;
305 					case '>':
306 						b.append("&gt;");
307 						break;
308 					default:
309 						b.append(nextChar);
310 					}
311 
312 					if (isSpecial) {
313 						b.append("</font>");
314 					}
315 
316 				}
317 
318 				b.append("</html>");
319 
320 				rawMessage = b.toString();
321 
322 			} else {
323 
324 				rawMessage = FormatUtil.formatEr7(msg.getRawMessage(), false).replace("\r", "<br>");
325 
326 			}
327 
328 			setText(rawMessage);
329 
330 		} else {
331 
332 			setText("<html>" + msg.getRawMessage().replace("\r", "<br>") + "</html>");
333 		}
334 
335 //		setBackground(Color.white);
336 		setForeground(Color.black);
337 		setFont(myFixedWidthFont);
338 
339 		updatePreferredHeight(theTable, theRow);
340 		
341 	}
342 
343 	private void updatePreferredHeight(final JTable theTable, final int theRow) {
344 		final int newHeight = (int) getPreferredSize().getHeight();
345 		if (theTable.getRowHeight(theRow) != newHeight) {
346 			EventQueue.invokeLater(new Runnable() {
347 				public void run() {
348 					theTable.setRowHeight(theRow, newHeight);
349 //					theTable.getColumnModel().getColumn(2).setWidth(5000);
350 				}
351 			});
352 		}
353 	}
354 
355 	public void markScrollToBottom() {
356 		myScrollToBottom = true;
357 	}
358 }