/*
* Eoulsan development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public License version 2.1 or
* later and CeCILL-C. This should be distributed with the code.
* If you do not have a copy, see:
*
* http://www.gnu.org/licenses/lgpl-2.1.txt
* http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt
*
* Copyright for this code is held jointly by the Genomic platform
* of the Institut de Biologie de l'École normale supérieure and
* the individual authors. These should be listed in @author doc
* comments.
*
* For more information on the Eoulsan project and its aims,
* or to join the Eoulsan Google group, visit the home page
* at:
*
* http://outils.genomique.biologie.ens.fr/eoulsan
*
*/
package fr.ens.biologie.genomique.eoulsan.ui;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Strings;
import fr.ens.biologie.genomique.eoulsan.Globals;
import fr.ens.biologie.genomique.eoulsan.core.Step;
import fr.ens.biologie.genomique.eoulsan.core.Workflow;
import fr.ens.biologie.genomique.eoulsan.core.Step.StepState;
/**
* This class define a basic UI for Eoulsan.
* @author Laurent Jourdren
* @since 2.0
*/
public class BasicUI extends AbstractUI {
private Workflow workflow;
private final Map<Step, Double> steps = new HashMap<>();
private int lastMessageLength = 0;
//
// UI methods
//
@Override
public String getName() {
return "basic";
}
@Override
public void init(final Workflow workflow) {
checkNotNull(workflow, "workflow is null");
this.workflow = workflow;
// Search step to follow
searchSteps();
}
@Override
public void notifyStepState(final Step step) {
// Check if the UI has been initialized
checkState(this.workflow != null, "The UI has not been initialized");
if (step == null || step.getWorkflow() != this.workflow) {
return;
}
if (step.getState() == StepState.WORKING) {
notifyStepState(step, 0, 0, 0.0);
}
}
@Override
public void notifyStepState(final Step step, final int contextId,
final String contextName, final double progress) {
// Check if the UI has been initialized
checkState(this.workflow != null, "The UI has not been initialized");
// DO nothing
}
@Override
public void notifyStepState(final Step step, final int terminatedTasks,
final int submittedTasks, final double progress) {
// Check if the UI has been initialized
checkState(this.workflow != null, "The UI has not been initialized");
if (!isInteractiveMode()
|| step == null || step.getWorkflow() != this.workflow
|| step.getState() != StepState.WORKING
|| !this.steps.containsKey(step)) {
return;
}
final double globalProgress = computeGlobalProgress(step, progress);
if (globalProgress == 0 && this.lastMessageLength == 0) {
System.out.println(Globals.WELCOME_MSG);
}
final String msg = String.format(
"%.0f%% workflow done (currently process step %s #%d, %.0f%% done)",
globalProgress * 100.0, step.getId(), step.getNumber(),
progress * 100.0);
// Clear previous message
System.out.print(Strings.repeat("\r", this.lastMessageLength));
System.out.print(Strings.repeat(" ", this.lastMessageLength));
System.out.print(Strings.repeat("\r", this.lastMessageLength));
this.lastMessageLength = msg.length();
System.out.print(msg);
// At the end of the workflow print \n
if (globalProgress == 1.0) {
System.out.println();
}
System.out.flush();
}
@Override
public void notifyStepState(final Step step, final String note) {
// Check if the UI has been initialized
checkState(this.workflow != null, "The UI has not been initialized");
if (step == null || step.getWorkflow() != this.workflow) {
return;
}
System.out.printf("Step "
+ step.getId() + " " + step.getState().toString() + " note: " + note);
}
@Override
public void notifyWorkflowSuccess(final boolean success,
final String message) {
// Do nothing
}
@Override
public void notifyTaskSubmitted(Step step, int contextId) {
// Do nothing
}
@Override
public void notifyTaskRunning(Step step, int contextId) {
// Do nothing
}
@Override
public void notifyTaskDone(Step step, int contextId) {
// Do nothing
}
//
// Other methods
//
/**
* Search steps to follow.
*/
private void searchSteps() {
for (Step step : this.workflow.getSteps()) {
if (step == null) {
continue;
}
switch (step.getType()) {
case CHECKER_STEP:
case GENERATOR_STEP:
case STANDARD_STEP:
if (!step.isSkip()) {
this.steps.put(step, 0.0);
}
break;
default:
break;
}
}
}
/**
* Compute global progress.
* @param step step to update progress
* @param progress progress value of the step
* @return global progress as percent
*/
private double computeGlobalProgress(final Step step, final double progress) {
if (!this.steps.containsKey(step)) {
return -1;
}
// Update progress
this.steps.put(step, progress);
double sum = 0;
for (double p : this.steps.values()) {
sum += p;
}
return sum / this.steps.size();
}
}