source: trunk/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java@ 6533

Last change on this file since 6533 was 6533, checked in by jmt12, 20 years ago

Finished the design of a new 'simple' creating/progress pane, including merging the two progress bars into one

  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 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.ArrayList;
41import java.util.StringTokenizer;
42import javax.swing.JProgressBar;
43import org.greenstone.gatherer.Configuration;
44import org.greenstone.gatherer.Dictionary;
45import org.greenstone.gatherer.Gatherer;
46import org.greenstone.gatherer.shell.GShellElement;
47import org.greenstone.gatherer.shell.GShellProgressMonitor;
48import org.greenstone.gatherer.util.StaticStrings;
49
50/** This implementation of <i>GShellProgressMonitor</i> is designed to parse and translate the progress of a import.pl call.
51 * @author John Thompson, Greenstone Digital Library, University of Waikato
52 * @version 2.1
53 */
54public class GImportProgressMonitor
55 implements GShellProgressMonitor {
56 /** Indicates if the progress bar is currently showing a string. */
57 private boolean showing_string = false;
58 /** Indicates if the GUI has asked the process this object monitors to stop. */
59 private boolean stop = false;
60 /** A count of the extracted files processed so far. */
61 private int extracted_file_count;
62 /** The number of documents processed (or rejected) so far. */
63 private int file_count;
64 /** 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%) */
65 private int next_progress_value;
66 /** The number of files expected to be scanned by this import process. */
67 private int num_expected_docs;
68 /** This holds the number of documents actually processed by the import command, as garnered from the final block of text output. */
69 private int num_docs;
70
71 private int threshold = Configuration.SYSTEMS_MODE;
72 /** The progress bar this monitor updates. */
73 private JProgressBar progress_bar;
74
75 /** The progress bar that is shared with build monitor. */
76 private JProgressBar shared_progress_bar;
77
78 /** */
79 static final private String BLOCKED_ATTRIBUTE = "blocked";
80 static final private String CONSIDERED_ATTRIBUTE = "considered";
81 static final private String IGNORED_ATTRIBUTE = "ignored";
82 static final private String IMPORT_ELEMENT = "Import";
83 static final private String PROCESSED_ATTRIBUTE = "processed";
84 /** */
85 static final private String NAME_ATTRIBUTE = "n";
86 /** */
87 static final private String PLUGIN_ATTRIBUTE = "p";
88 /** The fixed portion of the progress bar used for the calculating of file size and other pre-import functions. */
89 static final private int CALCULATION = 50000;
90 /** The fixed portion of the progress bar used for extracted metadata. */
91 static final private int EXTRACTED = 200000;
92 /** The minimum value for this progress bar. */
93 static final private int MIN = 0;
94 /** The fixed portion of the progress bar used for processed documents. */
95 static final private int PROCESSED = 750000;
96 /** The element name of a file detected message. */
97 static final private String FILE_ELEMENT = "File";
98 /** The element name of a file processing message. */
99 static final private String FILEPROCESSING_ELEMENT = "Processing";
100 /** The element name of an import complete message. */
101 static final private String IMPORTCOMPLETE_ELEMENT = "ImportComplete";
102
103 public GImportProgressMonitor() {
104 progress_bar = new JProgressBar();
105 progress_bar.setIndeterminate(false);
106 progress_bar.setMaximum(CALCULATION + PROCESSED + EXTRACTED);
107 progress_bar.setMinimum(MIN);
108 progress_bar.setString(null);
109 progress_bar.setStringPainted(true);
110 next_progress_value = CALCULATION;
111 shared_progress_bar = new JProgressBar();
112 shared_progress_bar.setIndeterminate(false);
113 shared_progress_bar.setMaximum((CALCULATION + PROCESSED + EXTRACTED) * 2);
114 shared_progress_bar.setMinimum(MIN);
115 shared_progress_bar.setString(null); // Default string
116 shared_progress_bar.setStringPainted(true);
117 setValue(MIN);
118 }
119
120 /** Method to register a new progress bar with this monitor.
121 * @param progress_bar The new <strong>JProgressBar</strong>.
122 */
123 public void addProgressBar(JProgressBar progress_bar) {
124 this.progress_bar = progress_bar;
125 progress_bar.setMaximum(CALCULATION + PROCESSED + EXTRACTED);
126 progress_bar.setMinimum(MIN);
127 setValue(MIN);
128 next_progress_value = CALCULATION;
129 }
130
131 /** 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.
132 * @return A <i>int</i> with a value of zero if and only if the script was successful.
133 */
134 public int exitValue() {
135 if(num_docs > 0) {
136 return 0;
137 }
138 return 1;
139 }
140
141 /** Retrieve the number of documents recorded by the import monitor during the execution of the import scripts.
142 * @return An <i>int</i> giving the document number.
143 */
144 public int getNumberOfDocuments() {
145 return num_docs;
146 }
147
148 /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>JProgressBar</strong> but there may be others implemented later.
149 * @return A <strong>Component</strong> on which the progress of the process is being displayed.
150 */
151 public Component getProgress() {
152 return progress_bar;
153 }
154
155 public JProgressBar getSharedProgress() {
156 return shared_progress_bar;
157 }
158
159 /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
160 * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
161 */
162 public synchronized boolean hasSignalledStop() {
163 return stop;
164 }
165
166 /** 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. */
167 public void increment() {
168 extracted_file_count++;
169 // The current progress is calculated to be:
170 // 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).
171 setValue(CALCULATION + PROCESSED + ((EXTRACTED * extracted_file_count) / num_docs));
172 }
173
174 /** This method is used to 'feed in' a line of text captured from the process.
175 * @param queue a queue which at the moment should contain a single GShellEvent
176 */
177 public void process(ArrayList queue) {
178 // Retrieve the first event.
179 GShellEvent event = (GShellEvent) queue.get(0);
180 // Remove 'import.pl> ' bit
181 String line = event.getMessage();
182 line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
183 line = line.trim();
184 ///ystem.err.println("Process: " + line);
185 if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
186 // No original event is passed on, even in the lower modes
187 event.veto();
188 // Create a new element from it
189 GShellElement element = new GShellElement(line);
190 String name = element.getElementName();
191 ///ystem.err.println("Gatherer tag: " + name);
192 // 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'
193 if(name.equals(IMPORT_ELEMENT)) {
194 ///ystem.err.println("#Import");
195 // We're into parsing output, so we don't need the 'calculating file size' etc string.
196 if(showing_string) {
197 progress_bar.setString(null);
198 showing_string = false;
199 }
200 if(Gatherer.config.getMode() <= threshold) {
201 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportBegun1"), event.getStatus()));
202 }
203 }
204 else if(name.equals(FILE_ELEMENT)) {
205 ///ystem.err.println("#File");
206 file_count++;
207 // Set the next progress
208 if(next_progress_value > 0) {
209 setValue(next_progress_value);
210 }
211 // Now we calculate the next progress value
212 next_progress_value = CALCULATION + ((PROCESSED * file_count) / num_expected_docs);
213 event.veto(); // Unconditional veto
214 }
215 // Or we're being told what plugin is actually processing the file
216 else if(name.equals(FILEPROCESSING_ELEMENT)) {
217 ///ystem.err.println("#FileProcessing");
218 // If we are at lower mode settings fire a new 'dumbed down' event
219 if(Gatherer.config.getMode() <= threshold) {
220 String args[] = new String[2];
221 args[0] = element.getAttribute(NAME_ATTRIBUTE);
222 args[1] = element.getAttribute(PLUGIN_ATTRIBUTE);
223 if(!args[1].equals("")) {
224 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileProcessing", args), event.getStatus()));
225 }
226 else {
227 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.FileNotProcessed", args), event.getStatus()));
228 }
229 args = null;
230 }
231 }
232 // Or the import complete element
233 else if(name.equals(IMPORTCOMPLETE_ELEMENT)) {
234 // Set the next progress
235 setValue(next_progress_value);
236 // If we are at lower mode settings fire a new 'dumbed down' event
237 if(Gatherer.config.getMode() <= threshold) {
238 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete1"), event.getStatus()));
239 String args[] = new String[1];
240 args[0] = element.getAttribute(CONSIDERED_ATTRIBUTE);
241 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete2", args), event.getStatus()));
242 // The number of documents processed
243 String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
244 if(!processed_str.equals(StaticStrings.ZERO_CHARACTER)) {
245 args = new String[3];
246 args[0] = element.getAttribute(PROCESSED_ATTRIBUTE);
247 if(args[0].equals(StaticStrings.ONE_CHARACTER)) {
248 args[1] = Dictionary.get("GShell.Import.Was");
249 args[2] = Dictionary.get("GShell.Import.Is");
250 }
251 else {
252 args[1] = Dictionary.get("GShell.Import.Were");
253 args[2] = Dictionary.get("GShell.Import.Are");
254 }
255 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete.Processed", args), event.getStatus()));
256 }
257 // Try to set num docs
258 try {
259 num_docs = Integer.parseInt(processed_str);
260 }
261 catch(Exception exception) {
262 num_docs = 0;
263 }
264
265 processed_str = null;
266 // The number of documents blocked
267 String blocked_str = element.getAttribute(BLOCKED_ATTRIBUTE);
268 if(!blocked_str.equals(StaticStrings.ZERO_CHARACTER)) {
269 args = new String[2];
270 args[0] = element.getAttribute(BLOCKED_ATTRIBUTE);
271 if(args[0].equals(StaticStrings.ONE_CHARACTER)) {
272 args[1] = Dictionary.get("GShell.Import.Was");
273 }
274 else {
275 args[1] = Dictionary.get("GShell.Import.Were");
276 }
277 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete.Blocked", args), event.getStatus()));
278 }
279 blocked_str = null;
280 // The number of documents ignored
281 String ignored_str = element.getAttribute(IGNORED_ATTRIBUTE);
282 if(!ignored_str.equals(StaticStrings.ZERO_CHARACTER)) {
283 args = new String[3];
284 args[0] = element.getAttribute(IGNORED_ATTRIBUTE);
285 if(args[0].equals(StaticStrings.ONE_CHARACTER)) {
286 args[1] = Dictionary.get("GShell.Import.Was");
287 args[2] = Dictionary.get("GShell.Import.Is");
288 }
289 else {
290 args[1] = Dictionary.get("GShell.Import.Were");
291 args[2] = Dictionary.get("GShell.Import.Are");
292 }
293 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete.Ignored", args), event.getStatus()));
294 }
295 ignored_str = null;
296 args = null;
297 // Message is finally ready
298 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Import.ImportComplete3"), event.getStatus()));
299 }
300 else {
301 // Try to set num docs
302 String processed_str = element.getAttribute(PROCESSED_ATTRIBUTE);
303 try {
304 num_docs = Integer.parseInt(processed_str);
305 }
306 catch(Exception exception) {
307 num_docs = 0;
308 }
309 }
310 }
311 else {
312 // Veto it
313 event.veto();
314 }
315 }
316 else if(Gatherer.config.getMode() <= threshold) {
317 event.veto();
318 }
319 }
320
321 public void reset() {
322 setValue(MIN);
323 progress_bar.setString(null);
324 progress_bar.updateUI();
325 }
326
327 public void saving() {
328 progress_bar.setString(Dictionary.get("SaveProgressDialog.Title"));
329 showing_string = true;
330 }
331
332 /** 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.
333 * @param state The desired state of the stop flag as a <strong>boolean</strong>.
334 */
335 public synchronized void setStop(boolean state) {
336 this.stop = state;
337 }
338
339 /** This method resets this monitor to the start, reseting the process parsing and progress bar.
340 */
341 public void start() {
342 stop = false;
343 setValue(MIN);
344 progress_bar.setString(Dictionary.get("FileActions.Calculating_Size"));
345 showing_string = true;
346 extracted_file_count = 0;
347 file_count = 0;
348 next_progress_value = -1;
349 num_docs = -1;
350 num_expected_docs = Gatherer.c_man.getCollection().getCount();
351 }
352
353 /** This method indicates the process is complete.
354 */
355 public void stop() {
356 setValue(CALCULATION + PROCESSED + EXTRACTED);
357 }
358
359 int previous_value = -1;
360 private void setValue(int value) {
361 progress_bar.setValue(value);
362 shared_progress_bar.setValue(value);
363 if(value != 0 && value < previous_value) {
364 Gatherer.println("Progress is decreasing! " + previous_value + " -> " + value);
365 }
366 previous_value = value;
367 }
368}
369
Note: See TracBrowser for help on using the repository browser.