source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

File size: 20.1 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.shell;
38
39import java.awt.Component;
40import java.util.*;
41import org.greenstone.gatherer.Configuration;
42import org.greenstone.gatherer.DebugStream;
43import org.greenstone.gatherer.Dictionary;
44import org.greenstone.gatherer.Gatherer;
45import org.greenstone.gatherer.gui.GProgressBar;
46import org.greenstone.gatherer.util.StaticStrings;
47
48/** This implementation of <i>GShellProgressMonitor</i> is designed to parse and translate the progress of a import.pl call.
49 * @author John Thompson, Greenstone Digital Library, University of Waikato
50 * @version 2.1
51 */
52public class GImportProgressMonitor
53 implements GShellProgressMonitor {
54 /** Indicates if the progress bar is currently showing a string. */
55 private boolean showing_string = false;
56 /** Indicates if the GUI has asked the process this object monitors to stop. */
57 private boolean stop = false;
58 /** A count of the extracted files processed so far. */
59 private int extracted_file_count;
60 /** The number of documents processed (or rejected) so far. */
61 private int file_count;
62 /** The next value to be set for the progress bar - I use this rather than a compounding progress measure to try to limit rounding inaccuracies (nothing looks worse than the progress bar having to jump the last 10-15%) */
63 private int next_progress_value;
64 /** The number of files expected to be scanned by this import process. */
65 private int num_expected_docs;
66 /** This holds the number of documents actually processed by the import command, as garnered from the final block of text output. */
67 private int num_docs;
68
69 private int threshold = Configuration.LIBRARIAN_MODE;
70 /** The progress bar this monitor updates. */
71 private GProgressBar progress_bar;
72
73 /** The progress bar that is shared with build monitor. */
74 private GProgressBar shared_progress_bar;
75
76 /** */
77 static final private String BLOCKED_ATTRIBUTE = "blocked";
78 static final private String CONSIDERED_ATTRIBUTE = "considered";
79 static final private String FAILED_ATTRIBUTE = "failed";
80 static final private String IGNORED_ATTRIBUTE = "ignored";
81 static final private String IMPORT_ELEMENT = "Import";
82 static final private String PROCESSED_ATTRIBUTE = "processed";
83
84 static final private String ARGUMENT_ATTRIBUTE = "a";
85 /** */
86 static final private String NAME_ATTRIBUTE = "n";
87 /** */
88 static final private String PLUGIN_ATTRIBUTE = "p";
89 static final private String REASON_ATTRIBUTE = "r";
90 /** The fixed portion of the progress bar used for the calculating of file size and other pre-import functions. */
91 static final private int CALCULATION = 50000;
92 /** The fixed portion of the progress bar used for extracted metadata. */
93 static final private int EXTRACTED = 200000;
94 /** The fixed portion of the progress bar used for processed documents. */
95 static final private int PROCESSED = 750000;
96 /** The maximum value for this progress bar. */
97 static final private int MAXIMUM = CALCULATION + EXTRACTED + PROCESSED;
98 /** The minimum value for this progress bar. */
99 static final private int MINIMUM = 0;
100 /** The element name of a file detected message. */
101 static final private String FILE_ELEMENT = "File";
102 /** The element name of a file processing message. */
103 static final private String PROCESSING_ELEMENT = "Processing";
104 /** The element name of a processing error message. */
105 static final private String PROCESSINGERROR_ELEMENT = "ProcessingError";
106 /** The element name of an import complete message. */
107 static final private String IMPORTCOMPLETE_ELEMENT = "ImportComplete";
108 /** The element name of a file not processed. */
109 static final private String NONPROCESSEDFILE_ELEMENT = "NonProcessedFile";
110 /** The element name of a file not recognised. */
111 static final private String NONRECOGNISEDFILE_ELEMENT = "NonRecognisedFile";
112 /** The element name of a Warning message */
113 static final private String WARNING_ELEMENT = "Warning";
114 /** The element name of a BadArgument message */
115 static final private String BADARGUMENT_ELEMENT = "BadArgument";
116 static final private String BADARGUMENTVALUE_ELEMENT = "BadArgumentValue";
117 static final private String BADPLUGIN_ELEMENT = "BadPlugin";
118
119 public GImportProgressMonitor() {
120 progress_bar = new GProgressBar();
121 progress_bar.setIndeterminate(false);
122 progress_bar.setMaximum(MAXIMUM);
123 progress_bar.setMinimum(MINIMUM);
124 progress_bar.setString(null);
125 progress_bar.setStringPainted(true);
126 next_progress_value = CALCULATION;
127 shared_progress_bar = new GProgressBar();
128 shared_progress_bar.setIndeterminate(false);
129 shared_progress_bar.setMaximum(MAXIMUM * 2);
130 shared_progress_bar.setMinimum(MINIMUM);
131 shared_progress_bar.setString(null); // Default string
132 shared_progress_bar.setStringPainted(true);
133 setValue(MINIMUM);
134 }
135
136 /** Method to register a new progress bar with this monitor.
137 * @param progress_bar The new <strong>GProgressBar</strong>.
138 */
139 public void addProgressBar(GProgressBar progress_bar) {
140 this.progress_bar = progress_bar;
141 progress_bar.setMaximum(MAXIMUM);
142 progress_bar.setMinimum(MINIMUM);
143 setValue(MINIMUM);
144 next_progress_value = CALCULATION;
145 }
146
147 /** Determine the script exit value according to the progress monitor. This gets around a problem where several script failures actually result with a successful exit value.
148 * @return A <i>int</i> with a value of zero if and only if the script was successful.
149 */
150 public int exitValue() {
151 if(num_docs > 0) {
152 return 0;
153 }
154 return 1;
155 }
156
157 /** Retrieve the number of documents recorded by the import monitor during the execution of the import scripts.
158 * @return An <i>int</i> giving the document number.
159 */
160 public int getNumberOfDocuments() {
161 return num_docs;
162 }
163
164 /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>GProgressBar</strong> but there may be others implemented later.
165 * @return A <strong>Component</strong> on which the progress of the process is being displayed.
166 */
167 public Component getProgress() {
168 return progress_bar;
169 }
170
171 public GProgressBar getSharedProgress() {
172 return shared_progress_bar;
173 }
174
175 public void messageOnProgressBar(String message)
176 {
177 if (message!=null && !message.equals("")) {
178 progress_bar.setString(message);
179 shared_progress_bar.setString(message);
180 showing_string = true;
181 }
182 else {
183 progress_bar.setString(null);
184 shared_progress_bar.setString(null);
185 showing_string = false;
186 }
187 }
188
189 /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
190 * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
191 */
192 public synchronized boolean hasSignalledStop() {
193 return stop;
194 }
195
196 /** Inform the progress bar that it should programatically increment progress by one step. This is only called during the metadata archive extraction so each step should be (1000000 / 5) / num_docs. */
197 public void increment() {
198 extracted_file_count++;
199 // The current progress is calculated to be:
200 // The fixed calculation value plus the fixed processed value plus some portion of the fixed extracted value. This portion is the extracted_file_count over the total number of documents available. Note that this breaks badly for bibliographical files (for now).
201 setValue(CALCULATION + PROCESSED + ((EXTRACTED * extracted_file_count) / num_docs));
202 }
203
204 /** This method is used to 'feed in' a line of text captured from the process.
205 * @param queue a queue which at the moment should contain a single GShellEvent
206 */
207 public void process(ArrayList queue) {
208 // Retrieve the first event.
209 GShellEvent event = (GShellEvent) queue.get(0);
210 // Remove 'import.pl> ' bit
211 String line = event.getMessage();
212 line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
213 line = line.trim();
214 // System.err.println("**** line = " + line);
215
216 ///ystem.err.println("Process: " + line);
217 if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
218 // No original event is passed on, even in the lower modes
219 event.veto();
220 // Create a new element from it
221 GShellElement element = new GShellElement(line);
222 String name = element.getElementName();
223 ///ystem.err.println("Gatherer tag: " + name);
224 // We may be reading a file. Remember we have to offset process as we recieve this message 'before' a document is processed. Hence the use of 'next_progress_value'
225 if(name.equals(IMPORT_ELEMENT)) {
226 ///ystem.err.println("#Import");
227 // We're into parsing output, so we don't need the 'calculating file size' etc string.
228 if(showing_string) {
229 progress_bar.setString(null);
230 showing_string = false;
231 }
232 if(Configuration.getMode() <= threshold) {
233 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportBegun1"), event.getStatus()));
234 }
235 }
236 else if(name.equals(FILE_ELEMENT)) {
237 ///ystem.err.println("#File");
238 file_count++;
239 // Set the next progress
240 if(next_progress_value > 0) {
241 setValue(next_progress_value);
242 }
243 // Now we calculate the next progress value
244 next_progress_value = CALCULATION + ((PROCESSED * file_count) / num_expected_docs);
245 event.veto(); // Unconditional veto
246 }
247 // Or we're being told what plugin is actually processing the file
248 else if(name.equals(PROCESSING_ELEMENT)) {
249 ///ystem.err.println("#FileProcessing");
250 // If we are at lower mode settings fire a new 'dumbed down' event
251 if(Configuration.getMode() <= threshold) {
252 String args[] = new String[2];
253 args[0] = element.getAttribute(NAME_ATTRIBUTE);
254 args[1] = element.getAttribute(PLUGIN_ATTRIBUTE);
255 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessing", args), event.getStatus()));
256 args = null;
257 }
258 }
259 // processing error
260 else if (name.equals(PROCESSINGERROR_ELEMENT)) {
261 if(Configuration.getMode() <= threshold) {
262 String args[] = new String[1];
263 args[0] = element.getAttribute(NAME_ATTRIBUTE);
264 String reason = element.getAttribute(REASON_ATTRIBUTE);
265 if (reason == null || reason.equals("")) {
266 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessingError", args), event.getStatus()));
267 }
268 else {
269 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessingError", args) + " (" + reason + ")", event.getStatus()));
270 }
271 args = null;
272 }
273 }
274 // unrecognised file
275 else if (name.equals(NONRECOGNISEDFILE_ELEMENT)) {
276 if(Configuration.getMode() <= threshold) {
277 String args[] = new String[1];
278 args[0] =element.getAttribute(NAME_ATTRIBUTE);
279 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileNotRecognised", args), event.getStatus()));
280 args = null;
281 }
282 }
283 // unprocessed file
284 else if (name.equals(NONPROCESSEDFILE_ELEMENT)) {
285 if(Configuration.getMode() <= threshold) {
286 String args[] = new String[1];
287 args[0] =element.getAttribute(NAME_ATTRIBUTE);
288 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileNotProcessed", args), event.getStatus()));
289 args = null;
290 }
291 }
292 // We had a bad argument to a plugin
293 else if (name.equals(BADARGUMENT_ELEMENT)) {
294 if(Configuration.getMode() <= threshold) {
295 String args[] = new String[1];
296 args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);
297 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgument", args), event.getStatus()));
298 args = null;
299 }
300 }
301 // We had a bad argument value to a plugin
302 else if (name.equals(BADARGUMENTVALUE_ELEMENT)) {
303 if(Configuration.getMode() <= threshold) {
304 String args[] = new String[1];
305 args[0] = element.getAttribute(ARGUMENT_ATTRIBUTE);
306 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadArgumentValue", args), event.getStatus()));
307 args = null;
308 }
309 }
310 // And this one tellsa us the plugin
311 else if (name.equals(BADPLUGIN_ELEMENT)) {
312 if(Configuration.getMode() <= threshold) {
313 String args[] = new String[1];
314 args[0] = element.getAttribute(PLUGIN_ATTRIBUTE);
315 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.BadPluginOptions", args), event.getStatus()));
316 args = null;
317 }
318 }
319 else if (name.equals(WARNING_ELEMENT)) {
320 if(Configuration.getMode() <= threshold) {
321 String args[] = new String[1];
322 args[0] = element.getAttribute(PLUGIN_ATTRIBUTE);
323 String reason = element.getAttribute(REASON_ATTRIBUTE);
324 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.Warning", args) + " " + reason, event.getStatus()));
325 args = null;
326 }
327 }
328
329
330 // Or the import complete element
331 else if(name.equals(IMPORTCOMPLETE_ELEMENT)) {
332 // Set the next progress
333 setValue(next_progress_value);
334 // If we are at lower mode settings fire a new 'dumbed down' event
335 if(Configuration.getMode() <= threshold) {
336 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete1"), event.getStatus()));
337 String considered_str = element.getAttribute(CONSIDERED_ATTRIBUTE);
338
339 if (considered_str.equals(StaticStrings.ONE_CHARACTER)) {
340 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete2.1"), event.getStatus()));
341 } else {
342 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete2", considered_str), event.getStatus()));
343 }
344 considered_str = null;
345 // The number of documents processed
346 String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
347 if(!processed_str.equals(StaticStrings.ZERO_CHARACTER)) {
348 if(processed_str.equals(StaticStrings.ONE_CHARACTER)) {
349 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Processed.1"), event.getStatus()));
350 }
351 else {
352 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Processed", processed_str), event.getStatus()));
353 }
354 }
355 // Try to set num docs
356 try {
357 num_docs = Integer.parseInt(processed_str);
358 }
359 catch(Exception exception) {
360 num_docs = 0;
361 }
362 processed_str = null;
363
364 // The number of documents blocked
365 String blocked_str = element.getAttribute(BLOCKED_ATTRIBUTE);
366 if(!blocked_str.equals(StaticStrings.ZERO_CHARACTER)) {
367 if (blocked_str.equals(StaticStrings.ONE_CHARACTER)) {
368 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Blocked.1"), event.getStatus()));
369 } else {
370 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Blocked", blocked_str), event.getStatus()));
371 }
372 }
373 blocked_str = null;
374
375 // The number of documents ignored
376 String ignored_str = element.getAttribute(IGNORED_ATTRIBUTE);
377 if(!ignored_str.equals(StaticStrings.ZERO_CHARACTER)) {
378 if(ignored_str.equals(StaticStrings.ONE_CHARACTER)) {
379 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Ignored.1"), event.getStatus()));
380 } else {
381 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Ignored", ignored_str), event.getStatus()));
382 }
383 }
384 ignored_str = null;
385
386 // The number of documents failed
387 String failed_str = element.getAttribute(FAILED_ATTRIBUTE);
388 if(!failed_str.equals(StaticStrings.ZERO_CHARACTER)) {
389 if(failed_str.equals(StaticStrings.ONE_CHARACTER)) {
390 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Failed.1"), event.getStatus()));
391 } else {
392 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), " "+Dictionary.get("GShell.Import.ImportComplete.Failed", failed_str), event.getStatus()));
393 }
394 }
395 failed_str = null;
396 // Message is finally ready
397 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete3"), event.getStatus()));
398 } // if mode below threshhold
399 else {
400 // Try to set num docs
401 String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
402 try {
403 num_docs = Integer.parseInt(processed_str);
404 }
405 catch(Exception exception) {
406 num_docs = 0;
407 }
408 }
409 }
410 else {
411 // Veto it
412 event.veto();
413 }
414 } // GLI output
415 else if(Configuration.getMode() <= threshold) {
416 event.veto();
417 }
418 }
419
420 public void reset() {
421 setValue(MINIMUM);
422 progress_bar.setString(null);
423 progress_bar.updateUI();
424 }
425
426 public void saving() {
427 progress_bar.setString(Dictionary.get("SaveProgressDialog.Title"));
428 showing_string = true;
429 }
430
431 /** Since the creator of this process monitor is actually in the GUI, this class provides the simpliest way to send a cancel process message between the two.
432 * @param state The desired state of the stop flag as a <strong>boolean</strong>.
433 */
434 public synchronized void setStop(boolean state) {
435 this.stop = state;
436 }
437
438 /** This method resets this monitor to the start, reseting the process parsing and progress bar.
439 */
440 public void start() {
441 stop = false;
442 setValue(MINIMUM);
443 progress_bar.setString(Dictionary.get("FileActions.Calculating_Size"));
444 showing_string = true;
445 extracted_file_count = 0;
446 file_count = 0;
447 next_progress_value = -1;
448 num_docs = -1;
449 // !! HACK: This is multiplied by 2 because the metadata_read now outputs a <File> tag also
450 // Ideally the metadata read pass would be completely separate and the GLI could work out the number
451 // of documents accurately and provide a much better progress bar
452 num_expected_docs = Gatherer.c_man.getCollection().getCount() * 2;
453 }
454
455 /** This method indicates the process is complete.
456 */
457 public void stop() {
458 setValue(MAXIMUM);
459 }
460
461 int previous_value = -1;
462
463 private void setValue(int value)
464 {
465 // Don't let the value go higher than the maximum
466 if (value > MAXIMUM) {
467 DebugStream.println("Error: Tried to set progress bar higher than maximum!\n");
468 return;
469 }
470 // Don't let the value go backwards
471 if (value != 0 && value < previous_value) {
472 DebugStream.println("Error: Tried to set progress bar smaller than previous!\n");
473 return;
474 }
475
476 progress_bar.setValue(value);
477 shared_progress_bar.setValue(value);
478 previous_value = value;
479 }
480}
481
Note: See TracBrowser for help on using the repository browser.