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
247   775   121   4.19
84   555   0.49   59
59     2.05  
1    
 
  XWikiSyntaxChainingRenderer       Line # 46 247 0% 121 3 99.2% 0.99230766
 
  (326)
 
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.renderer.xwiki20;
21   
22    import java.util.Map;
23   
24    import org.apache.commons.lang3.StringUtils;
25    import org.xwiki.rendering.internal.renderer.xwiki20.reference.XWikiSyntaxResourceRenderer;
26    import org.xwiki.rendering.listener.Format;
27    import org.xwiki.rendering.listener.HeaderLevel;
28    import org.xwiki.rendering.listener.ListType;
29    import org.xwiki.rendering.listener.MetaData;
30    import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
31    import org.xwiki.rendering.listener.chaining.ListenerChain;
32    import org.xwiki.rendering.listener.chaining.StackableChainingListener;
33    import org.xwiki.rendering.listener.reference.ResourceReference;
34    import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
35    import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
36    import org.xwiki.rendering.renderer.printer.VoidWikiPrinter;
37    import org.xwiki.rendering.renderer.printer.WikiPrinter;
38    import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer;
39   
40    /**
41    * Convert listener events to XWiki Syntax 2.0 output.
42    *
43    * @version $Id: 22985c815aa52215b4b14fed18236f06ab90290c $
44    * @since 1.8RC1
45    */
 
46    public class XWikiSyntaxChainingRenderer extends AbstractChainingPrintRenderer implements StackableChainingListener
47    {
48    private XWikiSyntaxResourceRenderer linkResourceRenderer;
49   
50    private XWikiSyntaxResourceRenderer imageResourceRenderer;
51   
52    private XWikiSyntaxMacroRenderer macroPrinter;
53   
54    private ResourceReferenceSerializer linkReferenceSerializer;
55   
56    private ResourceReferenceSerializer imageReferenceSerializer;
57   
58    // Custom States
59   
60    private boolean isFirstElementRendered = false;
61   
62    private StringBuffer listStyle = new StringBuffer();
63   
64    private Map<String, String> previousFormatParameters;
65   
66    /**
67    * @since 2.5RC1
68    */
 
69  379 toggle public XWikiSyntaxChainingRenderer(ListenerChain listenerChain,
70    ResourceReferenceSerializer linkReferenceSerializer, ResourceReferenceSerializer imageReferenceSerializer)
71    {
72  379 setListenerChain(listenerChain);
73   
74  379 this.linkReferenceSerializer = linkReferenceSerializer;
75  379 this.imageReferenceSerializer = imageReferenceSerializer;
76  379 this.linkResourceRenderer = createXWikiSyntaxLinkRenderer(getListenerChain(), linkReferenceSerializer);
77  379 this.imageResourceRenderer = createXWikiSyntaxImageRenderer(getListenerChain(), imageReferenceSerializer);
78  379 this.macroPrinter = new XWikiSyntaxMacroRenderer();
79    }
80   
81    /**
82    * @since 2.5RC1
83    */
 
84  318 toggle protected XWikiSyntaxResourceRenderer createXWikiSyntaxLinkRenderer(ListenerChain listenerChain,
85    ResourceReferenceSerializer linkReferenceSerializer)
86    {
87  318 return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, linkReferenceSerializer);
88    }
89   
90    /**
91    * @since 2.5RC1
92    */
 
93  318 toggle protected XWikiSyntaxResourceRenderer createXWikiSyntaxImageRenderer(ListenerChain listenerChain,
94    ResourceReferenceSerializer imageReferenceSerializer)
95    {
96  318 return new XWikiSyntaxResourceRenderer((XWikiSyntaxListenerChain) listenerChain, imageReferenceSerializer);
97    }
98   
99    // State
100   
 
101  600 toggle private BlockStateChainingListener getBlockState()
102    {
103  600 return getXWikiSyntaxListenerChain().getBlockStateChainingListener();
104    }
105   
 
106  33 toggle @Override
107    public StackableChainingListener createChainingListenerInstance()
108    {
109  33 XWikiSyntaxChainingRenderer renderer = new XWikiSyntaxChainingRenderer(getListenerChain(),
110    this.linkReferenceSerializer, this.imageReferenceSerializer);
111  33 renderer.setPrinter(getPrinter());
112  33 return renderer;
113    }
114   
 
