/*
* Copyright (c) Fabien Hermenier
*
* This file is part of Entropy.
*
* Entropy is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Entropy 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Entropy. If not, see <http://www.gnu.org/licenses/>.
*/
package entropy.plan.visualization;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.GanttRenderer;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import entropy.plan.Plan;
import entropy.plan.TimedReconfigurationPlan;
import entropy.plan.action.Action;
import entropy.plan.action.Migration;
import entropy.plan.action.Pause;
import entropy.plan.action.Resume;
import entropy.plan.action.Run;
import entropy.plan.action.Shutdown;
import entropy.plan.action.Startup;
import entropy.plan.action.Stop;
import entropy.plan.action.Suspend;
import entropy.plan.action.UnPause;
/**
* Visualize a reconfiguration plan as a agenda.
* Image can be stored as a JPEG or a PNG file.
*
* @author Fabien Hermenier
*/
public class GanttVisualizer implements PlanVisualizer {
/**
* Available image format.
*/
public static enum Format {
jpg, png
}
/**
* The format used.
*/
private Format fmt;
/**
* The output file.
*/
private String out;
/**
* Make a new visualizer. Image is stored as a PNG file
*
* @param path the path name to the output file
*/
public GanttVisualizer(String path) {
this(path, Format.png);
}
/**
* Make a new visualizer.
*
* @param path the path name to the output file
* @param format the format of the output image
*/
public GanttVisualizer(String path, Format format) {
this.out = path;
this.fmt = format;
}
/**
* Get the path of the output file.
*
* @return a path
*/
public String getOutputFile() {
return out;
}
/**
* Set the output path of the visualization
*
* @param path the path to the output file
*/
public void setOutputFile(String path) {
this.out = path;
}
/**
* Set the output file format.
*
* @param f the format of the output image
*/
public void setOutputFormat(Format f) {
this.fmt = f;
}
/**
* Get the format of the output image.
*
* @return a format
*/
public Format getOutputFormat() {
return this.fmt;
}
/**
* Build the plan agenda
*
* @param plan the plan to visualize
* @return {@code true} if the generation succeeds
*/
@Override
public boolean buildVisualization(TimedReconfigurationPlan plan) {
File parent = new File(out).getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
Plan.logger.error("Unable to create '" + getOutputFile() + "'");
return false;
}
final TaskSeriesCollection collection = new TaskSeriesCollection();
TaskSeries ts = new TaskSeries("actions");
for (Action action : plan) {
Task t = new Task(action.toString(), new SimpleTimePeriod(action.getStartMoment(), action.getFinishMoment()));
ts.add(t);
}
collection.add(ts);
ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme());
final JFreeChart chart = ChartFactory.createGanttChart(
null, // chart title
"Actions", // domain axis label
"Time", // range axis label
collection, // data
false, // include legend
true, // tooltips
false // urls
);
CategoryPlot plot = chart.getCategoryPlot();
DateAxis da = (DateAxis) plot.getRangeAxis();
SimpleDateFormat sdfmt = new SimpleDateFormat();
sdfmt.applyPattern("S");
da.setDateFormatOverride(sdfmt);
((GanttRenderer) plot.getRenderer()).setShadowVisible(false);
int width = 500 + 10 * plan.getDuration();
int height = 50 + 20 * plan.size();
try {
switch (fmt) {
case png:
ChartUtilities.saveChartAsPNG(new File(getOutputFile()), chart, width, height);
break;
case jpg:
ChartUtilities.saveChartAsJPEG(new File(getOutputFile()), chart, width, height);
break;
}
} catch (IOException e) {
Plan.logger.error(e.getMessage(), e);
return false;
}
return true;
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Migration a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Run a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Stop a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Startup a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Shutdown a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Resume a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Suspend a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(Pause a) {
}
/**
* Unused.
*
* @param a the action to add
*/
@Override
public void inject(UnPause a) {
}
}