1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.rendering.internal.macro.chart

File ChartMacro.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

10
49
6
1
220
128
13
0.27
8.17
6
2.17

Classes

Class Line # Actions
ChartMacro 59 49 0% 13 4
0.9384615493.8%
 

Contributing tests

This file is covered by 8 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.rendering.internal.macro.chart;
21   
22    import java.util.Collections;
23    import java.util.HashMap;
24    import java.util.List;
25    import java.util.Map;
26   
27    import javax.inject.Inject;
28    import javax.inject.Named;
29    import javax.inject.Singleton;
30   
31    import org.apache.commons.lang3.StringUtils;
32    import org.xwiki.chart.ChartGenerator;
33    import org.xwiki.chart.ChartGeneratorException;
34    import org.xwiki.component.annotation.Component;
35    import org.xwiki.component.manager.ComponentLookupException;
36    import org.xwiki.component.manager.ComponentManager;
37    import org.xwiki.rendering.block.Block;
38    import org.xwiki.rendering.block.ImageBlock;
39    import org.xwiki.rendering.block.LinkBlock;
40    import org.xwiki.rendering.block.ParagraphBlock;
41    import org.xwiki.rendering.internal.macro.chart.source.DataSource;
42    import org.xwiki.rendering.listener.reference.ResourceReference;
43    import org.xwiki.rendering.listener.reference.ResourceType;
44    import org.xwiki.rendering.macro.AbstractMacro;
45    import org.xwiki.rendering.macro.MacroExecutionException;
46    import org.xwiki.rendering.macro.chart.ChartMacroParameters;
47    import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor;
48    import org.xwiki.rendering.transformation.MacroTransformationContext;
49   
50    /**
51    * A macro for rendering charts.
52    *
53    * @version $Id: ceca8b8041508d0dee9cafb2526524e7a2262fc6 $
54    * @since 2.0M1
55    */
56    @Component
57    @Named("chart")
58    @Singleton
 