115  873 toggle private XWikiSyntaxListenerChain getXWikiSyntaxListenerChain()
116    {
117  873 return (XWikiSyntaxListenerChain) getListenerChain();
118    }
119   
 
120  310 toggle private XWikiSyntaxResourceRenderer getLinkRenderer()
121    {
122  310 return this.linkResourceRenderer;
123    }
124   
 
125  78 toggle private XWikiSyntaxResourceRenderer getImageRenderer()
126    {
127  78 return this.imageResourceRenderer;
128    }
129   
 
130  131 toggle private XWikiSyntaxMacroRenderer getMacroPrinter()
131    {
132  131 return this.macroPrinter;
133    }
134   
 
135  33 toggle @Override
136    public void beginGroup(Map<String, String> parameters)
137    {
138  33 if (!getBlockState().isInLine()) {
139  24 printEmptyLine();
140    }
141   
142  33 if (parameters.size() > 0) {
143  14 printParameters(parameters, true);
144    }
145   
146  33 print("(((");
147  33 print("\n");
148   
149    // Create a new listener stack in order to preserve current states, to handle the group.
150  33 getListenerChain().pushAllStackableListeners();
151    }
152   
153    /**
154    * {@inheritDoc}
155    * @since 3.0M2
156    */
 
157  398 toggle @Override
158    public void endDocument(MetaData metaData)
159    {
160    // Ensure that all data in the escape printer have been flushed
161  398 getXWikiPrinter().flush();
162    }
163   
 
164  33 toggle @Override
165    public void endGroup(Map<String, String> parameters)
166    {
167  33 print("\n");
168  33 print(")))");
169   
170    // Restore previous listeners that were stacked
171  33 getListenerChain().popAllStackableListeners();
172    }
173   
 
174  78 toggle @Override
175    public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map<String, String> parameters)
176    {
177    // Flush test content before the link.
178    // TODO: improve the block state renderer to be able to make the difference between what is bufferized
179    // before the link and what in the label link
180  78 getXWikiPrinter().setBeforeLink(true);
181    // escape open link syntax when before a link
182  78 if (getLinkRenderer().forceFullSyntax(getXWikiPrinter(), isFreeStandingURI, parameters)
183    && getXWikiPrinter().getBuffer().length() > 0
184    && getXWikiPrinter().getBuffer().charAt(getXWikiPrinter().getBuffer().length() - 1) == '[') {
185  1 getXWikiPrinter().setEscapeLastChar(true);
186    }
187  78 getXWikiPrinter().flush();
188  78 getXWikiPrinter().setBeforeLink(false);
189   
190  78 int linkDepth = getBlockState().getLinkDepth();
191   
192    // If we are at a depth of 2 or greater it means we're in a link inside a link and in this case we
193    // shouldn't output the nested link as a link unless it's a free standing link.
194  78 if (linkDepth < 2) {
195  77 getLinkRenderer().beginRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, parameters);
196   
197  77 XWikiSyntaxEscapeWikiPrinter linkLabelPrinter =
198    new XWikiSyntaxEscapeWikiPrinter(new DefaultWikiPrinter(), getXWikiSyntaxListenerChain());
199   
200    // Make sure the escape handler knows there is already characters before
201  77 linkLabelPrinter.setOnNewLine(getXWikiPrinter().isOnNewLine());
202   
203    // Defer printing the link content since we need to gather all nested elements
204  77 pushPrinter(linkLabelPrinter);
205  1 } else if (isFreeStandingURI) {
206  1 print(getLinkRenderer().serialize(reference, isFreeStandingURI));
207    }
208    }
209   
 
210  78 toggle @Override
211    public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map<String, String> parameters)
212    {
213    // The links in a top level link label are not rendered as link (only the label is printed)
214  78 if (getBlockState().getLinkDepth() == 1) {
215  77 XWikiSyntaxEscapeWikiPrinter linkBlocksPrinter = getXWikiPrinter();
216  77 linkBlocksPrinter.flush();
217  77 String content = linkBlocksPrinter.toString();
218  77 popPrinter();
219   
220  77 getLinkRenderer().renderLinkContent(getXWikiPrinter(), content);
221  77 getLinkRenderer().endRenderLink(getXWikiPrinter(), reference, isFreeStandingURI, parameters);
222    }
223    }
224   
 
