1 20 package org.openi.chart; 21 22 import com.tonbeller.jpivot.chart.ChartComponent; 23 import com.tonbeller.jpivot.core.ModelChangeEvent; 24 import com.tonbeller.jpivot.core.ModelChangeListener; 25 import com.tonbeller.jpivot.olap.model.Cell; 26 import com.tonbeller.jpivot.olap.model.OlapException; 27 import com.tonbeller.jpivot.olap.model.OlapModel; 28 import com.tonbeller.jpivot.olap.model.Result; 29 import com.tonbeller.jpivot.olap.navi.DrillThrough; 30 31 import com.tonbeller.wcf.component.Component; 32 import com.tonbeller.wcf.controller.Dispatcher; 33 import com.tonbeller.wcf.controller.DispatcherSupport; 34 import com.tonbeller.wcf.controller.RequestContext; 35 import com.tonbeller.wcf.controller.RequestListener; 36 import com.tonbeller.wcf.table.ITableComponent; 37 import com.tonbeller.wcf.table.TableModel; 38 import com.tonbeller.wcf.utils.DomUtils; 39 import com.tonbeller.wcf.utils.XmlUtils; 40 41 import org.apache.log4j.Logger; 42 43 import org.jfree.chart.ChartRenderingInfo; 44 import org.jfree.chart.JFreeChart; 45 import org.jfree.chart.Legend; 46 import org.jfree.chart.StandardLegend; 47 import org.jfree.chart.axis.DateAxis; 48 import org.jfree.chart.entity.ChartEntity; 49 import org.jfree.chart.entity.EntityCollection; 50 import org.jfree.chart.entity.StandardEntityCollection; 51 import org.jfree.chart.plot.PlotOrientation; 52 import org.jfree.chart.plot.XYPlot; 53 import org.jfree.chart.renderer.xy.StandardXYItemRenderer; 54 import org.jfree.chart.renderer.xy.XYItemRenderer; 55 import org.jfree.chart.servlet.ServletUtilities; 56 import org.jfree.chart.title.Title; 57 import org.jfree.chart.urls.CategoryURLGenerator; 58 import org.jfree.chart.urls.StandardCategoryURLGenerator; 59 import org.jfree.chart.urls.StandardPieURLGenerator; 60 61 import org.jfree.data.category.CategoryDataset; 62 import org.jfree.data.category.DefaultCategoryDataset; 63 import org.jfree.data.general.PieDataset; 64 import org.jfree.data.xy.XYDataset; 65 66 import org.jfree.ui.Spacer; 67 68 import org.jfree.util.TableOrder; 69 70 import org.openi.xmla.DatasetAdapter; 71 72 import org.w3c.dom.Document ; 73 import org.w3c.dom.Element ; 74 75 import java.awt.Color ; 76 import java.awt.Font ; 77 import java.awt.Paint ; 78 79 import java.io.ByteArrayInputStream ; 80 import java.io.InputStream ; 81 82 import java.text.SimpleDateFormat ; 83 84 import java.util.Iterator ; 85 import java.util.List ; 86 import java.util.Locale ; 87 88 import javax.servlet.http.HttpSession ; 89 90 import javax.xml.parsers.DocumentBuilder ; 91 92 93 99 public class EnhancedChartComponent extends ChartComponent 100 implements ModelChangeListener { 101 private static Logger logger = Logger.getLogger(EnhancedChartComponent.class); 102 protected String ref; 103 protected Document document; 104 protected OlapModel olapModel; 105 protected boolean dirty = true; 106 protected Locale locale; 107 108 protected Element rootElement; 112 protected int colCount; 113 114 protected String CHART_SERVLET = "/DisplayChart"; 118 final String CHART_SERVLET_KEY = "chartServlet"; 119 protected String filename = null; 120 121 public static final int DEFAULT_CHART_WIDTH = 500; 123 public static final int DEFAULT_CHART_HEIGHT = 300; 124 final static double DEFAULT_LEGEND_WIDTH = 100.0; 125 protected String chartTitle = ""; 126 protected java.awt.Font titleFont = JFreeChart.DEFAULT_TITLE_FONT; 127 protected String fontName = "SansSerif"; 128 protected int fontStyle = java.awt.Font.BOLD; 129 protected int fontSize = 18; 130 protected String slicerFontName = "SansSerif"; 131 protected int slicerFontStyle = java.awt.Font.PLAIN; 132 protected int slicerFontSize = 12; 133 protected String axisFontName = "SansSerif"; 134 protected int axisFontStyle = java.awt.Font.PLAIN; 135 protected int axisFontSize = 12; 136 protected String axisTickFontName = "SansSerif"; 137 protected int axisTickFontStyle = java.awt.Font.PLAIN; 138 protected int axisTickFontSize = 10; 139 protected String legendFontName = "SansSerif"; 140 protected int legendFontStyle = java.awt.Font.PLAIN; 141 protected int legendFontSize = 10; 142 protected int legendPosition = Legend.EAST; 143 protected int slicerPosition = Title.BOTTOM; 144 protected int slicerAlignment = Title.CENTER; 145 146 protected int bgColorR = 255; 148 protected int bgColorG = 255; 149 protected int bgColorB = 255; 150 protected int chartType = 1; 151 protected int chartHeight = DEFAULT_CHART_HEIGHT; 152 protected int chartWidth = DEFAULT_CHART_WIDTH; 153 protected String horizAxisLabel = ""; 154 protected String vertAxisLabel = ""; 155 protected boolean showLegend = true; 156 protected boolean showSlicer = true; 157 protected boolean showTooltips = true; 158 protected boolean drillThroughEnabled = true; 159 protected int tickLabelRotate = 30; protected ChartRenderingInfo info = null; 161 protected Dispatcher dispatcher = new DispatcherSupport(); 162 protected List colorPalette; 163 164 168 protected double foregroundAlpha = 1.0; 169 protected boolean showPareto = false; 170 protected boolean useChartSize = false; private boolean rangeIsPercentage = true; 172 private boolean rangeIsCurrency = true; 173 private boolean rangeIsDefault = true; 174 private boolean writeImageMap = true; 175 176 181 public EnhancedChartComponent(String id, Component parent, String ref, 182 RequestContext context) { 183 super(id, parent, ref, context); 184 this.ref = ref; 185 this.olapModel = (OlapModel) context.getModelReference(ref); 186 this.olapModel.addModelChangeListener(this); 187 this.locale = context.getLocale(); 188 189 getDispatcher().addRequestListener(null, null, dispatcher); 191 192 String chartServlet = context.getServletContext() 194 .getInitParameter(CHART_SERVLET_KEY); 195 196 if (chartServlet != null) { 197 this.CHART_SERVLET = chartServlet; 198 } 199 } 200 201 204 public void initialize(RequestContext context) throws Exception { 205 super.initialize(context); 206 } 207 208 215 public Document render(RequestContext context) throws Exception { 216 if (dirty) { 218 dispatcher.clear(); 220 rangeIsPercentage = false; 224 rangeIsCurrency = false; 225 rangeIsDefault = false; 226 227 228 dirty = false; 230 231 try { 233 logger.debug("trying to build axis labels"); 234 235 AxisLabelGenerator axisLabeller = new AxisLabelGenerator(); 236 this.setHorizAxisLabel(axisLabeller.getHorizAxisLabel( 237 this.getOlapModel())); 238 this.setVertAxisLabel(axisLabeller.getVertAxisLabel( 239 this.getOlapModel())); 240 } catch (Exception e) { 241 logger.error("Error generating axis label:\n" + e); 242 } 243 245 JFreeChart chart = EnhancedChartFactory.createChart(olapModel, 246 chartType, chartTitle, 247 horizAxisLabel, vertAxisLabel, 248 showLegend, showTooltips, 249 drillThroughEnabled, titleFont, 250 new Color (this.getBgColorR(), this.getBgColorG(), this.getBgColorB()), 251 new Font (this.getSlicerFontName(), this.getSlicerFontStyle(), this.getSlicerFontSize()), 252 new Font (this.getAxisFontName(), this.getAxisFontStyle(), this.getAxisFontSize()), 253 new Font (this.getAxisTickFontName(), this.getAxisTickFontStyle(), this.getAxisTickFontSize()), 254 new Font (this.getLegendFontName(), this.getLegendFontStyle(), this.getLegendFontSize()), 255 legendPosition, 256 tickLabelRotate, 257 1.0f, 258 showSlicer, 259 slicerPosition, 260 slicerAlignment, 261 showPareto, this.getLocale()); 262 263 try { 264 268 269 270 info = new ChartRenderingInfo(new StandardEntityCollection()); 271 272 HttpSession session = context.getSession(); 274 filename = ServletUtilities.saveChartAsPNG(chart, chartWidth, 275 chartHeight, info, session); 276 } catch (Exception e) { 277 logger.error(e); 278 filename = "public_error_500x300.png"; 279 dirty = true; 280 } 281 } 282 283 DocumentBuilder parser = XmlUtils.getParser(); 285 286 String xchart = null; 289 290 if (this.getWriteImageMap()) { 292 xchart = "<xchart>" + writeImageMap(filename, info, false) + 293 "</xchart>"; 294 } else { 295 xchart = "<xchart/>"; 296 } 297 298 InputStream stream = new ByteArrayInputStream (xchart.getBytes("UTF-8")); 300 301 document = parser.parse(stream); 302 303 Element root = document.getDocumentElement(); 304 305 String graphURL = context.getRequest().getContextPath() + 307 CHART_SERVLET + "?filename=" + filename; 308 Element img = document.createElement("img"); 309 img.setAttribute("src", graphURL); 310 img.setAttribute("width", new Integer (chartWidth).toString()); 311 img.setAttribute("height", new Integer (chartHeight).toString()); 312 img.setAttribute("style", "border:0;"); 313 img.setAttribute("usemap", "#" + filename); 314 root.appendChild(img); 315 316 return document; 317 } 318 319 320 321 322 323 335 public String writeImageMap(String name, ChartRenderingInfo info, 336 boolean useOverLibForToolTips) { 337 StringBuffer sb = new StringBuffer (); 338 sb.append("<map name=\"" + name + "\">"); 339 340 EntityCollection entities = info.getEntityCollection(); 341 Iterator iterator = entities.iterator(); 342 343 while (iterator.hasNext()) { 344 ChartEntity entity = (ChartEntity) iterator.next(); 345 346 String area = ""; 349 350 if (useOverLibForToolTips) { 352 area = entity.getImageMapAreaTag(new org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator(), 353 new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator()); 354 } else { 355 area = entity.getImageMapAreaTag(new org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator(), 356 new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator()); 357 } 358 359 area = area.replaceAll("&", "&"); 361 362 area = area.replaceAll(">$", "/>"); 364 365 if (area.length() > 0) { 368 sb.append(area); 369 } 370 } 371 372 sb.append("</map>"); 373 374 return sb.toString(); 375 } 376 377 380 public int getColCount() { 381 return colCount; 382 } 383 384 387 public boolean isDirty() { 388 return dirty; 389 } 390 391 public void setDirty(boolean dirty) { 392 this.dirty = dirty; 393 } 394 395 public void modelChanged(ModelChangeEvent e) { 396 this.dirty = true; 397 } 398 399 public void structureChanged(ModelChangeEvent e) { 400 this.dirty = true; 401 } 402 403 406 public int getChartHeight() { 407 return chartHeight; 408 } 409 410 413 public void setChartHeight(int chartHeight) { 414 this.chartHeight = chartHeight; 415 this.dirty = true; 416 } 417 418 421 public String getChartTitle() { 422 return chartTitle; 423 } 424 425 428 public void setChartTitle(String chartTitle) { 429 this.chartTitle = chartTitle; 430 this.dirty = true; 431 } 432 433 436 public int getChartType() { 437 return chartType; 438 } 439 440 443 public void setChartType(int chartType) { 444 this.chartType = chartType; 445 this.dirty = true; 446 } 447 448 451 public int getChartWidth() { 452 return chartWidth; 453 } 454 455 458 public void setChartWidth(int chartWidth) { 459 this.chartWidth = chartWidth; 460 this.dirty = true; 461 } 462 463 466 public String getHorizAxisLabel() { 467 return horizAxisLabel; 468 } 469 470 473 public void setHorizAxisLabel(String axisLabel) { 474 horizAxisLabel = axisLabel; 475 this.dirty = true; 476 } 477 478 481 public boolean getShowLegend() { 482 return showLegend; 483 } 484 485 488 public void setShowLegend(boolean showLegend) { 489 this.showLegend = showLegend; 490 this.dirty = true; 491 } 492 493 496 public String getFontName() { 497 return fontName; 498 } 499 500 503 public void setFontName(String fontname) { 504 this.fontName = fontname; 505 this.dirty = true; 506 } 507 508 511 public String getVertAxisLabel() { 512 return vertAxisLabel; 513 } 514 515 518 public void setVertAxisLabel(String axisLabel) { 519 vertAxisLabel = axisLabel; 520 this.dirty = true; 521 } 522 523 526 public int getFontSize() { 527 return fontSize; 528 } 529 530 533 public void setFontSize(int fontSize) { 534 this.fontSize = fontSize; 535 this.dirty = true; 536 } 537 538 541 public int getFontStyle() { 542 return fontStyle; 543 } 544 545 548 public void setFontStyle(int fontStyle) { 549 this.fontStyle = fontStyle; 550 this.dirty = true; 551 } 552 553 556 public int getBgColorB() { 557 return bgColorB; 558 } 559 560 563 public void setBgColorB(int bgColorB) { 564 this.bgColorB = checkRGB(bgColorB); 565 this.dirty = true; 566 } 567 568 571 public int getBgColorG() { 572 return bgColorG; 573 } 574 575 578 public void setBgColorG(int bgColorG) { 579 this.bgColorG = checkRGB(bgColorG); 580 this.dirty = true; 581 } 582 583 586 public int getBgColorR() { 587 return bgColorR; 588 } 589 590 593 public void setBgColorR(int bgColorR) { 594 this.bgColorR = checkRGB(bgColorR); 595 this.dirty = true; 596 } 597 598 601 private int checkRGB(int v) { 602 if (v > 255) { 603 v = 255; 604 } else if (v < 0) { 605 v = 0; 606 } 607 608 return v; 609 } 610 611 protected boolean canDrillThrough(Cell cell) { 612 return ((DrillThrough) olapModel.getExtension(DrillThrough.ID)).canDrillThrough((Cell) cell.getRootDecoree()); 613 } 614 615 620 protected TableModel drillThrough(Cell cell) { 621 return ((DrillThrough) olapModel.getExtension(DrillThrough.ID)).drillThrough((Cell) cell.getRootDecoree()); 622 } 623 624 public boolean isDrillThroughEnabled() { 625 return drillThroughEnabled; 626 } 627 628 public void setDrillThroughEnabled(boolean drillThroughEnabled) { 629 this.drillThroughEnabled = drillThroughEnabled; 630 } 631 632 635 public String getAxisFontName() { 636 return axisFontName; 637 } 638 639 642 public void setAxisFontName(String axisFontName) { 643 this.axisFontName = axisFontName; 644 } 645 646 649 public int getAxisFontSize() { 650 return axisFontSize; 651 } 652 653 656 public void setAxisFontSize(int axisFontSize) { 657 this.axisFontSize = axisFontSize; 658 } 659 660 663 public int getAxisFontStyle() { 664 return axisFontStyle; 665 } 666 667 670 public void setAxisFontStyle(int axisFontStyle) { 671 this.axisFontStyle = axisFontStyle; 672 } 673 674 677 public String getLegendFontName() { 678 return legendFontName; 679 } 680 681 684 public void setLegendFontName(String legendFontName) { 685 this.legendFontName = legendFontName; 686 } 687 688 691 public int getLegendFontSize() { 692 return legendFontSize; 693 } 694 695 698 public void setLegendFontSize(int legendFontSize) { 699 this.legendFontSize = legendFontSize; 700 } 701 702 705 public int getLegendFontStyle() { 706 return legendFontStyle; 707 } 708 709 712 public void setLegendFontStyle(int legendFontStyle) { 713 this.legendFontStyle = legendFontStyle; 714 } 715 716 719 public int getSlicerAlignment() { 720 return slicerAlignment; 721 } 722 723 726 public void setSlicerAlignment(int slicerAlignment) { 727 this.slicerAlignment = slicerAlignment; 728 } 729 730 733 public String getSlicerFontName() { 734 return slicerFontName; 735 } 736 737 740 public void setSlicerFontName(String slicerFontName) { 741 this.slicerFontName = slicerFontName; 742 } 743 744 747 public int getSlicerFontSize() { 748 return slicerFontSize; 749 } 750 751 754 public void setSlicerFontSize(int slicerFontSize) { 755 this.slicerFontSize = slicerFontSize; 756 } 757 758 761 public int getSlicerFontStyle() { 762 return slicerFontStyle; 763 } 764 765 768 public void setSlicerFontStyle(int slicerFontStyle) { 769 this.slicerFontStyle = slicerFontStyle; 770 } 771 772 775 public int getSlicerPosition() { 776 return slicerPosition; 777 } 778 779 782 public void setSlicerPosition(int slicerPosition) { 783 this.slicerPosition = slicerPosition; 784 } 785 786 789 public int getLegendPosition() { 790 return legendPosition; 791 } 792 793 796 public void setLegendPosition(int legendPosition) { 797 this.legendPosition = legendPosition; 798 } 799 800 803 public String getAxisTickFontName() { 804 return axisTickFontName; 805 } 806 807 810 public void setAxisTickFontName(String axisTickFontName) { 811 this.axisTickFontName = axisTickFontName; 812 } 813 814 817 public int getAxisTickFontSize() { 818 return axisTickFontSize; 819 } 820 821 824 public void setAxisTickFontSize(int axisTickFontSize) { 825 this.axisTickFontSize = axisTickFontSize; 826 } 827 828 831 public int getAxisTickFontStyle() { 832 return axisTickFontStyle; 833 } 834 835 838 public void setAxisTickFontStyle(int axisTickFontStyle) { 839 this.axisTickFontStyle = axisTickFontStyle; 840 } 841 842 845 public int getTickLabelRotate() { 846 return tickLabelRotate; 847 } 848 849 852 public void setTickLabelRotate(int tickLabelRotate) { 853 this.tickLabelRotate = tickLabelRotate; 854 } 855 856 859 public boolean isShowSlicer() { 860 return showSlicer; 861 } 862 863 866 public void setShowSlicer(boolean showSlicer) { 867 this.showSlicer = showSlicer; 868 } 869 870 873 public String getFilename() { 874 return filename; 875 } 876 877 880 public List getColorPalette() { 881 return colorPalette; 882 } 883 884 887 public void setColorPalette(List seriesPalette) { 888 this.colorPalette = seriesPalette; 889 } 890 891 894 public boolean getShowPareto() { 895 return showPareto; 896 } 897 898 public double getForegroundAlpha() { 899 return foregroundAlpha; 900 } 901 902 public boolean isUseChartSize() { 903 return useChartSize; 904 } 905 906 909 public void setShowPareto(boolean showPareto) { 910 this.showPareto = showPareto; 911 } 912 913 public void setForegroundAlpha(double foregroundAlpha) { 914 this.foregroundAlpha = foregroundAlpha; 915 } 916 917 public void setUseChartSize(boolean useChartSize) { 918 this.useChartSize = useChartSize; 919 } 920 921 924 public boolean getWriteImageMap() { 925 return writeImageMap; 926 } 927 928 931 public void setWriteImageMap(boolean writeImageMap) { 932 this.writeImageMap = writeImageMap; 933 } 934 935 public OlapModel getOlapModel() { 936 return olapModel; 937 } 938 939 public void setOlapModel(OlapModel olapModel) { 940 this.olapModel = olapModel; 941 } 942 943 948 public class jpivotPieURLGenerator extends StandardPieURLGenerator { 949 950 private String prefix = ""; 951 private List cells = null; 952 private int rowCount; 953 private TableOrder order; 955 jpivotPieURLGenerator(Result result) { 956 cells = result.getCells(); 957 } 958 959 jpivotPieURLGenerator(String prefix) { 960 this.prefix = prefix; 961 } 962 963 967 jpivotPieURLGenerator(TableOrder order, DefaultCategoryDataset dataset) { 968 this.order = order; 969 this.rowCount = dataset.getRowCount(); 970 } 971 972 984 public String generateURL(PieDataset data, Comparable key, int pieIndex) { 985 String url = prefix; 986 int index = data.getIndex(key); 987 988 int cellpos; 989 990 if (cells == null) { 992 try { 993 cells = olapModel.getResult().getCells(); 994 } catch (Exception e) { 995 logger.error(e); 996 } 997 } 998 999 if (order == TableOrder.BY_COLUMN) { 1000 cellpos = (pieIndex * rowCount) + index; 1001 } else { 1002 cellpos = pieIndex + (rowCount * index); 1003 } 1004 1005 if (canDrillThrough((Cell) cells.get(cellpos)) && 1006 (!((Cell) cells.get(cellpos)).isNull())) { 1007 String id = DomUtils.randomId(); 1008 dispatcher.addRequestListener(id, null, 1009 new DrillThroughHandler((Cell) cells.get(cellpos))); 1010 1011 boolean firstParameter = url.indexOf("?") == -1; 1012 url += (firstParameter ? "?" : "&"); 1013 url += id; 1014 1015 return url; 1016 } else { 1017 return null; 1018 } 1019 } 1020 } 1021 1022 1027 public class jpivotCategoryURLGenerator extends StandardCategoryURLGenerator { 1028 1029 private String prefix = ""; 1030 1031 1032 private String seriesParameterName = "col"; 1033 1034 1035 private String categoryParameterName = "row"; 1036 private List cells = null; 1037 1038 jpivotCategoryURLGenerator(Result result) { 1039 cells = result.getCells(); 1040 } 1041 1042 jpivotCategoryURLGenerator(Result result, String prefix) { 1043 this.prefix = prefix; 1044 cells = result.getCells(); 1045 } 1046 1047 1059 public String generateURL(CategoryDataset data, int series, int category) { 1060 String url = prefix; 1061 1062 int cellpos = (category * colCount) + series; 1066 1067 if (canDrillThrough((Cell) cells.get(cellpos)) && 1068 (!((Cell) cells.get(cellpos)).isNull())) { 1069 String id = DomUtils.randomId(); 1070 dispatcher.addRequestListener(id, null, 1071 new DrillThroughHandler((Cell) cells.get(cellpos))); 1072 1073 boolean firstParameter = url.indexOf("?") == -1; 1074 url += (firstParameter ? "?" : "&"); 1075 url += id; 1076 1077 return url; 1078 } else { 1079 return null; 1080 } 1081 } 1082 } 1083 1084 1090 1091 class DrillThroughHandler implements RequestListener { 1119 Cell cell; 1120 1121 DrillThroughHandler(Cell cell) { 1122 this.cell = cell; 1123 } 1124 1125 public void request(RequestContext context) throws Exception { 1126 if (canDrillThrough(cell)) { 1127 HttpSession session = context.getSession(); 1128 final String drillTableRef = olapModel.getID() + 1129 ".drillthroughtable"; 1130 ITableComponent tc = (ITableComponent) session.getAttribute(drillTableRef); 1131 1132 TableModel tm = drillThrough(cell); 1134 tc.setModel(tm); 1135 tc.setVisible(true); 1136 } 1137 } 1138 } 1139} 1140 | Popular Tags |