59    public class ChartMacro extends AbstractMacro<ChartMacroParameters>
60    {
61    /**
62    * The description of the macro.
63    */
64    private static final String DESCRIPTION = "Displays a graphical chart generated from miscellaneous data sources";
65   
66    /**
67    * The description of the macro content.
68    */
69    private static final String CONTENT_DESCRIPTION = "Input data for the chart macro (Ex. for 'inline' source mode)";
70   
71    /**
72    * Used for building the actual chart.
73    */
74    @Inject
75    private ChartGenerator chartGenerator;
76   
77    /**
78    * The component manager needed for instantiating the datasource factory.
79    */
80    @Inject
81    private ComponentManager componentManager;
82   
83    /**
84    * Used to compute the chart image storage location and URL to access it.
85    */
86    @Inject
87    @Named("tmp")
88    private ChartImageWriter imageWriter;
89   
90    /**
91    * Create and initialize the descriptor of the macro.
92    */
 
93  9 toggle public ChartMacro()
94    {
95  9 super("Chart", DESCRIPTION, new DefaultContentDescriptor(CONTENT_DESCRIPTION, false),
96    ChartMacroParameters.class);
97  9 setDefaultCategory(DEFAULT_CATEGORY_CONTENT);
98    }
99   
 
100  1 toggle @Override
101    public boolean supportsInlineMode()
102    {
103  1 return true;
104    }
105   
 
106  15 toggle @Override
107    public List<Block> execute(ChartMacroParameters macroParams, String content, MacroTransformationContext context)
108    throws MacroExecutionException
109    {
110    // Generate the chart image in a temporary location.
111  15 generateChart(macroParams, content, context);
112   
113  15 String imageLocation = this.imageWriter.getURL(new ImageId(macroParams));
114  15 String title = macroParams.getTitle();
115  15 ResourceReference reference = new ResourceReference(imageLocation, ResourceType.URL);
116  15 ImageBlock imageBlock = new ImageBlock(new ResourceReference(imageLocation, ResourceType.URL), true);
117  15 imageBlock.setParameter("alt", title);
118  15 LinkBlock linkBlock = new LinkBlock(Collections.singletonList((Block) imageBlock), reference, true);
119  15 linkBlock.setParameter("title", title);
120   
121    // If the macro is used standalone then we need to wrap it in a paragraph block.
122  15 Block resultBlock;
123  15 if (context.isInline()) {
124  1 resultBlock = linkBlock;
125    } else {
126  14 resultBlock = new ParagraphBlock(Collections.singletonList((Block) linkBlock));
127    }
128   
129  15 return Collections.singletonList(resultBlock);
130    }
131   
132    /**
133    * Builds the chart image according to the specifications passed in.
134    *
135    * @param parameters the macro parameters
136    * @param content the macro content
137    * @param context the macro transformation context, used for example to find out the current document reference
138    * @throws MacroExecutionException if an error occurs while generating / saving the chart image
139    */
 
140  15 toggle private void generateChart(ChartMacroParameters parameters, String content, MacroTransformationContext context)
141    throws MacroExecutionException
142    {
143  15 String source = computeSource(parameters.getSource(), content);
144   
145  15 DataSource dataSource;
146  15 try {
147  15 dataSource = this.componentManager.getInstance(DataSource.class, source);
148    } catch (ComponentLookupException e) {
149  0 throw new MacroExecutionException(String.format("Invalid source parameter [%s]",
150    parameters.getSource()), e);
151    }
152   
153  15 Map<String, String> sourceParameters = getSourceParameters(parameters, source);
154   
155  15 dataSource.buildDataset(content, sourceParameters, context);
156   
157  15 try {
158  15 this.imageWriter.writeImage(new ImageId(parameters),
159    this.chartGenerator.generate(dataSource.getChartModel(), sourceParameters));
160    } catch (ChartGeneratorException e) {
161  0 throw new MacroExecutionException("Error while rendering chart", e);
162    }
163    }
164   
165    /**
166    * Compute what Data Source to use. If the user has specified one then use it. Otherwise if there's content
167    * in the macro default to using the "inline" source and if not default to using the "xdom" source.
168    *
169    * @param userDefinedSource the user specified source value from the Macro parameter (is null if not specified)
170    * @param content the Macro content
171    * @return the hint of the {@link DataSource} component to use
172    */
 
173  15 toggle private String computeSource(String userDefinedSource, String content)
174    {
175  15 String source = userDefinedSource;
176  15 if (source == null) {
177  6 if (StringUtils.isEmpty(content)) {
178  2 source = "xdom";
179    } else {
180  4 source = "inline";
181    }
182    }
183  15 return source;
184    }
185   
186    /**
187    * TODO There is no way to escape the ';' character.
188    *
189    * @param chartMacroParameters The macro parameters.
190    * @param sourceHint the hint of the Data Source component to use
191    * @return A map containing the source parameters.
192    */
 
193  15 toggle private Map<String, String> getSourceParameters(ChartMacroParameters chartMacroParameters, String sourceHint)
194    {
195  15 Map<String, String> parameters = new HashMap<String, String>();
196  15 parameters.put(ChartGenerator.TITLE_PARAM, chartMacroParameters.getTitle());
197  15 parameters.put(ChartGenerator.WIDTH_PARAM, String.valueOf(chartMacroParameters.getWidth()));
198  15 parameters.put(ChartGenerator.HEIGHT_PARAM, String.valueOf(chartMacroParameters.getHeight()));
199  15 parameters.put(ChartGenerator.TYPE_PARAM, chartMacroParameters.getType());
200  15 parameters.put(DataSource.SOURCE_PARAM, sourceHint);
201  15 parameters.put(DataSource.PARAMS_PARAM, chartMacroParameters.getParams());
202   
203  15 String sourceParameters = chartMacroParameters.getParams();
204   
205  15 if (null != sourceParameters) {
206  12 String[] segments = sourceParameters.split(";");
207  12 for (String segment : segments) {
208  57 String[] keyValue = segment.split(":", 2);
209  57 String key = StringUtils.trim(keyValue[0]);
210  57 if (keyValue.length == 2) {
211  57 parameters.put(key, keyValue[1]);
212    } else {
213  0 parameters.put(key, null);
214    }
215    }
216    }
217   
218  15 return parameters;
219    }
220    }