225  86 toggle @Override
226    public void beginFormat(Format format, Map<String, String> parameters)
227    {
228    // If the previous format had parameters and the parameters are different from the current ones then close them
229  86 if (this.previousFormatParameters != null) {
230  9 if (parameters.isEmpty()) {
231    //print("(%%)");
232    //this.previousFormatParameters = null;
233  7 } else if (!this.previousFormatParameters.equals(parameters)) {
234  6 this.previousFormatParameters = null;
235  6 printParameters(parameters, false);
236    } else {
237  1 this.previousFormatParameters = null;
238    }
239  77 } else if (this.previousFormatParameters == null) {
240  77 printParameters(parameters, false);
241    }
242   
243  86 switch (format) {
244  25 case BOLD:
245    // Handle empty formatting parameters.
246  25 if (this.previousFormatParameters != null) {
247  1 getPrinter().print("(%%)");
248  1 this.previousFormatParameters = null;
249    }
250   
251  25 getXWikiPrinter().printBeginBold();
252  25 break;
253  19 case ITALIC:
254    // Handle empty formatting parameters.
255  19 if (this.previousFormatParameters != null) {
256  1 getPrinter().print("(%%)");
257  1 this.previousFormatParameters = null;
258    }
259   
260  19 getXWikiPrinter().printBeginItalic();
261  19 break;
262  4 case STRIKEDOUT:
263  4 print("--");
264  4 break;
265  2 case UNDERLINED:
266  2 print("__");
267  2 break;
268  2 case SUPERSCRIPT:
269  2 print("^^");
270  2 break;
271  2 case SUBSCRIPT:
272  2 print(",,");
273  2 break;
274  3 case MONOSPACE:
275  3 print("##");
276  3 break;
277  29 case NONE:
278  29 break;
279    }
280    }
281   
 
282  86 toggle @Override
283    public void endFormat(Format format, Map<String, String> parameters)
284    {
285  86 switch (format) {
286  25 case BOLD:
287  25 print("**");
288  25 break;
289  19 case ITALIC:
290  19 getXWikiPrinter().printEndItalic();
291  19 break;
292  4 case STRIKEDOUT:
293  4 print("--");
294  4 break;
295  2 case UNDERLINED:
296  2 print("__");
297  2 break;
298  2 case SUPERSCRIPT:
299  2 print("^^");
300  2 break;
301  2 case SUBSCRIPT:
302  2 print(",,");
303  2 break;
304  3 case MONOSPACE:
305  3 print("##");
306  3 break;
307  29 case NONE:
308  29 break;
309    }
310  86 if (!parameters.isEmpty()) {
311  38 this.previousFormatParameters = parameters;
312    }
313    }
314   
 
315  283 toggle @Override
316    public void beginParagraph(Map<String, String> parameters)
317    {
318  283 printEmptyLine();
319  283 printParameters(parameters);
320    }
321   
 
322  283 toggle @Override
323    public void endParagraph(Map<String, String> parameters)
324    {
325  283 this.previousFormatParameters = null;
326   
327    // Ensure that any not printed characters are flushed.
328    // TODO: Fix this better by introducing a state listener to handle escapes
329  283 getXWikiPrinter().flush();
330    }
331   
 
332  90 toggle @Override
333    public void onNewLine()
334    {
335    // - If we're inside a table cell, a paragraph, a list or a section header then if we have already outputted
336    // a new line before then this new line should be a line break in order not to break the table cell,
337    // paragraph, list or section header.
338   
339    // - If the new line is the last element of the paragraph, list or section header then it should be a line break
340    // as otherwise it'll be considered as an empty line event next time the generated syntax is read by the XWiki
341    // parser.
342   
343  90 if (getBlockState().isInLine()) {
344  89 if (getXWikiSyntaxListenerChain().getConsecutiveNewLineStateChainingListener().getNewLineCount() > 1) {
345  6 print("\\\\");
346  83 } else if (getXWikiSyntaxListenerChain().getLookaheadChainingListener().getNextEvent().eventType
347    .isInlineEnd()) {
348  8 print("\\\\");
349    } else {
350  75 print("\n");
351    }
352    } else {
353  1 print("\n");
354    }
355    }
356   
 
