/**
*
* The MIT License
*
* Copyright (c) 2011 the original author or authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.googlecode.charts4j.parameters;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import com.googlecode.charts4j.AxisStyle;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.Data;
import com.googlecode.charts4j.DataEncoding;
import com.googlecode.charts4j.GeographicalArea;
import com.googlecode.charts4j.LegendPosition;
import com.googlecode.charts4j.LineStyle;
import com.googlecode.charts4j.Marker;
import com.googlecode.charts4j.Priority;
import com.googlecode.charts4j.collect.ImmutableList;
import com.googlecode.charts4j.collect.Lists;
import com.googlecode.charts4j.collect.Maps;
/**
* <b>For Charts4J internal use only.</b> The ParameterManager contains all
* the parameters for a given chart that is being built up. These parameters
* will eventually be serialized to a string.
*
* @author Julien Chastang (julien.c.chastang at gmail dot com)
*/
public final class ParameterManager {
/** The parameter map. */
private final Map<Class<? extends Parameter>, Parameter> parameterMap = Maps.newHashMap();
/** The Google Chart API URL. */
private String url;
/**
* Instantiates a new parameter manager with the Google Chart API URL.
*
* @param url
* the url
*/
public ParameterManager() {
}
/**
* Inits the.
*/
public void init(final String url) {
this.url = url;
parameterMap.clear();
}
/**
* Adds the axis label position.
*
* @param index
* the index
* @param positions
* the positions
*/
public void addAxisLabelPosition(final int index, final ImmutableList<? extends Number> positions) {
getParameter(AxisLabelPositionsParameter.class).addLabelPosition(index, positions);
}
/**
* Adds the axis labels.
*
* @param index
* the index
* @param labels
* the labels
*/
public void addAxisLabels(final int index, final ImmutableList<? extends String> labels) {
getParameter(AxisLabelsParameter.class).addAxisLabels(index, labels);
}
/**
* Adds the axis range.
*
* @param index
* the index
* @param startOfRange
* the start of range
* @param endOfRange
* the end of range
* @param interval
* the numeric label interval
*/
public void addAxisRange(final int index, final double startOfRange, final double endOfRange, final double interval) {
getParameter(AxisRangesParameter.class).addAxisRange(index, startOfRange, endOfRange, interval);
}
/**
* Adds the axis style.
*
* @param index
* the index
* @param axisStyle
* the axisStyle
*/
public void addAxisStyle(final int index, final AxisStyle axisStyle) {
getParameter(AxisStylesParameter.class).addAxisStyle(index, axisStyle);
}
/**
* Adds the tick mark length.
*
* @param index
* the axis index
* @param tickMarkLength
* the tick mark length
*/
public void addTickMarkLength(final int index, final int tickMarkLength) {
getParameter(TickMarkLengthParameter.class).addTickMarkLength(index, tickMarkLength);
}
/**
* Adds the axis types.
*
* @param axisTypes
* the axis types
*/
public void addAxisTypes(final AxisTypes axisTypes) {
getParameter(AxisTypesParameter.class).addAxisTypes(axisTypes);
}
/**
* Sets the bar chart width and spacing parameter.
*
* @param width
* the width
* @param spaceBetweenBarsInGroup
* the space between bars in group
* @param spaceBetweenGroups
* the space between groups
*/
public void setBarChartWidthAndSpacingParameter(final int width, final int spaceBetweenBarsInGroup, final int spaceBetweenGroups) {
parameterMap.put(BarChartWidthAndSpacingParameter.class, new BarChartWidthAndSpacingParameter(width, spaceBetweenBarsInGroup, spaceBetweenGroups));
}
/**
* Sets the bar chart zero line parameter.
*
* @param d
* the new bar chart zero line parameter
*/
public void setBarChartZeroLineParameter(final double d) {
getParameter(BarChartZeroLinesParameter.class).addZeroLine(d);
}
/**
* Adds the linear gradient fill.
*
* @param fillType
* the fill type
* @param angle
* the angle
* @param colorAndOffsets
* the color and offsets
*/
public void addLinearGradientFill(final FillType fillType, final int angle, final ImmutableList<? extends ColorAndOffset> colorAndOffsets) {
getParameter(ChartFillsParameter.class).addLinearGradientFill(fillType, angle, colorAndOffsets);
}
/**
* Adds the linear stripe fill.
*
* @param fillType
* the fill type
* @param angle
* the angle
* @param colorAndWidths
* the color and widths
*/
public void addLinearStripeFill(final FillType fillType, final int angle, final ImmutableList<? extends ColorAndWidth> colorAndWidths) {
getParameter(ChartFillsParameter.class).addLinearStripeFill(fillType, angle, colorAndWidths);
}
/**
* Adds the solid fill.
*
* @param solidFillType
* the solid fill type
* @param color
* the color
*/
public void addSolidFill(final SolidFillType solidFillType, final Color color) {
getParameter(ChartFillsParameter.class).addSolidFill(solidFillType, color);
}
/**
* Adds the fill area marker.
*
* @param fillAreaType
* the fill area type
* @param color
* the color
* @param startLineIndex
* the start line index
* @param endLineIndex
* the end line index
*/
public void addFillAreaMarker(final FillAreaType fillAreaType, final Color color, final int startLineIndex, final int endLineIndex) {
getParameter(ChartMarkersParameter.class).addFillAreaMarker(fillAreaType, color, startLineIndex, endLineIndex);
}
/**
* Adds the line style marker.
*
* @param color
* the color
* @param dataSetIndex
* the data set index
* @param dataPoint
* the data point
* @param size
* the size
* @param priority
* the priority
*/
public void addLineStyleMarker(final Color color, final int dataSetIndex, final int dataPoint, final int size, final Priority priority) {
getParameter(ChartMarkersParameter.class).addLineStyleMarker(color, dataSetIndex, dataPoint, size, priority);
}
/**
* Add a marker(s) to the plot.
*
* @param marker
* the marker
* @param dataSetIndex
* the data set index
* @param startIndex
* The start index for the marker range.
* @param endIndex
* The end index for the marker range.
* @param n
* Marker on every n-th data point.
*/
public void addMarker(final Marker marker, final int dataSetIndex, final int startIndex, final int endIndex, final int n) {
getParameter(ChartMarkersParameter.class).addMarker(marker, dataSetIndex, startIndex, endIndex, n);
}
/**
* Add markers to each point on the plot.
*
* @param marker
* the marker
* @param dataSetIndex
* the data set index
*/
public void addMarkers(final Marker marker, final int dataSetIndex) {
getParameter(ChartMarkersParameter.class).addMarkers(marker, dataSetIndex);
}
/**
* Adds the free marker.
*
* @param marker
* the marker
* @param xPos
* the x pos
* @param yPos
* the y pos
*/
public void addFreeMarker(final Marker marker, final double xPos, final double yPos) {
getParameter(ChartMarkersParameter.class).addFreeMarker(marker, xPos, yPos);
}
/**
* Adds the vertical range marker.
*
* @param color
* the color
* @param startPoint
* the start point
* @param endPoint
* the end point
*/
public void addVerticalRangeMarker(final Color color, final double startPoint, final double endPoint) {
getParameter(ChartMarkersParameter.class).addVerticalRangeMarker(color, startPoint, endPoint);
}
/**
* Adds the horizontal range marker.
*
* @param color
* the color
* @param startPoint
* the start point
* @param endPoint
* the end point
*/
public void addHorizontalRangeMarker(final Color color, final double startPoint, final double endPoint) {
getParameter(ChartMarkersParameter.class).addHorizontalRangeMarker(color, startPoint, endPoint);
}
/**
* Sets the chart size parameter.
*
* @param width
* the width
* @param height
* the height
*/
public void setChartSizeParameter(final int width, final int height) {
parameterMap.put(ChartSizeParameter.class, new ChartSizeParameter(width, height));
}
/**
* Sets the chart title color and size parameter.
*
* @param color
* the color
* @param fontSize
* the font size
*/
public void setChartTitleColorAndSizeParameter(final Color color, final int fontSize) {
parameterMap.put(ChartTitleColorAndSizeParameter.class, new ChartTitleColorAndSizeParameter(color, fontSize));
}
/**
* Sets the chart title parameter.
*
* @param title
* the new chart title parameter
*/
public void setChartTitleParameter(final String title) {
parameterMap.put(ChartTitleParameter.class, new ChartTitleParameter(title));
}
/**
* Sets the chart type parameter.
*
* @param chartType
* the new chart type parameter
*/
public void setChartTypeParameter(final ChartType chartType) {
parameterMap.put(ChartTypeParameter.class, new ChartTypeParameter(chartType));
}
/**
* Adds the color.
*
* @param color
* the color
*/
public void addColor(final Color color) {
final List<ImmutableList<Color>> colors = Lists.newArrayList();
colors.add(Lists.of(color));
getParameter(ColorsParameter.class).addColors(Lists.copyOf(colors));
}
/**
* Add the colors. This is a 2D data structure because in some cases
* (e.g. individually colored bars in a bar chart) there can be more
* than one color in a data series. In most cases, however, the inner
* list, is only going to be 1 long.
*
* @param colors
* the colors
*/
public void addColors(final ImmutableList<? extends ImmutableList<? extends Color>> colors) {
getParameter(ColorsParameter.class).addColors(colors);
}
/**
* Adds the legend.
*
* @param legend
* the legend
*/
public void addLegend(final String legend) {
getParameter(DataLegendsParameter.class).addLegends(Lists.of(legend));
}
/**
* Adds the legends.
*
* @param legends
* the legends
*/
public void addLegends(final ImmutableList<? extends String> legends) {
getParameter(DataLegendsParameter.class).addLegends(legends);
}
/**
* Adds the data.
*
* @param data
* the data
*/
public void addData(final Data data) {
getParameter(DataParameter.class).addData(data);
}
/**
* Sets the data encoding.
*
* @param dataEncoding
* the new data encoding
*/
public void setDataEncoding(final DataEncoding dataEncoding) {
getParameter(DataParameter.class).setDataEncoding(dataEncoding);
}
/**
* Adds the geo code.
*
* @param geoCode
* the geo code
*/
public void addGeoCode(final String geoCode) {
getParameter(GeoCodesParameter.class).addGeoCode(geoCode);
}
/**
* Sets the geographical area parameter.
*
* @param geographicalArea
* the new geographical area parameter
*/
public void setGeographicalAreaParameter(final GeographicalArea geographicalArea) {
parameterMap.put(GeographicalAreaParameter.class, new GeographicalAreaParameter(geographicalArea));
}
/**
* Sets the grid line parameter.
*
* @param xAxisStepSize
* the x axis step size
* @param yAxisStepSize
* the y axis step size
* @param lengthOfLineSegment
* the length of line segment
* @param lengthOfBlankSegment
* the length of blank segment
*/
public void setGridLineParameter(final double xAxisStepSize, final double yAxisStepSize, final int lengthOfLineSegment, final int lengthOfBlankSegment) {
parameterMap.put(GridLineParameter.class, new GridLineParameter(xAxisStepSize, yAxisStepSize, lengthOfLineSegment, lengthOfBlankSegment));
}
/**
* Sets the legend position parameter.
*
* @param legendPosition
* the new legend position parameter
*/
public void setLegendPositionParameter(final LegendPosition legendPosition) {
parameterMap.put(LegendPositionParameter.class, new LegendPositionParameter(legendPosition));
}
/**
* Adds the line chart line style.
*
* @param lineStyle
* the line style
*/
public void addLineChartLineStyle(final LineStyle lineStyle) {
getParameter(LineChartLineStylesParameter.class).addLineStyle(lineStyle);
}
/**
* Adds the pie chart and google o meter legend.
*
* @param legend
* the legend
*/
public void addPieChartAndGoogleOMeterLegend(final String legend) {
getParameter(PieChartAndGoogleOMeterLegendParameter.class).addLegend(legend);
}
/**
* Sets the margins.
*
* @param leftMargin
* the left margin
* @param rightMargin
* the right margin
* @param topMargin
* the top margin
* @param bottomMargin
* the bottom margin
*/
public void setMargins(final int leftMargin, final int rightMargin, final int topMargin, final int bottomMargin) {
getParameter(MarginsParameter.class).setMargins(bottomMargin, leftMargin, rightMargin, topMargin);
}
/**
* Sets the legend margins.
*
* @param width
* the width
* @param height
* the height
*/
public void setLegendMargins(final int width, final int height) {
getParameter(MarginsParameter.class).setLegendMargins(width, height);
}
/**
* Add a pie chart orientation.
*
* @param orientation
* the orientation
*/
public void addPieChartOrientation(final double orientation) {
parameterMap.put(PieChartOrientationParameter.class, new PieChartOrientationParameter(orientation));
}
/**
* Get the parameter map for generating the Google Chart API URL.
*
* @return the parameterMap
*/
public final Map<String, String> getParameterMap() {
final Map<String, String> map = Maps.newHashMap();
for (Parameter p : parameterMap.values()) {
map.put(p.getKey(), p.getValue());
}
return Collections.unmodifiableMap(map);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final Collection<Parameter> c = parameterMap.values();
final List<String> parameters = Lists.newLinkedList();
for (Parameter p : c) {
final String paramString = p.toURLParameterString();
if (!"".equals(paramString)) {
parameters.add(paramString);
}
}
Collections.sort(parameters, new Comparator<String>() {
public int compare(final String s1, final String s2) {
return s1.length() - s2.length();
}
});
int cnt = 0;
final StringBuilder sb = new StringBuilder(url + "?");
for (String p : parameters) {
sb.append(cnt++ > 0 ? "&" : "").append(p);
}
return sb.toString();
}
/**
* Get the parameter.
*
* @param <T>
* type of parameter to retrieve
* @param clazz
* the class of the parameter to retrieve
*
* @return the parameter
* @throws ParameterInstantiationException
* if the parameter could not be instantiated
*/
private <T extends Parameter> T getParameter(final Class<T> clazz) throws ParameterInstantiationException {
// Should always be safe.
@SuppressWarnings("unchecked")
T p = (T) parameterMap.get(clazz);
if (p == null) {
try {
p = clazz.newInstance();
} catch (InstantiationException e) {
throw new ParameterInstantiationException("Internal error: Could not instatiate " + clazz.getName(), e);
} catch (IllegalAccessException e) {
throw new ParameterInstantiationException("Internal error: Could not instatiate " + clazz.getName(), e);
}
parameterMap.put(clazz, p);
}
return p;
}
/**
* The exception class for cases where the parameter cannot be instantiated
* through reflection.
*/
public static class ParameterInstantiationException extends RuntimeException {
/** The serial version uid. */
private static final long serialVersionUID = -7837316818196725716L;
/**
* Instantiates a new parameter instantiation exception.
*
* @param message
* the message
* @param cause
* the cause
*/
private ParameterInstantiationException(final String message, final Throwable cause) {
super(message, cause);
}
}
}