1 package ca.uhn.hl7v2.testpanel.controller;
2
3 import java.beans.PropertyChangeListener;
4 import java.beans.PropertyChangeSupport;
5 import java.io.BufferedReader;
6 import java.io.File;
7 import java.io.FileNotFoundException;
8 import java.io.FileReader;
9
10 import javax.swing.SwingUtilities;
11
12 import org.apache.commons.lang.StringUtils;
13
14 import ca.uhn.hl7v2.HL7Exception;
15 import ca.uhn.hl7v2.testpanel.ui.tools.Hl7V2FileDiffDialog;
16 import ca.uhn.hl7v2.testpanel.util.CharCountingReaderWrapper;
17 import ca.uhn.hl7v2.testpanel.util.compare.BulkHl7V2Comparison;
18 import ca.uhn.hl7v2.testpanel.util.compare.Hl7V2MessageCompare;
19 import ca.uhn.hl7v2.testpanel.util.compare.IComparisonListener;
20 import ca.uhn.hl7v2.util.Hl7InputStreamMessageIterator;
21 import ca.uhn.hl7v2.util.Terser;
22
23 public class Hl7V2FileDiffController {
24
25 private static final int OUTPUT_LINES = 1000;
26 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Hl7V2FileDiffController.class);
27
28 public static final String PROP_RUNNING = Hl7V2FileDiffController.class.getName() + "_RUNNING";
29 public static final String PROP_FAILED = Hl7V2FileDiffController.class.getName() + "_FAILED";
30 public static final String PROP_PERCENT_DONE = Hl7V2FileDiffController.class.getName() + "_PERCENT_DONE";
31 public static final String PROP_OUTPUT = Hl7V2FileDiffController.class.getName() + "_OUTPUT";
32
33 private final PropertyChangeSupport myPcs = new PropertyChangeSupport(this);
34 private boolean myRunning;
35 private final Hl7V2FileDiffDialog myView;
36 private final Controller myMasterController;
37 private long myFile1Size;
38 private long myFile2Size;
39 private CharCountingReaderWrapper myCountingReader1;
40 private CharCountingReaderWrapper myCountingReader2;
41 private Hl7InputStreamMessageIterator myMessageIter1;
42 private Hl7InputStreamMessageIterator myMessageIter2;
43 private BulkHl7V2Comparison myCompare;
44 private RunningThread myThread;
45 private boolean myFailed;
46 private int myPercentDone;
47 private String[] myOutput = new String[OUTPUT_LINES];
48 private int myOutputNextIndex = 0;
49 private int myOutputSize = 0;
50 private int myNumMessagesTotal;
51 private int myNumMessagesPassed;
52 private int myNumMessagesFailed;
53
54 public Hl7V2FileDiffController(Controller theMasterController) {
55 myMasterController = theMasterController;
56 myView = new Hl7V2FileDiffDialog(this);
57 }
58
59 public void addOutput(final String... theLines) {
60 if (!SwingUtilities.isEventDispatchThread()) {
61 SwingUtilities.invokeLater(new Runnable() {
62 public void run() {
63 addOutput(theLines);
64 }
65 });
66 return;
67 }
68
69 if (theLines == null || theLines.length == 0) {
70 return;
71 }
72
73 for (String string : theLines) {
74 myOutput[myOutputNextIndex] = string;
75 if (myOutputSize < OUTPUT_LINES) {
76 myOutputSize++;
77 }
78 myOutputNextIndex++;
79 myOutputNextIndex %= OUTPUT_LINES;
80 }
81
82 myPcs.firePropertyChange(PROP_OUTPUT, null, null);
83 }
84
85
86
87
88 public int getOutputSize() {
89 return myOutputSize;
90 }
91
92 public String getOutputLine(int theIndex) {
93 if (myOutputSize < OUTPUT_LINES) {
94 return myOutput[theIndex];
95 } else {
96 int index = (myOutputNextIndex + theIndex) % OUTPUT_LINES;
97 return myOutput[index];
98 }
99 }
100
101 public void addPropertyChangeListener(String theProperty, PropertyChangeListener listener) {
102 this.myPcs.addPropertyChangeListener(theProperty, listener);
103 }
104
105
106
107
108 public boolean isRunning() {
109 return myRunning;
110 }
111
112 public void removePropertyChangeListener(String theProperty, PropertyChangeListener listener) {
113 this.myPcs.removePropertyChangeListener(theProperty, listener);
114 }
115
116 private void setRunning(boolean theRunning) {
117 boolean oldValue = myRunning;
118 myRunning = theRunning;
119 myPcs.firePropertyChange(PROP_RUNNING, oldValue, theRunning);
120 }
121
122 public void show() {
123 myView.setVisible(true);
124 myView.requestFocusInWindow();
125 }
126
127 public void begin() {
128 assert SwingUtilities.isEventDispatchThread() : "Shouldn't be called from " + Thread.currentThread().getName();
129
130 File file1 = new File(myView.getFile1Text());
131 if (file1.exists() == false) {
132 myMasterController.showDialogError("File does not exist: " + myView.getFile1Text());
133 return;
134 }
135 if (file1.isDirectory()) {
136 myMasterController.showDialogError("File is a directory: " + myView.getFile1Text());
137 return;
138 }
139
140 File file2 = new File(myView.getFile2Text());
141 if (file2.exists() == false) {
142 myMasterController.showDialogError("File does not exist: " + myView.getFile2Text());
143 return;
144 }
145 if (file2.isDirectory()) {
146 myMasterController.showDialogError("File is a directory: " + myView.getFile2Text());
147 return;
148 }
149
150 myFile1Size = file1.length();
151 myFile2Size = file2.length();
152
153 try {
154 myCountingReader1 = new CharCountingReaderWrapper(new BufferedReader(new FileReader(file1)));
155 myCountingReader2 = new CharCountingReaderWrapper(new BufferedReader(new FileReader(file2)));
156 } catch (FileNotFoundException e) {
157 myMasterController.showDialogError(e.getMessage());
158 return;
159 }
160
161 myMessageIter1 = new Hl7InputStreamMessageIterator(myCountingReader1);
162 myMessageIter1.setIgnoreComments(true);
163 myMessageIter2 = new Hl7InputStreamMessageIterator(myCountingReader2);
164 myMessageIter2.setIgnoreComments(true);
165
166 myCompare = new BulkHl7V2Comparison();
167 myCompare.setStopOnFirstFailure(myView.isStopOnFirstError());
168 myCompare.setExpectedMessages(myMessageIter1);
169 myCompare.setActualMessages(myMessageIter2);
170 myCompare.setExpectedAndActualDescription("File 1", "File 2");
171
172 setRunning(true);
173 setFailed(false);
174 clearOutput();
175
176 myNumMessagesTotal = 0;
177 myNumMessagesFailed = 0;
178 myNumMessagesPassed = 0;
179
180 myThread = new RunningThread();
181 myThread.start();
182
183 }
184
185 private void clearOutput() {
186 myOutputNextIndex = 0;
187 myOutputSize = 0;
188 myPcs.firePropertyChange(PROP_OUTPUT, null, null);
189 }
190
191
192
193
194 public int getPercentDone() {
195 return myPercentDone;
196 }
197
198
199
200
201
202 public void setPercentDone(int thePercentDone) {
203 int oldValue = myPercentDone;
204 myPercentDone = thePercentDone;
205 myPcs.firePropertyChange(PROP_PERCENT_DONE, oldValue, thePercentDone);
206 }
207
208 private void setFailed(boolean theFailed) {
209 boolean oldValue = myFailed;
210 myFailed = theFailed;
211 myPcs.firePropertyChange(PROP_FAILED, oldValue, theFailed);
212 }
213
214
215
216
217 public boolean isFailed() {
218 return myFailed;
219 }
220
221 private class RunningThread extends Thread implements IComparisonListener {
222
223 @Override
224 public void run() {
225
226 try {
227 addOutput("Beginning comparison");
228
229 myCompare.addComparisonListener(this);
230 try {
231 myCompare.compare();
232 } catch (Exception e) {
233 markFailed();
234 ourLog.error("Unexpected test failure: ", e);
235 addOutput("Comparison failed unexpectedly, this is probably a bug: " + e.getMessage());
236 return;
237 }
238
239 if (isRunning() && !isFailed()) {
240 addOutput("No differences found");
241 }
242
243 } finally {
244 SwingUtilities.invokeLater(new Runnable() {
245 public void run() {
246 setRunning(false);
247 }
248 });
249 }
250 }
251
252 public void failure(Hl7V2MessageCompare theComparison) {
253 myNumMessagesTotal++;
254 myNumMessagesFailed++;
255
256 markFailed();
257 updatePercentDone();
258 cancelIfNeccesary();
259
260 addOutput(" ");
261
262 String controlId1 = "", controlId2 = "";
263 try {
264 controlId1 = new Terser(theComparison.getExpectedMessage()).get("/MSH-10");
265 controlId2 = new Terser(theComparison.getActualMessage()).get("/MSH-10");
266 } catch (HL7Exception e) {
267
268 }
269
270 StringBuilder b= new StringBuilder();
271 b.append("<html><span style=\"color: red;\">Difference Found in message " + myNumMessagesTotal);
272 b.append(" (Control ID ").append(controlId1);
273 if (StringUtils.equals(controlId1, controlId2) == false) {
274 b.append(" / ").append(controlId2);
275 }
276 b.append(")");
277 b.append("</span></html>");
278 addOutput(b.toString());
279
280 if (myView.isShowWholeMessageOnError()) {
281 addOutput("Message in file 1:");
282 try {
283 addOutput(theComparison.getExpectedMessage().printStructure().split("\\n"));
284 } catch (HL7Exception e) {
285 ourLog.error("Failed to print structure", e);
286 }
287
288 addOutput(" ");
289 addOutput("Message in file 2:");
290 try {
291 addOutput(theComparison.getExpectedMessage().printStructure().split("\\n"));
292 } catch (HL7Exception e) {
293 ourLog.error("Failed to print structure", e);
294 }
295
296 addOutput(" ");
297 addOutput("Differences:");
298 }
299
300 String difference = theComparison.describeDifference();
301 addOutput(difference.split("\\n"));
302
303 }
304
305 public void success(Hl7V2MessageCompare theComparison) {
306 myNumMessagesTotal++;
307 myNumMessagesPassed++;
308
309 updatePercentDone();
310 cancelIfNeccesary();
311 }
312
313 private void cancelIfNeccesary() {
314 if (!isRunning()) {
315 myCompare.cancel();
316 }
317 }
318
319 private void updatePercentDone() {
320 int percent = (int) ((myCountingReader1.getCount() * 100) / myFile1Size);
321 setPercentDone(percent);
322 }
323
324 public void markFailed() {
325 SwingUtilities.invokeLater(new Runnable() {
326 public void run() {
327 setFailed(true);
328 }
329 });
330 }
331
332 public void progressLog(String theMsgLine) {
333
334 }
335
336 }
337
338 public void cancel() {
339 setRunning(false);
340 }
341
342 }