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

Last change on this file since 8231 was 8231, checked in by mdewsnip, 20 years ago

Replaced all "Gatherer.config" with "Configuration".

  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 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 public void messageOnProgressBar(String message)
170 {
171 if ((message!=null) & (message!="")) {
172 progress_bar.setString(message);
173 shared_progress_bar.setString(message);
174 }
175 else {
176 progress_bar.setString(null);
177 shared_progress_bar.setString(null);
178 }
179 }
180
181 /** Method to determine the state of the stop flag, which may be set by the visual component that created this monitor.
182 * @return A <strong>boolean</strong> indicating if the process has been asked to stop.
183 */
184 public synchronized boolean hasSignalledStop() {
185 return stop;
186 }
187 /** Inform the progress bar that it should programatically increment progress by one step. */
188 public void increment() {
189 // There is no reason this should be called for a build.
190 }
191
192 /** This method is used to 'feed in' a line of text captured from the process.
193 * @param queue a queue which at the moment should contain a single GShellEvent
194 */
195 public void process(ArrayList queue) {
196 GShellEvent event = (GShellEvent) queue.get(0);
197 // Remove 'build.pl> ' bit
198 String line = event.getMessage();
199 line = line.substring(line.indexOf(StaticStrings.GREATER_THAN_CHARACTER) + 1);
200 line = line.trim();
201 // We are only really interested in processing pseudo-XML tags
202 if(line.startsWith(StaticStrings.LESS_THAN_CHARACTER) && line.endsWith(StaticStrings.GREATER_THAN_CHARACTER)) {
203 // All events are vetoed
204 event.veto();
205
206 // Create a new element from it
207 GShellElement element = new GShellElement(line);
208 // Now change states within the state machine as appropriate. A state change may subsequently incur a progress update.
209 String name = null;
210 String value = null;
211 switch(state) {
212 case BASE:
213 // The only thing we would expect is a build message
214 name = element.getElementName();
215 if(name.equals(BUILD_ELEMENT)) {
216 progress_bar.setIndeterminate(false);
217 state = BUILD;
218 // Produce a lower detail message if required
219 if(Configuration.getMode() <= threshold && !stop) {
220 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildBegun1"), event.getStatus()));
221 }
222 }
223 else {
224 // Unknown command, go indeterminate
225 Gatherer.println("Unknown name: " + name);
226 progress_bar.setIndeterminate(true);
227 }
228 name = null;
229 break;
230 case BUILD:
231 // The only thing we would expect is a stage element
232 name = element.getElementName();
233 if(name.equals(STAGE_ELEMENT)) {
234 progress_bar.setIndeterminate(false);
235 // Now we determine what stage we are moving to
236 value = element.getAttribute(NAME_ATTRIBUTE);
237 if(value.equals(COMPRESSTEXT_VALUE)) {
238 state = COMPRESSTEXT;
239 if(Configuration.getMode() <= threshold) {
240 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.CompressText"), event.getStatus()));
241 }
242 }
243 else if(value.equals(INDEX_VALUE)) {
244 state = INDEX;
245 if(Configuration.getMode() <= threshold) {
246 String args[] = new String[1];
247 args[0] = element.getAttribute(SOURCE_ATTRIBUTE);
248 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Index", args), event.getStatus()));
249 args = null;
250 }
251 }
252 else if(value.equals(CREATEINFODATA_VALUE)) {
253 state = CREATEINFODATA;
254 if(Configuration.getMode() <= threshold) {
255 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.InfoDatabase"), event.getStatus()));
256 }
257 }
258 else if(value.equals(PHIND_VALUE)) {
259 state = PHIND;
260 if(Configuration.getMode() <= threshold) {
261 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Phind"), event.getStatus()));
262 }
263 }
264 else if(value.equals(CREATINGAUXILARY_VALUE)) {
265 state = CREATINGAUXILARY;
266 if(Configuration.getMode() <= threshold) {
267 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.Auxilary"), event.getStatus()));
268 }
269 }
270 else {
271 // Unknown command, go indeterminate
272 Gatherer.println("Unknown value: " + value);
273 progress_bar.setIndeterminate(true);
274 }
275 value = null;
276 }
277 // The build end message indicates a successfulish build.
278 else if(name.equals(BUILD_ELEMENT) && element.isClosed()) {
279 progress_bar.setIndeterminate(false);
280 setValue(MAX);
281 state = BASE;
282 if(Configuration.getMode() <= threshold) {
283 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.BuildComplete1"), event.getStatus()));
284 }
285 }
286 else {
287 // Unknown command, go indeterminate
288 Gatherer.println("Unknown name: " + name);
289 progress_bar.setIndeterminate(true);
290 }
291 name = null;
292 break;
293 case COMPRESSTEXT:
294 // We are either dealing with a phase, aa fatal error or an end stage
295 name = element.getElementName();
296 if(name.equals(PHASE_ELEMENT)) {
297 // There are three phases within compressing text (or of four possible ones)
298 value = element.getAttribute(NAME_ATTRIBUTE);
299 if(value.equals(COLLECTTEXTSTATS_VALUE)) {
300 // Nothing to do
301 }
302 else if(value.equals(CREATINGCOMPRESS_VALUE) || value.equals(SKIPCREATINGCOMP_VALUE)) {
303 // One third complete
304 progress_bar.setIndeterminate(false);
305 setValue((int)(((double)current_stages + 0.3d) * MAX) / expected_stages);
306 }
307 else if(value.equals(COMPRESSINGTEXT_VALUE)) {
308 // Two thirds complete
309 progress_bar.setIndeterminate(false);
310 setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
311 }
312 else {
313 // Unknown command, go indeterminate
314 Gatherer.println("Unknown value: " + value);
315 progress_bar.setIndeterminate(true);
316 }
317 value = null;
318 }
319 // 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.
320 else if(name.equals(FATALERROR_ELEMENT)) {
321 // On simplier modes produce a meaningful message
322 queue.add(new GShellEvent(event.getSource(), 0, event.getType(), Dictionary.get("GShell.Build.FatalError"), event.getStatus()));
323 }
324 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
325 // Increase progress so that stage is complete.
326 current_stages++;
327 progress_bar.setIndeterminate(false);
328 setValue((current_stages * MAX) / expected_stages);
329 state = BUILD;
330 }
331 else {
332 // Unknown command, go indeterminate
333 Gatherer.println("Unknown name: " + name);
334 progress_bar.setIndeterminate(true);
335 }
336 name = null;
337 break;
338 case INDEX:
339 /** @todo - If on lower modes output a meaningful message. */
340 name = element.getElementName();
341 if(name.equals(PHASE_ELEMENT)) {
342 value = element.getAttribute(NAME_ATTRIBUTE);
343 if(value.equals(CREATINGINDEXDIC_VALUE)) {
344 // Nothing to do
345 }
346 else if(value.equals(INVERTINGTEXT_VALUE)) {
347 // One fifth complete
348 progress_bar.setIndeterminate(false);
349 setValue((int)(((double)current_stages + 0.2d) * MAX) / expected_stages);
350 }
351 else if(value.equals(CREATETHEWEIGHTS_VALUE)) {
352 // Two fifths complete
353 progress_bar.setIndeterminate(false);
354 setValue((int)(((double)current_stages + 0.4d) * MAX) / expected_stages);
355 }
356 else if(value.equals(CREATESTEMMEDDIC_VALUE)) {
357 // Three fifths complete
358 progress_bar.setIndeterminate(false);
359 setValue((int)(((double)current_stages + 0.6d) * MAX) / expected_stages);
360 }
361 else if(value.equals(CREATINGSTEMINDX_VALUE)) {
362 // Four fifths complete
363 progress_bar.setIndeterminate(false);
364 setValue((int)(((double)current_stages + 0.8d) * MAX) / expected_stages);
365 }
366 else {
367 // Unknown command, go indeterminate
368 Gatherer.println("Unknown value: " + value);
369 progress_bar.setIndeterminate(true);
370 }
371 value = null;
372 }
373 else if(name.equals(WARNING_ELEMENT)) {
374 /** @todo - If on lower modes output a meaningful message. */
375 }
376 // 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.
377 else if(name.equals(FATALERROR_ELEMENT)) {
378 // On lower modes output a meaningful message.
379
380 }
381 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
382 // Increase progress so that stage is complete.
383 current_stages++;
384 progress_bar.setIndeterminate(false);
385 setValue((current_stages * MAX) / expected_stages);
386 state = BUILD;
387 }
388 else {
389 // Unknown command, go indeterminate
390 Gatherer.println("Unknown name: " + name);
391 progress_bar.setIndeterminate(true);
392 }
393 name = null;
394 break;
395 case PHIND:
396 name = element.getElementName();
397 if(name.equals(PHASE_ELEMENT)) {
398 value = element.getAttribute(NAME_ATTRIBUTE);
399 if(value.equals(EXTRACTINGVOCAB_VALUE)) {
400 // Nothing to do
401 }
402 else if(value.equals(EXTRACTINGPHRASE_VALUE)) {
403 // One sixth complete
404 progress_bar.setIndeterminate(false);
405 setValue((int)(((double)current_stages + 0.16d) * MAX) / expected_stages);
406 }
407 else if(value.equals(SORTANDRENUMBER_VALUE)) {
408 // Two sixths complete
409 progress_bar.setIndeterminate(false);
410 setValue((int)(((double)current_stages + 0.33d) * MAX) / expected_stages);
411 }
412 else if(value.equals(PHRASEDATABASES_VALUE)) {
413 // Three sixths complete
414 progress_bar.setIndeterminate(false);
415 setValue((int)(((double)current_stages + 0.5d) * MAX) / expected_stages);
416 }
417 else if(value.equals(WORDLEVELINDEXES_VALUE)) {
418 // Four sixths complete
419 progress_bar.setIndeterminate(false);
420 setValue((int)(((double)current_stages + 0.66d) * MAX) / expected_stages);
421 }
422 else if(value.equals(DOCINFODATABASES_VALUE)) {
423 // Five sixths complete
424 progress_bar.setIndeterminate(false);
425 setValue((int)(((double)current_stages + 0.83d) * MAX) / expected_stages);
426 }
427 else {
428 // Unknown command, go indeterminate
429 Gatherer.println("Unknown value: " + value);
430 progress_bar.setIndeterminate(true);
431 }
432 value = null;
433 }
434 else if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
435 // Increase progress so that stage is complete.
436 current_stages++;
437 progress_bar.setIndeterminate(false);
438 setValue((current_stages * MAX) / expected_stages);
439 state = BUILD;
440 }
441 else {
442 // Unknown command, go indeterminate
443 Gatherer.println("Unknown name: " + name);
444 progress_bar.setIndeterminate(true);
445 }
446 name = null;
447 break;
448 case CREATEINFODATA:
449 case CREATINGAUXILARY:
450 name = element.getElementName();
451 if(name.equals(STAGE_ELEMENT) && element.isClosed()) {
452 // Another stage complete
453 current_stages++;
454 progress_bar.setIndeterminate(false);
455 setValue((current_stages * MAX) / expected_stages);
456 state = BUILD;
457 }
458 else {
459 // Unknown command, go indeterminate
460 Gatherer.println("Unknown name: " + name);
461 progress_bar.setIndeterminate(true);
462 }
463 name = null;
464 break;
465 default:
466 // Unknown command, go indeterminate
467 Gatherer.println("Unknown name: " + name);
468 progress_bar.setIndeterminate(true);
469 }
470 }
471 // 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
472 else if(Configuration.getMode() <= threshold) {
473 event.veto();
474 }
475 }
476
477 public void reset() {
478 current_stages = 0;
479 expected_stages = 0;
480 progress_bar.setIndeterminate(false);
481 progress_bar.setString(null);
482 setValue(MIN);
483 state = BASE;
484 progress_bar.updateUI();
485 }
486
487 public void saving() {
488 }
489
490 public void setSharedProgressBar(JProgressBar shared_progress_bar) {
491 this.shared_progress_bar = shared_progress_bar;
492 }
493
494 /** 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.
495 * @param state The desired state of the stop flag as a <strong>boolean</strong>.
496 */
497 public synchronized void setStop(boolean state) {
498 this.stop = state;
499 progress_bar.setIndeterminate(false);
500 }
501 /** This method resets this monitor to the start, reseting the process parsing and progress bar.
502 * TODO Everthing.
503 */
504 public void start() {
505 stop = false;
506 setValue(MIN);
507 expected_stages = 3; // Always compress text, create info database and auxiliary creation
508 // Retrieve cdm.
509 CollectionDesignManager cdm = Gatherer.c_man.getCollection().cdm;
510 // If we are using MGPP the number of indexes is always 1
511 if(cdm.searchtype_manager.isMGPPEnabled()) {
512 expected_stages = expected_stages + 1;
513 }
514 else {
515 int num_indexes = cdm.index_manager.getSize();
516 int num_partitions = cdm.subcollectionindex_manager.getSize();
517 if(num_partitions > 0) {
518 num_indexes = num_indexes * num_partitions;
519 }
520 int num_languages = cdm.language_manager.getSize();
521 if(num_languages > 0) {
522 num_indexes = num_indexes * num_languages;
523 }
524 expected_stages = expected_stages + num_indexes;
525 }
526 // And if we have a phind classifier, we have one further index
527 if(cdm.classifier_manager.isPhindClassifierAssigned()) {
528 expected_stages = expected_stages + 1;
529 }
530 cdm = null;
531 }
532 /** This method indicates the process is complete.
533 * TODO Everthing.
534 */
535 public void stop() {
536 progress_bar.setIndeterminate(false);
537 setValue(MAX);
538 }
539
540 private void setValue(int value) {
541 progress_bar.setValue(value);
542 // 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.
543 if(value > MIN) {
544 shared_progress_bar.setValue(MAX + value);
545 }
546 }
547}
548
Note: See TracBrowser for help on using the repository browser.