357  107 toggle @Override
358    public void onMacro(String id, Map<String, String> parameters, String content, boolean isInline)
359    {
360  107 if (!isInline) {
361  82 printEmptyLine();
362  82 print(getMacroPrinter().renderMacro(id, parameters, content, isInline));
363    } else {
364  25 getXWikiPrinter().printInlineMacro(getMacroPrinter().renderMacro(id, parameters, content, isInline));
365    }
366    }
367   
 
368  50 toggle @Override
369    public void beginHeader(HeaderLevel level, String id, Map<String, String> parameters)
370    {
371  50 printEmptyLine();
372  50 printParameters(parameters);
373  50 print(StringUtils.repeat("=", level.getAsInt()) + " ");
374    }
375   
 
376  50 toggle @Override
377    public void endHeader(HeaderLevel level, String id, Map<String, String> parameters)
378    {
379  50 print(" " + StringUtils.repeat("=", level.getAsInt()));
380    }
381   
 
382  1004 toggle @Override
383    public void onWord(String word)
384    {
385  1004 printDelayed(word);
386    }
387   
 
388  552 toggle @Override
389    public void onSpace()
390    {
391  552 printDelayed(" ");
392    }
393   
 
394  289 toggle @Override
395    public void onSpecialSymbol(char symbol)
396    {
397  289 printDelayed("" + symbol);
398    }
399   
 
400  66 toggle @Override
401    public void beginList(ListType listType, Map<String, String> parameters)
402    {
403  66 if (getBlockState().getListDepth() == 1) {
404  39 printEmptyLine();
405    } else {
406  27 getPrinter().print("\n");
407    }
408   
409  66 if (listType == ListType.BULLETED) {
410  58 this.listStyle.append("*");
411    } else {
412  8 this.listStyle.append("1");
413    }
414  66 printParameters(parameters);
415    }
416   
 
417  76 toggle @Override
418    public void beginListItem()
419    {
420  76 if (getBlockState().getListItemIndex() > 0) {
421  10 getPrinter().print("\n");
422    }
423   
424  76 print(this.listStyle.toString());
425  76 if (StringUtils.contains(this.listStyle.toString(), '1')) {
426  12 print(".");
427    }
428  76 print(" ");
429    }
430   
 
431  66 toggle @Override
432    public void endList(ListType listType, Map<String, String> parameters)
433    {
434  66 this.listStyle.setLength(this.listStyle.length() - 1);
435   
436    // Ensure that any not printed characters are flushed.
437    // TODO: Fix this better by introducing a state listener to handle escapes
438  66 getXWikiPrinter().flush();
439    }
440   
 
441  76 toggle @Override
442    public void endListItem()
443    {
444  76 this.previousFormatParameters = null;
445    }
446   
 
447  24 toggle @Override
448    public void beginMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
449    {
450  24 if (!isInline) {
451  14 printEmptyLine();
452    }
453   
454    // When we encounter a macro marker we ignore all other blocks inside since we're going to use the macro
455    // definition wrapped by the macro marker to construct the xwiki syntax.
456  24 pushPrinter(new XWikiSyntaxEscapeWikiPrinter(VoidWikiPrinter.VOIDWIKIPRINTER, getXWikiSyntaxListenerChain()));
457    }
458   
 
459  24 toggle @Override
460    public void endMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline)
461    {
462  24 this.previousFormatParameters = null;
463   
464  24 popPrinter();
465   
466  24 print(getMacroPrinter().renderMacro(name, parameters, content, isInline));
467    }
468   
 
469  6 toggle @Override
470    public void onId(String name)
471    {
472  6 print("{{id name=\"" + name + "\"/}}");
473    }
474   
 
475  13 toggle @Override
476    public void onHorizontalLine(Map<String, String> parameters)
477    {
478  13 printEmptyLine();
479  13 printParameters(parameters);
480  13 print("----");
481    }
482   
 
