    001/* ===========================================================
    002 * JFreeChart : a free chart library for the Java(tm) platform
    003 * ===========================================================
    004 *
    005 * (C) Copyright 2000-2011, by Object Refinery Limited and Contributors.
    006 *
    007 * Project Info:  http://www.jfree.org/jfreechart/index.html
    008 *
    009 * This library is free software; you can redistribute it and/or modify it
    010 * under the terms of the GNU Lesser General Public License as published by
    011 * the Free Software Foundation; either version 2.1 of the License, or
    012 * (at your option) any later version.
    013 *
    014 * This library is distributed in the hope that it will be useful, but
    015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    017 * License for more details.
    018 *
    019 * You should have received a copy of the GNU Lesser General Public
    020 * License along with this library; if not, write to the Free Software
    021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    022 * USA.
    023 *
    024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    025 * Other names may be trademarks of their respective owners.]
    026 *
    027 * ----------------------
    028 * ImageMapUtilities.java
    029 * ----------------------
    030 * (C) Copyright 2004-2009, by Richard Atkinson and Contributors.
    031 *
    032 * Original Author:  Richard Atkinson;
    033 * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034 *                   Fawad Halim - bug 2690293;
    035 *
    036 * Changes
    037 * -------
    038 * 02-Aug-2004 : Initial version (RA);
    039 * 13-Jan-2005 : Renamed ImageMapUtilities (DG);
    040 * 19-Jan-2005 : Reversed order of tags for chart entities to get correct
    041 *               layering (DG);
    042 * ------------- JFREECHART 1.0.x ---------------------------------------------
    043 * 06-Feb-2006 : API doc updates (DG);
    044 * 04-Dec-2007 : Added htmlEscape() method, and escape 'name' in
    045 *               getImageMap() (DG);
    046 * 19-Mar-2009 : Added javascriptEscape() method - see bug 2690293 by FH (DG);
    047 * 25-Mar-2009 : Reimplemented javascriptEscape() (DG);
    048 *
    049 */
    050
    051package org.jfree.chart.imagemap;
    052
    053import java.io.IOException;
    054import java.io.PrintWriter;
    055
    056import org.jfree.chart.ChartRenderingInfo;
    057import org.jfree.chart.entity.ChartEntity;
    058import org.jfree.chart.entity.EntityCollection;
    059import org.jfree.util.StringUtils;
    060
    061/**
    062 * Collection of utility methods related to producing image maps.
    063 * Functionality was originally in {@link org.jfree.chart.ChartUtilities}.
    064 */
    065public class ImageMapUtilities {
    066
    067    /**
    068     * Writes an image map to an output stream.
    069     *
    070     * @param writer  the writer (<code>null</code> not permitted).
    071     * @param name  the map name (<code>null</code> not permitted).
    072     * @param info  the chart rendering info (<code>null</code> not permitted).
    073     *
    074     * @throws java.io.IOException if there are any I/O errors.
    075     */
    076    public static void writeImageMap(PrintWriter writer, String name,
    077            ChartRenderingInfo info) throws IOException {
    078
    079        // defer argument checking...
    080        ImageMapUtilities.writeImageMap(writer, name, info,
    081                new StandardToolTipTagFragmentGenerator(),
    082                new StandardURLTagFragmentGenerator());
    083
    084    }
    085
    086    /**
    087     * Writes an image map to an output stream.
    088     *
    089     * @param writer  the writer (<code>null</code> not permitted).
    090     * @param name  the map name (<code>null</code> not permitted).
    091     * @param info  the chart rendering info (<code>null</code> not permitted).
    092     * @param useOverLibForToolTips  whether to use OverLIB for tooltips
    093     *                               (http://www.bosrup.com/web/overlib/).
    094     *
    095     * @throws java.io.IOException if there are any I/O errors.
    096     */
    097    public static void writeImageMap(PrintWriter writer,
    098            String name, ChartRenderingInfo info,
    099            boolean useOverLibForToolTips) throws IOException {
    100
    101        ToolTipTagFragmentGenerator toolTipTagFragmentGenerator = null;
    102        if (useOverLibForToolTips) {
    103            toolTipTagFragmentGenerator
    104                    = new OverLIBToolTipTagFragmentGenerator();
    105        }
    106        else {
    107            toolTipTagFragmentGenerator
    108                    = new StandardToolTipTagFragmentGenerator();
    109        }
    110        ImageMapUtilities.writeImageMap(writer, name, info,
    111                toolTipTagFragmentGenerator,
    112                new StandardURLTagFragmentGenerator());
    113
    114    }
    115
    116    /**
    117     * Writes an image map to an output stream.
    118     *
    119     * @param writer  the writer (<code>null</code> not permitted).
    120     * @param name  the map name (<code>null</code> not permitted).
    121     * @param info  the chart rendering info (<code>null</code> not permitted).
    122     * @param toolTipTagFragmentGenerator  a generator for the HTML fragment
    123     *     that will contain the tooltip text (<code>null</code> not permitted
    124     *     if <code>info</code> contains tooltip information).
    125     * @param urlTagFragmentGenerator  a generator for the HTML fragment that
    126     *     will contain the URL reference (<code>null</code> not permitted if
    127     *     <code>info</code> contains URLs).
    128     *
    129     * @throws java.io.IOException if there are any I/O errors.
    130     */
    131    public static void writeImageMap(PrintWriter writer, String name,
    132            ChartRenderingInfo info,
    133            ToolTipTagFragmentGenerator toolTipTagFragmentGenerator,
    134            URLTagFragmentGenerator urlTagFragmentGenerator)
    135        throws IOException {
    136
    137        writer.println(ImageMapUtilities.getImageMap(name, info,
    138                toolTipTagFragmentGenerator, urlTagFragmentGenerator));
    139    }
    140
    141    /**
    142     * Creates an image map element that complies with the XHTML 1.0
    143     * specification.
    144     *
    145     * @param name  the map name (<code>null</code> not permitted).
    146     * @param info  the chart rendering info (<code>null</code> not permitted).
    147     *
    148     * @return The map element.
    149     */
    150    public static String getImageMap(String name, ChartRenderingInfo info) {
    151        return ImageMapUtilities.getImageMap(name, info,
    152                new StandardToolTipTagFragmentGenerator(),
    153                new StandardURLTagFragmentGenerator());
    154    }
    155
    156    /**
    157     * Creates an image map element that complies with the XHTML 1.0
    158     * specification.
    159     *
    160     * @param name  the map name (<code>null</code> not permitted).
    161     * @param info  the chart rendering info (<code>null</code> not permitted).
    162     * @param toolTipTagFragmentGenerator  a generator for the HTML fragment
    163     *     that will contain the tooltip text (<code>null</code> not permitted
    164     *     if <code>info</code> contains tooltip information).
    165     * @param urlTagFragmentGenerator  a generator for the HTML fragment that
    166     *     will contain the URL reference (<code>null</code> not permitted if
    167     *     <code>info</code> contains URLs).
    168     *
    169     * @return The map tag.
    170     */
    171    public static String getImageMap(String name, ChartRenderingInfo info,
    172            ToolTipTagFragmentGenerator toolTipTagFragmentGenerator,
    173            URLTagFragmentGenerator urlTagFragmentGenerator) {
    174
    175        StringBuffer sb = new StringBuffer();
    176        sb.append("<map id=\"" + htmlEscape(name) + "\" name=\""
    177                + htmlEscape(name) + "\">");
    178        sb.append(StringUtils.getLineSeparator());
    179        EntityCollection entities = info.getEntityCollection();
    180        if (entities != null) {
    181            int count = entities.getEntityCount();
    182            for (int i = count - 1; i >= 0; i--) {
    183                ChartEntity entity = entities.getEntity(i);
    184                if (entity.getToolTipText() != null
    185                        || entity.getURLText() != null) {
    186                    String area = entity.getImageMapAreaTag(
    187                            toolTipTagFragmentGenerator,
    188                            urlTagFragmentGenerator);
    189                    if (area.length() > 0) {
    190                        sb.append(area);
    191                        sb.append(StringUtils.getLineSeparator());
    192                    }
    193                }
    194            }
    195        }
    196        sb.append("</map>");
    197        return sb.toString();
    198
    199    }
    200
    201    /**
    202     * Returns a string that is equivalent to the input string, but with
    203     * special characters converted to HTML escape sequences.
    204     *
    205     * @param input  the string to escape (<code>null</code> not permitted).
    206     *
    207     * @return A string with characters escaped.
    208     *
    209     * @since 1.0.9
    210     */
    211    public static String htmlEscape(String input) {
    212        if (input == null) {
    213            throw new IllegalArgumentException("Null 'input' argument.");
    214        }
    215        StringBuffer result = new StringBuffer();
    216        int length = input.length();
    217        for (int i = 0; i < length; i++) {
    218            char c = input.charAt(i);
    219            if (c == '&') {
    220                result.append("&amp;");
    221            }
    222            else if (c == '\"') {
    223                result.append("&quot;");
    224            }
    225            else if (c == '<') {
    226                result.append("&lt;");
    227            }
    228            else if (c == '>') {
    229                result.append("&gt;");
    230            }
    231            else if (c == '\'') {
    232                result.append("&#39;");
    233            }
    234            else if (c == '\\') {
    235                result.append("&#092;");
    236            }
    237            else {
    238                result.append(c);
    239            }
    240        }
    241        return result.toString();
    242    }
    243
    244    /**
    245     * Returns a string that is equivalent to the input string, but with
    246     * special characters converted to JavaScript escape sequences.
    247     *
    248     * @param input  the string to escape (<code>null</code> not permitted).
    249     *
    250     * @return A string with characters escaped.
    251     *
    252     * @since 1.0.13
    253     */
    254    public static String javascriptEscape(String input) {
    255        if (input == null) {
    256            throw new IllegalArgumentException("Null 'input' argument.");
    257        }
    258        StringBuffer result = new StringBuffer();
    259        int length = input.length();
    260        for (int i = 0; i < length; i++) {
    261            char c = input.charAt(i);
    262            if (c == '\"') {
    263                result.append("\\\"");
    264            }
    265            else if (c == '\'') {
    266                result.append("\\'");
    267            }
    268            else if (c == '\\') {
    269                result.append("\\\\");
    270            }
    271            else {
    272                result.append(c);
    273            }
    274        }
    275        return result.toString();
    276    }
    277}