/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* 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.apache.org/licenses/LICENSE-2.0
*
* 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 org.arakhne.afc.progress;
import java.lang.ref.WeakReference;
import java.text.NumberFormat;
import java.util.logging.Logger;
/**
* An object that permits to indicates the progression of
* a task. This monitor display on the console the progression
* of the task.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public class ProgressionConsoleMonitor implements ProgressionListener {
private final NumberFormat numberFormat;
private Progression model = new DefaultProgression();
private Logger logger;
private int previousValue;
/** Construct a monitor.
*/
public ProgressionConsoleMonitor() {
this.numberFormat = NumberFormat.getPercentInstance();
this.numberFormat.setMaximumFractionDigits(0);
this.logger = null;
this.previousValue = this.model.getValue();
this.model.addProgressionListener(new WeakListener(this, this.model));
}
/** Replies the task progression model.
*
* @return the task progression model.
*/
public Progression getModel() {
return this.model;
}
/** Change the task progression model.
*
* @param model - the task progression model.
*/
public void setModel(Progression model) {
this.model.removeProgressionListener(new WeakListener(this, this.model));
if (model == null) {
this.model = new DefaultProgression();
} else {
this.model = model;
}
this.previousValue = this.model.getValue();
this.model.addProgressionListener(new WeakListener(this, this.model));
}
/** Replies the logger used by this monitor.
*
* @return the logger, never <code>null</code>
*/
public Logger getLogger() {
return this.logger;
}
/** Change the logger used by this monitor.
* If the given logger is <code>null</code>, then
* the {@link Logger#getAnonymousLogger() default anonymous logger}
* will be used.
*
* @param logger - the new logger.
*/
public void setLogger(Logger logger) {
this.logger = logger;
}
@Override
@SuppressWarnings("checkstyle:regexp")
public void onProgressionValueChanged(ProgressionEvent event) {
if (!event.isIndeterminate() && event.getValue() != this.previousValue) {
this.previousValue = event.getValue();
final String message = buildMessage(
event.getProgressionFactor(),
event.getComment(),
event.isRoot(),
event.isFinished(),
this.numberFormat);
if (this.logger == null) {
System.out.println(message);
} else {
this.logger.info(message);
}
}
}
/** Build the logging message from the given data.
* This function is defined for enabling overriding in sub classes.
*
* @param progress - progression indicator between 0 and 1.
* @param comment - associated comment.
* @param isRoot - indicates if the progression model is a root model.
* @param isFinished - indicates if the task is finished.
* @param numberFormat - instance of the number formatter.
* @return the message.
*/
@SuppressWarnings("static-method")
protected String buildMessage(double progress, String comment, boolean isRoot, boolean isFinished,
NumberFormat numberFormat) {
final StringBuilder txt = new StringBuilder();
txt.append('[');
txt.append(numberFormat.format(progress));
txt.append("] "); //$NON-NLS-1$
if (comment != null) {
txt.append(comment);
}
return txt.toString();
}
/** Progression listener that is weakly referencing another listener.
*
* @author $Author: sgalland$
* @version $Name$ $Revision$ $Date$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private static class WeakListener implements ProgressionListener {
private final WeakReference<ProgressionListener> listener;
private final WeakReference<Progression> model;
/** Constuct a listener.
*
* @param listener the original listener.
* @param model the progression model.
*/
WeakListener(ProgressionListener listener, Progression model) {
this.listener = new WeakReference<>(listener);
this.model = new WeakReference<>(model);
}
@Override
public void onProgressionValueChanged(ProgressionEvent event) {
final ProgressionListener list = this.listener.get();
if (list != null) {
list.onProgressionValueChanged(event);
} else {
removeListener();
}
}
@Override
public void onProgressionStateChanged(ProgressionEvent event) {
final ProgressionListener list = this.listener.get();
if (list != null) {
list.onProgressionStateChanged(event);
} else {
removeListener();
}
}
private void removeListener() {
final Progression prog = this.model.get();
if (prog != null) {
prog.removeProgressionListener(this);
}
}
}
}