0001: /*********************************************************************************
0002: * The contents of this file are subject to the OpenI Public License Version 1.0
0003: * ("License"); You may not use this file except in compliance with the
0004: * License. You may obtain a copy of the License at
0005: * http://www.openi.org/docs/LICENSE.txt
0006: *
0007: * Software distributed under the License is distributed on an "AS IS" basis,
0008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
0009: * the specific language governing rights and limitations under the License.
0010: *
0011: * The Original Code is: OpenI Open Source
0012: *
0013: * The Initial Developer of the Original Code is Loyalty Matrix, Inc.
0014: * Portions created by Loyalty Matrix, Inc. are
0015: * Copyright (C) 2005 Loyalty Matrix, Inc.; All Rights Reserved.
0016: *
0017: * Contributor(s): ______________________________________.
0018: *
0019: ********************************************************************************/package org.openi.chart;
0020:
0021: import java.awt.Color;
0022: import java.awt.Font;
0023: import java.io.ByteArrayInputStream;
0024: import java.io.InputStream;
0025: import java.util.Iterator;
0026: import java.util.List;
0027: import java.util.Locale;
0028:
0029: import javax.servlet.http.HttpSession;
0030: import javax.xml.parsers.DocumentBuilder;
0031:
0032: import org.apache.log4j.Logger;
0033: import org.jfree.chart.ChartRenderingInfo;
0034: import org.jfree.chart.JFreeChart;
0035: import org.jfree.chart.entity.ChartEntity;
0036: import org.jfree.chart.entity.EntityCollection;
0037: import org.jfree.chart.entity.StandardEntityCollection;
0038: import org.jfree.chart.servlet.ServletUtilities;
0039: import org.jfree.chart.urls.StandardCategoryURLGenerator;
0040: import org.jfree.chart.urls.StandardPieURLGenerator;
0041: import org.jfree.data.category.CategoryDataset;
0042: import org.jfree.data.category.DefaultCategoryDataset;
0043: import org.jfree.data.general.PieDataset;
0044: import org.jfree.util.TableOrder;
0045: import org.openi.project.ProjectContext;
0046: import org.w3c.dom.Document;
0047: import org.w3c.dom.Element;
0048:
0049: import com.tonbeller.jpivot.chart.ChartComponent;
0050: import com.tonbeller.jpivot.core.ModelChangeEvent;
0051: import com.tonbeller.jpivot.core.ModelChangeListener;
0052: import com.tonbeller.jpivot.olap.model.Cell;
0053: import com.tonbeller.jpivot.olap.model.OlapModel;
0054: import com.tonbeller.jpivot.olap.model.Result;
0055: import com.tonbeller.jpivot.olap.navi.DrillThrough;
0056: import com.tonbeller.wcf.component.Component;
0057: import com.tonbeller.wcf.controller.Dispatcher;
0058: import com.tonbeller.wcf.controller.DispatcherSupport;
0059: import com.tonbeller.wcf.controller.RequestContext;
0060: import com.tonbeller.wcf.controller.RequestListener;
0061: import com.tonbeller.wcf.table.ITableComponent;
0062: import com.tonbeller.wcf.table.TableModel;
0063: import com.tonbeller.wcf.utils.DomUtils;
0064: import com.tonbeller.wcf.utils.XmlUtils;
0065:
0066: /**
0067: * Started as an exact copy of com.tonbeller.jpivot.chart.ChartComponent. Needed
0068: * to enhance the render functionality to handle different series colors and palettes.
0069: * There was no way to overload, override that functionality without copying a significant amount
0070: * of the class, so here is a complete copy. Will likely evolve into something quite different.
0071: */
0072: public class EnhancedChartComponent extends ChartComponent implements
0073: ModelChangeListener {
0074: private static Logger logger = Logger
0075: .getLogger(EnhancedChartComponent.class);
0076: protected String ref;
0077: protected Document document;
0078: protected OlapModel olapModel;
0079: protected boolean dirty = true;
0080: protected Locale locale;
0081:
0082: // protected Result result;
0083: // protected Iterator cellIterator;
0084: // protected int dimCount;
0085: protected Element rootElement;
0086: protected int colCount;
0087:
0088: // servlet mapping - optionally can be set as a servlet context parameter
0089: // with name "chartServlet"
0090: // for example:
0091: protected String CHART_SERVLET = "/DisplayChart";
0092: final String CHART_SERVLET_KEY = "chartServlet";
0093: protected String filename = null;
0094:
0095: // chart properties
0096: public static final int DEFAULT_CHART_WIDTH = 500;
0097: public static final int DEFAULT_CHART_HEIGHT = 300;
0098: final static double DEFAULT_LEGEND_WIDTH = 100.0;
0099: protected String chartTitle = "";
0100: protected java.awt.Font titleFont = JFreeChart.DEFAULT_TITLE_FONT;
0101: protected String fontName = "SansSerif";
0102: protected int fontStyle = java.awt.Font.BOLD;
0103: protected int fontSize = 18;
0104: protected String slicerFontName = "SansSerif";
0105: protected int slicerFontStyle = java.awt.Font.PLAIN;
0106: protected int slicerFontSize = 12;
0107: protected String axisFontName = "SansSerif";
0108: protected int axisFontStyle = java.awt.Font.PLAIN;
0109: protected int axisFontSize = 12;
0110: protected String axisTickFontName = "SansSerif";
0111: protected int axisTickFontStyle = java.awt.Font.PLAIN;
0112: protected int axisTickFontSize = 10;
0113: protected String legendFontName = "SansSerif";
0114: protected int legendFontStyle = java.awt.Font.PLAIN;
0115: protected int legendFontSize = 10;
0116: protected int legendPosition = 3;//RectangleEdge.RIGHT;//Legend.EAST;
0117: protected int slicerPosition = 1;//Title.BOTTOM;
0118: protected int slicerAlignment = 0;//Title.CENTER;
0119:
0120: //java.awt.Color bgColor = java.awt.Color.white;
0121: protected int bgColorR = 255;
0122: protected int bgColorG = 255;
0123: protected int bgColorB = 255;
0124: protected int chartType = 1;
0125: protected int chartHeight = DEFAULT_CHART_HEIGHT;
0126: protected int chartWidth = DEFAULT_CHART_WIDTH;
0127: protected String horizAxisLabel = "";
0128: protected String vertAxisLabel = "";
0129: protected boolean showLegend = true;
0130: protected boolean showSlicer = true;
0131: protected boolean showTooltips = true;
0132: protected boolean drillThroughEnabled = true;
0133: protected int tickLabelRotate = 30; //default 30 degree rotation
0134: protected ChartRenderingInfo info = null;
0135: protected Dispatcher dispatcher = new DispatcherSupport();
0136: protected List colorPalette;
0137:
0138: /*As there is no float type formatter in com.tonbeller.wcf.format.BasicTypes class, making
0139: foregroundAlpha as double type. But in library, this field of float type. So need to cast into
0140: float type while setting foreground alpha for chart.
0141: */
0142: protected double foregroundAlpha = 1.0;
0143: protected boolean showPareto = false;
0144: protected boolean useChartSize = false; // chart size based on saved width and height.
0145: // private boolean rangeIsPercentage = true;
0146: // private boolean rangeIsCurrency = true;
0147: //private boolean rangeIsDefault = true;
0148: private boolean writeImageMap = true;
0149:
0150: /**
0151: * Constructor
0152: * @param id the id of this component
0153: * @param ref a reference to an olap model
0154: */
0155: public EnhancedChartComponent(String id, Component parent,
0156: String ref, RequestContext context) {
0157: super (id, parent, ref, context);
0158: this .ref = ref;
0159: this .olapModel = (OlapModel) context.getModelReference(ref);
0160: this .olapModel.addModelChangeListener(this );
0161:
0162: ProjectContext prjctx = (ProjectContext) context.getSession()
0163: .getAttribute("projectContext");
0164: this .locale = prjctx.getUser().getLocale();
0165:
0166: // extend the controller
0167: getDispatcher().addRequestListener(null, null, dispatcher);
0168:
0169: // optional servlet context parameter for chart servlet location
0170: String chartServlet = context.getServletContext()
0171: .getInitParameter(CHART_SERVLET_KEY);
0172:
0173: if (chartServlet != null) {
0174: this .CHART_SERVLET = chartServlet;
0175: }
0176: }
0177:
0178: /**
0179: * called once by the creating tag
0180: */
0181: public void initialize(RequestContext context) throws Exception {
0182: super .initialize(context);
0183: }
0184:
0185: /**
0186: * Entry point for producing charts, called by wcf render tag.
0187: * Produces a jfreechart dataset from olap model, then creates a chart and
0188: * writes it to the servlet container temp directory.
0189: * Returns a DOM document for Renderer to transform into html.
0190: * Requires that jfreechart servlet is installed in this application context.
0191: */
0192: public Document render(RequestContext context) throws Exception {
0193: // check if we need to produce a new chart
0194: if (dirty) {
0195: // clear old listeners
0196: dispatcher.clear();
0197: // this.result = olapModel.getResult();
0198: // this.cellIterator = result.getCells().iterator();
0199: // this.dimCount = result.getAxes().length;
0200: //rangeIsPercentage = false;
0201: //rangeIsCurrency = false;
0202: // rangeIsDefault = false;
0203:
0204: // re-set dirty flag
0205: dirty = false;
0206:
0207: //set X/Y Axis Label
0208: try {
0209: logger.debug("trying to build axis labels");
0210:
0211: AxisLabelGenerator axisLabeller = new AxisLabelGenerator();
0212: this .setHorizAxisLabel(axisLabeller
0213: .getHorizAxisLabel(this .getOlapModel()));
0214: this .setVertAxisLabel(axisLabeller
0215: .getVertAxisLabel(this .getOlapModel()));
0216: } catch (Exception e) {
0217: logger.error("Error generating axis label:\n" + e);
0218: }
0219: // DefaultCategoryDataset dataset = new DatasetAdapter().buildCategoryDataset(this.getOlapModel());
0220:
0221: JFreeChart chart = EnhancedChartFactory.createChart(
0222: olapModel, chartType, chartTitle, horizAxisLabel,
0223: vertAxisLabel, showLegend, showTooltips,
0224: drillThroughEnabled, titleFont, new Color(this
0225: .getBgColorR(), this .getBgColorG(), this
0226: .getBgColorB()), new Font(this
0227: .getSlicerFontName(), this
0228: .getSlicerFontStyle(), this
0229: .getSlicerFontSize()), new Font(this
0230: .getAxisFontName(),
0231: this .getAxisFontStyle(), this
0232: .getAxisFontSize()), new Font(this
0233: .getAxisTickFontName(), this
0234: .getAxisTickFontStyle(), this
0235: .getAxisTickFontSize()), new Font(this
0236: .getLegendFontName(), this
0237: .getLegendFontStyle(), this
0238: .getLegendFontSize()), legendPosition,
0239: tickLabelRotate, 1.0f, showSlicer, slicerPosition,
0240: slicerAlignment, showPareto, this .locale);
0241:
0242: try {
0243: /*
0244: ChartCustomizer customizer = new ChartCustomizer();
0245: customizer.customizeChart(this, dataset, chart);
0246: */
0247:
0248: info = new ChartRenderingInfo(
0249: new StandardEntityCollection());
0250:
0251: // Write the chart image to the temporary directory
0252: HttpSession session = context.getSession();
0253: filename = ServletUtilities.saveChartAsPNG(chart,
0254: chartWidth, chartHeight, info, session);
0255: } catch (Exception e) {
0256: logger.error(e);
0257: filename = "public_error_500x300.png";
0258: dirty = true;
0259: }
0260: }
0261:
0262: // new DOM document
0263: DocumentBuilder parser = XmlUtils.getParser();
0264:
0265: // get an image map for the chart, wrap it in xchart tags
0266: // temporarily commenting out - with our < chars, breaks with a SAXException
0267: String xchart = null;
0268:
0269: // see org.jfree.chart.ChartUtilities.writeImageMap(..)
0270: if (this .getWriteImageMap()) {
0271: xchart = "<xchart>" + writeImageMap(filename, info, false)
0272: + "</xchart>";
0273: } else {
0274: xchart = "<xchart/>";
0275: }
0276:
0277: // create an InputStream from the DOM document
0278: InputStream stream = new ByteArrayInputStream(xchart
0279: .getBytes("UTF-8"));
0280:
0281: document = parser.parse(stream);
0282:
0283: Element root = document.getDocumentElement();
0284:
0285: // create url for img tag
0286: String graphURL = context.getRequest().getContextPath()
0287: + CHART_SERVLET + "?filename=" + filename;
0288: Element img = document.createElement("img");
0289: img.setAttribute("src", graphURL);
0290: img.setAttribute("width", new Integer(chartWidth).toString());
0291: img.setAttribute("height", new Integer(chartHeight).toString());
0292: img.setAttribute("style", "border:0;");
0293: img.setAttribute("usemap", "#" + filename);
0294: root.appendChild(img);
0295:
0296: return document;
0297: }
0298:
0299: /**
0300: * Writes an image map as a String
0301: * This function has been requested to be added to jfreechart
0302: * Also requires slight change to ChartEntity.getImageMapAreaTag()
0303: * to produce valid xml tag and use & entity in urls.
0304: * Diffs sent to jfreechart project - so hopefully this will be in there soon
0305: *
0306: * @param name the map name.
0307: * @param info the chart rendering info.
0308: * @param useOverLibForToolTips whether to use OverLIB for tooltips
0309: * (http://www.bosrup.com/web/overlib/).
0310: */
0311: public String writeImageMap(String name, ChartRenderingInfo info,
0312: boolean useOverLibForToolTips) {
0313: StringBuffer sb = new StringBuffer();
0314: sb.append("<map name=\"" + name + "\">");
0315: EntityCollection entities = info.getEntityCollection();
0316: Iterator iterator = entities.iterator();
0317:
0318: while (iterator.hasNext()) {
0319: ChartEntity entity = (ChartEntity) iterator.next();
0320: // the tag returned by getImageMapAreaTag is not valid xml
0321: //String area = entity.getImageMapAreaTag(useOverLibForToolTips);
0322:
0323: String area = "";
0324:
0325: if (useOverLibForToolTips)
0326: area = entity
0327: .getImageMapAreaTag(
0328: new org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator(),
0329: new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator());
0330: else
0331: area = entity
0332: .getImageMapAreaTag(
0333: new org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator(),
0334: new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator());
0335: // modify to valid xml tag
0336: area = area.replaceAll("&", "&");
0337: //area = area.toLowerCase();
0338: //area = area.replaceAll(">$", "/>");
0339: if (area.length() > 0) {
0340: sb.append(area);
0341: }
0342: }
0343: sb.append("</map>");
0344: return sb.toString();
0345: }
0346:
0347: /*public String writeImageMap(String name, ChartRenderingInfo info,
0348: boolean useOverLibForToolTips) {
0349: StringBuffer sb = new StringBuffer();
0350: sb.append("<map name=\"" + name + "\">");
0351:
0352: EntityCollection entities = info.getEntityCollection();
0353: Iterator iterator = entities.iterator();
0354:
0355: while (iterator.hasNext()) {
0356: ChartEntity entity = (ChartEntity) iterator.next();
0357:
0358: // the tag returned by getImageMapAreaTag is not valid xml
0359: //String area = entity.getImageMapAreaTag(useOverLibForToolTips);
0360: String area = "";
0361:
0362: // logger.debug("useOverLibForToolTips=" + useOverLibForToolTips);
0363: if (useOverLibForToolTips) {
0364: area = entity.getImageMapAreaTag(new org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator(),
0365: new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator());
0366: } else {
0367: area = entity.getImageMapAreaTag(new org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator(),
0368: new org.jfree.chart.imagemap.StandardURLTagFragmentGenerator());
0369: }
0370:
0371: // modify to valid xml tag
0372: area = area.replaceAll("&", "&");
0373:
0374: //area = area.toLowerCase();
0375: area = area.replaceAll(">$", "/>");
0376:
0377: // can't do this one, b/c the image map will not work (just displays as html)
0378: // area = area.replaceAll("<", "<");
0379: if (area.length() > 0) {
0380: sb.append(area);
0381: }
0382: }
0383:
0384: sb.append("</map>");
0385:
0386: return sb.toString();
0387: }*/
0388:
0389: /**
0390: * @return
0391: */
0392: public int getColCount() {
0393: return colCount;
0394: }
0395:
0396: /**
0397: * true means that render() will create a new chart
0398: */
0399: public boolean isDirty() {
0400: return dirty;
0401: }
0402:
0403: public void setDirty(boolean dirty) {
0404: this .dirty = dirty;
0405: }
0406:
0407: public void modelChanged(ModelChangeEvent e) {
0408: this .dirty = true;
0409: }
0410:
0411: public void structureChanged(ModelChangeEvent e) {
0412: this .dirty = true;
0413: }
0414:
0415: /**
0416: * @return
0417: */
0418: public int getChartHeight() {
0419: return chartHeight;
0420: }
0421:
0422: /**
0423: * @param chartHeight
0424: */
0425: public void setChartHeight(int chartHeight) {
0426: this .chartHeight = chartHeight;
0427: this .dirty = true;
0428: }
0429:
0430: /**
0431: * @return
0432: */
0433: public String getChartTitle() {
0434: return chartTitle;
0435: }
0436:
0437: /**
0438: * @param chartTitle
0439: */
0440: public void setChartTitle(String chartTitle) {
0441: this .chartTitle = chartTitle;
0442: this .dirty = true;
0443: }
0444:
0445: /**
0446: * @return
0447: */
0448: public int getChartType() {
0449: return chartType;
0450: }
0451:
0452: /**
0453: * @param chartType
0454: */
0455: public void setChartType(int chartType) {
0456: this .chartType = chartType;
0457: this .dirty = true;
0458: }
0459:
0460: /**
0461: * @return
0462: */
0463: public int getChartWidth() {
0464: return chartWidth;
0465: }
0466:
0467: /**
0468: * @param chartWidth
0469: */
0470: public void setChartWidth(int chartWidth) {
0471: this .chartWidth = chartWidth;
0472: this .dirty = true;
0473: }
0474:
0475: /**
0476: * @return
0477: */
0478: public String getHorizAxisLabel() {
0479: return horizAxisLabel;
0480: }
0481:
0482: /**
0483: * @param axisLabel
0484: */
0485: public void setHorizAxisLabel(String axisLabel) {
0486: horizAxisLabel = axisLabel;
0487: this .dirty = true;
0488: }
0489:
0490: /**
0491: * @return
0492: */
0493: public boolean getShowLegend() {
0494: return showLegend;
0495: }
0496:
0497: /**
0498: * @param showLegend
0499: */
0500: public void setShowLegend(boolean showLegend) {
0501: this .showLegend = showLegend;
0502: this .dirty = true;
0503: }
0504:
0505: /**
0506: * @return
0507: */
0508: public String getFontName() {
0509: return fontName;
0510: }
0511:
0512: /**
0513: * @param titleFont
0514: */
0515: public void setFontName(String fontname) {
0516: this .fontName = fontname;
0517: this .dirty = true;
0518: }
0519:
0520: /**
0521: * @return
0522: */
0523: public String getVertAxisLabel() {
0524: return vertAxisLabel;
0525: }
0526:
0527: /**
0528: * @param axisLabel
0529: */
0530: public void setVertAxisLabel(String axisLabel) {
0531: vertAxisLabel = axisLabel;
0532: this .dirty = true;
0533: }
0534:
0535: /**
0536: * @return
0537: */
0538: public int getFontSize() {
0539: return fontSize;
0540: }
0541:
0542: /**
0543: * @param fontSize
0544: */
0545: public void setFontSize(int fontSize) {
0546: this .fontSize = fontSize;
0547: this .dirty = true;
0548: }
0549:
0550: /**
0551: * @return
0552: */
0553: public int getFontStyle() {
0554: return fontStyle;
0555: }
0556:
0557: /**
0558: * @param fontStyle
0559: */
0560: public void setFontStyle(int fontStyle) {
0561: this .fontStyle = fontStyle;
0562: this .dirty = true;
0563: }
0564:
0565: /**
0566: * @return
0567: */
0568: public int getBgColorB() {
0569: return bgColorB;
0570: }
0571:
0572: /**
0573: * @param bgColorB
0574: */
0575: public void setBgColorB(int bgColorB) {
0576: this .bgColorB = checkRGB(bgColorB);
0577: this .dirty = true;
0578: }
0579:
0580: /**
0581: * @return
0582: */
0583: public int getBgColorG() {
0584: return bgColorG;
0585: }
0586:
0587: /**
0588: * @param bgColorG
0589: */
0590: public void setBgColorG(int bgColorG) {
0591: this .bgColorG = checkRGB(bgColorG);
0592: this .dirty = true;
0593: }
0594:
0595: /**
0596: * @return
0597: */
0598: public int getBgColorR() {
0599: return bgColorR;
0600: }
0601:
0602: /**
0603: * @param bgColorR
0604: */
0605: public void setBgColorR(int bgColorR) {
0606: this .bgColorR = checkRGB(bgColorR);
0607: this .dirty = true;
0608: }
0609:
0610: /**
0611: * Enforce limits of 0 - 255 for RGB values.
0612: */
0613: private int checkRGB(int v) {
0614: if (v > 255) {
0615: v = 255;
0616: } else if (v < 0) {
0617: v = 0;
0618: }
0619:
0620: return v;
0621: }
0622:
0623: protected boolean canDrillThrough(Cell cell) {
0624: return ((DrillThrough) olapModel.getExtension(DrillThrough.ID))
0625: .canDrillThrough((Cell) cell.getRootDecoree());
0626: }
0627:
0628: /**
0629: * returns a DrillThroughTableModel for the drill through
0630: * @param cell
0631: * @return
0632: */
0633: protected TableModel drillThrough(Cell cell) {
0634: return ((DrillThrough) olapModel.getExtension(DrillThrough.ID))
0635: .drillThrough((Cell) cell.getRootDecoree());
0636: }
0637:
0638: public boolean isDrillThroughEnabled() {
0639: return drillThroughEnabled;
0640: }
0641:
0642: public void setDrillThroughEnabled(boolean drillThroughEnabled) {
0643: this .drillThroughEnabled = drillThroughEnabled;
0644: }
0645:
0646: /**
0647: * @return
0648: */
0649: public String getAxisFontName() {
0650: return axisFontName;
0651: }
0652:
0653: /**
0654: * @param axisFontName
0655: */
0656: public void setAxisFontName(String axisFontName) {
0657: this .axisFontName = axisFontName;
0658: }
0659:
0660: /**
0661: * @return
0662: */
0663: public int getAxisFontSize() {
0664: return axisFontSize;
0665: }
0666:
0667: /**
0668: * @param axisFontSize
0669: */
0670: public void setAxisFontSize(int axisFontSize) {
0671: this .axisFontSize = axisFontSize;
0672: }
0673:
0674: /**
0675: * @return
0676: */
0677: public int getAxisFontStyle() {
0678: return axisFontStyle;
0679: }
0680:
0681: /**
0682: * @param axisFontStyle
0683: */
0684: public void setAxisFontStyle(int axisFontStyle) {
0685: this .axisFontStyle = axisFontStyle;
0686: }
0687:
0688: /**
0689: * @return
0690: */
0691: public String getLegendFontName() {
0692: return legendFontName;
0693: }
0694:
0695: /**
0696: * @param legendFontName
0697: */
0698: public void setLegendFontName(String legendFontName) {
0699: this .legendFontName = legendFontName;
0700: }
0701:
0702: /**
0703: * @return
0704: */
0705: public int getLegendFontSize() {
0706: return legendFontSize;
0707: }
0708:
0709: /**
0710: * @param legendFontSize
0711: */
0712: public void setLegendFontSize(int legendFontSize) {
0713: this .legendFontSize = legendFontSize;
0714: }
0715:
0716: /**
0717: * @return
0718: */
0719: public int getLegendFontStyle() {
0720: return legendFontStyle;
0721: }
0722:
0723: /**
0724: * @param legendFontStyle
0725: */
0726: public void setLegendFontStyle(int legendFontStyle) {
0727: this .legendFontStyle = legendFontStyle;
0728: }
0729:
0730: /**
0731: * @return
0732: */
0733: public int getSlicerAlignment() {
0734: return slicerAlignment;
0735: }
0736:
0737: /**
0738: * @param slicerAlignment
0739: */
0740: public void setSlicerAlignment(int slicerAlignment) {
0741: this .slicerAlignment = slicerAlignment;
0742: }
0743:
0744: /**
0745: * @return
0746: */
0747: public String getSlicerFontName() {
0748: return slicerFontName;
0749: }
0750:
0751: /**
0752: * @param slicerFontName
0753: */
0754: public void setSlicerFontName(String slicerFontName) {
0755: this .slicerFontName = slicerFontName;
0756: }
0757:
0758: /**
0759: * @return
0760: */
0761: public int getSlicerFontSize() {
0762: return slicerFontSize;
0763: }
0764:
0765: /**
0766: * @param slicerFontSize
0767: */
0768: public void setSlicerFontSize(int slicerFontSize) {
0769: this .slicerFontSize = slicerFontSize;
0770: }
0771:
0772: /**
0773: * @return
0774: */
0775: public int getSlicerFontStyle() {
0776: return slicerFontStyle;
0777: }
0778:
0779: /**
0780: * @param slicerFontStyle
0781: */
0782: public void setSlicerFontStyle(int slicerFontStyle) {
0783: this .slicerFontStyle = slicerFontStyle;
0784: }
0785:
0786: /**
0787: * @return
0788: */
0789: public int getSlicerPosition() {
0790: return slicerPosition;
0791: }
0792:
0793: /**
0794: * @param slicerPosition
0795: */
0796: public void setSlicerPosition(int slicerPosition) {
0797: this .slicerPosition = slicerPosition;
0798: }
0799:
0800: /**
0801: * @return
0802: */
0803: public int getLegendPosition() {
0804: return legendPosition;
0805: }
0806:
0807: /**
0808: * @param legendPosition
0809: */
0810: public void setLegendPosition(int legendPosition) {
0811: this .legendPosition = legendPosition;
0812: }
0813:
0814: /**
0815: * @return
0816: */
0817: public String getAxisTickFontName() {
0818: return axisTickFontName;
0819: }
0820:
0821: /**
0822: * @param axisTickFontName
0823: */
0824: public void setAxisTickFontName(String axisTickFontName) {
0825: this .axisTickFontName = axisTickFontName;
0826: }
0827:
0828: /**
0829: * @return
0830: */
0831: public int getAxisTickFontSize() {
0832: return axisTickFontSize;
0833: }
0834:
0835: /**
0836: * @param axisTickFontSize
0837: */
0838: public void setAxisTickFontSize(int axisTickFontSize) {
0839: this .axisTickFontSize = axisTickFontSize;
0840: }
0841:
0842: /**
0843: * @return
0844: */
0845: public int getAxisTickFontStyle() {
0846: return axisTickFontStyle;
0847: }
0848:
0849: /**
0850: * @param axisTickFontStyle
0851: */
0852: public void setAxisTickFontStyle(int axisTickFontStyle) {
0853: this .axisTickFontStyle = axisTickFontStyle;
0854: }
0855:
0856: /**
0857: * @return Returns the tickLabelRotate.
0858: */
0859: public int getTickLabelRotate() {
0860: return tickLabelRotate;
0861: }
0862:
0863: /**
0864: * @param tickLabelRotate The tickLabelRotate to set.
0865: */
0866: public void setTickLabelRotate(int tickLabelRotate) {
0867: this .tickLabelRotate = tickLabelRotate;
0868: }
0869:
0870: /**
0871: * @return
0872: */
0873: public boolean isShowSlicer() {
0874: return showSlicer;
0875: }
0876:
0877: /**
0878: * @param showSlicer
0879: */
0880: public void setShowSlicer(boolean showSlicer) {
0881: this .showSlicer = showSlicer;
0882: }
0883:
0884: /**
0885: * @return
0886: */
0887: public String getFilename() {
0888: return filename;
0889: }
0890:
0891: /**
0892: * @return Returns the colorPalette.
0893: */
0894: public List getColorPalette() {
0895: return colorPalette;
0896: }
0897:
0898: /**
0899: * @param colorPalette The colorPalette to set.
0900: */
0901: public void setColorPalette(List seriesPalette) {
0902: this .colorPalette = seriesPalette;
0903: }
0904:
0905: /**
0906: * @return Returns the generatePareto.
0907: */
0908: public boolean getShowPareto() {
0909: return showPareto;
0910: }
0911:
0912: public double getForegroundAlpha() {
0913: return foregroundAlpha;
0914: }
0915:
0916: public boolean isUseChartSize() {
0917: return useChartSize;
0918: }
0919:
0920: /**
0921: * @param generatePareto The generatePareto to set.
0922: */
0923: public void setShowPareto(boolean showPareto) {
0924: this .showPareto = showPareto;
0925: }
0926:
0927: public void setForegroundAlpha(double foregroundAlpha) {
0928: this .foregroundAlpha = foregroundAlpha;
0929: }
0930:
0931: public void setUseChartSize(boolean useChartSize) {
0932: this .useChartSize = useChartSize;
0933: }
0934:
0935: /**
0936: * @return Returns the writeImageMap.
0937: */
0938: public boolean getWriteImageMap() {
0939: return writeImageMap;
0940: }
0941:
0942: /**
0943: * @param writeImageMap The writeImageMap to set.
0944: */
0945: public void setWriteImageMap(boolean writeImageMap) {
0946: this .writeImageMap = writeImageMap;
0947: }
0948:
0949: public OlapModel getOlapModel() {
0950: return olapModel;
0951: }
0952:
0953: public void setOlapModel(OlapModel olapModel) {
0954: this .olapModel = olapModel;
0955: }
0956:
0957: /**
0958: * A URLGenerator class to generate pie urls that work with jpivot
0959: * @author ati
0960: *
0961: */
0962: public class jpivotPieURLGenerator extends StandardPieURLGenerator {
0963: /** Prefix to the URL */
0964: private String prefix = "";
0965: private List cells = null;
0966: private int rowCount;
0967: private TableOrder order; // COLUMN or ROW - used to calculate cell Position
0968:
0969: jpivotPieURLGenerator(Result result) {
0970: cells = result.getCells();
0971: }
0972:
0973: jpivotPieURLGenerator(String prefix) {
0974: this .prefix = prefix;
0975: }
0976:
0977: /*
0978: * Use this constructor to set dataExtraction type (PER_COLUMN/PER_ROW), and allow for
0979: * rowcount of current dataset (could be changed to just take rowCount)
0980: */
0981: jpivotPieURLGenerator(TableOrder order,
0982: DefaultCategoryDataset dataset) {
0983: this .order = order;
0984: this .rowCount = dataset.getRowCount();
0985: }
0986:
0987: /**
0988: * Implementation of generateURL that integrates with jpivot/wcf framework.
0989: * A request handler is added for each cell/item.
0990: * No test is done to see if a cell is drillable, since the url has to added (I think, like an all or nothing ?)
0991: * Generates a URL for a particular item within a series.
0992: *
0993: * @param data the dataset.
0994: * @param key the data item key.
0995: * @param pieIndex the index of the pie containing key (zero-based).
0996: *
0997: * @return the generated URL
0998: */
0999: public String generateURL(PieDataset data, Comparable key,
1000: int pieIndex) {
1001: String url = prefix;
1002: int index = data.getIndex(key);
1003:
1004: int cellpos;
1005:
1006: // if cells is null, initialize cells
1007: if (cells == null) {
1008: try {
1009: cells = olapModel.getResult().getCells();
1010: } catch (Exception e) {
1011: logger.error(e);
1012: }
1013: }
1014:
1015: if (order == TableOrder.BY_COLUMN) {
1016: cellpos = (pieIndex * rowCount) + index;
1017: } else {
1018: cellpos = pieIndex + (rowCount * index);
1019: }
1020:
1021: if (canDrillThrough((Cell) cells.get(cellpos))
1022: && (!((Cell) cells.get(cellpos)).isNull())) {
1023: String id = DomUtils.randomId();
1024: dispatcher.addRequestListener(id, null,
1025: new DrillThroughHandler((Cell) cells
1026: .get(cellpos)));
1027:
1028: boolean firstParameter = url.indexOf("?") == -1;
1029: url += (firstParameter ? "?" : "&");
1030: url += id;
1031:
1032: return url;
1033: } else {
1034: return null;
1035: }
1036: }
1037: }
1038:
1039: /**
1040: * A URLGenerator class to generate chart urls that work with jpivot
1041: * @author robin
1042: *
1043: */
1044: public class jpivotCategoryURLGenerator extends
1045: StandardCategoryURLGenerator {
1046: /** Prefix to the URL */
1047: private String prefix = "";
1048:
1049: /** Series parameter name to go in each URL */
1050: private String seriesParameterName = "col";
1051:
1052: /** Category parameter name to go in each URL */
1053: private String categoryParameterName = "row";
1054: private List cells = null;
1055:
1056: jpivotCategoryURLGenerator(Result result) {
1057: cells = result.getCells();
1058: }
1059:
1060: jpivotCategoryURLGenerator(Result result, String prefix) {
1061: this .prefix = prefix;
1062: cells = result.getCells();
1063: }
1064:
1065: /**
1066: * Implementation of generateURL that integrates with jpivot/wcf framework.
1067: * A request handler is added for each cell/item.
1068: * No test is done to see if a cell is drillable, since the url has to added (I think, like an all or nothing ?)
1069: * Generates a URL for a particular item within a series.
1070: *
1071: * @param data the dataset.
1072: * @param series the series index (zero-based).
1073: * @param category the category index (zero-based).
1074: *
1075: * @return the generated URL
1076: */
1077: public String generateURL(CategoryDataset data, int series,
1078: int category) {
1079: String url = prefix;
1080:
1081: // convert col, row into ordinal
1082: // series is col, category is row
1083: // (reverese terminology to jfreechart, that way series on measures which is more logical)
1084: int cellpos = (category * colCount) + series;
1085:
1086: if (canDrillThrough((Cell) cells.get(cellpos))
1087: && (!((Cell) cells.get(cellpos)).isNull())) {
1088: String id = DomUtils.randomId();
1089: dispatcher.addRequestListener(id, null,
1090: new DrillThroughHandler((Cell) cells
1091: .get(cellpos)));
1092:
1093: boolean firstParameter = url.indexOf("?") == -1;
1094: url += (firstParameter ? "?" : "&");
1095: url += id;
1096:
1097: return url;
1098: } else {
1099: return null;
1100: }
1101: }
1102: }
1103:
1104: /**
1105: * request handler for chart drill through
1106: * does nothing if cell can't be drilled through (e.g. calculated measure)
1107: * @author robin
1108: *
1109: */
1110:
1111: // class DrillThroughHandler implements RequestListener {
1112: // Cell cell;
1113: // DrillThroughHandler(Cell cell) {
1114: // this.cell = cell;
1115: // }
1116: // public void request(RequestContext context) throws Exception {
1117: //
1118: // if ( canDrillThrough(cell) ) {
1119: //
1120: // HttpSession session = context.getSession();
1121: // final String drillTableRef = olapModel.getID() + ".drillthroughtable";
1122: // com.tonbeller.wcf.table.TableComponent tc =
1123: // (com.tonbeller.wcf.table.TableComponent)
1124: // session.getAttribute(drillTableRef);
1125: // // get a new drill through table model
1126: // TableModel tm = drillThrough(cell);
1127: //
1128: // // need to create a new table model for each drill through request
1129: // // because table model creates an array of columns
1130: // tc = new com.tonbeller.wcf.table.TableComponent(drillTableRef, tm);
1131: // tc.initialize(context);
1132: // ((DefaultSelectionModel) tc.getSelectionModel()).setMode(SelectionModel.NO_SELECTION);
1133: // session.setAttribute(drillTableRef, tc);
1134: // tc.setVisible(true);
1135: // }
1136: // }
1137: // }
1138: class DrillThroughHandler implements RequestListener {
1139: Cell cell;
1140:
1141: DrillThroughHandler(Cell cell) {
1142: this .cell = cell;
1143: }
1144:
1145: public void request(RequestContext context) throws Exception {
1146: if (canDrillThrough(cell)) {
1147: HttpSession session = context.getSession();
1148: final String drillTableRef = olapModel.getID()
1149: + ".drillthroughtable";
1150: ITableComponent tc = (ITableComponent) session
1151: .getAttribute(drillTableRef);
1152:
1153: // get a new drill through table model
1154: TableModel tm = drillThrough(cell);
1155: tc.setModel(tm);
1156: tc.setVisible(true);
1157: }
1158: }
1159: }
1160: }
|