Clover Coverage Report - XWiki Rendering - Parent POM 4.0-SNAPSHOT (Aggregated)
Coverage timestamp: Mon Mar 12 2012 18:03:13 CET
../../../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
76   226   28   19
32   148   0.37   4
4     7  
1    
 
  RadeoxMacrosFilter       Line # 50 76 0% 28 0 100% 1.0
 
  (92)
 
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.parser.xwiki10;
21   
22    import java.util.regex.Matcher;
23    import java.util.regex.Pattern;
24   
25    import javax.inject.Inject;
26    import javax.inject.Named;
27    import javax.inject.Singleton;
28   
29    import org.slf4j.Logger;
30    import org.xwiki.component.annotation.Component;
31    import org.xwiki.component.manager.ComponentLookupException;
32    import org.xwiki.component.manager.ComponentManager;
33    import org.xwiki.component.phase.Initializable;
34    import org.xwiki.component.phase.InitializationException;
35    import org.xwiki.rendering.parser.xwiki10.AbstractFilter;
36    import org.xwiki.rendering.parser.xwiki10.FilterContext;
37    import org.xwiki.rendering.parser.xwiki10.macro.RadeoxMacroConverter;
38    import org.xwiki.rendering.parser.xwiki10.macro.RadeoxMacroParameters;
39    import org.xwiki.rendering.parser.xwiki10.util.CleanUtil;
40   
41    /**
42    * Convert 1.0 radeox macros to 2.0 macro. A conversion can be added by implementing RadeoxMacroConverter.
43    *
44    * @version $Id: 9ae6a40cebd71fa7ab2b3c8c33c1fb838aa6b621 $
45    * @since 1.8M1
46    */
47    @Component
48    @Named("radeoxmacros")
49    @Singleton
 
