Java tutorial
/* * Copyright 2014 by Yields. * * 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 io.yields.plugins.kpi; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.CompareToBuilder; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.CategoryDataset; import org.jfree.ui.RectangleEdge; import org.jfree.ui.RectangleInsets; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.util.DataSetBuilder; import hudson.util.Graph; import io.yields.math.framework.kpi.ScoreResult; import static io.yields.plugins.kpi.LocalMessages.PROJECT_ACTION_DISPLAY_NAME; import static java.util.Collections.sort; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; /** * Project action showing the overall trend of KPIs for multiple builds. */ public class KPIReportProjectAction implements Action { private static final String PLUGIN_NAME = "yields-dashboard"; private final AbstractProject<?, ?> project; private KPIReportConfig config; public KPIReportProjectAction(final AbstractProject project, final KPIReportConfig config) { this.project = project; this.config = config; } public String getDisplayName() { return PROJECT_ACTION_DISPLAY_NAME.toString(); } public String getUrlName() { return PLUGIN_NAME; } public String getIconFileName() { return "/plugin/kpis/yields.png"; } /** * Method necessary to get the side-panel included in the Jelly file * * @return this {@link hudson.model.AbstractProject} */ public AbstractProject<?, ?> getProject() { return this.project; } public boolean showSummary() { return isNotEmpty(getKPIReports()); } public List<KPIReport> getKPIReportsForDetail() { List<KPIReport> kpiReports = getKPIReports(); if (kpiReports.size() > config.getDetailSize()) { kpiReports = kpiReports.subList(kpiReports.size() - config.getDetailSize(), kpiReports.size()); } return kpiReports; } public List<KPIReport> getKPIReports() { final List<KPIReport> kpiReports = new ArrayList<KPIReport>(); if (null == this.project) { return kpiReports; } final List<? extends AbstractBuild<?, ?>> builds = project.getBuilds(); int count = 0; for (AbstractBuild<?, ?> currentBuild : builds) { if (count > config.getTrendSize()) { break; } final KPIReportBuildAction buildAction = currentBuild.getAction(KPIReportBuildAction.class); if (buildAction == null) { // try previous build continue; } final KPIReport report = buildAction.getBuildActionResultsDisplay().getKPIReport(); if (report == null) { break; } kpiReports.add(report); count++; } sort(kpiReports, new Comparator<KPIReport>() { @Override public int compare(KPIReport kpiReport, KPIReport other) { return new CompareToBuilder().append(kpiReport.getBuildNumber(), other.getBuildNumber()) .toComparison(); } }); return kpiReports; } public void doSummaryGraph(final StaplerRequest request, final StaplerResponse response) throws IOException { final Integer width = getOrElse(request, "width", 400); final Integer height = getOrElse(request, "height", 300); final Graph graph = new KPIGraph("", width, height) { protected DataSetBuilder<String, Integer> createDataSet() { DataSetBuilder<String, Integer> dataSetBuilder = new DataSetBuilder<String, Integer>(); List<KPIReport> kpiReports = getKPIReports(); Map<Integer, Map<String, ScoreResult>> testResults = new TreeMap<Integer, Map<String, ScoreResult>>(); if (CollectionUtils.isNotEmpty(kpiReports)) { for (KPIReport kpiReport : kpiReports) { int buildNumber = kpiReport.getBuildAction().getBuild().getNumber(); Map<String, ScoreResult> buildScores = testResults.get(buildNumber); if (buildScores == null) { buildScores = new HashMap<String, ScoreResult>(); testResults.put(buildNumber, buildScores); } for (String kpiName : kpiReport.getKpiScoreNames()) { ScoreResult kpiScore = kpiReport.getKpiScore(kpiName); if (kpiScore.isOfficial()) { buildScores.put(kpiName, kpiScore); } } } } for (Map.Entry<Integer, Map<String, ScoreResult>> entry : testResults.entrySet()) { Integer buildNumber = entry.getKey(); Map<String, ScoreResult> buildScores = entry.getValue(); for (Map.Entry<String, ScoreResult> buildEntry : buildScores.entrySet()) { dataSetBuilder.add(buildEntry.getValue().getScore(), buildEntry.getKey(), buildNumber); } } return dataSetBuilder; } }; graph.doPng(request, response); } public void doTrendGraph(final StaplerRequest request, final StaplerResponse response) throws IOException { final Integer width = getOrElse(request, "width", 400); final Integer height = getOrElse(request, "height", 300); final Graph graph = new KPIGraph("", width, height) { protected DataSetBuilder<String, Integer> createDataSet() { DataSetBuilder<String, Integer> dataSetBuilder = new DataSetBuilder<String, Integer>(); List<KPIReport> kpiReports = getKPIReports(); Map<Integer, Map<String, ScoreResult>> testResults = new TreeMap<Integer, Map<String, ScoreResult>>(); if (CollectionUtils.isNotEmpty(kpiReports)) { for (KPIReport kpiReport : kpiReports) { int buildNumber = kpiReport.getBuildAction().getBuild().getNumber(); Map<String, ScoreResult> buildScores = testResults.get(buildNumber); if (buildScores == null) { buildScores = new HashMap<String, ScoreResult>(); testResults.put(buildNumber, buildScores); } for (String kpiName : kpiReport.getKpiScoreNames()) { ScoreResult kpiScore = kpiReport.getKpiScore(kpiName); if (kpiScore.isOfficial()) { buildScores.put(kpiName, kpiScore); } } } } for (Map.Entry<Integer, Map<String, ScoreResult>> entry : testResults.entrySet()) { Integer buildNumber = entry.getKey(); Map<String, ScoreResult> buildScores = entry.getValue(); for (Map.Entry<String, ScoreResult> buildEntry : buildScores.entrySet()) { dataSetBuilder.add(buildEntry.getValue().getScore(), buildEntry.getKey(), buildNumber); } } return dataSetBuilder; } }; graph.doPng(request, response); } private Integer getOrElse(StaplerRequest request, String parameterName, int defaultValue) { String value = request.getParameter(parameterName); if (StringUtils.isNotBlank(value)) { return Integer.parseInt(value); } else { return defaultValue; } } private abstract class KPIGraph extends Graph { private final String title; private final String xLabel; protected KPIGraph(final String title, final int width, final int height) { super(-1, width, height); this.title = title; this.xLabel = "Build Number"; } protected abstract DataSetBuilder<String, Integer> createDataSet(); protected JFreeChart createGraph() { final CategoryDataset dataSet = createDataSet().build(); double min = 1; double max = 0; for (int row = 0; row < dataSet.getRowCount(); row++) { for (int column = 0; column < dataSet.getColumnCount(); column++) { Number value = dataSet.getValue(row, column); if (value != null) { min = Math.min(min, value.doubleValue()); max = Math.max(max, value.doubleValue()); } } } final JFreeChart chart = ChartFactory.createLineChart(title, xLabel, null, dataSet, PlotOrientation.VERTICAL, true, true, false); chart.setBackgroundPaint(Color.white); CategoryPlot plot = ChartUtil.enhanceColors((CategoryPlot) chart.getPlot()); // if min would be eq to max, this range would render and empty graph if (min == max) { min = min - (min * 0.1); max = max + (max * 0.1); } NumberAxis yAxis = new NumberAxis(""); yAxis.setLowerMargin(0.1); yAxis.setUpperMargin(0.1); yAxis.setRangeWithMargins(min, max); plot.setRangeAxis(yAxis); chart.getLegend().setPosition(RectangleEdge.BOTTOM); chart.getLegend().setMargin(new RectangleInsets(0, 10, 0, 0)); return chart; } } public SortedSet<String> getTestNames() { SortedSet<String> testNames = new TreeSet<String>(); for (KPIReport kpiReport : getKPIReports()) { for (ScoreResult scoreResult : kpiReport.getKpiScores()) { if (scoreResult.isOfficial()) { testNames.add(scoreResult.getName()); } } } return testNames; } }