001    package railo.runtime.tag;
002    
003    import java.awt.Color;
004    import java.awt.Font;
005    import java.awt.GradientPaint;
006    import java.awt.Rectangle;
007    import java.awt.image.BufferedImage;
008    import java.io.ByteArrayOutputStream;
009    import java.io.IOException;
010    import java.io.OutputStream;
011    import java.io.Serializable;
012    import java.util.ArrayList;
013    import java.util.Collections;
014    import java.util.Iterator;
015    import java.util.List;
016    import java.util.TimeZone;
017    
018    import org.jfree.chart.ChartFactory;
019    import org.jfree.chart.ChartRenderingInfo;
020    import org.jfree.chart.ChartUtilities;
021    import org.jfree.chart.JFreeChart;
022    import org.jfree.chart.axis.Axis;
023    import org.jfree.chart.axis.CategoryAxis;
024    import org.jfree.chart.axis.ValueAxis;
025    import org.jfree.chart.block.ColumnArrangement;
026    import org.jfree.chart.block.LineBorder;
027    import org.jfree.chart.imagemap.ImageMapUtilities;
028    import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator;
029    import org.jfree.chart.imagemap.URLTagFragmentGenerator;
030    import org.jfree.chart.plot.CategoryPlot;
031    import org.jfree.chart.plot.PiePlot;
032    import org.jfree.chart.plot.PiePlot3D;
033    import org.jfree.chart.plot.Plot;
034    import org.jfree.chart.plot.PlotOrientation;
035    import org.jfree.chart.plot.XYPlot;
036    import org.jfree.chart.renderer.category.BarRenderer3D;
037    import org.jfree.chart.renderer.category.CategoryItemRenderer;
038    import org.jfree.chart.renderer.category.LineAndShapeRenderer;
039    import org.jfree.chart.renderer.xy.XYItemRenderer;
040    import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
041    import org.jfree.chart.title.LegendTitle;
042    import org.jfree.chart.title.TextTitle;
043    import org.jfree.data.Range;
044    import org.jfree.data.category.CategoryDataset;
045    import org.jfree.data.category.DefaultCategoryDataset;
046    import org.jfree.data.general.DefaultPieDataset;
047    import org.jfree.data.time.Second;
048    import org.jfree.data.time.TimeSeries;
049    import org.jfree.data.time.TimeSeriesCollection;
050    import org.jfree.data.xy.XYDataset;
051    import org.jfree.ui.HorizontalAlignment;
052    import org.jfree.ui.RectangleAnchor;
053    import org.jfree.ui.RectangleEdge;
054    import org.jfree.ui.RectangleInsets;
055    import org.jfree.util.ShapeUtilities;
056    
057    import railo.commons.color.ColorCaster;
058    import railo.commons.io.IOUtil;
059    import railo.commons.io.res.Resource;
060    import railo.commons.io.res.util.ResourceUtil;
061    import railo.commons.lang.Md5;
062    import railo.commons.lang.StringUtil;
063    import railo.runtime.chart.BarRenderer3DWrap;
064    import railo.runtime.chart.CategoryToolTipGeneratorImpl;
065    import railo.runtime.chart.EmptyURLTagFragmentGenerator;
066    import railo.runtime.chart.LabelFormatUtil;
067    import railo.runtime.chart.PieSectionLabelGeneratorImpl;
068    import railo.runtime.chart.PieSectionLegendLabelGeneratorImpl;
069    import railo.runtime.chart.PieToolTipGeneratorImpl;
070    import railo.runtime.chart.TickUnitsImpl;
071    import railo.runtime.chart.ToolTipTagFragmentGeneratorImpl;
072    import railo.runtime.converter.JavaConverter;
073    import railo.runtime.engine.ThreadLocalPageContext;
074    import railo.runtime.exp.ApplicationException;
075    import railo.runtime.exp.ExpressionException;
076    import railo.runtime.exp.PageException;
077    import railo.runtime.ext.tag.BodyTagImpl;
078    import railo.runtime.functions.dateTime.DateAdd;
079    import railo.runtime.img.Image;
080    import railo.runtime.op.Caster;
081    import railo.runtime.op.date.DateCaster;
082    import railo.runtime.type.dt.DateTime;
083    
084    
085    public final class Chart extends BodyTagImpl implements Serializable {
086    
087            
088            
089            public static final Color COLOR_999999=new Color(0x99,0x99,0x99);
090            public static final Color COLOR_666666=new Color(0x66,0x66,0x66);
091            public static final Color COLOR_333333=new Color(0x33,0x33,0x33);
092            
093            public static final String FONT_ARIAL = "arial";
094            public static final String FONT_TIMES = "times";
095            public static final String FONT_COURIER = "courier";
096            public static final String FONT_ARIAL_UNICODE_MS = "arialunicodems";
097    
098            public static final int FORMAT_GIF = 0;
099            public static final int FORMAT_JPG = 1;
100            public static final int FORMAT_PNG = 2;
101            public static final int FORMAT_FLASH=3;
102    
103    
104            public static final int PIE_SLICE_STYLE_SOLID = 0;
105            public static final int PIE_SLICE_STYLE_SLICED = 1;
106            
107            public static final int SERIES_PLACEMENT_DEFAULT = 0;
108            public static final int SERIES_PLACEMENT_CLUSTER = 1;
109            public static final int SERIES_PLACEMENT_STACKED = 2;
110            public static final int SERIES_PLACEMENT_PERCENT = 3;
111    
112            public static final int TIP_STYLE_NONE = 0;
113            public static final int TIP_STYLE_FORMATS = 1;
114            public static final int TIP_STYLE_MOUSEDOWN = 2;
115            public static final int TIP_STYLE_MOUSEOVER = 3;
116            
117            private static final int NONE = 0;
118            private static final int YES = 1;
119            private static final int NO = 2;
120            
121    
122            private static int chartIndex=0;
123            
124            private Color backgroundcolor=Color.WHITE;
125            private Color databackgroundcolor=Color.WHITE;
126            private Color foregroundcolor=Color.BLACK;
127            private Color tipbgcolor=Color.WHITE;
128            private String xaxistitle=null;
129            private String yaxistitle=null;
130            
131    
132            private int chartheight=240;
133            private int chartwidth=320;
134            
135            private String font=FONT_ARIAL;
136            private int fontstyle=0;
137            private int fontsize=11;
138            
139            private int format=FORMAT_PNG;
140            private int gridlines=10;
141            
142            private int labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER;
143            private int markersize=-1;
144            
145            private String name=null;
146            
147            private int pieslicestyle=PIE_SLICE_STYLE_SLICED;
148    
149            private double scalefrom=Double.NaN;
150            private double scaleto=Double.NaN;
151            private boolean legendMultiLine=false;
152            
153            private int seriesplacement=SERIES_PLACEMENT_DEFAULT;
154    
155            private boolean show3d=false;
156            private boolean showtooltip=true;
157            private boolean showborder=false;
158            private boolean showlegend=true;
159            private boolean showmarkers=true;
160            private int showxgridlines=NONE;
161            private boolean showygridlines=false;
162            private boolean sortxaxis=false;
163    
164            private String style=null;
165            private String title="";
166            
167            private int tipstyle=TIP_STYLE_MOUSEOVER;
168            private List<ChartSeriesBean> _series=new ArrayList<ChartSeriesBean>();
169    
170            private String url;
171            private double xoffset=0.1;
172            private double yoffset=0.1;
173            private String xaxistype="category";
174            private String yaxistype="category";
175            private double smallest;
176            private double biggest;
177            private boolean showXLabel=true;
178            private String source;
179            
180            public void release() {
181                    _series.clear();
182    
183                    url=null;
184                    xoffset=0.1;
185                    yoffset=0.1;
186                    xaxistype="category";
187                    yaxistype="category";
188                    
189                    
190                    
191                    xaxistitle="";
192                    yaxistitle="";
193                    legendMultiLine=false;
194                    // TODO super.release();
195                    backgroundcolor=Color.WHITE;
196                    databackgroundcolor=Color.WHITE;
197                    foregroundcolor=Color.BLACK;
198                    tipbgcolor=Color.WHITE;
199                    
200                    chartheight=240;
201                    chartwidth=320;
202                    
203                    font=FONT_ARIAL;
204                    fontstyle=0;
205                    fontsize=11;
206                    
207                    format=FORMAT_PNG;
208                    gridlines=10;
209                    
210                    labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER;
211                    markersize=-1;
212                    name=null;
213                    
214                    pieslicestyle=PIE_SLICE_STYLE_SLICED;
215                    
216                    scalefrom=Double.NaN;
217                    scaleto=Double.NaN;
218                    seriesplacement=SERIES_PLACEMENT_DEFAULT;
219                    
220                    show3d=false;
221                    showborder=false;
222                    showlegend=true;
223                    showmarkers=true;
224                    showxgridlines=NONE;
225                    showygridlines=false;
226                    sortxaxis=false;
227                    showXLabel=true;
228                    showtooltip=true;
229                    style=null;
230                    title="";
231                    source=null;
232                    tipstyle=TIP_STYLE_MOUSEOVER;
233            }
234            
235            
236    
237            public void setShowxlabel(boolean showXLabel) {
238                    this.showXLabel = showXLabel;
239            }
240            public void setSource(String source) {
241                    this.source = source;
242            }
243            public void setShowtooltip(boolean showtooltip) {
244                    this.showtooltip = showtooltip;
245            }
246            public void setBackgroundcolor(String strBackgroundColor) throws ExpressionException {
247                    this.backgroundcolor = ColorCaster.toColor(strBackgroundColor);
248            }
249            
250            public void setDatabackgroundcolor(String strDatabackgroundcolor) throws ExpressionException {
251                    this.databackgroundcolor = ColorCaster.toColor(strDatabackgroundcolor);
252            }
253    
254            public void setForegroundcolor(String strForegroundcolor) throws ExpressionException {
255                    this.foregroundcolor = ColorCaster.toColor(strForegroundcolor);
256            }
257    
258            public void setTipbgcolor(String strTipbgcolor) throws ExpressionException {
259                    this.tipbgcolor = ColorCaster.toColor(strTipbgcolor);
260            }
261            
262            public void setChartheight(double chartheight) {
263                    this.chartheight = (int) chartheight;
264            }
265    
266            public void setChartwidth(double chartwidth) {
267                    this.chartwidth = (int) chartwidth;
268            }
269    
270            public void setFont(String strFont) {
271                    strFont=strFont.trim().toLowerCase();
272                    if("arial".equals(strFont))font=FONT_ARIAL;
273                    else if("times".equals(strFont))font=FONT_TIMES;
274                    else if("courier".equals(strFont))font=FONT_COURIER;
275                    else if("arialunicodems".equals(strFont))font=FONT_ARIAL_UNICODE_MS;
276                    else font=strFont;
277                    //else throw new ExpressionException("invalid value ["+strFont+"] for attribute font, for this attribute only the following values are supported [arial,times,courier,arialunicodeMS]");
278            }
279    
280            public void setFontbold(boolean fontbold) {
281                    if(fontbold)fontstyle+=Font.BOLD;
282            }
283    
284            public void setFontitalic(boolean fontitalic) {
285                    if(fontitalic)fontstyle+=Font.ITALIC;
286            }
287    
288            public void setFontsize(double fontsize) {
289                    this.fontsize = (int) fontsize;
290            }
291    
292            public void setFormat(String strFormat) throws ExpressionException {
293                    strFormat=strFormat.trim().toLowerCase();
294                    if("gif".equals(strFormat))                     format=FORMAT_GIF;
295                    else if("jpg".equals(strFormat))        format=FORMAT_JPG;
296                    else if("jpeg".equals(strFormat))       format=FORMAT_JPG;
297                    else if("jpe".equals(strFormat))        format=FORMAT_JPG;
298                    else if("png".equals(strFormat))        format=FORMAT_PNG;
299                    //else if("flash".equals(strFormat))    format=FORMAT_FLASH;
300                    //else if("swf".equals(strFormat))      format=FORMAT_FLASH;
301                    
302                    else throw new ExpressionException("invalid value ["+strFormat+"] for attribute format, for this attribute only the following values are supported [gif,jpg,png]");
303            }
304    
305            public void setGridlines(double gridlines) {
306                    this.gridlines = (int) gridlines;
307            }
308    
309            public void setLabelformat(String strLabelFormat) throws ExpressionException {
310                    strLabelFormat=strLabelFormat.trim().toLowerCase();
311                    if("number".equals(strLabelFormat))                     labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER;
312                    else if("numeric".equals(strLabelFormat))       labelFormat=LabelFormatUtil.LABEL_FORMAT_NUMBER;
313                    else if("currency".equals(strLabelFormat))      labelFormat=LabelFormatUtil.LABEL_FORMAT_CURRENCY;
314                    else if("date".equals(strLabelFormat))          labelFormat=LabelFormatUtil.LABEL_FORMAT_DATE;
315                    else if("percent".equals(strLabelFormat))       labelFormat=LabelFormatUtil.LABEL_FORMAT_PERCENT;
316                    //else if("integer".equals(strLabelFormat))     labelFormat=LabelFormatUtil.LABEL_FORMAT_INTEGER;
317                    
318                    else throw new ExpressionException("invalid value ["+strLabelFormat+"] for attribute labelFormat, for this attribute only the following values are supported [date,percent,currency,number]");
319            }
320    
321            public void setMarkersize(double markersize) throws ExpressionException {
322                    if(markersize<1) throw new ExpressionException("invalid value ["+markersize+"] for attribute markersize, value must be a positive integer greater than 0");
323                    this.markersize=(int) markersize;
324            }
325    
326            public void setName(String name) {
327                    this.name = name;
328            }
329    
330            public void setPieslicestyle(String strPieslicestyle) throws ExpressionException {
331                    strPieslicestyle=strPieslicestyle.trim().toLowerCase();
332                    if("sliced".equals(strPieslicestyle))           pieslicestyle=PIE_SLICE_STYLE_SLICED;
333                    else if("slice".equals(strPieslicestyle))       pieslicestyle=PIE_SLICE_STYLE_SLICED;
334                    else if("solid".equals(strPieslicestyle))       pieslicestyle=PIE_SLICE_STYLE_SOLID;
335                    
336                    else throw new ExpressionException("invalid value ["+strPieslicestyle+"] for attribute pieSliceStyle, for this attribute only the following values are supported [sliced,solid]");
337            }
338    
339            public void setScaleto(double scaleto) {
340                    //if(scaleto<0) throw new ExpressionException("invalid value ["+scaleto+"] for attribute scaleto, value must be a positive integer greater or equal than 0");
341                    this.scaleto =  scaleto;
342            }
343    
344            public void setScalefrom(double scaletrom)  {
345                    //if(scaletrom<0) throw new ExpressionException("invalid value ["+scaletrom+"] for attribute scaletrom, value must be a positive integer greater or equal than 0");
346                    this.scalefrom =  scaletrom;
347            }
348    
349            public void setSeriesplacement(String strSeriesplacement) throws ExpressionException {
350                    strSeriesplacement=strSeriesplacement.trim().toLowerCase();
351                    if("default".equals(strSeriesplacement))        seriesplacement=SERIES_PLACEMENT_DEFAULT;
352                    else if("cluster".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_CLUSTER;
353                    else if("stacked".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_STACKED;
354                    else if("percent".equals(strSeriesplacement))seriesplacement=SERIES_PLACEMENT_PERCENT;
355                    
356                    else throw new ExpressionException("invalid value ["+strSeriesplacement+"] for attribute seriesplacement, for this attribute only the following values are supported [default,cluster,percent,stacked]");
357            }
358    
359            public void setShow3d(boolean show3d) {
360                    this.show3d = show3d;
361            }
362    
363            public void setShowborder(boolean showborder) {
364                    this.showborder = showborder;
365            }
366    
367            public void setShowlegend(boolean showlegend) {
368                    this.showlegend = showlegend;
369            }
370    
371            public void setShowmarkers(boolean showmarkers) {
372                    this.showmarkers = showmarkers;
373            }
374    
375            public void setShowxgridlines(boolean showxgridlines) {
376                    this.showxgridlines = showxgridlines?YES:NO;
377            }
378    
379            public void setShowygridlines(boolean showygridlines) {
380                    this.showygridlines = showygridlines;
381            }
382    
383            public void setSortxaxis(boolean sortxaxis) {
384                    this.sortxaxis = sortxaxis;
385            }
386    
387            public void setStyle(String style) {
388                    this.style = style;
389            }
390    
391            public void setTitle(String title) {
392                    this.title = title;
393            }
394    
395            public void setTipstyle(String strTipstyle) throws ExpressionException {
396                    strTipstyle=strTipstyle.trim().toLowerCase();
397                    if("mousedown".equals(strTipstyle))             tipstyle=TIP_STYLE_MOUSEDOWN;
398                    else if("mouseover".equals(strTipstyle))tipstyle=TIP_STYLE_MOUSEOVER;
399                    else if("none".equals(strTipstyle))             tipstyle=TIP_STYLE_NONE;
400                    else if("formats".equals(strTipstyle))  tipstyle=TIP_STYLE_FORMATS;
401                    
402                    else throw new ExpressionException("invalid value ["+strTipstyle+"] for attribute Tipstyle, for this attribute only the following values are supported [mouseover,mousedown,one,formats]");
403            }
404            
405    
406            
407            /**
408             * @param xaxistitle the xaxistitle to set
409             */
410            public void setXaxistitle(String xaxistitle) {
411                    this.xaxistitle = xaxistitle;
412            }
413    
414            /**
415             * @param yaxistitle the yaxistitle to set
416             */
417            public void setYaxistitle(String yaxistitle) {
418                    this.yaxistitle = yaxistitle;
419            }
420    
421            public void addChartSeries(ChartSeriesBean series) {
422                    _series.add(series);
423            }
424            
425    
426            public int doStartTag() {
427                    return EVAL_BODY_INCLUDE;
428            }
429    
430            @Override
431            public int doEndTag() throws PageException {
432                    if(_series.size()==0) throw new ApplicationException("at least one cfchartseries tag required inside cfchart"); 
433                    //if(_series.size()>1) throw new ApplicationException("only one cfchartseries tag allowed inside cfchart"); 
434                    //doSingleSeries((ChartSeriesBean) _series.get(0));
435                    ChartSeriesBean first= _series.get(0);
436                    
437                    try {
438                                    
439                            if(first.getType()==ChartSeriesBean.TYPE_BAR)
440                                    //throw new ApplicationException("type bar is not supported");
441                                    chartBar();
442                            else if(first.getType()==ChartSeriesBean.TYPE_TIME)
443                                    chartTimeLine();
444                            else if(first.getType()==ChartSeriesBean.TYPE_AREA)
445                                    chartArea();
446                            else if(first.getType()==ChartSeriesBean.TYPE_CONE)
447                                    throw new ApplicationException("type cone is not supported");
448                            else if(first.getType()==ChartSeriesBean.TYPE_CURVE)
449                                    chartLine();
450                                    //throw new ApplicationException("type curve is not supported");
451                            else if(first.getType()==ChartSeriesBean.TYPE_CYLINDER)
452                                    throw new ApplicationException("type cylinder is not supported");
453                            else if(first.getType()==ChartSeriesBean.TYPE_HORIZONTALBAR)
454                                    throw new ApplicationException("type horizontalbar is not supported");
455                            else if(first.getType()==ChartSeriesBean.TYPE_LINE)
456                                    chartLine();
457                                    //throw new ApplicationException("type line is not supported");
458                            else if(first.getType()==ChartSeriesBean.TYPE_PIE)
459                                    chartPie();
460                            else if(first.getType()==ChartSeriesBean.TYPE_PYRAMID)
461                                    throw new ApplicationException("type pyramid is not supported");
462                            else if(first.getType()==ChartSeriesBean.TYPE_SCATTER)
463                                    throw new ApplicationException("type scatter is not supported");
464                            else if(first.getType()==ChartSeriesBean.TYPE_STEP)
465                                    throw new ApplicationException("type step is not supported");
466                    }
467                    catch(IOException ioe) {
468                            throw Caster.toPageException(ioe);
469                    }
470                    
471                    return EVAL_PAGE;
472            }
473    
474            private void chartPie() throws PageException, IOException {
475                    // do dataset
476                    DefaultPieDataset dataset = new DefaultPieDataset();
477                    ChartSeriesBean csb =  _series.get(0);
478            
479                    ChartDataBean cdb;
480            
481                    List datas=csb.getDatas();
482                    if(sortxaxis)Collections.sort(datas);
483            Iterator itt = datas.iterator();
484            while(itt.hasNext()) {
485                    cdb=(ChartDataBean) itt.next();
486                    dataset.setValue(cdb.getItemAsString(), cdb.getValue());
487            }       
488                    
489            
490            JFreeChart chart = show3d?
491                            ChartFactory.createPieChart3D   (title, dataset, false, true, true):
492                            ChartFactory.createPieChart             (title, dataset, false, true, true);
493            
494            Plot p = chart.getPlot();
495                    PiePlot pp = (PiePlot)p;
496            
497                    Font _font = getFont();
498            pp.setLegendLabelGenerator(new PieSectionLegendLabelGeneratorImpl(_font,chartwidth));
499            pp.setBaseSectionOutlinePaint(Color.GRAY); // rand der st゚cke
500            pp.setLegendItemShape(new Rectangle(7,7));
501            pp.setLabelFont(new Font(font,0,11));
502            pp.setLabelLinkPaint(COLOR_333333);
503            pp.setLabelLinkMargin(-0.05);
504            pp.setInteriorGap(0.123);
505            pp.setLabelGenerator(new PieSectionLabelGeneratorImpl(labelFormat));
506            
507            
508            
509            
510            databackgroundcolor=backgroundcolor;
511            
512            setBackground(chart,p);
513                    setBorder(chart,p);
514                    setLegend(chart,p,_font);
515                    set3d(p);
516                    setFont(chart, _font);
517            setTooltip(chart);
518            setScale(chart);
519            
520            // Slice Type and colors
521            boolean doSclice=pieslicestyle==PIE_SLICE_STYLE_SLICED;
522            Color[] colors = csb.getColorlist();
523            Iterator it = csb.getDatas().iterator();
524            int count=0;
525            while(it.hasNext()) {
526                    cdb=(ChartDataBean) it.next();
527                if(doSclice)pp.setExplodePercent(cdb.getItemAsString(), 0.13);
528                
529                if(count<colors.length){
530                    pp.setSectionPaint(cdb.getItemAsString(), colors[count]);
531                }
532                count++;
533            }
534            
535            writeOut(chart);
536            }
537            
538    
539            private void set3d(Plot plot) {
540            if(!show3d) return;
541            
542            plot.setForegroundAlpha(0.6f);
543            
544            if(plot instanceof CategoryPlot) {
545                plot.setForegroundAlpha(0.8f);
546                    CategoryPlot cp=(CategoryPlot) plot;
547                    CategoryItemRenderer renderer = cp.getRenderer();
548                    if(renderer instanceof BarRenderer3D) {
549                            BarRenderer3D br3d=(BarRenderer3D) renderer;
550                            cp.setRenderer(new BarRenderer3DWrap(br3d,xoffset,yoffset));
551                    }
552                    
553            }
554            else if(plot instanceof PiePlot3D) {
555                    PiePlot3D pp3d=(PiePlot3D) plot;
556                pp3d.setDepthFactor(0.10);    
557            }
558            
559            
560    
561            //CategoryItemRenderer renderer = plot.getRenderer();
562            
563            }
564    
565            private void setFont(JFreeChart chart, Font font) {
566                    // title
567                    TextTitle title=chart.getTitle();
568                    if(title!=null) {
569                            title.setFont(font);
570                            title.setPaint(foregroundcolor);
571                            chart.setTitle(title);
572                    }
573                    
574                    // axis fonts
575                    Plot plot = chart.getPlot();
576                    if(plot instanceof CategoryPlot) {
577                            CategoryPlot cp = (CategoryPlot)plot;
578                            setAxis(cp.getRangeAxis(),font);
579                            setAxis(cp.getDomainAxis(),font);
580                    }
581                    if(plot instanceof XYPlot) {
582                            XYPlot cp = (XYPlot)plot;
583                            setAxis(cp.getRangeAxis(),font);
584                            setAxis(cp.getDomainAxis(),font);
585                    }
586                    
587                    
588            }
589            
590            
591            private void setAxis(Axis axis, Font font) {
592                    if(axis!=null) {
593                            axis.setLabelFont(font);
594                            axis.setLabelPaint(foregroundcolor);
595                            
596                            axis.setTickLabelFont(font);
597                    axis.setTickLabelPaint(foregroundcolor);
598                    axis.setTickLabelsVisible(true);
599                    }
600            }
601    
602    
603    
604            private void setLegend(JFreeChart chart, Plot plot, Font font) {
605                    if(!showlegend) return;
606                            
607                            
608                    Color bg = backgroundcolor==null?databackgroundcolor:backgroundcolor;
609                    if(font==null)font=getFont();
610                    
611                    
612                    
613                    LegendTitle legend = legendMultiLine?
614                            new LegendTitle(plot,new ColumnArrangement(), new ColumnArrangement()):
615                            new LegendTitle(plot);
616            legend.setBackgroundPaint(bg);
617            legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
618            legend.setFrame(new LineBorder());
619            legend.setPosition(RectangleEdge.BOTTOM);
620            legend.setHorizontalAlignment(HorizontalAlignment.LEFT);
621            
622            legend.setWidth(chartwidth-20);// geht nicht
623            legend.setItemFont(font);
624                    legend.setItemPaint(foregroundcolor);
625    
626                    //RectangleInsets labelPadding;
627                    legend.setItemLabelPadding(new RectangleInsets(2,2,2,2));
628                    legend.setBorder(0,0,0,0); 
629                    legend.setLegendItemGraphicLocation(RectangleAnchor.TOP_LEFT);
630                    legend.setLegendItemGraphicPadding(new RectangleInsets(8,10,0,0));
631                    chart.addLegend(legend);
632                    
633            }
634    
635    
636    
637            private void setBorder(JFreeChart chart, Plot plot) {
638                    chart.setBorderVisible(false);
639                    chart.setBorderPaint(foregroundcolor);
640                    plot.setOutlinePaint(foregroundcolor);
641            }
642    
643    
644    
645            private void setBackground(JFreeChart chart, Plot plot) {
646                    //Color bg = backgroundcolor==null?databackgroundcolor:backgroundcolor;
647    
648                    chart.setBackgroundPaint(backgroundcolor);
649                    plot.setBackgroundPaint(databackgroundcolor);
650                    chart.setBorderPaint(databackgroundcolor);
651                    
652                    
653            plot.setOutlineVisible(false);
654                    
655                    // Pie
656                    if(plot instanceof PiePlot) {
657                            PiePlot pp=(PiePlot) plot;
658                            pp.setLabelOutlinePaint(backgroundcolor); 
659                    pp.setLabelBackgroundPaint(backgroundcolor);
660                    pp.setLabelShadowPaint(backgroundcolor);
661                    pp.setShadowPaint(backgroundcolor);
662                    }
663                    // Bar
664                    /*if(plot instanceof CategoryPlot) {
665                            CategoryPlot cp=(CategoryPlot) plot;
666                            
667                    }*/
668            }
669    
670    
671    
672            
673     
674            private Font getFont() {
675                    return new Font(font,fontstyle,fontsize);
676            }
677    
678            private void writeOut(JFreeChart jfc) throws PageException, IOException {
679                    final ChartRenderingInfo info=new ChartRenderingInfo();
680            
681                    // map name
682                    chartIndex++;
683                    if(chartIndex<0)chartIndex=0;
684                    String mapName="chart_"+(chartIndex++);
685                    
686                    // write out to variable
687                    if(!StringUtil.isEmpty(name)){
688                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
689                            copy(baos, jfc,info);
690                            pageContext.setVariable(name, baos.toByteArray());
691                            return;
692                    }
693                    
694                    // write out as link
695                    String id=Md5.getDigestAsString(JavaConverter.serialize(this));
696                    Resource graph = pageContext.getConfig().getTempDirectory().getRealResource("graph");
697                    Resource res = graph.getRealResource(id);
698                    if(!res.exists()) {
699                            clean(graph);
700                            copy(res.getOutputStream(),jfc,info);
701                    }
702                    
703                    String src="/railo-context/graph.cfm?img="+id+"&type="+formatToString(format);
704                    if(!StringUtil.isEmpty(source)) {
705                            pageContext.setVariable(source, src);
706                            return;
707                    }
708                    try {
709                            // Tooltip
710                            if(showtooltip) {
711                                    ToolTipTagFragmentGenerator tttfg = new ToolTipTagFragmentGeneratorImpl(url);
712                                    URLTagFragmentGenerator utfg=new EmptyURLTagFragmentGenerator();
713                                    
714                                    String map=ImageMapUtilities.getImageMap(mapName, info,tttfg,utfg).trim();
715                                    pageContext.write(map);
716                            }
717                            pageContext.write("<img border=\"0\" usemap=\"#"+mapName+"\" src=\""+src+"\">");
718                    } 
719                    catch (IOException e) {
720                            throw Caster.toPageException(e);
721                    }               
722            }
723    
724            private void copy(OutputStream os, JFreeChart jfc, ChartRenderingInfo info) throws ApplicationException, IOException, ExpressionException {
725                    //OutputStream os = null;
726                    try {
727                            //os = res.getOutputStream();
728                            BufferedImage bi = jfc.createBufferedImage(chartwidth,chartheight,info);
729                            Image img;
730                            
731                            // add border
732                            if(showborder) {
733                                    try {
734                                            img = new Image(bi);
735                                            img.addBorder(1,Color.BLACK,Image.BORDER_TYPE_CONSTANT);
736                                            bi=img.getBufferedImage();
737                                    }
738                                    catch (PageException e) {}
739                            }
740                            if(format==FORMAT_PNG)          ChartUtilities.writeBufferedImageAsPNG(os, bi);
741                            else if(format==FORMAT_JPG)     ChartUtilities.writeBufferedImageAsJPEG(os, bi);
742                            else if(format==FORMAT_GIF)     {
743                                    img = new railo.runtime.img.Image(bi);
744                                    img.writeOut(os, "gif",1,true);
745                                    
746                                    //throw new ApplicationException("format gif not supported");
747                            }
748                            else if(format==FORMAT_FLASH)throw new ApplicationException("format flash not supported");
749                    }
750                    finally {
751                            IOUtil.flushEL(os);
752                            IOUtil.closeEL(os);
753                    }
754            }
755    
756            private String formatToString(int format) {
757                    if(format==FORMAT_GIF) return "gif";
758                    if(format==FORMAT_JPG) return "jpeg";
759                    if(format==FORMAT_PNG) return "png";
760                    return "swf";
761            }
762    
763            private void clean(Resource graph) throws IOException {
764                    if(!graph.exists())graph.createDirectory(true);
765                    else if(graph.isDirectory() && ResourceUtil.getRealSize(graph)>(1024*1024)) {
766                            
767                            Resource[] children = graph.listResources();
768                            long maxAge=System.currentTimeMillis()-(1000*60);
769                            for(int i=0;i<children.length;i++) {
770                                    if(children[i].lastModified()<maxAge)
771                                            children[i].delete();
772                            }
773                    }
774            }
775    
776            private void chartBar() throws PageException, IOException {
777                    // create the chart...
778            final JFreeChart chart = show3d?
779                    ChartFactory.createBarChart3D(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false):
780                    ChartFactory.createBarChart  (title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false);
781            Plot p = chart.getPlot();
782            Font _font = getFont();
783            // settings
784            
785            
786            setBackground(chart,p);
787                    setBorder(chart,p);
788                    set3d(p);
789                    setFont(chart,_font);
790                    setLabelFormat(chart);
791                    setLegend(chart, p, _font);
792            setTooltip(chart);
793                    setScale(chart);
794            setAxis(chart);
795            setColor(chart);
796            
797            writeOut(chart);
798            }
799            
800    
801    
802    
803    
804            private void chartLine() throws PageException, IOException {
805                    // create the chart...
806            final JFreeChart chart = show3d?
807                    ChartFactory.createLineChart3D(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false):
808                    ChartFactory.createLineChart(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false);
809            Plot p = chart.getPlot();
810            Font _font = getFont();
811            
812            // settings
813            setMarker(chart,p);
814            setBackground(chart,p);
815                    setBorder(chart,p);
816                    set3d(p);
817                    setFont(chart,_font);
818                    setLabelFormat(chart);
819                    setLegend(chart, p, _font);
820            setTooltip(chart);
821                    setScale(chart);
822            setAxis(chart);
823            setColor(chart);
824            
825            writeOut(chart);
826            }
827            
828            private void chartArea() throws PageException, IOException {
829                    // create the chart...
830            final JFreeChart chart = ChartFactory.createAreaChart(title,xaxistitle,yaxistitle,createDatasetCategory(),PlotOrientation.VERTICAL,false,true,false);
831            Plot p = chart.getPlot();
832            Font _font = getFont();
833            
834            // settings
835            setMarker(chart,p);
836            setBackground(chart,p);
837                    setBorder(chart,p);
838                    set3d(p);
839                    setFont(chart,_font);
840                    setLabelFormat(chart);
841                    setLegend(chart, p, _font);
842            setTooltip(chart);
843                    setScale(chart);
844            setAxis(chart);
845            setColor(chart);
846            
847            writeOut(chart);
848            }
849            
850            private void chartTimeLine() throws PageException, IOException {
851                    // create the chart...
852            final JFreeChart chart = ChartFactory.createTimeSeriesChart(title,xaxistitle,yaxistitle,createTimeSeriesCollection(),false,true,false);
853            Plot p = chart.getPlot();
854            Font _font = getFont();
855            
856            // settings
857            setMarker(chart,p);
858            setBackground(chart,p);
859                    setBorder(chart,p);
860                    set3d(p);
861                    setFont(chart,_font);
862                    setLabelFormat(chart);
863                    setLegend(chart, p, _font);
864            setTooltip(chart);
865                    setScale(chart);
866            setAxis(chart);
867            setColor(chart);
868            
869            writeOut(chart);
870            }
871    
872    
873    
874            private void setMarker(JFreeChart chart, Plot p) {
875                    if(!showmarkers) return;
876                    
877                    if(markersize<1 || markersize>100) markersize=4;
878                    
879                    
880                    
881                    if(p instanceof XYPlot) {
882                            XYPlot xyp=(XYPlot) p;
883                            XYItemRenderer r = xyp.getRenderer();
884                            if (r instanceof XYLineAndShapeRenderer) {
885                                    XYLineAndShapeRenderer xyr = (XYLineAndShapeRenderer) r;
886                                    xyr.setBaseShapesVisible(true);
887                                    xyr.setBaseShapesFilled(true);
888                                    
889                                    int seriesCount=_series.size();
890                                    for(int i=0;i<seriesCount;i++){
891                                            xyr.setSeriesShapesVisible(i, true);
892                                            xyr.setSeriesItemLabelsVisible(i, true);
893                                            xyr.setSeriesShape(i, ShapeUtilities.createDiamond(markersize));
894                                            xyr.setUseFillPaint(true);
895                                            xyr.setBaseFillPaint(databackgroundcolor);
896                                    }
897                            }
898                    }
899                    else if(p instanceof CategoryPlot) {
900                            CategoryPlot cp=(CategoryPlot) p;
901                            CategoryItemRenderer r = cp.getRenderer();
902                            if (r instanceof LineAndShapeRenderer) {
903                                    LineAndShapeRenderer lsr = (LineAndShapeRenderer)r;
904                            
905                                    int seriesCount=_series.size();
906                                    for(int i=0;i<seriesCount;i++){
907                                            lsr.setSeriesShapesVisible(i, true);
908                                            lsr.setSeriesItemLabelsVisible(i, true);
909                                            lsr.setSeriesShape(i, ShapeUtilities.createDiamond(markersize));
910                                    lsr.setUseFillPaint(true);
911                                    lsr.setBaseFillPaint(databackgroundcolor);
912                                    }
913                            }
914                    }
915            }
916    
917    
918    
919            private void setAxis(JFreeChart chart) {
920                    Plot plot = chart.getPlot();
921                    if(plot instanceof CategoryPlot) {
922                            CategoryPlot cp=(CategoryPlot)plot;
923                            
924                            // Y
925                            cp.setDomainGridlinesVisible(showygridlines);
926                            if(showygridlines) cp.setDomainGridlinePaint(foregroundcolor);
927                            
928                            cp.setRangeGridlinesVisible(showxgridlines!=NO);
929                            if(showxgridlines==NONE)cp.setRangeGridlinePaint(Color.GRAY);
930                            else if(showxgridlines==YES)cp.setRangeGridlinePaint(foregroundcolor);
931                    }
932                    else if(plot instanceof XYPlot) {
933                            XYPlot cp=(XYPlot)plot;
934                            
935                            // Y
936                            cp.setDomainGridlinesVisible(showygridlines);
937                            if(showygridlines) cp.setDomainGridlinePaint(foregroundcolor);
938                            
939                            cp.setRangeGridlinesVisible(showxgridlines!=NO);
940                            if(showxgridlines==NONE)cp.setRangeGridlinePaint(Color.GRAY);
941                            else if(showxgridlines==YES)cp.setRangeGridlinePaint(foregroundcolor);
942                    }
943            }
944    
945    
946    
947            private void setTooltip(JFreeChart chart) {
948                    Plot plot = chart.getPlot();
949                    if(plot instanceof PiePlot) {
950                            PiePlot pp = (PiePlot)plot;             
951                            
952                            pp.setToolTipGenerator(new PieToolTipGeneratorImpl(labelFormat));
953                            
954                    }
955                    else if(plot instanceof CategoryPlot) {
956                            CategoryPlot cp=(CategoryPlot) plot;
957                            CategoryItemRenderer renderer = cp.getRenderer();
958                            renderer.setBaseToolTipGenerator(new CategoryToolTipGeneratorImpl(labelFormat));
959                    }
960                    /*else if(plot instanceof XYPlot) {
961                            XYPlot cp=(XYPlot) plot;
962                            XYItemRenderer renderer = cp.getRenderer();
963                            renderer.setBaseToolTipGenerator(new XYToolTipGeneratorImpl(labelFormat));
964                    }*/
965                    
966            }
967    
968    
969    
970            private void setScale(JFreeChart chart) {
971                    Plot plot = chart.getPlot();
972                    if(plot instanceof CategoryPlot) {
973                            CategoryPlot cp=(CategoryPlot) plot;
974                            ValueAxis rangeAxis = cp.getRangeAxis();
975                            Range r=rangeAxis.getRange();
976                            double lower=r.getLowerBound();
977                            double upper=r.getUpperBound();
978                            
979                            if(labelFormat==LabelFormatUtil.LABEL_FORMAT_DATE && rangeAxis.getRange().getLowerBound()==0) {
980                                    lower = smallest;
981                                    upper=biggest;
982                                    try     {
983                                            DateTime d = Caster.toDate(Caster.toDouble(lower),true,null,null);
984                                            lower = DateAdd.call(pageContext,"yyyy", -1, d).castToDoubleValue(lower);       
985                                    }
986                                    catch (PageException e) {}
987                            }
988                            if(!Double.isNaN(scalefrom))lower=scalefrom;
989                            if(!Double.isNaN(scaleto))upper=scaleto;
990                            rangeAxis.setRange(new Range(lower,upper),true,true);
991                    }
992                    else if(plot instanceof XYPlot) {
993                            XYPlot cp=(XYPlot) plot;
994                            ValueAxis rangeAxis = cp.getRangeAxis();
995                            Range r=rangeAxis.getRange();
996                            double lower=r.getLowerBound();
997                            double upper=r.getUpperBound();
998                            
999                            if(labelFormat==LabelFormatUtil.LABEL_FORMAT_DATE && rangeAxis.getRange().getLowerBound()==0) {
1000                                    lower = smallest;
1001                                    upper=biggest;
1002                                    try     {
1003                                            DateTime d = Caster.toDate(Caster.toDouble(lower),true,null,null);
1004                                            lower = DateAdd.call(pageContext,"yyyy", -1, d).castToDoubleValue(lower);       
1005                                    }
1006                                    catch (PageException e) {}
1007                            }
1008                            if(!Double.isNaN(scalefrom))lower=scalefrom;
1009                            if(!Double.isNaN(scaleto))upper=scaleto;
1010                            rangeAxis.setRange(new Range(lower,upper),true,true);
1011                    }
1012            }
1013    
1014            private void setLabelFormat(JFreeChart chart) {
1015                    Plot plot = chart.getPlot();
1016                    if(plot instanceof CategoryPlot) {
1017                            CategoryPlot cp=(CategoryPlot) plot;
1018                            ValueAxis rangeAxis = cp.getRangeAxis();
1019                            rangeAxis.setAutoTickUnitSelection(true);
1020                            rangeAxis.setStandardTickUnits(new TickUnitsImpl(rangeAxis.getStandardTickUnits(),labelFormat));
1021                            CategoryItemRenderer r = cp.getRenderer();
1022                            r.setBaseItemLabelsVisible(false);
1023                            
1024                            CategoryAxis da = cp.getDomainAxis();
1025                            if(!showXLabel)da.setTickLabelsVisible(false);
1026                            //da.setVisible(false);
1027                    }
1028                    if(plot instanceof XYPlot) {
1029                            XYPlot cp=(XYPlot) plot;
1030                            ValueAxis rangeAxis = cp.getRangeAxis();
1031                            rangeAxis.setAutoTickUnitSelection(true);
1032                            rangeAxis.setStandardTickUnits(new TickUnitsImpl(rangeAxis.getStandardTickUnits(),labelFormat));
1033                            XYItemRenderer r = cp.getRenderer();
1034                            r.setBaseItemLabelsVisible(false);
1035                            
1036                            ValueAxis da = cp.getDomainAxis();
1037                            if(!showXLabel)da.setTickLabelsVisible(false);
1038                            //da.setVisible(false);
1039                    }
1040            }
1041    
1042    
1043    
1044            // set individual colors for series
1045            private void setColor(JFreeChart chart) {
1046                    Plot p = chart.getPlot();
1047                    if(p instanceof CategoryPlot) {
1048                            CategoryPlot cp=(CategoryPlot) p;
1049                            
1050                            CategoryItemRenderer renderer = cp.getRenderer();
1051                    
1052                            
1053                            
1054                            Iterator<ChartSeriesBean> cs = _series.iterator();
1055                            //int seriesCount=_series.size();
1056                            ChartSeriesBean csb;
1057                            GradientPaint gp;
1058                            Color c=null;
1059                            Color[] ac;
1060                            
1061                            int index=0;
1062                            while(cs.hasNext()) {
1063                                    csb= cs.next();
1064                                    // more than 1 series
1065                                    //if(seriesCount>1) {
1066                                            c=csb.getSeriesColor();
1067                                            if(c==null) {
1068                                                    ac=csb.getColorlist();
1069                                                    if(ac!=null && ac.length>0)c=ac[0];
1070                                            }
1071                                            
1072                                    //}
1073                                    if(c==null) continue;
1074                                    gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f,c);
1075                                    renderer.setSeriesPaint(index++, gp);
1076                            }
1077                    }
1078                    else if(p instanceof XYPlot) {
1079                            XYPlot cp=(XYPlot) p;
1080                            
1081                            XYItemRenderer renderer = cp.getRenderer();
1082                    
1083                            
1084                            
1085                            Iterator<ChartSeriesBean> cs = _series.iterator();
1086                            //int seriesCount=_series.size();
1087                            ChartSeriesBean csb;
1088                            GradientPaint gp;
1089                            Color c=null;
1090                            Color[] ac;
1091                            
1092                            int index=0;
1093                            while(cs.hasNext()) {
1094                                    csb= cs.next();
1095                                    // more than 1 series
1096                                    //if(seriesCount>1) {
1097                                            c=csb.getSeriesColor();
1098                                            if(c==null) {
1099                                                    ac=csb.getColorlist();
1100                                                    if(ac!=null && ac.length>0)c=ac[0];
1101                                            }
1102                                            
1103                                    //}
1104                                    if(c==null) continue;
1105                                    gp = new GradientPaint(0.0f, 0.0f, c, 0.0f, 0.0f,c);
1106                                    renderer.setSeriesPaint(index++, gp);
1107                            }
1108                    }
1109            }
1110    
1111    
1112    
1113            private DefaultPieDataset createDatasetPie() {
1114                    DefaultPieDataset dataset = new DefaultPieDataset();
1115                    ChartSeriesBean csb =  _series.get(0);
1116            
1117                    ChartDataBean cdb;
1118            // write data set
1119            Iterator itt = csb.getDatas().iterator();
1120            while(itt.hasNext()) {
1121                    cdb=(ChartDataBean) itt.next();
1122                    dataset.setValue(cdb.getItemAsString(), cdb.getValue());
1123            }       
1124            return dataset;
1125        }
1126            
1127    
1128            
1129            
1130    
1131            private CategoryDataset createDatasetCategory() {
1132            final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
1133            Iterator<ChartSeriesBean> it = _series.iterator();
1134            //int seriesCount=_series.size();
1135            Iterator itt;
1136            List datas;
1137            ChartSeriesBean csb;
1138            ChartDataBean cdb;
1139            int count=0;
1140            smallest=Double.MAX_VALUE;
1141            biggest = Double.MIN_VALUE;
1142            String label;
1143            boolean hasLabels=false;
1144            while(it.hasNext()) {
1145                    count++;
1146                    csb= it.next();
1147                    label=csb.getSeriesLabel();
1148                    if(StringUtil.isEmpty(label))label=""+count;
1149                    else hasLabels=true;
1150                    datas = csb.getDatas();
1151                    if(sortxaxis)Collections.sort(datas);
1152                itt=datas.iterator();
1153                while(itt.hasNext()) {
1154                            cdb=(ChartDataBean) itt.next();
1155                            if(smallest>cdb.getValue())smallest=cdb.getValue();
1156                            if(biggest<cdb.getValue())biggest=cdb.getValue();
1157                            //if(seriesCount>1)
1158                            
1159                            dataset.addValue(cdb.getValue(), label,cdb.getItemAsString());
1160                            
1161                            //else dataset.addValue(cdb.getValue(), cdb.getItem(),"");
1162                            
1163                    
1164                    }
1165            }
1166            if(!hasLabels)showlegend=false;
1167            return dataset;
1168        }
1169            private XYDataset createTimeSeriesCollection() {
1170                    TimeZone tz = ThreadLocalPageContext.getTimeZone();
1171                    final TimeSeriesCollection coll=new TimeSeriesCollection(tz);
1172                    
1173            //final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
1174            Iterator<ChartSeriesBean> it = _series.iterator();
1175            //int seriesCount=_series.size();
1176            Iterator itt;
1177            List datas;
1178            ChartSeriesBean csb;
1179            ChartDataBean cdb;
1180            int count=0;
1181            smallest=Double.MAX_VALUE;
1182            biggest = Double.MIN_VALUE;
1183            String label;
1184            boolean hasLabels=false;
1185            while(it.hasNext()) {
1186                    count++;
1187                    csb=it.next();
1188                    label=csb.getSeriesLabel();
1189                    if(StringUtil.isEmpty(label))label=""+count;
1190                    else hasLabels=true;
1191                    datas = csb.getDatas();
1192                    if(sortxaxis)Collections.sort(datas);
1193                itt=datas.iterator();
1194                TimeSeries ts=new TimeSeries(label,Second.class);
1195                while(itt.hasNext()) {
1196                            cdb=(ChartDataBean) itt.next();
1197                            if(smallest>cdb.getValue())smallest=cdb.getValue();
1198                            if(biggest<cdb.getValue())biggest=cdb.getValue();
1199                            //if(seriesCount>1)
1200                            ts.addOrUpdate(new Second(DateCaster.toDateSimple(cdb.getItem(),false,false, tz,null)), cdb.getValue());
1201                            
1202                            //else dataset.addValue(cdb.getValue(), cdb.getItem(),"");
1203                            
1204                    
1205                    }
1206                coll.addSeries(ts);
1207            }
1208            if(!hasLabels)showlegend=false;
1209            return coll;
1210        }
1211    
1212            /**
1213             * @param url the url to set
1214             */
1215            public void setUrl(String url) {
1216                    this.url = url;
1217            }
1218    
1219            /**
1220             * @param xoffset the xoffset to set
1221             */
1222            public void setXoffset(double xoffset) {
1223                    this.xoffset = xoffset;
1224            }
1225    
1226            /**
1227             * @param yoffset the yoffset to set
1228             */
1229            public void setYoffset(double yoffset) {
1230                    this.yoffset = yoffset;
1231            }
1232    
1233            /**
1234             * @param yaxistype the yaxistype to set
1235             */
1236            public void setYaxistype(String yaxistype) {
1237                    this.yaxistype = yaxistype;
1238            }
1239            /**
1240             * @param yaxistype the yaxistype to set
1241             */
1242            public void setXaxistype(String xaxistype) {
1243                    this.xaxistype = xaxistype;
1244            }
1245            
1246    }