50    public class RadeoxMacrosFilter extends AbstractFilter implements Initializable
51    {
52    /**
53    * Regex pattern for matching macros that are written on single line.
54    */
55    public static final Pattern SINGLE_LINE_MACRO_PATTERN = Pattern.compile("\\{(\\w+)(:(.+))?\\}");
56   
57    /**
58    * Regex pattern for matching macros that span several lines (i.e. macros that have a body block). Note that we're
59    * using the {@link Pattern#DOTALL} flag to tell the compiler that "." should match any characters, including new
60    * lines.
61    */
62    public static final Pattern MULTI_LINE_MACRO_PATTERN = Pattern.compile("\\{(\\w+)(:(.+?))?\\}(.+?)\\{\\1\\}",
63    Pattern.DOTALL);
64   
65    @Inject
66    private ComponentManager componentManager;
67   
68    /**
69    * The logger to log.
70    */
71    @Inject
72    private Logger logger;
73   
 
74  92 toggle @Override
75    public void initialize() throws InitializationException
76    {
77  92 setPriority(100);
78    }
79   
 
80  92 toggle @Override
81    public String filter(String content, FilterContext filterContext)
82    {
83  92 content = filterMacros(content, SINGLE_LINE_MACRO_PATTERN, false, filterContext);
84  92 content = filterMacros(content, MULTI_LINE_MACRO_PATTERN, true, filterContext);
85   
86  92 return content;
87    }
88   
 
89  184 toggle private String filterMacros(String content, Pattern pattern, boolean supportContent, FilterContext filterContext)
90    {
91  184 StringBuffer result = new StringBuffer();
92  184 Matcher matcher = pattern.matcher(content);
93   
94  184 int currentIndex = 0;
95  184 RadeoxMacroConverter currentMacro = null;
96  219 for (; matcher.find(); currentIndex = matcher.end()) {
97  35 String before = content.substring(currentIndex, matcher.start());
98   
99  35 if (currentMacro != null && !currentMacro.isInline()) {
100  1 before = CleanUtil.setLeadingNewLines(before, 2);
101    }
102   
103  35 String allcontent = matcher.group(0);
104   
105  35 String macroName = matcher.group(1);
106  35 String params = matcher.group(3);
107  35 String macroContent = matcher.groupCount() >= 4 ? matcher.group(4) : null;
108   
109  35 boolean velocityOpen = false;
110  35 boolean velocityClose = false;
111   
112  35 if (params != null) {
113    // Clean velocity open macro inside params
114  20 Matcher velocityOpenMatcher = VelocityFilter.VELOCITYOPEN_PATTERN.matcher(params);
115  20 velocityOpen |= velocityOpenMatcher.find();
116  20 params = velocityOpenMatcher.replaceAll("");
117  20 Matcher velocityCloseMatcher = VelocityFilter.VELOCITYCLOSE_PATTERN.matcher(params);
118  20 velocityClose |= velocityCloseMatcher.find();
119  20 params = velocityCloseMatcher.replaceAll("");
120    }
121   
122  35 if (macroContent != null) {
123    // Clean velocity close macro inside content
124  7 Matcher velocityOpenMatcher = VelocityFilter.VELOCITYOPEN_PATTERN.matcher(macroContent);
125  7 velocityOpen |= velocityOpenMatcher.find();
126  7 macroContent = velocityOpenMatcher.replaceAll("");
127  7 Matcher velocityCloseMatcher = VelocityFilter.VELOCITYCLOSE_PATTERN.matcher(macroContent);
128  7 velocityClose |= velocityCloseMatcher.find();
129  7 macroContent = velocityCloseMatcher.replaceAll("");
130    }
131   
132  35 try {
133  35 currentMacro = this.componentManager.lookup(RadeoxMacroConverter.class, macroName);
134   
135  31 if (currentMacro.supportContent() == supportContent) {
136    // a standalone new line is not interpreted by XWiki 1.0 rendering
137  18 before = CleanUtil.removeTrailingNewLines(before, 1, true);
138   
139  18 if (!currentMacro.isInline()) {
140  4 before = CleanUtil.setTrailingNewLines(before, 2);
141    }
142   
143  18 allcontent =
144    currentMacro.convert(macroName, getMacroParameters(currentMacro, params), macroContent,
145    filterContext);
146  18 if (currentMacro.protectResult()) {
147  14 allcontent = filterContext.addProtectedContent(allcontent, currentMacro.isInline());
148    }
149    } else {
150  13 currentMacro = null;
151    }
152    } catch (ComponentLookupException e) {
153  4 this.logger.debug("Can't find macro converter [" + macroName + "]", e);
154   
155  4 currentMacro = null;
156    }
157   
158  35 result.append(before);
159   
160  35 boolean multilines = allcontent.indexOf("\n") != -1;
161   
162  35 if (velocityOpen) {
163  1 VelocityFilter.appendVelocityOpen(result, filterContext, multilines);
164    }
165   
166  35 result.append(allcontent);
167   
168  35 if (velocityClose) {
169  1 VelocityFilter.appendVelocityClose(result, filterContext, multilines);
170    }
171    }
172   
173  184 if (currentIndex == 0) {
174  170 return content;
175    }
176   
177  14 if (currentMacro != null && !currentMacro.isInline()) {
178  3 result.append(CleanUtil.setLeadingNewLines(content.substring(currentIndex), 2));
179    } else {
180  11 result.append(content.substring(currentIndex));
181    }
182   
183  14 return result.toString();
184    }
185   
 
186  22 toggle public static RadeoxMacroParameters getMacroParameters(RadeoxMacroConverter macroConverter, String parameters)
187    {
188  22 RadeoxMacroParameters parameterMap = new RadeoxMacroParameters();
189   
190  22 if (parameters != null) {
191  17 String[] parameterTable = parameters.split("\\|");
192   
193  63 for (int parameterIndex = 0; parameterIndex < parameterTable.length; ++parameterIndex) {
194  46 String parameter = parameterTable[parameterIndex];
195  46 int equalIndex = parameter.indexOf('=');
196   
197  46 try {
198  46 int parameterType = macroConverter.getParameterType(parameterIndex);
199  46 String parameterName;
200  46 String parameterValue;
201  46 if (equalIndex >= 0) {
202  24 parameterName = parameter.substring(0, equalIndex);
203  24 parameterValue = parameter.substring(equalIndex + 1);
204    } else {
205  22 parameterName = macroConverter.getParameterName(parameterIndex);
206  22 parameterValue = parameter;
207    }
208   
209  46 if (parameterType != RadeoxMacroConverter.PARAMETER_SIMPLE
210    && ((parameterType & RadeoxMacroConverter.PARAMETER_NOTEMPTY) != 0 && parameterValue.trim()
211    .length() == 0)
212    || (((parameterType & RadeoxMacroConverter.PARAMETER_NOTNONE) != 0 && "none"
213    .equals(parameterValue)))) {
214  1 parameterValue = null;
215    }
216   
217  46 parameterMap.addParameter(parameterIndex, parameterName, parameterValue);
218    } catch (Throwable t) {
219    // skip parameter
220    }
221    }
222    }
223   
224  22 return parameterMap;
225    }
226    }