de.tsystems.mms.apm.performancesignature.PerfSigProjectAction.java Source code

Java tutorial

Introduction

Here is the source code for de.tsystems.mms.apm.performancesignature.PerfSigProjectAction.java

Source

/*
 * Copyright (c) 2014 T-Systems Multimedia Solutions GmbH
 *
 * 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 de.tsystems.mms.apm.performancesignature;

import de.tsystems.mms.apm.performancesignature.dynatrace.model.ChartDashlet;
import de.tsystems.mms.apm.performancesignature.dynatrace.model.DashboardReport;
import de.tsystems.mms.apm.performancesignature.dynatrace.model.Measure;
import de.tsystems.mms.apm.performancesignature.dynatrace.model.TestRun;
import de.tsystems.mms.apm.performancesignature.model.MeasureNameHelper;
import de.tsystems.mms.apm.performancesignature.util.PerfSigUtils;
import hudson.FilePath;
import hudson.model.AbstractBuild;
import hudson.model.Job;
import hudson.model.ProminentProjectAction;
import hudson.model.Run;
import hudson.tasks.junit.TestResult;
import hudson.tasks.junit.TestResultAction;
import hudson.tasks.test.TestResultProjectAction;
import hudson.util.ChartUtil;
import hudson.util.ColorPalette;
import hudson.util.DataSetBuilder;
import hudson.util.ShiftedCategoryAxis;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang.StringUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PerfSigProjectAction extends PerfSigBaseAction implements ProminentProjectAction {
    private final Job<?, ?> job;

    public PerfSigProjectAction(final Job<?, ?> job) {
        this.job = job;
    }

    @Override
    protected String getTitle() {
        return job.getDisplayName() + " PerfSig";
    }

    public Job<?, ?> getJob() {
        return job;
    }

    public TestResultProjectAction getTestResultProjectAction() {
        return job.getAction(TestResultProjectAction.class);
    }

    public Class getPerfSigUtils() {
        return PerfSigUtils.class;
    }

    public void doSummarizerGraph(final StaplerRequest request, final StaplerResponse response)
            throws IOException, InterruptedException {
        if (ChartUtil.awtProblemCause != null) {
            // not available. send out error message
            response.sendRedirect2(request.getContextPath() + "/images/headless.png");
            return;
        }

        final String id = request.getParameter("id");
        final JSONArray jsonArray = JSONArray.fromObject(getDashboardConfiguration());

        if (request.getParameterMap().get("customName") == null
                && request.getParameterMap().get("customBuildCount") == null) {
            for (int i = 0; i < jsonArray.size(); i++) {
                final JSONObject obj = jsonArray.getJSONObject(i);
                if (obj.getString("id").equals(id)) {
                    //for json version < 2.1 put a empty aggregation value to avoid missing json object
                    if (!obj.has("aggregation"))
                        obj.put("aggregation", "");
                    ChartUtil.generateGraph(request, response, createChart(obj, buildDataSet(obj)),
                            PerfSigUtils.calcDefaultSize());
                    return;
                }
            }
        } else {
            for (DashboardReport dashboardReport : getLastDashboardReports())
                for (ChartDashlet chartDashlet : dashboardReport.getChartDashlets())
                    for (Measure measure : chartDashlet.getMeasures())
                        if (id.equals(DigestUtils
                                .md5Hex(dashboardReport.getName() + chartDashlet.getName() + measure.getName()))) {
                            final JSONObject jsonObject = new JSONObject();
                            jsonObject.put("id", id);
                            jsonObject.put("dashboard", dashboardReport.getName());
                            jsonObject.put("chartDashlet", chartDashlet.getName());
                            jsonObject.put("measure", measure.getName());
                            jsonObject.put("customName", request.getParameter("customName"));
                            jsonObject.put("customBuildCount", request.getParameter("customBuildCount"));
                            jsonObject.put("aggregation", request.getParameter("aggregation"));

                            ChartUtil.generateGraph(request, response,
                                    createChart(jsonObject, buildDataSet(jsonObject)),
                                    PerfSigUtils.calcDefaultSize());
                            return;
                        }
        }
    }

    private CategoryDataset buildDataSet(final JSONObject jsonObject) throws IOException {
        String dashboard = jsonObject.getString("dashboard");
        String chartDashlet = jsonObject.getString("chartDashlet");
        String measure = jsonObject.getString("measure");
        String buildCount = jsonObject.getString("customBuildCount");
        String aggregation = jsonObject.getString("aggregation");
        int customBuildCount = 0, i = 0;

        if (StringUtils.isNotBlank(buildCount))
            customBuildCount = Integer.parseInt(buildCount);

        Map<Run<?, ?>, DashboardReport> dashboardReports = getDashBoardReports(dashboard);
        DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel> dsb = new DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel>();

        for (Map.Entry<Run<?, ?>, DashboardReport> dashboardReport : dashboardReports.entrySet()) {
            double metricValue = 0;
            if (dashboardReport.getValue().getChartDashlets() != null) {
                Measure m = dashboardReport.getValue().getMeasure(chartDashlet, measure);
                if (m != null)
                    metricValue = StringUtils.isBlank(aggregation) ? m.getMetricValue()
                            : m.getMetricValue(aggregation);
            }
            i++;
            dsb.add(metricValue, chartDashlet,
                    new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) dashboardReport.getKey()));
            if (customBuildCount != 0 && i == customBuildCount)
                break;
        }
        return dsb.build();
    }

    private JFreeChart createChart(final JSONObject jsonObject, final CategoryDataset dataset)
            throws UnsupportedEncodingException {
        final String measure = jsonObject.getString(Messages.PerfSigProjectAction_ReqParamMeasure());
        final String chartDashlet = jsonObject.getString("chartDashlet");
        final String testCase = jsonObject.getString("dashboard");
        final String customMeasureName = jsonObject.getString("customName");
        final String aggregation = jsonObject.getString("aggregation");

        String unit = "", color = Messages.PerfSigProjectAction_DefaultColor();

        for (DashboardReport dr : getLastDashboardReports()) {
            if (dr.getName().equals(testCase)) {
                final Measure m = dr.getMeasure(chartDashlet, measure);
                if (m != null) {
                    unit = aggregation.equalsIgnoreCase("Count") ? "num" : m.getUnit();
                    color = URLDecoder.decode(m.getColor(), "UTF-8");
                }
                break;
            }
        }

        String title = customMeasureName;
        if (StringUtils.isBlank(customMeasureName))
            title = PerfSigUtils.generateTitle(measure, chartDashlet);

        final JFreeChart chart = ChartFactory.createBarChart(title, // title
                "build", // category axis label
                unit, // value axis label
                dataset, // data
                PlotOrientation.VERTICAL, // orientation
                false, // include legend
                false, // tooltips
                false // urls
        );

        chart.setBackgroundPaint(Color.white);

        final CategoryPlot plot = chart.getCategoryPlot();

        plot.setBackgroundPaint(Color.WHITE);
        plot.setOutlinePaint(null);
        plot.setForegroundAlpha(0.8f);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.black);

        final CategoryAxis domainAxis = new ShiftedCategoryAxis(null);
        plot.setDomainAxis(domainAxis);
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
        //domainAxis.setLowerMargin(0.0);
        //domainAxis.setUpperMargin(0.0);
        //domainAxis.setCategoryMargin(0.0);

        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        final BarRenderer renderer = (BarRenderer) chart.getCategoryPlot().getRenderer();
        renderer.setSeriesPaint(0, Color.decode(color));

        return chart;
    }

    public void doTestRunGraph(final StaplerRequest request, final StaplerResponse response)
            throws IOException, InterruptedException {
        if (ChartUtil.awtProblemCause != null) {
            // not available. send out error message
            response.sendRedirect2(request.getContextPath() + "/images/headless.png");
            return;
        }

        //get customName and customBuildCount from persisted json
        if (request.getParameterMap().get("customName") == null
                && request.getParameterMap().get("customBuildCount") == null) {
            final JSONArray jsonArray = JSONArray.fromObject(getDashboardConfiguration());
            for (int i = 0; i < jsonArray.size(); i++) {
                final JSONObject obj = jsonArray.getJSONObject(i);
                if (obj.getString("id").equals("unittest_overview")) {
                    ChartUtil.generateGraph(request, response,
                            createTestRunChart(buildTestRunDataSet(obj.getString("customBuildCount")),
                                    obj.getString("customName")),
                            PerfSigUtils.calcDefaultSize());
                    return;
                }
            }
        } else { //generate test run graph with GET parameters
            ChartUtil.generateGraph(request, response,
                    createTestRunChart(buildTestRunDataSet(request.getParameter("customBuildCount")),
                            request.getParameter("customName")),
                    PerfSigUtils.calcDefaultSize());
        }
    }

    private CategoryDataset buildTestRunDataSet(final String customBuildCount) {
        final DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel> dsb = new DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel>();
        int buildCount = 0, i = 0;
        if (StringUtils.isNotBlank(customBuildCount))
            buildCount = Integer.parseInt(customBuildCount);

        for (Run<?, ?> run : job.getBuilds()) {
            PerfSigTestDataWrapper testDataWrapper = run.getAction(PerfSigTestDataWrapper.class);
            if (testDataWrapper != null && testDataWrapper.getTestRuns() != null) {
                TestRun testRun = TestRun.mergeTestRuns(testDataWrapper.getTestRuns());
                if (testRun != null) {
                    dsb.add(testRun.getNumFailed(), "failed",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                    dsb.add(testRun.getNumDegraded(), "degraded",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                    dsb.add(testRun.getNumImproved(), "improved",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                    dsb.add(testRun.getNumPassed(), "passed",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                    dsb.add(testRun.getNumVolatile(), "volatile",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                    dsb.add(testRun.getNumInvalidated(), "invalidated",
                            new ChartUtil.NumberOnlyBuildLabel((AbstractBuild<?, ?>) run));
                }
            }
            i++;
            if (buildCount != 0 && i == buildCount)
                break;
        }
        return dsb.build();
    }

    private JFreeChart createTestRunChart(final CategoryDataset dataset, final String customName) {
        String title = "UnitTest overview";
        if (StringUtils.isNotBlank(customName)) {
            title = customName;
        }

        final JFreeChart chart = ChartFactory.createBarChart(title, // title
                "build", // category axis label
                "num", // value axis label
                dataset, // data
                PlotOrientation.VERTICAL, // orientation
                true, // include legend
                true, // tooltips
                false // urls
        );

        chart.setBackgroundPaint(Color.white);

        final CategoryPlot plot = chart.getCategoryPlot();

        plot.setBackgroundPaint(Color.WHITE);
        plot.setOutlinePaint(null);
        plot.setForegroundAlpha(0.8f);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.black);

        final CategoryAxis domainAxis = new ShiftedCategoryAxis(null);
        plot.setDomainAxis(domainAxis);
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
        //domainAxis.setLowerMargin(0.0);
        //domainAxis.setUpperMargin(0.0);
        //domainAxis.setCategoryMargin(0.0);

        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        final StackedBarRenderer br = new StackedBarRenderer();
        plot.setRenderer(br);
        br.setSeriesPaint(0, new Color(0xFF, 0x99, 0x99)); // degraded
        br.setSeriesPaint(1, ColorPalette.RED); // failed
        br.setSeriesPaint(2, new Color(0x00, 0xFF, 0x00)); // improved
        br.setSeriesPaint(3, ColorPalette.GREY); // invalidated
        br.setSeriesPaint(4, ColorPalette.BLUE); // passed
        br.setSeriesPaint(5, ColorPalette.YELLOW); // volatile

        return chart;
    }

    public List<DashboardReport> getLastDashboardReports() {
        final Run<?, ?> tb = job.getLastSuccessfulBuild();

        Run<?, ?> b = job.getLastBuild();
        while (b != null) {
            PerfSigBuildAction a = b.getAction(PerfSigBuildAction.class);
            if (a != null && (!b.isBuilding()))
                return a.getDashboardReports();
            if (b == tb)
                return new ArrayList<DashboardReport>();
            b = b.getPreviousBuild();
        }
        return new ArrayList<DashboardReport>();
    }

    public TestRun getTestRun(final Run<?, ?> run) {
        if (run != null) {
            PerfSigTestDataWrapper testDataWrapper = run.getAction(PerfSigTestDataWrapper.class);
            if (testDataWrapper != null) {
                return TestRun.mergeTestRuns(testDataWrapper.getTestRuns());
            }
        }
        return null;
    }

    public TestResult getTestAction(final Run<?, ?> run) {
        if (run != null) {
            TestResultAction testResultAction = run.getAction(TestResultAction.class);
            if (testResultAction != null) {
                return testResultAction.getResult();
            }
        }
        return null;
    }

    public Map<Run<?, ?>, DashboardReport> getDashBoardReports(final String tc) {
        final Map<Run<?, ?>, DashboardReport> dashboardReports = new HashMap<Run<?, ?>, DashboardReport>();
        if (job == null) {
            return dashboardReports;
        }
        for (Run<?, ?> currentRun : job.getBuilds()) {
            final PerfSigBuildAction perfSigBuildAction = currentRun.getAction(PerfSigBuildAction.class);
            if (perfSigBuildAction != null) {
                DashboardReport dashboardReport = perfSigBuildAction.getBuildActionResultsDisplay()
                        .getDashBoardReport(tc);
                if (dashboardReport == null) {
                    dashboardReport = new DashboardReport(tc);
                }
                dashboardReports.put(currentRun, dashboardReport);
            }
        }
        return dashboardReports;
    }

    private FilePath getJsonConfigFilePath() {
        final FilePath configPath = new FilePath(job.getConfigFile().getFile());
        return configPath.getParent();
    }

    private String getDashboardConfiguration() throws IOException, InterruptedException {
        final List<FilePath> fileList = getJsonConfigFilePath().list(new RegexFileFilter("gridconfig-.*.json"));
        final StringBuilder sb = new StringBuilder("[");
        for (FilePath file : fileList) {
            final String tmp = file.readToString();
            sb.append(tmp.substring(1, tmp.length() - 1)).append(",");
        }
        sb.setLength(sb.length() - 1);
        sb.append("]");
        return sb.toString();
    }

    private String getDashboardConfiguration(final String dashboard) throws IOException, InterruptedException {
        final FilePath input = new FilePath(
                new File(getJsonConfigFilePath() + File.separator + "gridconfig-" + dashboard + ".json"));
        if (!input.exists())
            input.write(createJSONConfigString(dashboard), null);
        return input.readToString();
    }

    public void doGetDashboardConfiguration(final StaplerRequest request, final StaplerResponse response)
            throws IOException, InterruptedException {
        final String dashboard = request.getParameter("dashboard");
        if (StringUtils.isBlank(dashboard))
            return;
        String output = getDashboardConfiguration(dashboard);
        response.getOutputStream().print(output);
    }

    private String createJSONConfigString(final String dashboard) {
        int col = 1, row = 1;
        JSONArray array = new JSONArray();
        for (DashboardReport dashboardReport : getLastDashboardReports()) {
            if (!dashboardReport.getName().equals(dashboard))
                continue;
            if (dashboardReport.isUnitTest()) {
                JSONObject obj = new JSONObject();
                obj.put("id", "unittest_overview");
                obj.put("col", col++);
                obj.put("row", row);
                obj.put("dashboard", dashboardReport.getName());
                obj.put("chartDashlet", "");
                obj.put("measure", "");
                obj.put("show", true);
                obj.put("customName", "");
                obj.put("customBuildCount", 0);

                array.add(obj);
            }
            for (ChartDashlet chartDashlet : dashboardReport.getChartDashlets()) {
                for (Measure measure : chartDashlet.getMeasures()) {
                    JSONObject obj = new JSONObject();
                    obj.put("id", DigestUtils
                            .md5Hex(dashboardReport.getName() + chartDashlet.getName() + measure.getName()));
                    obj.put("col", col++);
                    obj.put("row", row);
                    obj.put("dashboard", dashboardReport.getName());
                    obj.put("chartDashlet", chartDashlet.getName());
                    obj.put("measure", measure.getName());
                    obj.put("description", chartDashlet.getDescription());
                    obj.put("show", true);
                    obj.put("aggregation", measure.getAggregation());
                    obj.put("customName", "");
                    obj.put("customBuildCount", 0);

                    array.add(obj);

                    if (col > 3) {
                        col = 1;
                        row++;
                    }
                }
            }
        }
        return array.toString();
    }

    public void doSetDashboardConfiguration(final StaplerRequest request, final StaplerResponse response) {
        final String dashboard = request.getParameter("dashboard");
        final String data = request.getParameter("data");
        if (StringUtils.isBlank(dashboard) || StringUtils.isBlank("data"))
            return;

        final Map<String, MeasureNameHelper> map = new HashMap<String, MeasureNameHelper>();
        //generate a map to link between id and chartname
        for (DashboardReport dashboardReport : getLastDashboardReports())
            if (dashboardReport.getName().equals(dashboard))
                for (ChartDashlet chartDashlet : dashboardReport.getChartDashlets())
                    for (Measure measure : chartDashlet.getMeasures())
                        map.put(DigestUtils
                                .md5Hex(dashboardReport.getName() + chartDashlet.getName() + measure.getName()),
                                new MeasureNameHelper(chartDashlet.getName(), measure.getName(),
                                        chartDashlet.getDescription()));

        try {
            final JSONArray gridConfiguration = JSONArray.fromObject(data);
            final JSONArray dashboardConfiguration = JSONArray.fromObject(getDashboardConfiguration(dashboard));
            //go through all configured grid items
            for (int i = 0; i < gridConfiguration.size(); i++) {
                final JSONObject obj = gridConfiguration.getJSONObject(i);
                final MeasureNameHelper tmp = map.get(obj.getString("id"));
                if (tmp != null) { //item needs some more information
                    obj.put("id", DigestUtils.md5Hex(
                            dashboard + tmp.getChartDashlet() + tmp.getMeasure() + obj.getString("customName")));
                    obj.put("chartDashlet", tmp.getChartDashlet());
                    obj.put("measure", tmp.getMeasure());
                    obj.put("description", tmp.getDescription());
                } else {
                    //items with custom names need some more information
                    for (int j = 0; j < dashboardConfiguration.size(); j++) {
                        final JSONObject jsonObject = dashboardConfiguration.getJSONObject(j);
                        if (jsonObject.get("id").equals(obj.get("id"))) {
                            if (!obj.get("id").equals("unittest_overview")) {
                                obj.put("dashboard", jsonObject.get("dashboard"));
                                obj.put("chartDashlet", jsonObject.get("chartDashlet"));
                                obj.put("measure", jsonObject.get("measure"));
                                obj.put("description", jsonObject.get("description"));
                                obj.put("aggregation", jsonObject.get("aggregation"));
                            }
                            if (StringUtils.isNotBlank(jsonObject.getString("customName")))
                                obj.put("customName", jsonObject.get("customName"));
                            if (StringUtils.isNotBlank(jsonObject.getString("customBuildCount")))
                                obj.put("customBuildCount", jsonObject.get("customBuildCount"));
                            break;
                        }
                    }
                }
            }

            FilePath output = new FilePath(
                    new File(getJsonConfigFilePath() + File.separator + "gridconfig-" + dashboard + ".json"));
            output.write(gridConfiguration.toString(), null);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doGetAvailableMeasures(final StaplerRequest request, final StaplerResponse response)
            throws IOException {
        final String dashboard = request.getParameter("dashboard");
        final String dashlet = request.getParameter("dashlet");
        if (StringUtils.isBlank(dashboard) || StringUtils.isBlank(dashlet))
            return;

        final Map<String, String> availableMeasures = new HashMap<String, String>();
        if (StringUtils.isNotBlank(dashlet)) {
            mainLoop: for (DashboardReport dashboardReport : getLastDashboardReports()) {
                if (dashboardReport.getName().equals(dashboard)) {
                    for (ChartDashlet chartDashlet : dashboardReport.getChartDashlets()) {
                        if (chartDashlet.getName().equals(dashlet)) {
                            for (Measure measure : chartDashlet.getMeasures())
                                availableMeasures.put(DigestUtils.md5Hex(
                                        dashboardReport.getName() + chartDashlet.getName() + measure.getName()),
                                        measure.getName());
                            break mainLoop;
                        }
                    }
                }
            }
        }
        JSONObject jsonObject = JSONObject.fromObject(availableMeasures);
        jsonObject.write(response.getWriter());
        response.flushBuffer();
    }

    public void doGetAggregationFromMeasure(final StaplerRequest request, final StaplerResponse response)
            throws IOException {
        final String dashboard = request.getParameter("dashboard");
        final String dashlet = request.getParameter("dashlet");
        final String measure = request.getParameter("measure");

        for (DashboardReport dashboardReport : getLastDashboardReports()) {
            if (dashboardReport.getName().equals(dashboard)) {
                for (ChartDashlet chartDashlet : dashboardReport.getChartDashlets()) {
                    if (chartDashlet.getName().equals(dashlet)) {
                        for (Measure m : chartDashlet.getMeasures())
                            if (m.getName().equals(measure)) {
                                response.getWriter().write(m.getAggregation());
                                return;
                            }
                    }
                }
            }
        }
    }

    //ToDo: provide fix to handle new, renamed or deleted measures
    public List<ChartDashlet> getFilteredChartDashlets(final DashboardReport dashboardReport)
            throws IOException, InterruptedException {
        final List<ChartDashlet> chartDashlets = new ArrayList<ChartDashlet>();
        final String json = getDashboardConfiguration(dashboardReport.getName());
        if (StringUtils.isBlank(json) || dashboardReport.getChartDashlets() == null)
            return chartDashlets;
        final JSONArray jsonArray = JSONArray.fromObject(json);

        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject obj = jsonArray.getJSONObject(i);
            String chartDashlet = obj.getString("chartDashlet");
            String measure = obj.getString("measure");

            for (ChartDashlet dashlet : dashboardReport.getChartDashlets()) {
                if (dashlet.getName().equals(chartDashlet)) {
                    for (Measure m : dashlet.getMeasures()) {
                        if (m.getName().equals(measure)) {
                            ChartDashlet d;
                            if (StringUtils.isBlank(obj.getString("customName")))
                                d = new ChartDashlet(PerfSigUtils.generateTitle(m.getName(), dashlet.getName()));
                            else
                                d = new ChartDashlet(obj.getString("customName"));
                            d.addMeasure(m);
                            chartDashlets.add(d);
                            break;
                        }
                    }
                }
            }
        }
        return chartDashlets;
    }
}