summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java
blob: 83419ef466e8666556f9150d7f23c908211b434d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package de.lmu.ifi.dbs.elki.logging.progress;

/*
 This file is part of ELKI:
 Environment for Developing KDD-Applications Supported by Index-Structures

 Copyright (C) 2013
 Ludwig-Maximilians-Universität München
 Lehr- und Forschungseinheit für Datenbanksysteme
 ELKI Development Team

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import de.lmu.ifi.dbs.elki.logging.Logging;

/**
 * A progress object for a given overall number of items to process. The number
 * of already processed items at a point in time can be updated.
 * 
 * The main feature of this class is to provide a String representation of the
 * progress suitable as a message for printing to the command line interface.
 * 
 * @author Arthur Zimek
 */
public class FiniteProgress extends AbstractProgress {
  /**
   * The overall number of items to process.
   */
  private final int total;

  /**
   * Holds the length of a String describing the total number.
   */
  // TODO: move this to a console logging related class instead?
  private final int totalLength;

  /**
   * A progress object for a given overall number of items to process.
   * 
   * @param task the name of the task
   * @param total the overall number of items to process
   */
  @Deprecated
  public FiniteProgress(String task, int total) {
    super(task);
    this.total = total;
    this.totalLength = Integer.toString(total).length();
  }

  /**
   * Constructor with auto-reporting to logging.
   * 
   * @param task the name of the task
   * @param total the overall number of items to process
   * @param logger the logger to report to
   */
  public FiniteProgress(String task, int total, Logging logger) {
    super(task);
    this.total = total;
    this.totalLength = Integer.toString(total).length();
    logger.progress(this);
  }

  /**
   * Sets the number of items already processed at a time being.
   * 
   * @param processed the number of items already processed at a time being
   * @throws IllegalArgumentException if the given number is negative or exceeds
   *         the overall number of items to process
   */
  @Override
  public void setProcessed(int processed) throws IllegalArgumentException {
    if (processed > total) {
      throw new IllegalArgumentException(processed + " exceeds total: " + total);
    }
    if (processed < 0) {
      throw new IllegalArgumentException("Negative number of processed: " + processed);
    }
    super.setProcessed(processed);
  }

  /**
   * Append a string representation of the progress to the given string buffer.
   * 
   * @param buf Buffer to serialize to
   * @return Buffer the data was serialized to.
   */
  @Override
  public StringBuilder appendToBuffer(StringBuilder buf) {
    String processedString = Integer.toString(getProcessed());
    int percentage = (int) (getProcessed() * 100.0 / total);
    buf.append(getTask());
    buf.append(": ");
    for (int i = 0; i < totalLength - processedString.length(); i++) {
      buf.append(' ');
    }
    buf.append(getProcessed());
    buf.append(" [");
    if (percentage < 100) {
      buf.append(' ');
    }
    if (percentage < 10) {
      buf.append(' ');
    }
    buf.append(percentage);
    buf.append("%]");
    return buf;
  }

  /**
   * Test whether the progress was completed.
   */
  @Override
  public boolean isComplete() {
    return getProcessed() == total;
  }

  /**
   * Get the final value for the progress.
   * 
   * @return final value
   */
  public int getTotal() {
    return total;
  }

  /**
   * Ensure that the progress was completed, to make progress bars disappear
   * 
   * @param logger Logger to report to.
   */
  public void ensureCompleted(Logging logger) {
    if (!isComplete()) {
      logger.warning("Progress had not completed automatically as expected: " + getProcessed() + "/" + total, new Throwable());
      setProcessed(getTotal());
      logger.progress(this);
    }
  }
}