source: trunk/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java@ 6540

Last change on this file since 6540 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: 20.9 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 javax.swing.JProgressBar;
42import org.greenstone.gatherer.Configuration;
43import org.greenstone.gatherer.Dictionary;
44import org.greenstone.gatherer.Gatherer;
45import org.greenstone.gatherer.cdm.CollectionDesignManager;
46import org.greenstone.gatherer.shell.GImportProgressMonitor;
47import org.greenstone.gatherer.shell.GShellElement;
48import org.greenstone.gatherer.shell.GShellEvent;
49import org.greenstone.gatherer.shell.GShellProgressMonitor;
50import org.greenstone.gatherer.util.StaticStrings;
51/** This implementation of <i>GShellProgressMonitor</i> is designed to parse and translate the progress of a buildcol.pl call.
52 * @author John Thompson, Greenstone Digital Library, University of Waikato
53 * @version 2.3
54 */
55public class GBuildProgressMonitor
56 implements GShellProgressMonitor {
57 /** The minimum value = 0 */
58 static final private int MIN = 0;
59 /** In order to get a smoothish progress bar, set the maximum to a large number = 1000000 */
60 static final private int MAX = 1000000;
61 /** The various states the build progress state machine can be in, starting at the base state. */
62 static final int BASE = -1;
63 static final int BUILD = 0;
64 static final int COMPRESSTEXT = 10;
65 static final int COMPRESSTEXT_COLLECTTEXTSTATS = 11;
66 static final int COMPRESSTEXT_CREATINGCOMPRESS = 12;
67 static final int COMPRESSTEXT_COMPRESSINGTEXT = 13;
68 static final int INDEX = 20;
69 static final int INDEX_CREATINGINDEXDIC = 21;
70 static final int INDEX_INVERTINGTEXT = 22;
71 static final int INDEX_CREATETHEWEIGHTS = 23;
72 static final int INDEX_CREATESTEMMEDDIC = 24;
73 static final int INDEX_CREATINGSTEMINDX = 25;
74 static final int CREATEINFODATA = 30;
75 static final int PHIND = 40;
76 static final int PHIND_EXTRACTINGVOCAB = 41;
77 static final int PHIND_EXTRACTINGPHRASE = 42;
78 static final int PHIND_SORTANDRENUMBER = 43;
79 static final int PHIND_PHRASEDATABASES = 44;
80 static final int PHIND_WORDLEVELINDEXES = 45;
81 static final int PHIND_DOCINFODATABASES = 46;
82 static final int CREATINGAUXILARY = 50;
83 /** Now the language independant sentinel strings. */
84 static final String BUILD_ELEMENT = "Build";
85 static final String COLLECTTEXTSTATS_VALUE = "CollectTextStats";
86 static final String COMPRESSINGTEXT_VALUE = "CompressingText";
87 static final String COMPRESSTEXT_VALUE = "CompressText";
88 static final String CREATINGAUXILARY_VALUE = "CreatingAuxilary";
89 static final String CREATINGCOMPRESS_VALUE = "CreatingCompress";
90 static final String CREATINGINDEXDIC_VALUE = "CreatingIndexDic";
91 static final String CREATINGSTEMINDX_VALUE = "CreatingStemIndx";
92 static final String CREATEINFODATA_VALUE = "CreateInfoData";
93 static final String CREATESTEMMEDDIC_VALUE = "CreateStemmedDic";
94 static final String CREATETHEWEIGHTS_VALUE = "CreateTheWeights";
95 static final String DOCINFODATABASES_VALUE = "DocInfoDatabases";
96 static final String EXTRACTINGPHRASE_VALUE = "ExtractingPhrase";
97 static final String EXTRACTINGVOCAB_VALUE = "ExtractingVocab";
98 static final String FATALERROR_ELEMENT = "FatalError";
99 static final String INDEX_VALUE = "Index";
100 static final String INVERTINGTEXT_VALUE = "InvertingText";
101 static final String NAME_ATTRIBUTE = "name";
102 static final String PHASE_ELEMENT = "Phase";
103 static final String PHIND_VALUE = "Phind";
104 static final String PHRASEDATABASES_VALUE = "PhraseDatabases";
105 static final String SKIPCREATINGCOMP_VALUE = "SkipCreatingComp";
106 static final String SORTANDRENUMBER_VALUE = "SortAndRenumber";
107 static final String SOURCE_ATTRIBUTE = "source";
108 static final String STAGE_ELEMENT = "Stage";
109 static final String WARNING_ELEMENT = "Warning";
110 static final String WORDLEVELINDEXES_VALUE = "WordLevelIndexes";
111 /** Indicates if the GUI has asked the process this object monitors to stop. */
112 private boolean stop = false;
113 /** The current number of stages we have completed. */
114 private int current_stages = 0;
115 /** The number of stages we are expecting to complete. */
116 private int expected_stages = 0;
117
118 private int threshold = Configuration.SYSTEMS_MODE;
119 /** The current state we are in. The state will change depending on the next flag recieved. */
120 private int state = BASE;
121 /** The progress bar this monitor updates. */
122 private JProgressBar progress_bar;
123 /** A progress bar that is shared between this this listener and the Import monitor. */
124 private JProgressBar shared_progress_bar;
125
126 /** Construct a new GBuildProgressMonitor. */
127 public GBuildProgressMonitor(JProgressBar shared_progress_bar) {
128 this.shared_progress_bar = shared_progress_bar;
129 progress_bar = new JProgressBar();
130 progress_bar.setMaximum(MAX);
131 progress_bar.setMinimum(MIN);
132 progress_bar.setString(null);
133 progress_bar.setStringPainted(true);
134 setValue(MIN);
135 }
136
137 /** Method to register a new progress bar with this monitor.
138 * @param progress_bar The new <strong>JProgressBar</strong>.
139 */
140 public void addProgressBar(JProgressBar progress_bar) {
141 this.progress_bar = progress_bar;
142 progress_bar.setMaximum(MAX);
143 progress_bar.setMinimum(MIN);
144 progress_bar.setStringPainted(false);
145 progress_bar.setString(null);
146 setValue(MIN);
147 }
148
149 /** 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.
150 * @return A <i>int</i> with a value of zero if and only if the script was successful.
151 */
152 public int exitValue() {
153 if(state == BASE) {
154 return 0;
155 }
156 return 1;
157 }
158 /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>JProgressBar</strong> but there may be others implemented later.
159 * @return A <strong>Component</strong> on which the progress of the process is being displayed.
160 */
161 public Component getProgress() {
162 return progress_bar;
163 }
164
165 public JProgressBar getSharedProgress() {
166 return shared_progress_bar;
167 }
168
169 /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
170 * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
171 */
172 public synchronized boolean hasSignalledStop() {
173 return stop;
174 }
175 /** Inform the progress bar that it should programatically increment progress by one step. */
176 public void increment() {
177 // There is no reason this should be called for a build.
178 }
179
180 /** This method is used to 'feed in' a line of text captured from the process.
181 * @param queue a queue which at the moment should contain a single GShellEvent
182 */
183 public void process(ArrayList queue) {
184 GShellEvent event = (GShellEvent) queue.get(0);
185 // Remove 'build.pl> ' bit
186 String line = event.getMessage();
187 line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
188 line = line.trim();
189 // We are only really interested in processing pseudo-XML tags
190 if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
191 // All events are vetoed
192 event.veto();
193
194 // Create a new element from it
195 GShellElement element = new GShellElement(line);
196 // Now change states within the state machine as appropriate. A state change may subsequently incur a progress update.
197 String name = null;
198 String value = null;
199 switch(state) {
200 case BASE:
201 // The only thing we would expect is a build message
202 name = element.getElementName();
203 if(name.equals(BUILD_ELEMENT)) {
204 progress_bar.setIndeterminate(false);
205 state = BUILD;
206 // Produce a lower detail message if required
207 if(Gatherer.config.getMode() <= threshold && !stop) {
208 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildBegun1"), event.getStatus()));
209 }
210 }
211 else {
212 // Unknown command, go indeterminate
213 Gatherer.println("Unknown name: " + name);
214 progress_bar.setIndeterminate(true);
215 }
216 name = null;
217 break;
218 case BUILD:
219 // The only thing we would expect is a stage element
220 name = element.getElementName();
221 if(name.equals(STAGE_ELEMENT)) {
222 progress_bar.setIndeterminate(false);
223 // Now we determine what stage we are moving to
224 value = element.getAttribute(NAME_ATTRIBUTE);
225 if(value.equals(COMPRESSTEXT_VALUE)) {
226 state = COMPRESSTEXT;
227 if(Gatherer.config.getMode() <= threshold) {
228 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.CompressText"), event.getStatus()));
229 }
230 }
231 else if(value.equals(INDEX_VALUE)) {
232 state = INDEX;
233 if(Gatherer.config.getMode() <= threshold) {
234 String args[] = new String[1];
235 args[0] = element.getAttribute(SOURCE_ATTRIBUTE);
236 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Index", args), event.getStatus()));
237 args = null;
238 }
239 }
240 else if(value.equals(CREATEINFODATA_VALUE)) {
241 state = CREATEINFODATA;
242 if(Gatherer.config.getMode() <= threshold) {
243 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.InfoDatabase"), event.getStatus()));
244 }
245 }
246 else if(value.equals(PHIND_VALUE)) {
247 state = PHIND;
248 if(Gatherer.config.getMode() <= threshold) {
249 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Phind"), event.getStatus()));
250 }
251 }
252 else if(value.equals(CREATINGAUXILARY_VALUE)) {
253 state = CREATINGAUXILARY;
254 if(Gatherer.config.getMode() <= threshold) {
255 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Auxilary"), event.getStatus()));
256 }
257 }
258 else {
259 // Unknown command, go indeterminate
260 Gatherer.println("Unknown value: " + value);
261 progress_bar.setIndeterminate(true);
262 }
263 value = null;
264 }
265 // The build end message indicates a successfulish build.
266 else if(name.equals(BUILD_ELEMENT) && element.isClosed()) {
267 progress_bar.setIndeterminate(false);
268 setValue(MAX);
269 state = BASE;
270 if(Gatherer.config.getMode() <= threshold) {
271 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildComplete1"), event.getStatus()));
272 }
273 }
274 else {
275 // Unknown command, go indeterminate
276 Gatherer.println("Unknown name: " + name);
277 progress_bar.setIndeterminate(true);
278 }
279 name = null;
280 break;
281 case COMPRESSTEXT:
282 // We are either dealing with a phase, aa fatal error or an end stage
283 name = element.getElementName();
284 if(name.equals(PHASE_ELEMENT)) {
285 // There are three phases within compressing text (or of four possible ones)
286 value = element.getAttribute(NAME_ATTRIBUTE);
287 if(value.equals(COLLECTTEXTSTATS_VALUE)) {
288 // Nothing to do
289 }
290 else if(value.equals(CREATINGCOMPRESS_VALUE) || value.equals(SKIPCREATINGCOMP_VALUE)) {
291 // One third complete
292 progress_bar.setIndeterminate(false);
293 setValue((int)(((double)current_stages + 0.3d) * MAX) / expected_stages);
294 }
295 else if(value.equals(COMPRESSINGTEXT_VALUE)) {
296 // Two thirds complete
297 progress_bar.setIndeterminate(false);
298 setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
299 }
300 else {
301 // Unknown command, go indeterminate
302 Gatherer.println("Unknown value: " + value);
303 progress_bar.setIndeterminate(true);
304 }
305 value = null;
306 }
307 // Note that a fatal error is always followed by an end-stage, but not an end build. Thus the final state will be build (not base) and calls to exitValue() with indicate failure.
308 else if(name.equals(FATALERROR_ELEMENT)) {
309 // On simplier modes produce a meaningful message
310 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.FatalError"), event.getStatus()));
311 }
312 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
313 // Increase progress so that stage is complete.
314 current_stages++;
315 progress_bar.setIndeterminate(false);
316 setValue((current_stages * MAX) / expected_stages);
317 state = BUILD;
318 }
319 else {
320 // Unknown command, go indeterminate
321 Gatherer.println("Unknown name: " + name);
322 progress_bar.setIndeterminate(true);
323 }
324 name = null;
325 break;
326 case INDEX:
327 /** @todo - If on lower modes output a meaningful message. */
328 name = element.getElementName();
329 if(name.equals(PHASE_ELEMENT)) {
330 value = element.getAttribute(NAME_ATTRIBUTE);
331 if(value.equals(CREATINGINDEXDIC_VALUE)) {
332 // Nothing to do
333 }
334 else if(value.equals(INVERTINGTEXT_VALUE)) {
335 // One fifth complete
336 progress_bar.setIndeterminate(false);
337 setValue((int)(((double)current_stages + 0.2d) * MAX) / expected_stages);
338 }
339 else if(value.equals(CREATETHEWEIGHTS_VALUE)) {
340 // Two fifths complete
341 progress_bar.setIndeterminate(false);
342 setValue((int)(((double)current_stages + 0.4d) * MAX) / expected_stages);
343 }
344 else if(value.equals(CREATESTEMMEDDIC_VALUE)) {
345 // Three fifths complete
346 progress_bar.setIndeterminate(false);
347 setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
348 }
349 else if(value.equals(CREATINGSTEMINDX_VALUE)) {
350 // Four fifths complete
351 progress_bar.setIndeterminate(false);
352 setValue((int)(((double)current_stages + 0.8d) * MAX) / expected_stages);
353 }
354 else {
355 // Unknown command, go indeterminate
356 Gatherer.println("Unknown value: " + value);
357 progress_bar.setIndeterminate(true);
358 }
359 value = null;
360 }
361 else if(name.equals(WARNING_ELEMENT)) {
362 /** @todo - If on lower modes output a meaningful message. */
363 }
364 // Note that a fatal error is always followed by an end-stage, but not an end build. Thus the final state will be build (not base) and calls to exitValue() with indicate failure.
365 else if(name.equals(FATALERROR_ELEMENT)) {
366 // On lower modes output a meaningful message.
367
368 }
369 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
370 // Increase progress so that stage is complete.
371 current_stages++;
372 progress_bar.setIndeterminate(false);
373 setValue((current_stages * MAX) / expected_stages);
374 state = BUILD;
375 }
376 else {
377 // Unknown command, go indeterminate
378 Gatherer.println("Unknown name: " + name);
379 progress_bar.setIndeterminate(true);
380 }
381 name = null;
382 break;
383 case PHIND:
384 name = element.getElementName();
385 if(name.equals(PHASE_ELEMENT)) {
386 value = element.getAttribute(NAME_ATTRIBUTE);
387 if(value.equals(EXTRACTINGVOCAB_VALUE)) {
388 // Nothing to do
389 }
390 else if(value.equals(EXTRACTINGPHRASE_VALUE)) {
391 // One sixth complete
392 progress_bar.setIndeterminate(false);
393 setValue((int)(((double)current_stages + 0.16d) * MAX) / expected_stages);
394 }
395 else if(value.equals(SORTANDRENUMBER_VALUE)) {
396 // Two sixths complete
397 progress_bar.setIndeterminate(false);
398 setValue((int)(((double)current_stages + 0.33d) * MAX) / expected_stages);
399 }
400 else if(value.equals(PHRASEDATABASES_VALUE)) {
401 // Three sixths complete
402 progress_bar.setIndeterminate(false);
403 setValue((int)(((double)current_stages + 0.5d) * MAX) / expected_stages);
404 }
405 else if(value.equals(WORDLEVELINDEXES_VALUE)) {
406 // Four sixths complete
407 progress_bar.setIndeterminate(false);
408 setValue((int)(((double)current_stages + 0.66d) * MAX) / expected_stages);
409 }
410 else if(value.equals(DOCINFODATABASES_VALUE)) {
411 // Five sixths complete
412 progress_bar.setIndeterminate(false);
413 setValue((int)(((double)current_stages + 0.83d) * MAX) / expected_stages);
414 }
415 else {
416 // Unknown command, go indeterminate
417 Gatherer.println("Unknown value: " + value);
418 progress_bar.setIndeterminate(true);
419 }
420 value = null;
421 }
422 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
423 // Increase progress so that stage is complete.
424 current_stages++;
425 progress_bar.setIndeterminate(false);
426 setValue((current_stages * MAX) / expected_stages);
427 state = BUILD;
428 }
429 else {
430 // Unknown command, go indeterminate
431 Gatherer.println("Unknown name: " + name);
432 progress_bar.setIndeterminate(true);
433 }
434 name = null;
435 break;
436 case CREATEINFODATA:
437 case CREATINGAUXILARY:
438 name = element.getElementName();
439 if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
440 // Another stage complete
441 current_stages++;
442 progress_bar.setIndeterminate(false);
443 setValue((current_stages * MAX) / expected_stages);
444 state = BUILD;
445 }
446 else {
447 // Unknown command, go indeterminate
448 Gatherer.println("Unknown name: " + name);
449 progress_bar.setIndeterminate(true);
450 }
451 name = null;
452 break;
453 default:
454 // Unknown command, go indeterminate
455 Gatherer.println("Unknown name: " + name);
456 progress_bar.setIndeterminate(true);
457 }
458 }
459 // If we are dealing with lower detail modes then veto any other messages. We do this here as the progress monitors are garuenteed to recieve this message before anything else
460 else if(Gatherer.config.getMode() <= threshold) {
461 event.veto();
462 }
463 }
464
465 public void reset() {
466 current_stages = 0;
467 expected_stages = 0;
468 progress_bar.setIndeterminate(false);
469 progress_bar.setString(null);
470 setValue(MIN);
471 state = BASE;
472 progress_bar.updateUI();
473 }
474
475 public void saving() {
476 }
477
478 public void setSharedProgressBar(JProgressBar shared_progress_bar) {
479 this.shared_progress_bar = shared_progress_bar;
480 }
481
482 /** 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.
483 * @param state The desired state of the stop flag as a <strong>boolean</strong>.
484 */
485 public synchronized void setStop(boolean state) {
486 this.stop = state;
487 progress_bar.setIndeterminate(false);
488 }
489 /** This method resets this monitor to the start, reseting the process parsing and progress bar.
490 * TODO Everthing.
491 */
492 public void start() {
493 stop = false;
494 setValue(MIN);
495 expected_stages = 3; // Always compress text, create info database and auxiliary creation
496 // Retrieve cdm.
497 CollectionDesignManager cdm = Gatherer.c_man.getCollection().cdm;
498 // If we are using MGPP the number of indexes is always 1
499 if(cdm.searchtype_manager.isMGPPEnabled()) {
500 expected_stages = expected_stages + 1;
501 }
502 else {
503 int num_indexes = cdm.index_manager.getSize();
504 int num_partitions = cdm.subcollectionindex_manager.getSize();
505 if(num_partitions > 0) {
506 num_indexes = num_indexes * num_partitions;
507 }
508 int num_languages = cdm.language_manager.getSize();
509 if(num_languages > 0) {
510 num_indexes = num_indexes * num_languages;
511 }
512 expected_stages = expected_stages + num_indexes;
513 }
514 // And if we have a phind classifier, we have one further index
515 if(cdm.classifier_manager.isPhindClassifierAssigned()) {
516 expected_stages = expected_stages + 1;
517 }
518 cdm = null;
519 }
520 /** This method indicates the process is complete.
521 * TODO Everthing.
522 */
523 public void stop() {
524 progress_bar.setIndeterminate(false);
525 setValue(MAX);
526 }
527
528 private void setValue(int value) {
529 progress_bar.setValue(value);
530 // Incrementing the shared progress bar is a little more problematic as we may very well be trying to set it to MIN but instead set it to halfway if we're not careful.
531 if(value > MIN) {
532 shared_progress_bar.setValue(MAX + value);
533 }
534 }
535}
536
Note: See TracBrowser for help on using the repository browser.