/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.util;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* A progress listener that writes the progress messages to the standard error stream ({@link System#err}).
*
* @author Michael Dittenbach
* @author Rudolf Mayer
* @version $Id: StdErrProgressWriter.java 3883 2010-11-02 17:13:23Z frank $
*/
public class StdErrProgressWriter implements ProgressListener {
protected String message = "";
protected int currentStep = 0;
protected int totalSteps = 0;
protected int stepWidth = 1;
protected long startDate = 0;
private long elapsed = 0;
private long estimatedLength = 0;
private long estimatedEndDate = 0;
protected DateFormat format = new SimpleDateFormat("dd.MM.yy HH:mm:ss");
protected short messageLength = 0;
protected short screenWidth = Short.MAX_VALUE;
protected int newLineWidth;
protected boolean finished = false;
/**
* Initialises a progress writer with a {@link StdErrProgressWriter#stepWidth} of 1.
*/
public StdErrProgressWriter(int totalSteps, String message) {
this(totalSteps, message, 1);
}
/**
* Initialises a new progress writer.
*
* @param totalSteps The total number of steps
* @param message The basic message, "x of y, ETA hh:mm:ss zzz" will be added automatically to this.
* @param stepWidth How often the message should be updated. Use a bigger stepWidth to improve the performance. The
* first and last step are printed regardless of the value of the stepWith.
*/
public StdErrProgressWriter(int totalSteps, String message, int stepWidth) {
this.message = message;
this.messageLength = (short) message.length();
this.screenWidth = getScreenWidth();
this.totalSteps = totalSteps;
this.stepWidth = stepWidth;
if (stepWidth == 0) {
this.stepWidth = 1;
}
startDate = new Date().getTime();
}
private short getScreenWidth() {
String lines = System.getenv("LINES");
if (lines != null) {
try {
short w = Short.parseShort(lines);
return w;
} catch (Exception e) {
}
}
return Short.MAX_VALUE;
}
public StdErrProgressWriter(int totalSteps, String message, int stepWidth, int newLineWidth) {
this(totalSteps, message, stepWidth);
this.newLineWidth = Math.max(totalSteps / 20, 1000);
newLineWidth = newLineWidth / stepWidth * stepWidth;
}
@Override
public void progress() {
progress(++currentStep);
}
@Override
public void progress(int currentStep) {
if (finished) {
return;
}
if (currentStep == 1 || currentStep == totalSteps || currentStep % stepWidth == 0) {
this.currentStep = currentStep;
long currentDate = new Date().getTime();
elapsed = currentDate - startDate;
double percentDone = (double) currentStep / (double) totalSteps * 100.0d;
estimatedLength = (long) (elapsed / percentDone) * 100;
estimatedEndDate = startDate + estimatedLength;
StringBuilder log = new StringBuilder(messageLength + 30);
log.append("\r").append(message).append(currentStep).append(" of ").append(totalSteps).append(", ETA: ").append(
format.format(new Date(estimatedEndDate))).append(", ").append(
DateUtils.shortFormatDuration(estimatedEndDate - currentDate)).append(" left").append(" ");
System.err.print(log);
if (newLineWidth != 0 && currentStep % newLineWidth == 0) {
System.err.println();
}
if (currentStep == totalSteps) {
System.err.println("\n\t --> Finished, took " + DateUtils.formatDuration(elapsed));
finished = true;
}
}
}
@Override
public void progress(String message) {
progress(message, currentStep + 1);
}
@Override
public void progress(String message, int currentStep) {
this.message = message.trim();
this.messageLength = (short) message.length();
progress(currentStep);
}
@Override
public void insertRow(int rows, String message) {
// currently not used in this implementation
}
@Override
public void insertColumn(int columns, String message) {
// currently not used in this implementation
}
public String getMessage() {
return message;
}
@Override
public int getCurrentStep() {
return currentStep;
}
public int getSteps() {
return totalSteps;
}
public void setCurrentStep(int currentStep) {
this.currentStep = currentStep;
}
}