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

File FormulaMacro.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart7.png
64% of files have more coverage

Code metrics

6
32
4
1
187
106
11
0.34
8
4
2.75

Classes

Class Line # Actions
FormulaMacro 60 32 0% 11 13
0.690476269%
 

Contributing tests

This file is covered by 2 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.formula;
21   
22    import java.util.Collections;
23    import java.util.List;
24   
25    import javax.inject.Inject;
26    import javax.inject.Named;
27    import javax.inject.Singleton;
28   
29    import org.apache.commons.lang3.StringUtils;
30    import org.slf4j.Logger;
31    import org.xwiki.bridge.DocumentAccessBridge;
32    import org.xwiki.component.annotation.Component;
33    import org.xwiki.component.manager.ComponentManager;
34    import org.xwiki.formula.FormulaRenderer;
35    import org.xwiki.formula.FormulaRenderer.FontSize;
36    import org.xwiki.formula.FormulaRenderer.Type;
37    import org.xwiki.model.reference.AttachmentReference;
38    import org.xwiki.rendering.block.Block;
39    import org.xwiki.rendering.block.ImageBlock;
40    import org.xwiki.rendering.block.ParagraphBlock;
41    import org.xwiki.rendering.block.WordBlock;
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.descriptor.DefaultContentDescriptor;
47    import org.xwiki.rendering.macro.formula.FormulaMacroConfiguration;
48    import org.xwiki.rendering.macro.formula.FormulaMacroParameters;
49    import org.xwiki.rendering.transformation.MacroTransformationContext;
50   
51    /**
52    * Displays a formula, in LaTeX syntax, as an image.
53    *
54    * @version $Id: aff07810bbe7469589ae4e1372c8e2b76ed27a9d $
55    * @since 2.0M3
56    */
57    @Component
58    @Named("formula")
59    @Singleton
 
60    public class FormulaMacro extends AbstractMacro<FormulaMacroParameters>
61    {
62    /** Predefined error message: empty formula. */
63    public static final String CONTENT_MISSING_ERROR = "The mandatory formula text is missing.";
64   
65    /** Predefined error message: invalid formula. */
66    public static final String WRONG_CONTENT_ERROR = "The formula text is not valid, please correct it.";
67   
68    /** The description of the macro. */
69    private static final String DESCRIPTION = "Displays a mathematical formula.";
70   
71    /** The description of the macro content. */
72    private static final String CONTENT_DESCRIPTION = "The mathematical formula, in LaTeX syntax";
73   
74    /** Component manager, needed for retrieving the selected formula renderer. */
75    @Inject
76    private ComponentManager manager;
77   
78    /** Defines from where to read the rendering configuration data. */
79    @Inject
80    private FormulaMacroConfiguration configuration;
81   
82    /** Needed for computing the URL for accessing the rendered image. */
83    @Inject
84    private DocumentAccessBridge dab;
85   
86    /**
87    * The logger to log.
88    */
89    @Inject
90    private Logger logger;
91   
92    /**
93    * Create and initialize the descriptor of the macro.
94    */
 
95  2 toggle public FormulaMacro()
96    {
97  2 super("Formula", DESCRIPTION, new DefaultContentDescriptor(CONTENT_DESCRIPTION), FormulaMacroParameters.class);
98  2 setDefaultCategory(DEFAULT_CATEGORY_CONTENT);
99    }
100   
 
101  2 toggle @Override
102    public List<Block> execute(FormulaMacroParameters parameters, String content, MacroTransformationContext context)
103    throws MacroExecutionException
104    {
105  2 if (StringUtils.isEmpty(content)) {
106  0 throw new MacroExecutionException(CONTENT_MISSING_ERROR);
107    }
108   
109  2 String rendererHint = this.configuration.getRenderer();
110  2 FontSize size = parameters.getFontSize();
111  2 Type type = parameters.getImageType();
112  2 Block result;
113  2 try {
114  2 result = render(content, context.isInline(), size, type, rendererHint);
115    } catch (MacroExecutionException ex) {
116  0 this.logger.debug("Failed to render content with the [{}] renderer. Falling back to the safe renderer.",
117    rendererHint, ex);
118  0 try {
119  0 result = render(content, context.isInline(), size, type, this.configuration.getSafeRenderer());
120    } catch (IllegalArgumentException ex2) {
121  0 throw new MacroExecutionException(WRONG_CONTENT_ERROR);
122    }
123    } catch (IllegalArgumentException ex) {
124  0 throw new MacroExecutionException(WRONG_CONTENT_ERROR);
125    }
126   
127    // If no image was generated, just return the original text
128  2 if (result == null) {
129  0 result = new WordBlock(content);
130    }
131    // Block level formulae should be wrapped in a paragraph element
132  2 if (!context.isInline()) {
133  2 result = new ParagraphBlock(Collections.<Block> singletonList(result));
134    }
135  2 return Collections.singletonList(result);
136    }
137   
138    /**
139    * Renders the formula using the specified renderer.
140    *
141    * @param formula the formula text
142    * @param inline is the formula supposed to be used inline or as a block-level element
143    * @param fontSize the specified font size
144    * @param imageType the specified resulting image type
145    * @param rendererHint the hint for the renderer to use
146    * @return the resulting block holding the generated image, or {@code null} in case of an error.
147    * @throws MacroExecutionException if no renderer exists for the passed hint or if that rendered failed to render
148    * the formula
149    * @throws IllegalArgumentException if the formula is not valid, according to the LaTeX syntax
150    */
 
151  2 toggle private Block render(String formula, boolean inline, FontSize fontSize, Type imageType, String rendererHint)
152    throws MacroExecutionException, IllegalArgumentException
153    {
154  2 try {
155  2 FormulaRenderer renderer = this.manager.getInstance(FormulaRenderer.class, rendererHint);
156  2 String imageName = renderer.process(formula, inline, fontSize, imageType);
157    // TODO: HACK!!
158    // We're going through the getAttachmentURL() API so that when the PdfURLFactory is used, the generated
159    // image is saved and then embedded in the exported PDF thanks to PDFURIResolver. In the future we need
160    // to remove this hack by introduce a proper Resource for generated image (say TemporaryResource),
161    // implement a TemporaryResourceSerializer<URL> and introduce a ResourceLoader interface and have it
162    // implemented for TemporaryResource...
163  2 AttachmentReference attachmentReference =
164    new AttachmentReference(imageName, this.dab.getCurrentDocumentReference());
165  2 String url = this.dab.getAttachmentURL(attachmentReference, false);
166    // Note that we have to replace the download action by the tex action since the getAttachmentURL() API
167    // will use the "download" action but when the generated URL is called by the browser it needs to point to
168    // the TexAction...
169  2 url = url.replace("/download/", "/tex/");
170    // TODO: end HACK!!
171  2 ResourceReference imageReference = new ResourceReference(url, ResourceType.URL);
172  2 ImageBlock result = new ImageBlock(imageReference, false);
173    // Set the alternative text for the image to be the original formula
174  2 result.setParameter("alt", formula);
175  2 return result;
176    } catch (Exception e) {
177  0 throw new MacroExecutionException(
178    String.format("Failed to render formula using the [%s] renderer", rendererHint), e);
179    }
180    }
181   
 
182  0 toggle @Override
183    public boolean supportsInlineMode()
184    {
185  0 return true;
186    }
187    }