/******************************************************************************* * Copyright 2014 Miami-Dade County * * 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 cirmlive; import java.text.DateFormat; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.scene.chart.PieChart; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; import javafx.scene.control.Dialog; import javafx.scene.input.MouseEvent; import org.sharegov.cirm.stats.CirmStatistics; import org.sharegov.cirm.utils.JsonUtil; /** * Manages a FX piechart for CirmStats data display. * * @author Thomas Hilpold */ public class CirmPieChart { enum SHOW_DATA {TOTAL, SUCCESS, FAILURE}; private ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(); private String title; private PieChart chart; private Map<String, CirmStatistics.StatsValue> pieChartDataDetail = new HashMap<>(); public CirmPieChart() { chart = new PieChart(pieChartData); chart.setTitle("Please select data"); pieChartData.add(new PieChart.Data("Zero results", 100)); chart.setStartAngle(90); } public PieChart getChart() { return chart; } /** * Updates pieChartData for the piechart, piechart will draw itself. * @param statsKeyValMap * @param componentFilter * @param actionFilter * @param dataFilter * @param showData */ public void updateData(TreeMap<CirmStatistics.StatsKey, CirmStatistics.StatsValue> statsKeyValMap, String componentFilter, String actionFilter, SHOW_DATA showData){ long totalCount = 0; long successCount = 0; long failedCount = 0; Date earlierst = new Date(); TreeSet<PieChart.Data> newData = new TreeSet<>(new CirmPieDataComparator()); pieChartDataDetail.clear(); for (Map.Entry<CirmStatistics.StatsKey, CirmStatistics.StatsValue> keyVal : statsKeyValMap.entrySet()) { CirmStatistics.StatsKey key = keyVal.getKey(); CirmStatistics.StatsValue val = keyVal.getValue(); String type = key.gettype(); if (earlierst.after(val.getFirstEntryTime())) earlierst = val.getFirstEntryTime(); if (type.startsWith("legacy:")) type = type.substring("legacy:".length()); if (componentFilter.equals(key.getComponent()) && actionFilter.equals(key.getAction()) || componentFilter.equals(CirmStatistics.ALL) && actionFilter.equals(key.getAction()) || componentFilter.equals(key.getComponent()) && actionFilter.equals(CirmStatistics.ALL) || componentFilter.equals(CirmStatistics.ALL) && actionFilter.equals(CirmStatistics.ALL)) { long value = 0; if (showData.equals(SHOW_DATA.TOTAL)) { value = val.getSuccessCount() + val.getFailureCount(); } else if (showData.equals(SHOW_DATA.SUCCESS)) { value = val.getSuccessCount(); } else if (showData.equals(SHOW_DATA.FAILURE)) { value = val.getFailureCount(); } else { throw new IllegalArgumentException("SHOW_DATA was " + showData); } totalCount += (val.getSuccessCount() + val.getFailureCount()); successCount += val.getSuccessCount(); failedCount += val.getFailureCount(); if(value > 0) { String chartKey = value + "-" + type; newData.add(new PieChart.Data(chartKey, value)); pieChartDataDetail.put(chartKey, val); } } else { //action does not match dataFilter } } // for double failedPercent = totalCount == 0? 0 : ((failedCount * 100 * 100) / totalCount)/ 100.0; String failed = "Failed: " + failedCount + " (" + failedPercent + "%)"; DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); String titleSuffix; if (showData.equals(SHOW_DATA.TOTAL)) { titleSuffix = "\r\n Total : " + totalCount + " / " + failed + " since " + df.format(earlierst); } else if (showData.equals(SHOW_DATA.SUCCESS)) { titleSuffix = "\r\n Success : " + successCount + " / " + failed + " since " + df.format(earlierst); } else { titleSuffix = "\r\n " + failed + " since " + df.format(earlierst); } chart.setTitle(chart.getTitle() + titleSuffix); //sort newdata desc pieChartData.clear(); if (newData.isEmpty()) { pieChartData.add(new PieChart.Data("No data to display", 1)); } else { pieChartData.addAll(newData); // for (PieChart.Data d : newData) { // pieChartData.add(d); // } } setInteraction(); } public void setTitle(String title, Date d) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); String dateInTitle = "\r\n(" + df.format(d) + ")"; chart.setTitle(title + dateInTitle); } /** * use if data is diff * @param title * @param from * @param to */ public void setTitle(String title, Date from, Date to) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); String dateInTitle = "\r\n(" + df.format(from) + " to " + df.format(to) + ")"; chart.setTitle(title + dateInTitle); } /** * To display the data ordered large pie to small pie. */ public static class CirmPieDataComparator implements Comparator<PieChart.Data> { @Override public int compare(PieChart.Data o1, PieChart.Data o2) { int result = -Double.compare(o1.getPieValue(), o2.getPieValue()); if (result == 0) { result = o1.getName().compareTo(o2.getName()); } if (result == 0) { result = Long.compare(o1.hashCode(), o2.hashCode()); } return result; } } /** * Just a test for piechart clicks. */ public void setInteraction() { // caption.setTextFill(Color.DARKORANGE); // caption.setStyle("-fx-font: 24 arial;"); for (final PieChart.Data data : chart.getData()) { data.getNode().addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent e) { Dialog dataDlg = new Dialog(); dataDlg.setTitle(data.getName()); String contentText; if (pieChartDataDetail.containsKey(data.getName())) { contentText = JsonUtil.format(pieChartDataDetail.get(data.getName()).toJson()); } else { contentText = "No Data to display"; } dataDlg.getDialogPane().setContentText(contentText); ButtonType okButtonType = new ButtonType("Ok", ButtonBar.ButtonData.OK_DONE); dataDlg.getDialogPane().getButtonTypes().add(okButtonType); dataDlg.setResizable(true); dataDlg.show(); //data.setName("Selected"); } }); } } }