package railo.runtime.tag; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.TimeZone; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartRenderingInfo; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.Axis; import org.jfree.chart.axis.CategoryAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.block.ColumnArrangement; import org.jfree.chart.block.LineBorder; import org.jfree.chart.imagemap.ImageMapUtilities; import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator; import org.jfree.chart.imagemap.URLTagFragmentGenerator; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PiePlot; import org.jfree.chart.plot.PiePlot3D; import org.jfree.chart.plot.Plot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.category.BarRenderer3D; import org.jfree.chart.renderer.category.CategoryItemRenderer; import org.jfree.chart.renderer.category.LineAndShapeRenderer; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.chart.title.TextTitle; import org.jfree.data.Range; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.general.DefaultPieDataset; import org.jfree.data.time.Second; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.jfree.data.xy.XYDataset; import org.jfree.ui.HorizontalAlignment; import org.jfree.ui.RectangleAnchor; import org.jfree.ui.RectangleEdge; import org.jfree.ui.RectangleInsets; import org.jfree.util.ShapeUtilities; import railo.commons.color.ColorCaster; import railo.commons.io.IOUtil; import railo.commons.io.res.Resource; import railo.commons.io.res.util.ResourceUtil; import railo.commons.lang.Md5; import railo.commons.lang.StringUtil; import railo.runtime.chart.BarRenderer3DWrap; import railo.runtime.chart.CategoryToolTipGeneratorImpl; import railo.runtime.chart.EmptyURLTagFragmentGenerator; import railo.runtime.chart.LabelFormatUtil; import railo.runtime.chart.PieSectionLabelGeneratorImpl; import railo.runtime.chart.PieSectionLegendLabelGeneratorImpl; import railo.runtime.chart.PieToolTipGeneratorImpl; import railo.runtime.chart.TickUnitsImpl; import railo.runtime.chart.ToolTipTagFragmentGeneratorImpl; import railo.runtime.converter.JavaConverter; import railo.runtime.engine.ThreadLocalPageContext; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.ext.tag.BodyTagImpl; import railo.runtime.functions.dateTime.DateAdd; import railo.runtime.img.Image; import railo.runtime.op.Caster; import railo.runtime.op.date.DateCaster; import railo.runtime.type.dt.DateTime; public final class Chart extends BodyTagImpl implements Serializable { public static final Color COLOR_999999=new Color(0x99,0x99,0x99); public static final Color COLOR_666666=new Color(0x66,0x66,0x66); public static final Color COLOR_333333=new Color(0x33,0x33,0x33); public static final String FONT_ARIAL = "arial"; public static final String FONT_TIMES = "times"; public static final String FONT_COURIER = "courier"; public static final String FONT_ARIAL_UNICODE_MS = "arialunicodems"; public static final int FORMAT_GIF = 0; public static final int FORMAT_JPG = 1; public static final int FORMAT_PNG = 2; public static final int FORMAT_FLASH=3; public static final int PIE_SLICE_STYLE_SOLID = 0; public static final int PIE_SLICE_STYLE_SLICED = 1; public static final int SERIES_PLACEMENT_DEFAULT = 0; public static final int SERIES_PLACEMENT_CLUSTER = 1; public static final int SERIES_PLACEMENT_STACKED = 2; public static final int SERIES_PLACEMENT_PERCENT = 3; public static final int TIP_STYLE_NONE = 0; public static final int TIP_STYLE_FORMATS = 1; public static final int TIP_STYLE_MOUSEDOWN = 2; public static final int TIP_STYLE_MOUSEOVER = 3; private static final int NONE = 0; private static final int YES = 1; private static final int NO = 2; private static int chartIndex=0; private Color backgroundcolor=Color.WHITE; private Color databackgroundcolor=Color.WHITE; private Color foregroundcolor=Color.BLACK; private Color tipbgcolor=Color.WHITE; private String xaxistitle=null; private String yaxistitle=null; private int chartheight=240; private int chartwidth=320; private String font=FONT_ARIAL; private int fontstyle=0; private int fontsize=11; private int format=FORMAT_PNG; private int gridlines=10; private int labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER; private int markersize=-1; private String name=null; private int pieslicestyle=PIE_SLICE_STYLE_SLICED; private double scalefrom=Double.NaN; private double scaleto=Double.NaN; private boolean legendMultiLine=false; private int seriesplacement=SERIES_PLACEMENT_DEFAULT; private boolean show3d=false; private boolean showtooltip=true; private boolean showborder=false; private boolean showlegend=true; private boolean showmarkers=true; private int showxgridlines=NONE; private boolean showygridlines=false; private boolean sortxaxis=false; private String style=null; private String title=""; private int tipstyle=TIP_STYLE_MOUSEOVER; private List<ChartSeriesBean> _series=new ArrayList<ChartSeriesBean>(); private String url; private double xoffset=0.1; private double yoffset=0.1; private String xaxistype="category"; private String yaxistype="category"; private double smallest; private double biggest; private boolean showXLabel=true; private String source; public void release() { _series.clear(); url=null; xoffset=0.1; yoffset=0.1; xaxistype="category"; yaxistype="category"; xaxistitle=""; yaxistitle=""; legendMultiLine=false; // TODO super.release(); backgroundcolor=Color.WHITE; databackgroundcolor=Color.WHITE; foregroundcolor=Color.BLACK; tipbgcolor=Color.WHITE; chartheight=240; chartwidth=320; font=FONT_ARIAL; fontstyle=0; fontsize=11; format=FORMAT_PNG; gridlines=10; labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER; markersize=-1; name=null; pieslicestyle=PIE_SLICE_STYLE_SLICED; scalefrom=Double.NaN; scaleto=Double.NaN; seriesplacement=SERIES_PLACEMENT_DEFAULT; show3d=false; showborder=false; showlegend=true; showmarkers=true; showxgridlines=NONE; showygridlines=false; sortxaxis=false; showXLabel=true; showtooltip=true; style=null; title=""; source=null; tipstyle=TIP_STYLE_MOUSEOVER; } public void setShowxlabel(boolean showXLabel) { this.showXLabel = showXLabel; } public void setSource(String source) { this.source = source; } public void setShowtooltip(boolean showtooltip) { this.showtooltip = showtooltip; } public void setBackgroundcolor(String strBackgroundColor) throws ExpressionException { this.backgroundcolor = ColorCaster.toColor(strBackgroundColor); } public void setDatabackgroundcolor(String strDatabackgroundcolor) throws ExpressionException { this.databackgroundcolor = ColorCaster.toColor(strDatabackgroundcolor); } public void setForegroundcolor(String strForegroundcolor) throws ExpressionException { this.foregroundcolor = ColorCaster.toColor(strForegroundcolor); } public void setTipbgcolor(String strTipbgcolor) throws ExpressionException { this.tipbgcolor = ColorCaster.toColor(strTipbgcolor); } public void setChartheight(double chartheight) { this.chartheight = (int) chartheight; } public void setChartwidth(double chartwidth) { this.chartwidth = (int) chartwidth; } public void setFont(String strFont) { strFont=strFont.trim().toLowerCase(); if("arial".equals(strFont))font=FONT_ARIAL; else if("times".equals(strFont))font=FONT_TIMES; else if("courier".equals(strFont))font=FONT_COURIER; else if("arialunicodems".equals(strFont))font=FONT_ARIAL_UNICODE_MS; else font=strFont; //else throw new ExpressionException("invalid value ["+strFont+"] for attribute font, for this attribute only the following values are supported [arial,times,courier,arialunicodeMS]"); } public void setFontbold(boolean fontbold) { if(fontbold)fontstyle+=Font.BOLD; } public void setFontitalic(boolean fontitalic) { if(fontitalic)fontstyle+=Font.ITALIC; } public void setFontsize(double fontsize) { this.fontsize = (int) fontsize; } public void setFormat(String strFormat) throws ExpressionException { strFormat=strFormat.trim().toLowerCase(); if("gif".equals(strFormat)) format=FORMAT_GIF; else if("jpg".equals(strFormat)) format=FORMAT_JPG; else if("jpeg".equals(strFormat)) format=FORMAT_JPG; else if("jpe".equals(strFormat)) format=FORMAT_JPG; else if("png".equals(strFormat)) format=FORMAT_PNG; //else if("flash".equals(strFormat)) format=FORMAT_FLASH; //else if("swf".equals(strFormat)) format=FORMAT_FLASH; else throw new ExpressionException("invalid value ["+strFormat+"] for attribute format, for this attribute only the following values are supported [gif,jpg,png]"); } public void setGridlines(double gridlines) { this.gridlines = (int) gridlines; } public void setLabelformat(String strLabelFormat) throws ExpressionException { strLabelFormat=strLabelFormat.trim().toLowerCase(); if("number".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER; else if("numeric".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER; else if("currency".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_CURRENCY; else if("date".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_DATE; else if("percent".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_PERCENT; //else if("integer".equals(strLabelFormat)) labelFormat=LabelFormatUtil.LABEL_FORMAT_INTEGER; else throw new ExpressionException("invalid value ["+strLabelFormat+"] for attribute labelFormat, for this attribute only the following values are supported [date,percent,currency,number]"); } public void setMarkersize(double markersize) throws ExpressionException { if(markersize<1) throw new ExpressionException("invalid value ["+markersize+"] for attribute markersize, value must be a positive integer greater than 0"); this.markersize=(int) markersize; } public void setName(String name) { this.name = name; } public void setPieslicestyle(String strPieslicestyle) throws ExpressionException { strPieslicestyle=strPieslicestyle.trim().toLowerCase(); if("sliced".equals(strPieslicestyle)) pieslicestyle=PIE_SLICE_STYLE_SLICED; else if("slice".equals(strPieslicestyle)) pieslicestyle=PIE_SLICE_STYLE_SLICED; else if("solid".equals(strPieslicestyle)) pieslicestyle=PIE_SLICE_STYLE_SOLID; else throw new ExpressionException("invalid value ["+strPieslicestyle+"] for attribute pieSliceStyle, for this attribute only the following values are supported [sliced,solid]"); } public void setScaleto(double scaleto) { //if(scaleto<0) throw new ExpressionException("invalid value ["+scaleto+"] for attribute scaleto, value must be a positive integer greater or equal than 0"); this.scaleto = scaleto; } public void setScalefrom(double scaletrom) { //if(scaletrom<0) throw new ExpressionException("invalid value ["+scaletrom+"] for attribute scaletrom, value must be a positive integer greater or equal than 0"); this.scalefrom = scaletrom; } public void setSeriesplacement(String strSeriesplacement) throws ExpressionException { strSeriesplacement=strSeriesplacement.trim().toLowerCase(); if("default".equals(strSeriesplacement)) seriesplacement=SERIES_PLACEMENT_DEFAULT; else if("cluster".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_CLUSTER; else if("stacked".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_STACKED; else if("percent".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_PERCENT; else throw new ExpressionException("invalid value ["+strSeriesplacement+"] for attribute seriesplacement, for this attribute only the following values are supported [default,cluster,percent,stacked]"); } public void setShow3d(boolean show3d) { this.show3d = show3d; } public void setShowborder(boolean showborder) { this.showborder = showborder; } public void setShowlegend(boolean showlegend) { this.showlegend = showlegend; } public void setShowmarkers(boolean showmarkers) { this.showmarkers = showmarkers; } public void setShowxgridlines(boolean showxgridlines) { this.showxgridlines = showxgridlines?YES:NO; } public void setShowygridlines(boolean showygridlines) { this.showygridlines = showygridlines; } public void setSortxaxis(boolean sortxaxis) { this.sortxaxis = sortxaxis; } public void setStyle(String style) { this.style = style; } public void setTitle(String title) { this.title = title; } public void setTipstyle(String strTipstyle) throws ExpressionException { strTipstyle=strTipstyle.trim().toLowerCase(); if("mousedown".equals(strTipstyle)) tipstyle=TIP_STYLE_MOUSEDOWN; else if("mouseover".equals(strTipstyle))tipstyle=TIP_STYLE_MOUSEOVER; else if("none".equals(strTipstyle)) tipstyle=TIP_STYLE_NONE; else if("formats".equals(strTipstyle)) tipstyle=TIP_STYLE_FORMATS; else throw new ExpressionException("invalid value ["+strTipstyle+"] for attribute Tipstyle, for this attribute only the following values are supported [mouseover,mousedown,one,formats]"); } /** * @param xaxistitle the xaxistitle to set */ public void setXaxistitle(String xaxistitle) { this.xaxistitle = xaxistitle; } /** * @param yaxistitle the yaxistitle to set */ public void setYaxistitle(String yaxistitle) { this.yaxistitle = yaxistitle; } public void addChartSeries(ChartSeriesBean series) { _series.add(series); } public int doStartTag() { return EVAL_BODY_INCLUDE; } @Override public int doEndTag() throws PageException { if(_series.size()==0) throw new ApplicationException("at least one cfchartseries tag required inside cfchart"); //if(_series.size()>1) throw new ApplicationException("only one cfchartseries tag allowed inside cfchart"); //doSingleSeries((ChartSeriesBean) _series.get(0)); ChartSeriesBean first= _series.get(0); try { if(first.getType()==ChartSeriesBean.TYPE_BAR) //throw new ApplicationException("type bar is not supported"); chartBar(); else if(first.getType()==ChartSeriesBean.TYPE_TIME) chartTimeLine(); else if(first.getType()==ChartSeriesBean.TYPE_AREA) chartArea(); else if(first.getType()==ChartSeriesBean.TYPE_CONE) throw new ApplicationException("type cone is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_CURVE) chartLine(); //throw new ApplicationException("type curve is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_CYLINDER) throw new ApplicationException("type cylinder is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_HORIZONTALBAR) throw new ApplicationException("type horizontalbar is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_LINE) chartLine(); //throw new ApplicationException("type line is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_PIE) chartPie(); else if(first.getType()==ChartSeriesBean.TYPE_PYRAMID) throw new ApplicationException("type pyramid is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_SCATTER) throw new ApplicationException("type scatter is not supported"); else if(first.getType()==ChartSeriesBean.TYPE_STEP) throw new ApplicationException("type step is not supported"); } catch(IOException ioe) { throw Caster.toPageException(ioe); } return EVAL_PAGE; } private void chartPie() throws PageException, IOException { // do dataset DefaultPieDataset dataset = new DefaultPieDataset(); ChartSeriesBean csb = _series.get(0); ChartDataBean cdb; List datas=csb.getDatas(); if(sortxaxis)Collections.sort(datas); Iterator itt = datas.iterator(); while(itt.hasNext()) { cdb=(ChartDataBean) itt.next(); dataset.setValue(cdb.getItemAsString(), cdb.getValue()); } JFreeChart chart = show3d? ChartFactory.createPieChart3D (title, dataset, false, true, true): ChartFactory.createPieChart (title, dataset, false, true, true); Plot p = chart.getPlot(); PiePlot pp = (PiePlot)p; Font _font = getFont(); pp.setLegendLabelGenerator(new PieSectionLegendLabelGeneratorImpl(_font,chartwidth)); pp.setBaseSectionOutlinePaint(Color.GRAY); // rand der st゚cke pp.setLegendItemShape(new Rectangle(7,7)); pp.setLabelFont(new Font(font,0,11)); pp.setLabelLinkPaint(COLOR_333333); pp.setLabelLinkMargin(-0.05); pp.setInteriorGap(0.123); pp.setLabelGenerator(new PieSectionLabelGeneratorImpl(labelFormat)); databackgroundcolor=backgroundcolor; setBackground(chart,p); setBorder(chart,p); setLegend(chart,p,_font); set3d(p); setFont(chart, _font); setTooltip(chart); setScale(chart); // Slice Type and colors boolean doSclice=pieslicestyle==PIE_SLICE_STYLE_SLICED; Color[] colors = csb.getColorlist(); Iterator it = csb.getDatas().iterator(); int count=0; while(it.hasNext()) { cdb=(ChartDataBean) it.next(); if(doSclice)pp.setExplodePercent(cdb.getItemAsString(), 0.13); if(count<colors.length){ pp.setSectionPaint(cdb.getItemAsString(), colors[count]); } count++; } writeOut(chart); } private void set3d(Plot plot) { if(!show3d) return; plot.setForegroundAlpha(0.6f); if(plot instanceof CategoryPlot) { plot.setForegroundAlpha(0.8f); CategoryPlot cp=(CategoryPlot) plot; CategoryItemRenderer renderer = cp.getRenderer(); if(renderer instanceof BarRenderer3D) { BarRenderer3D br3d=(BarRenderer3D) renderer; cp.setRenderer(new BarRenderer3DWrap(br3d,xoffset,yoffset)); } } else if(plot instanceof PiePlot3D) { PiePlot3D pp3d=(PiePlot3D) plot; pp3d.setDepthFactor(0.10); } //CategoryItemRenderer renderer = plot.getRenderer(); } private void setFont(JFreeChart chart, Font font) { // title TextTitle title=chart.getTitle(); if(title!=null) { title.setFont(font); title.setPaint(foregroundcolor); chart.setTitle(title); } // axis fonts Plot plot = chart.getPlot(); if(plot instanceof CategoryPlot) { CategoryPlot cp = (CategoryPlot)plot; setAxis(cp.getRangeAxis(),font); setAxis(cp.getDomainAxis(),font); } if(plot instanceof XYPlot) { XYPlot cp = (XYPlot)plot; setAxis(cp.getRangeAxis(),font); setAxis(cp.getDomainAxis(),font); } } private void setAxis(Axis axis, Font font) { if(axis!=null) { axis.setLabelFont(font); axis.setLabelPaint(foregroundcolor); axis.setTickLabelFont(font); axis.setTickLabelPaint(foregroundcolor); axis.setTickLabelsVisible(true); } } private void setLegend(JFreeChart chart, Plot plot, Font font) { if(!showlegend) return; Color bg = backgroundcolor==null?databackgroundcolor:backgroundcolor; if(font==null)font=getFont(); LegendTitle legend = legendMultiLine? new LegendTitle(plot,new ColumnArrangement(), new ColumnArrangement()): new LegendTitle(plot); legend.setBackgroundPaint(bg); legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0)); legend.setFrame(new LineBorder()); legend.setPosition(RectangleEdge.BOTTOM); legend.setHorizontalAlignment(HorizontalAlignment.LEFT); legend.setWidth(chartwidth-20);// geht nicht legend.setItemFont(font); legend.setItemPaint(foregroundcolor); //RectangleInsets labelPadding; legend.setItemLabelPadding(new RectangleInsets(2,2,2,2)); legend.setBorder(0,0,0,0); legend.setLegendItemGraphicLocation(RectangleAnchor.TOP_LEFT); legend.setLegendItemGraphicPadding(new RectangleInsets(8,10,0,0)); chart.addLegend(legend); } private void setBorder(JFreeChart chart, Plot plot) { chart.setBorderVisible(false); chart.setBorderPaint(foregroundcolor); plot.setOutlinePaint(foregroundcolor); } private void setBackground(JFreeChart chart, Plot plot) { //Color bg = backgroundcolor==null?databackgroundcolor:backgroundcolor; chart.setBackgroundPaint(backgroundcolor); plot.setBackgroundPaint(databackgroundcolor); chart.setBorderPaint(databackgroundcolor); plot.setOutlineVisible(false); // Pie if(plot instanceof PiePlot) { PiePlot pp=(PiePlot) plot; pp.setLabelOutlinePaint(backgroundcolor); pp.setLabelBackgroundPaint(backgroundcolor); pp.setLabelShadowPaint(backgroundcolor); pp.setShadowPaint(backgroundcolor); } // Bar /*if(plot instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) plot; }*/ } private Font getFont() { return new Font(font,fontstyle,fontsize); } private void writeOut(JFreeChart jfc) throws PageException, IOException { final ChartRenderingInfo info=new ChartRenderingInfo(); // map name chartIndex++; if(chartIndex<0)chartIndex=0; String mapName="chart_"+(chartIndex++); // write out to variable if(!StringUtil.isEmpty(name)){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); copy(baos, jfc,info); pageContext.setVariable(name, baos.toByteArray()); return; } // write out as link String id=Md5.getDigestAsString(JavaConverter.serialize(this)); Resource graph = pageContext.getConfig().getTempDirectory().getRealResource("graph"); Resource res = graph.getRealResource(id); if(!res.exists()) { clean(graph); copy(res.getOutputStream(),jfc,info); } String src="/railo-context/graph.cfm?img="+id+"&type="+formatToString(format); if(!StringUtil.isEmpty(source)) { pageContext.setVariable(source, src); return; } try { // Tooltip if(showtooltip) { ToolTipTagFragmentGenerator tttfg = new ToolTipTagFragmentGeneratorImpl(url); URLTagFragmentGenerator utfg=new EmptyURLTagFragmentGenerator(); String map=ImageMapUtilities.getImageMap(mapName, info,tttfg,utfg).trim(); pageContext.write(map); } pageContext.write("<img border=\"0\" usemap=\"#"+mapName+"\" src=\""+src+"\">"); } catch (IOException e) { throw Caster.toPageException(e); } } private void copy(OutputStream os, JFreeChart jfc, ChartRenderingInfo info) throws ApplicationException, IOException, ExpressionException { //OutputStream os = null; try { //os = res.getOutputStream(); BufferedImage bi = jfc.createBufferedImage(chartwidth,chartheight,info); Image img; // add border if(showborder) { try { img = new Image(bi); img.addBorder(1,Color.BLACK,Image.BORDER_TYPE_CONSTANT); bi=img.getBufferedImage(); } catch (PageException e) {} } if(format==FORMAT_PNG) ChartUtilities.writeBufferedImageAsPNG(os, bi); else if(format==FORMAT_JPG) ChartUtilities.writeBufferedImageAsJPEG(os, bi); else if(format==FORMAT_GIF) { img = new railo.runtime.img.Image(bi); img.writeOut(os, "gif",1,true); //throw new ApplicationException("format gif not supported"); } else if(format==FORMAT_FLASH)throw new ApplicationException("format flash not supported"); } finally { IOUtil.flushEL(os); IOUtil.closeEL(os); } } private String formatToString(int format) { if(format==FORMAT_GIF) return "gif"; if(format==FORMAT_JPG) return "jpeg"; if(format==FORMAT_PNG) return "png"; return "swf"; } private void clean(Resource graph) throws IOException { if(!graph.exists())graph.createDirectory(true); else if(graph.isDirectory() && ResourceUtil.getRealSize(graph)>(1024*1024)) { Resource[] children = graph.listResources(); long maxAge=System.currentTimeMillis()-(1000*60); for(int i=0;i<children.length;i++) { if(children[i].lastModified()<maxAge) children[i].delete(); } } } private void chartBar() throws PageException, IOException { // create the chart... final JFreeChart chart = show3d? ChartFactory.createBarChart3D(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false): ChartFactory.createBarChart (title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false); Plot p = chart.getPlot(); Font _font = getFont(); // settings setBackground(chart,p); setBorder(chart,p); set3d(p); setFont(chart,_font); setLabelFormat(chart); setLegend(chart, p, _font); setTooltip(chart); setScale(chart); setAxis(chart); setColor(chart); writeOut(chart); } private void chartLine() throws PageException, IOException { // create the chart... final JFreeChart chart = show3d? ChartFactory.createLineChart3D(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false): ChartFactory.createLineChart(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false); Plot p = chart.getPlot(); Font _font = getFont(); // settings setMarker(chart,p); setBackground(chart,p); setBorder(chart,p); set3d(p); setFont(chart,_font); setLabelFormat(chart); setLegend(chart, p, _font); setTooltip(chart); setScale(chart); setAxis(chart); setColor(chart); writeOut(chart); } private void chartArea() throws PageException, IOException { // create the chart... final JFreeChart chart = ChartFactory.createAreaChart(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false); Plot p = chart.getPlot(); Font _font = getFont(); // settings setMarker(chart,p); setBackground(chart,p); setBorder(chart,p); set3d(p); setFont(chart,_font); setLabelFormat(chart); setLegend(chart, p, _font); setTooltip(chart); setScale(chart); setAxis(chart); setColor(chart); writeOut(chart); } private void chartTimeLine() throws PageException, IOException { // create the chart... final JFreeChart chart = ChartFactory.createTimeSeriesChart(title,xaxistitle,yaxistitle,createTimeSeriesCollection(),false,true,false); Plot p = chart.getPlot(); Font _font = getFont(); // settings setMarker(chart,p); setBackground(chart,p); setBorder(chart,p); set3d(p); setFont(chart,_font); setLabelFormat(chart); setLegend(chart, p, _font); setTooltip(chart); setScale(chart); setAxis(chart); setColor(chart); writeOut(chart); } private void setMarker(JFreeChart chart, Plot p) { if(!showmarkers) return; if(markersize<1 || markersize>100) markersize=4; if(p instanceof XYPlot) { XYPlot xyp=(XYPlot) p; XYItemRenderer r = xyp.getRenderer(); if (r instanceof XYLineAndShapeRenderer) { XYLineAndShapeRenderer xyr = (XYLineAndShapeRenderer) r; xyr.setBaseShapesVisible(true); xyr.setBaseShapesFilled(true); int seriesCount=_series.size(); for(int i=0;i<seriesCount;i++){ xyr.setSeriesShapesVisible(i, true); xyr.setSeriesItemLabelsVisible(i, true); xyr.setSeriesShape(i, ShapeUtilities.createDiamond(markersize)); xyr.setUseFillPaint(true); xyr.setBaseFillPaint(databackgroundcolor); } } } else if(p instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) p; CategoryItemRenderer r = cp.getRenderer(); if (r instanceof LineAndShapeRenderer) { LineAndShapeRenderer lsr = (LineAndShapeRenderer)r; int seriesCount=_series.size(); for(int i=0;i<seriesCount;i++){ lsr.setSeriesShapesVisible(i, true); lsr.setSeriesItemLabelsVisible(i, true); lsr.setSeriesShape(i, ShapeUtilities.createDiamond(markersize)); lsr.setUseFillPaint(true); lsr.setBaseFillPaint(databackgroundcolor); } } } } private void setAxis(JFreeChart chart) { Plot plot = chart.getPlot(); if(plot instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot)plot; // Y cp.setDomainGridlinesVisible(showygridlines); if(showygridlines) cp.setDomainGridlinePaint(foregroundcolor); cp.setRangeGridlinesVisible(showxgridlines!=NO); if(showxgridlines==NONE)cp.setRangeGridlinePaint(Color.GRAY); else if(showxgridlines==YES)cp.setRangeGridlinePaint(foregroundcolor); } else if(plot instanceof XYPlot) { XYPlot cp=(XYPlot)plot; // Y cp.setDomainGridlinesVisible(showygridlines); if(showygridlines) cp.setDomainGridlinePaint(foregroundcolor); cp.setRangeGridlinesVisible(showxgridlines!=NO); if(showxgridlines==NONE)cp.setRangeGridlinePaint(Color.GRAY); else if(showxgridlines==YES)cp.setRangeGridlinePaint(foregroundcolor); } } private void setTooltip(JFreeChart chart) { Plot plot = chart.getPlot(); if(plot instanceof PiePlot) { PiePlot pp = (PiePlot)plot; pp.setToolTipGenerator(new PieToolTipGeneratorImpl(labelFormat)); } else if(plot instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) plot; CategoryItemRenderer renderer = cp.getRenderer(); renderer.setBaseToolTipGenerator(new CategoryToolTipGeneratorImpl(labelFormat)); } /*else if(plot instanceof XYPlot) { XYPlot cp=(XYPlot) plot; XYItemRenderer renderer = cp.getRenderer(); renderer.setBaseToolTipGenerator(new XYToolTipGeneratorImpl(labelFormat)); }*/ } private void setScale(JFreeChart chart) { Plot plot = chart.getPlot(); if(plot instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) plot; ValueAxis rangeAxis = cp.getRangeAxis(); Range r=rangeAxis.getRange(); double lower=r.getLowerBound(); double upper=r.getUpperBound(); if(labelFormat==LabelFormatUtil.LABEL_FORMAT_DATE && rangeAxis.getRange().getLowerBound()==0) { lower = smallest; upper=biggest; try { DateTime d = Caster.toDate(Caster.toDouble(lower),true,null,null); lower = DateAdd.call(pageContext,"yyyy", -1, d).castToDoubleValue(lower); } catch (PageException e) {} } if(!Double.isNaN(scalefrom))lower=scalefrom; if(!Double.isNaN(scaleto))upper=scaleto; rangeAxis.setRange(new Range(lower,upper),true,true); } else if(plot instanceof XYPlot) { XYPlot cp=(XYPlot) plot; ValueAxis rangeAxis = cp.getRangeAxis(); Range r=rangeAxis.getRange(); double lower=r.getLowerBound(); double upper=r.getUpperBound(); if(labelFormat==LabelFormatUtil.LABEL_FORMAT_DATE && rangeAxis.getRange().getLowerBound()==0) { lower = smallest; upper=biggest; try { DateTime d = Caster.toDate(Caster.toDouble(lower),true,null,null); lower = DateAdd.call(pageContext,"yyyy", -1, d).castToDoubleValue(lower); } catch (PageException e) {} } if(!Double.isNaN(scalefrom))lower=scalefrom; if(!Double.isNaN(scaleto))upper=scaleto; rangeAxis.setRange(new Range(lower,upper),true,true); } } private void setLabelFormat(JFreeChart chart) { Plot plot = chart.getPlot(); if(plot instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) plot; ValueAxis rangeAxis = cp.getRangeAxis(); rangeAxis.setAutoTickUnitSelection(true); rangeAxis.setStandardTickUnits(new TickUnitsImpl(rangeAxis.getStandardTickUnits(),labelFormat)); CategoryItemRenderer r = cp.getRenderer(); r.setBaseItemLabelsVisible(false); CategoryAxis da = cp.getDomainAxis(); if(!showXLabel)da.setTickLabelsVisible(false); //da.setVisible(false); } if(plot instanceof XYPlot) { XYPlot cp=(XYPlot) plot; ValueAxis rangeAxis = cp.getRangeAxis(); rangeAxis.setAutoTickUnitSelection(true); rangeAxis.setStandardTickUnits(new TickUnitsImpl(rangeAxis.getStandardTickUnits(),labelFormat)); XYItemRenderer r = cp.getRenderer(); r.setBaseItemLabelsVisible(false); ValueAxis da = cp.getDomainAxis(); if(!showXLabel)da.setTickLabelsVisible(false); //da.setVisible(false); } } // set individual colors for series private void setColor(JFreeChart chart) { Plot p = chart.getPlot(); if(p instanceof CategoryPlot) { CategoryPlot cp=(CategoryPlot) p; CategoryItemRenderer renderer = cp.getRenderer(); Iterator<ChartSeriesBean> cs = _series.iterator(); //int seriesCount=_series.size(); ChartSeriesBean csb; GradientPaint gp; Color c=null; Color[] ac; int index=0; while(cs.hasNext()) { csb= cs.next(); // more than 1 series //if(seriesCount>1) { c=csb.getSeriesColor(); if(c==null) { ac=csb.getColorlist(); if(ac!=null && ac.length>0)c=ac[0]; } //} if(c==null) continue; gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f,c); renderer.setSeriesPaint(index++, gp); } } else if(p instanceof XYPlot) { XYPlot cp=(XYPlot) p; XYItemRenderer renderer = cp.getRenderer(); Iterator<ChartSeriesBean> cs = _series.iterator(); //int seriesCount=_series.size(); ChartSeriesBean csb; GradientPaint gp; Color c=null; Color[] ac; int index=0; while(cs.hasNext()) { csb= cs.next(); // more than 1 series //if(seriesCount>1) { c=csb.getSeriesColor(); if(c==null) { ac=csb.getColorlist(); if(ac!=null && ac.length>0)c=ac[0]; } //} if(c==null) continue; gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f,c); renderer.setSeriesPaint(index++, gp); } } } private DefaultPieDataset createDatasetPie() { DefaultPieDataset dataset = new DefaultPieDataset(); ChartSeriesBean csb = _series.get(0); ChartDataBean cdb; // write data set Iterator itt = csb.getDatas().iterator(); while(itt.hasNext()) { cdb=(ChartDataBean) itt.next(); dataset.setValue(cdb.getItemAsString(), cdb.getValue()); } return dataset; } private CategoryDataset createDatasetCategory() { final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); Iterator<ChartSeriesBean> it = _series.iterator(); //int seriesCount=_series.size(); Iterator itt; List datas; ChartSeriesBean csb; ChartDataBean cdb; int count=0; smallest=Double.MAX_VALUE; biggest = Double.MIN_VALUE; String label; boolean hasLabels=false; while(it.hasNext()) { count++; csb= it.next(); label=csb.getSeriesLabel(); if(StringUtil.isEmpty(label))label=""+count; else hasLabels=true; datas = csb.getDatas(); if(sortxaxis)Collections.sort(datas); itt=datas.iterator(); while(itt.hasNext()) { cdb=(ChartDataBean) itt.next(); if(smallest>cdb.getValue())smallest=cdb.getValue(); if(biggest<cdb.getValue())biggest=cdb.getValue(); //if(seriesCount>1) dataset.addValue(cdb.getValue(), label,cdb.getItemAsString()); //else dataset.addValue(cdb.getValue(), cdb.getItem(),""); } } if(!hasLabels)showlegend=false; return dataset; } private XYDataset createTimeSeriesCollection() { TimeZone tz = ThreadLocalPageContext.getTimeZone(); final TimeSeriesCollection coll=new TimeSeriesCollection(tz); //final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); Iterator<ChartSeriesBean> it = _series.iterator(); //int seriesCount=_series.size(); Iterator itt; List datas; ChartSeriesBean csb; ChartDataBean cdb; int count=0; smallest=Double.MAX_VALUE; biggest = Double.MIN_VALUE; String label; boolean hasLabels=false; while(it.hasNext()) { count++; csb=it.next(); label=csb.getSeriesLabel(); if(StringUtil.isEmpty(label))label=""+count; else hasLabels=true; datas = csb.getDatas(); if(sortxaxis)Collections.sort(datas); itt=datas.iterator(); TimeSeries ts=new TimeSeries(label,Second.class); while(itt.hasNext()) { cdb=(ChartDataBean) itt.next(); if(smallest>cdb.getValue())smallest=cdb.getValue(); if(biggest<cdb.getValue())biggest=cdb.getValue(); //if(seriesCount>1) ts.addOrUpdate(new Second(DateCaster.toDateSimple(cdb.getItem(),false,false, tz,null)), cdb.getValue()); //else dataset.addValue(cdb.getValue(), cdb.getItem(),""); } coll.addSeries(ts); } if(!hasLabels)showlegend=false; return coll; } /** * @param url the url to set */ public void setUrl(String url) { this.url = url; } /** * @param xoffset the xoffset to set */ public void setXoffset(double xoffset) { this.xoffset = xoffset; } /** * @param yoffset the yoffset to set */ public void setYoffset(double yoffset) { this.yoffset = yoffset; } /** * @param yaxistype the yaxistype to set */ public void setYaxistype(String yaxistype) { this.yaxistype = yaxistype; } /** * @param yaxistype the yaxistype to set */ public void setXaxistype(String xaxistype) { this.xaxistype = xaxistype; } }