483  20 toggle @Override
484    public void onVerbatim(String protectedString, boolean isInline, Map<String, String> parameters)
485    {
486  20 if (!isInline) {
487  9 printEmptyLine();
488    }
489  20 printParameters(parameters);
490   
491  20 print("{{{");
492  20 getXWikiPrinter().printVerbatimContent(protectedString);
493  20 print("}}}");
494    }
495   
 
496  8 toggle @Override
497    public void onEmptyLines(int count)
498    {
499  8 print(StringUtils.repeat('\n', count));
500    }
501   
502    /**
503    * {@inheritDoc}
504    * @since 2.0RC1
505    */
 
506  20 toggle @Override
507    public void beginDefinitionList(Map<String, String> parameters)
508    {
509  20 if (getBlockState().getDefinitionListDepth() == 1 && !getBlockState().isInList()) {
510  13 printEmptyLine();
511    } else {
512  7 print("\n");
513    }
514  20 printParameters(parameters);
515    }
516   
517    /**
518    * {@inheritDoc}
519    * @since 1.6M2
520    */
 
521  14 toggle @Override
522    public void beginDefinitionTerm()
523    {
524  14 if (getBlockState().getDefinitionListItemIndex() > 0) {
525  1 getPrinter().print("\n");
526    }
527   
528  14 if (this.listStyle.length() > 0) {
529  2 print(this.listStyle.toString());
530  2 if (this.listStyle.charAt(0) == '1') {
531  1 print(".");
532    }
533    }
534  14 print(StringUtils.repeat(':', getBlockState().getDefinitionListDepth() - 1));
535  14 print("; ");
536    }
537   
538    /**
539    * {@inheritDoc}
540    * @since 1.6M2
541    */
 
542  18 toggle @Override
543    public void beginDefinitionDescription()
544    {
545  18 if (getBlockState().getDefinitionListItemIndex() > 0) {
546  11 getPrinter().print("\n");
547    }
548   
549  18 if (this.listStyle.length() > 0) {
550  2 print(this.listStyle.toString());
551  2 if (this.listStyle.charAt(0) == '1') {
552  1 print(".");
553    }
554    }
555  18 print(StringUtils.repeat(':', getBlockState().getDefinitionListDepth() - 1));
556  18 print(": ");
557    }
558   
 
559  18 toggle @Override
560    public void endDefinitionDescription()
561    {
562  18 this.previousFormatParameters = null;
563   
564  18 getXWikiPrinter().flush();
565    }
566   
 
567  14 toggle @Override
568    public void endDefinitionTerm()
569    {
570  14 this.previousFormatParameters = null;
571   
572  14 getXWikiPrinter().flush();
573    }
574   
575    /**
576    * {@inheritDoc}
577    * @since 1.6M2
578    */
 
579  9 toggle @Override
580    public void beginQuotation(Map<String, String> parameters)
581    {
582  9 if (!getBlockState().isInQuotationLine()) {
583  7 printEmptyLine();
584    }
585   
586  9 if (!parameters.isEmpty()) {
587  1 printParameters(parameters);
588    }
589    }
590   
591    /**
592    * {@inheritDoc}
593    * @since 1.6M2
594    */
 
595  16 toggle @Override
596    public void beginQuotationLine()
597    {
598  16 if (getBlockState().getQuotationLineIndex() > 0) {
599  9 getPrinter().print("\n");
600    }
601   
602  16 print(StringUtils.repeat('>', getBlockState().getQuotationDepth()));
603    }
604   
 
605  16 toggle @Override
606    public void endQuotationLine()
607    {
608  16 this.previousFormatParameters = null;
609   
610  16 getXWikiPrinter().flush();
611    }
612   
 
613  21 toggle @Override
614    public void beginTable(Map<String, String> parameters)
615    {
616  21 printEmptyLine();
617  21 if (!parameters.isEmpty()) {
618  2 printParameters(parameters);
619    }
620    }
621   
 
622  53 toggle @Override
623    public void beginTableCell(Map<String, String> parameters)
624    {
625  53 print("|");
626  53 printParameters(parameters, false);
627    }
628   
 
629  31 toggle @Override
630    public void beginTableHeadCell(Map<String, String> parameters)
631    {
632  31 print("|=");
633  31 printParameters(parameters, false);
634    }
635