|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MacroTransformation | Line # 69 | 58 | 0% | 17 | 5 | 93.5% |
0.9350649
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
MacroTransformation.MacroHolder | Line # 95 | 3 | 0% | 2 | 0 | 100% |
1.0
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
(115) | |||
Result | |||
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.80487806
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.58536583
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5731707
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5609756
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.5121951
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.46341464
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
0.085365854
|
org.xwiki.rendering.test.integration.RenderingTest.execute org.xwiki.rendering.test.integration.RenderingTest.execute | 1 PASS | |
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.transformation.macro; | |
21 | ||
22 | import java.io.PrintWriter; | |
23 | import java.io.StringWriter; | |
24 | import java.util.ArrayList; | |
25 | import java.util.Arrays; | |
26 | import java.util.Collections; | |
27 | import java.util.List; | |
28 | import java.util.Map; | |
29 | ||
30 | import javax.inject.Inject; | |
31 | import javax.inject.Named; | |
32 | import javax.inject.Singleton; | |
33 | ||
34 | import org.slf4j.Logger; | |
35 | import org.xwiki.component.annotation.Component; | |
36 | import org.xwiki.properties.BeanManager; | |
37 | import org.xwiki.rendering.block.Block; | |
38 | import org.xwiki.rendering.block.FormatBlock; | |
39 | import org.xwiki.rendering.block.GroupBlock; | |
40 | import org.xwiki.rendering.block.MacroBlock; | |
41 | import org.xwiki.rendering.block.MacroMarkerBlock; | |
42 | import org.xwiki.rendering.block.VerbatimBlock; | |
43 | import org.xwiki.rendering.block.WordBlock; | |
44 | import org.xwiki.rendering.listener.Format; | |
45 | import org.xwiki.rendering.macro.Macro; | |
46 | import org.xwiki.rendering.macro.MacroId; | |
47 | import org.xwiki.rendering.macro.MacroLookupException; | |
48 | import org.xwiki.rendering.macro.MacroManager; | |
49 | import org.xwiki.rendering.transformation.MacroTransformationContext; | |
50 | import org.xwiki.rendering.syntax.Syntax; | |
51 | import org.xwiki.rendering.transformation.AbstractTransformation; | |
52 | import org.xwiki.rendering.transformation.TransformationContext; | |
53 | import org.xwiki.rendering.transformation.TransformationException; | |
54 | ||
55 | /** | |
56 | * Look for all {@link org.xwiki.rendering.block.MacroBlock} blocks in the passed {@link Block} and iteratively execute | |
57 | * each Macro in the correct order. Macros can: | |
58 | * <ul> | |
59 | * <li>provide a hint specifying when they should run (priority)</li> | |
60 | * <li>generate other Macros</li> | |
61 | * </ul> | |
62 | * | |
63 | * @version $Id: 66d225115a1f04891537cf0dbc5d143b71c14b7a $ | |
64 | * @since 1.5M2 | |
65 | */ | |
66 | @Component | |
67 | @Named("macro") | |
68 | @Singleton | |
69 | public class MacroTransformation extends AbstractTransformation | |
70 | { | |
71 | /** | |
72 | * Number of macro executions allowed when rendering the current content before considering that we are in a loop. | |
73 | * Such a loop can happen if a macro generates itself for example. | |
74 | */ | |
75 | private int maxMacroExecutions = 1000; | |
76 | ||
77 | /** | |
78 | * Handles macro registration and macro lookups. Injected by the Component Manager. | |
79 | */ | |
80 | @Inject | |
81 | private MacroManager macroManager; | |
82 | ||
83 | /** | |
84 | * Used to populate automatically macros parameters classes with parameters specified in the Macro Block. | |
85 | */ | |
86 | @Inject | |
87 | private BeanManager beanManager; | |
88 | ||
89 | /** | |
90 | * The logger to log. | |
91 | */ | |
92 | @Inject | |
93 | private Logger logger; | |
94 | ||
95 | private class MacroHolder implements Comparable<MacroHolder> | |
96 | { | |
97 | Macro< ? > macro; | |
98 | ||
99 | MacroBlock macroBlock; | |
100 | ||
101 | 1162 | public MacroHolder(Macro< ? > macro, MacroBlock macroBlock) |
102 | { | |
103 | 1162 | this.macro = macro; |
104 | 1162 | this.macroBlock = macroBlock; |
105 | } | |
106 | ||
107 | 22 | @Override |
108 | public int compareTo(MacroHolder holder) | |
109 | { | |
110 | 22 | return this.macro.compareTo(holder.macro); |
111 | } | |
112 | } | |
113 | ||
114 | 0 | @Override |
115 | public int getPriority() | |
116 | { | |
117 | // Make it one of the transformations that's executed first so that other transformations run on the executed | |
118 | // macros. | |
119 | 0 | return 100; |
120 | } | |
121 | ||
122 | 132 | @Override |
123 | public void transform(Block rootBlock, TransformationContext context) throws TransformationException | |
124 | { | |
125 | // Create a macro execution context with all the information required for macros. | |
126 | 132 | MacroTransformationContext macroContext = new MacroTransformationContext(context); |
127 | 132 | macroContext.setTransformation(this); |
128 | ||
129 | // Counter to prevent infinite recursion if a macro generates the same macro for example. | |
130 | 132 | int executions = 0; |
131 | 132 | List<MacroBlock> macroBlocks = rootBlock.getChildrenByType(MacroBlock.class, true); |
132 | 1277 | while (!macroBlocks.isEmpty() && executions < this.maxMacroExecutions) { |
133 | 1145 | transformOnce(rootBlock, macroContext, context.getSyntax()); |
134 | ||
135 | // TODO: Make this less inefficient by caching the blocks list. | |
136 | 1145 | macroBlocks = rootBlock.getChildrenByType(MacroBlock.class, true); |
137 | 1145 | executions++; |
138 | } | |
139 | } | |
140 | ||
141 | 1145 | private void transformOnce(Block rootBlock, MacroTransformationContext context, Syntax syntax) |
142 | { | |
143 | // 1) Get highest priority macro to execute | |
144 | 1145 | MacroHolder macroHolder = getHighestPriorityMacro(rootBlock, syntax); |
145 | 1145 | if (macroHolder == null) { |
146 | 5 | return; |
147 | } | |
148 | ||
149 | // 2) Verify if we're in macro inline mode and if the macro supports it. If not, send an error. | |
150 | 1140 | if (macroHolder.macroBlock.isInline()) { |
151 | 41 | context.setInline(true); |
152 | 41 | if (!macroHolder.macro.supportsInlineMode()) { |
153 | // The macro doesn't support inline mode, raise a warning but continue. | |
154 | // The macro will not be executed and we generate an error message instead of the macro | |
155 | // execution result. | |
156 | 5 | generateError(macroHolder.macroBlock, "Not an inline macro", |
157 | "This macro can only be used by itself on a new line"); | |
158 | 5 | this.logger.debug("The [" + macroHolder.macroBlock.getId() + "] macro doesn't support inline mode."); |
159 | 5 | return; |
160 | } | |
161 | } else { | |
162 | 1099 | context.setInline(false); |
163 | } | |
164 | ||
165 | // 3) Execute the highest priority macro | |
166 | 1135 | List<Block> newBlocks; |
167 | 1135 | try { |
168 | 1135 | context.setCurrentMacroBlock(macroHolder.macroBlock); |
169 | ||
170 | // Populate and validate macro parameters. | |
171 | 1135 | Object macroParameters; |
172 | 1135 | try { |
173 | 1135 | macroParameters = macroHolder.macro.getDescriptor().getParametersBeanClass().newInstance(); |
174 | 1135 | this.beanManager.populate(macroParameters, macroHolder.macroBlock.getParameters()); |
175 | } catch (Throwable e) { | |
176 | // One macro parameter was invalid. | |
177 | // The macro will not be executed and we generate an error message instead of the macro | |
178 | // execution result. | |
179 | 0 | generateError(macroHolder.macroBlock, "Invalid macro parameters used for the \"" |
180 | + macroHolder.macroBlock.getId() + "\" macro", e); | |
181 | 0 | this.logger.debug( |
182 | "Invalid macro parameter for the [" + macroHolder.macroBlock.getId() + "] macro. Internal error: [" | |
183 | + e.getMessage() + "]"); | |
184 | ||
185 | 0 | return; |
186 | } | |
187 | ||
188 | 1135 | newBlocks = |
189 | ((Macro<Object>) macroHolder.macro).execute(macroParameters, macroHolder.macroBlock.getContent(), | |
190 | context); | |
191 | } catch (Throwable e) { | |
192 | // The Macro failed to execute. | |
193 | // The macro will not be executed and we generate an error message instead of the macro | |
194 | // execution result. | |
195 | // Note: We catch any Exception because we want to never break the whole rendering. | |
196 | 10 | generateError(macroHolder.macroBlock, "Failed to execute the [" + macroHolder.macroBlock.getId() |
197 | + "] macro", e); | |
198 | 10 | this.logger.debug( |
199 | "Failed to execute the [" + macroHolder.macroBlock.getId() + "]macro. Internal error [" | |
200 | + e.getMessage() + "]"); | |
201 | ||
202 | 10 | return; |
203 | } | |
204 | ||
205 | // We wrap the blocks generated by the macro execution with MacroMarker blocks so that listeners/renderers | |
206 | // who wish to know the group of blocks that makes up the executed macro can. For example this is useful for | |
207 | // the XWiki Syntax renderer so that it can reconstruct the macros from the transformed XDOM. | |
208 | 1125 | Block resultBlock = wrapInMacroMarker(macroHolder.macroBlock, newBlocks); |
209 | ||
210 | // 4) Replace the MacroBlock by the Blocks generated by the execution of the Macro | |
211 | 1125 | macroHolder.macroBlock.getParent().replaceChild(resultBlock, macroHolder.macroBlock); |
212 | } | |
213 | ||
214 | /** | |
215 | * @return the macro with the highest priority for the passed syntax or null if no macro is found | |
216 | */ | |
217 | 1145 | private MacroHolder getHighestPriorityMacro(Block rootBlock, Syntax syntax) |
218 | { | |
219 | 1145 | List<MacroHolder> macroHolders = new ArrayList<MacroHolder>(); |
220 | ||
221 | // 1) Sort the macros by priority to find the highest priority macro to execute | |
222 | 1145 | for (MacroBlock macroBlock : rootBlock.getChildrenByType(MacroBlock.class, true)) { |
223 | 1167 | try { |
224 | 1167 | Macro< ? > macro = this.macroManager.getMacro(new MacroId(macroBlock.getId(), syntax)); |
225 | 1162 | macroHolders.add(new MacroHolder(macro, macroBlock)); |
226 | } catch (MacroLookupException e) { | |
227 | // Macro cannot be found. Generate an error message instead of the macro execution result. | |
228 | // TODO: make it internationalized | |
229 | 5 | generateError(macroBlock, "Unknown macro: " + macroBlock.getId(), "The \"" + macroBlock.getId() |
230 | + "\" macro is not in the list of registered macros. Verify the " | |
231 | + "spelling or contact your administrator."); | |
232 | 5 | this.logger.debug("Failed to locate the [" + macroBlock.getId() + "] macro. Ignoring it."); |
233 | } | |
234 | } | |
235 | ||
236 | // Sort the Macros by priority | |
237 | 1145 | Collections.sort(macroHolders); |
238 | ||
239 | 1145 | return macroHolders.size() > 0 ? macroHolders.get(0) : null; |
240 | } | |
241 | ||
242 | /** | |
243 | * Wrap the output of a macro block with a {@link MacroMarkerBlock}. | |
244 | * | |
245 | * @param macroBlockToWrap the block that should be replaced | |
246 | * @param newBlocks list of blocks to wrap | |
247 | * @return the wrapper | |
248 | */ | |
249 | 1145 | private Block wrapInMacroMarker(MacroBlock macroBlockToWrap, List<Block> newBlocks) |
250 | { | |
251 | 1145 | return new MacroMarkerBlock(macroBlockToWrap.getId(), macroBlockToWrap.getParameters(), macroBlockToWrap |
252 | .getContent(), newBlocks, macroBlockToWrap.isInline()); | |
253 | } | |
254 | ||
255 | 20 | private void generateError(MacroBlock macroToReplace, String message, String description) |
256 | { | |
257 | 20 | List<Block> errorBlocks = new ArrayList<Block>(); |
258 | ||
259 | 20 | Map<String, String> errorBlockParams = Collections.singletonMap("class", "xwikirenderingerror"); |
260 | 20 | Map<String, String> errorDescriptionBlockParams = |
261 | Collections.singletonMap("class", "xwikirenderingerrordescription hidden"); | |
262 | ||
263 | 20 | Block descriptionBlock = new VerbatimBlock(description, macroToReplace.isInline()); |
264 | ||
265 | 20 | if (macroToReplace.isInline()) { |
266 | 15 | errorBlocks.add(new FormatBlock(Arrays.<Block> asList(new WordBlock(message)), Format.NONE, |
267 | errorBlockParams)); | |
268 | 15 | errorBlocks.add(new FormatBlock(Arrays.asList(descriptionBlock), Format.NONE, errorDescriptionBlockParams)); |
269 | } else { | |
270 | 5 | errorBlocks.add(new GroupBlock(Arrays.<Block> asList(new WordBlock(message)), errorBlockParams)); |
271 | 5 | errorBlocks.add(new GroupBlock(Arrays.asList(descriptionBlock), errorDescriptionBlockParams)); |
272 | } | |
273 | ||
274 | 20 | macroToReplace.getParent().replaceChild(wrapInMacroMarker(macroToReplace, errorBlocks), macroToReplace); |
275 | } | |
276 | ||
277 | 10 | private void generateError(MacroBlock macroToReplace, String message, Throwable throwable) |
278 | { | |
279 | 10 | StringWriter writer = new StringWriter(); |
280 | 10 | throwable.printStackTrace(new PrintWriter(writer)); |
281 | 10 | generateError(macroToReplace, message, writer.getBuffer().toString()); |
282 | } | |
283 | } |
|