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
159   556   85   3.31
36   401   0.53   48
48     1.77  
1    
 
  XHTMLChainingRenderer       Line # 50 159 0% 85 14 94.2% 0.9423868
 
  (239)
 
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.xhtml;
21   
22    import java.util.LinkedHashMap;
23    import java.util.List;
24    import java.util.Map;
25   
26    import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
27    import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
28    import org.xwiki.rendering.listener.Format;
29    import org.xwiki.rendering.listener.HeaderLevel;
30    import org.xwiki.rendering.listener.ListType;
31    import org.xwiki.rendering.listener.MetaData;
32    import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
33    import org.xwiki.rendering.listener.chaining.BlockStateChainingListener.Event;
34    import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
35    import org.xwiki.rendering.listener.chaining.ListenerChain;
36    import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
37    import org.xwiki.rendering.listener.reference.ResourceReference;
38    import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
39    import org.xwiki.rendering.renderer.printer.WikiPrinter;
40    import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
41    import org.xwiki.rendering.syntax.Syntax;
42    import org.xwiki.rendering.syntax.SyntaxType;
43   
44    /**
45    * Convert listener events to XHTML.
46    *
47    * @version $Id: 66eaa41e855269d3062c5e22cc0a8409056dd146 $
48    * @since 1.8RC1
49    */
 
50    public class XHTMLChainingRenderer extends AbstractChainingPrintRenderer
51    {
52    private XHTMLLinkRenderer linkRenderer;
53   
54    private XHTMLImageRenderer imageRenderer;
55   
56    private XHTMLWikiPrinter xhtmlWikiPrinter;
57   
58    /**
59    * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
60    * rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
61    * the document exists, we get the document URL, etc.
62    * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
63    * image rendering depends on how the underlying system wants to handle it. For example for XWiki we
64    * check if the image exists as a document attachments, we get its URL, etc.
65    * @param listenerChain the chain of listener filters used to compute various states
66    */
 
67  247 toggle public XHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer, XHTMLImageRenderer imageRenderer,
68    ListenerChain listenerChain)
69    {
70  247 setListenerChain(listenerChain);
71   
72  247 this.linkRenderer = linkRenderer;
73  247 this.imageRenderer = imageRenderer;
74    }
75   
76    // State
77   
 
78  324 toggle protected BlockStateChainingListener getBlockState()
79    {
80  324 return (BlockStateChainingListener) getListenerChain().getListener(BlockStateChainingListener.class);
81    }
82   
 
83  95 toggle protected EmptyBlockChainingListener getEmptyBlockState()
84    {
85  95 return (EmptyBlockChainingListener) getListenerChain().getListener(EmptyBlockChainingListener.class);
86    }
87   
 
88  127 toggle protected MetaDataStateChainingListener getMetaDataState()
89    {
90  127 return (MetaDataStateChainingListener) getListenerChain().getListener(MetaDataStateChainingListener.class);
91    }
92   
93    // Printer
94   
 
95  247 toggle @Override
96    protected void pushPrinter(WikiPrinter wikiPrinter)
97    {
98  247 super.pushPrinter(wikiPrinter);
99  247 getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
100    }
101   
 
102  0 toggle @Override
103    protected void popPrinter()
104    {
105  0 super.popPrinter();
106  0 getXHTMLWikiPrinter().setWikiPrinter(getPrinter());
107    }
108   
 
109  3270 toggle protected XHTMLWikiPrinter getXHTMLWikiPrinter()
110    {
111  3270 if (this.xhtmlWikiPrinter == null) {
112  247 this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter());
113    }
114  3270 return this.xhtmlWikiPrinter;
115    }
116   
117    // Events
118   
 
119  24 toggle @Override
120    public void beginGroup(Map<String, String> parameters)
121    {
122  24 Map<String, String> clonedParameters = new LinkedHashMap<String, String>();
123  24 clonedParameters.putAll(parameters);
124  24 getXHTMLWikiPrinter().printXMLStartElement("div", clonedParameters);
125    }
126   
 
127  24 toggle @Override
128    public void endGroup(Map<String, String> parameters)
129    {
130  24 getXHTMLWikiPrinter().printXMLEndElement("div");
131    }
132   
 
133  79 toggle @Override
134    public void beginFormat(Format format, Map<String, String> parameters)
135    {
136  79 switch (format) {
137  18 case BOLD:
138  18 getXHTMLWikiPrinter().printXMLStartElement("strong");
139  18 break;
140  15 case ITALIC:
141  15 getXHTMLWikiPrinter().printXMLStartElement("em");
142  15 break;
143  3 case STRIKEDOUT:
144  3 getXHTMLWikiPrinter().printXMLStartElement("del");
145  3 break;
146  1 case UNDERLINED:
147  1 getXHTMLWikiPrinter().printXMLStartElement("ins");
148  1 break;
149  2 case SUPERSCRIPT:
150  2 getXHTMLWikiPrinter().printXMLStartElement("sup");
151  2 break;
152  2 case SUBSCRIPT:
153  2 getXHTMLWikiPrinter().printXMLStartElement("sub");
154  2 break;
155  2 case MONOSPACE:
156  2 getXHTMLWikiPrinter().printXMLStartElement("tt");
157  2 break;
158  36 case NONE:
159  36 break;
160    }
161  79 if (!parameters.isEmpty()) {
162  45 getXHTMLWikiPrinter().printXMLStartElement("span", parameters);
163    }
164    }
165   
 
166  79 toggle @Override
167    public void endFormat(Format format, Map<String, String> parameters)
168    {
169  79 if (!parameters.isEmpty()) {
170  45 getXHTMLWikiPrinter().printXMLEndElement("span");
171    }
172  79 switch (format) {
173  18 case BOLD:
174  18 getXHTMLWikiPrinter().printXMLEndElement("strong");
175  18 break;
176  15 case ITALIC:
177  15 getXHTMLWikiPrinter().printXMLEndElement("em");
178  15 break;
179  3 case STRIKEDOUT:
180  3 getXHTMLWikiPrinter().printXMLEndElement("del");
181  3 break;
182  1 case UNDERLINED:
183  1 getXHTMLWikiPrinter().printXMLEndElement("ins");
184  1 break;
185  2 case SUPERSCRIPT:
186  2 getXHTMLWikiPrinter().printXMLEndElement("sup");
187  2 break;
188  2 case SUBSCRIPT:
189  2 getXHTMLWikiPrinter().printXMLEndElement("sub");
190  2 break;
191  2 case MONOSPACE:
192  2 getXHTMLWikiPrinter().printXMLEndElement("tt");
193  2 break;
194  36 case NONE:
195  36 break;
196    }
197    }
198   
 
199  221 toggle @Override
200    public void beginParagraph(Map<String, String> parameters)
201    {
202  221 getXHTMLWikiPrinter().printXMLStartElement("p", parameters);
203    }
204   
 
205  221 toggle @Override
206    public void endParagraph(Map<String, String> parameters)
207    {
208  221 getXHTMLWikiPrinter().printXMLEndElement("p");
209    }
210   
 
211  87 toggle @Override
212    public void onNewLine()
213    {
214  87 getXHTMLWikiPrinter().printXMLElement("br");
215    }
216   
 
217  95 toggle @Override
218    public void beginLink(ResourceReference reference, boolean isFreeStandingURI, Map<String, String> parameters)
219    {
220    // Ensure the link renderer is using the latest printer since the original printer used could have been
221    // superseded by another one in the printer stack.
222  95 this.linkRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter());
223   
224    // If the ResourceReference doesn't have a base reference specified, then look for one in previously sent
225    // events (it's sent in begin/endMetaData events).
226  95 List<String> baseReferences = reference.getBaseReferences();
227  95 if (baseReferences.isEmpty()) {
228  94 reference.addBaseReferences(getMetaDataState().<String> getAllMetaData(MetaData.BASE));
229    }
230   
231  95 this.linkRenderer.beginLink(reference, isFreeStandingURI, parameters);
232    }
233   
 
234  95 toggle @Override
235    public void endLink(ResourceReference reference, boolean isFreeStandingURI, Map<String, String> parameters)
236    {
237  95 this.linkRenderer.setHasLabel(!getEmptyBlockState().isCurrentContainerBlockEmpty());
238  95 this.linkRenderer.endLink(reference, isFreeStandingURI, parameters);
239    }
240   
 
241  42 toggle @Override
242    public void beginHeader(HeaderLevel level, String id, Map<String, String> parameters)
243    {
244  42 Map<String, String> attributes = new LinkedHashMap<String, String>();
245   
246  42 attributes.put("id", id);
247  42 attributes.putAll(parameters);
248   
249    // Section editing feature:
250    // In order for the UI side to be able to add a section edit button we need to provide some information to it
251    // and especially we need to tell it if the header was a header generated by a macro or not. The reason is
252    // that macro-generated headers should not be editable by the user.
253    // TODO: In the future it's possible that we'll want this kind of behavior implemented using a Transformation.
254    // If we decide this then remove this code.
255  42 if (getBlockState().isInMacro()) {
256  0 String classAttributeName = "class";
257  0 String classValue = attributes.get(classAttributeName);
258  0 String newClassValue = "wikigeneratedheader";
259  0 if (classValue == null) {
260  0 classValue = newClassValue;
261    } else {
262  0 classValue = classValue.trim() + " " + newClassValue;
263    }
264  0 attributes.put(classAttributeName, classValue);
265    }
266   
267  42 getXHTMLWikiPrinter().printXMLStartElement("h" + level.getAsInt(), attributes);
268    // We generate a span so that CSS rules have a hook to perform some magic that wouldn't work on just a H
269    // element. Like some IE6 magic and others.
270  42 getXHTMLWikiPrinter().printXMLStartElement("span");
271    }
272   
 
273  42 toggle @Override
274    public void endHeader(HeaderLevel level, String id, Map<String, String> parameters)
275    {
276  42 getXHTMLWikiPrinter().printXMLEndElement("span");
277  42 getXHTMLWikiPrinter().printXMLEndElement("h" + level.getAsInt());
278    }
279   
 
280  756 toggle @Override
281    public void onWord(String word)
282    {
283  756 getXHTMLWikiPrinter().printXML(word);
284    }
285   
 
286  384 toggle @Override
287    public void onSpace()
288    {
289    // The XHTML printer will decide whether to print a normal space or a &nbsp;
290  384 getXHTMLWikiPrinter().printSpace();
291    }
292   
 
293  176 toggle @Override
294    public void onSpecialSymbol(char symbol)
295    {
296  176 getXHTMLWikiPrinter().printXML("" + symbol);
297    }
298   
 
299  41 toggle @Override
300    public void beginList(ListType listType, Map<String, String> parameters)
301    {
302  41 if (listType == ListType.BULLETED) {
303  36 getXHTMLWikiPrinter().printXMLStartElement("ul", parameters);
304    } else {
305  5 getXHTMLWikiPrinter().printXMLStartElement("ol", parameters);
306    }
307    }
308   
 
309  52 toggle @Override
310    public void beginListItem()
311    {
312  52 getXHTMLWikiPrinter().printXMLStartElement("li");
313    }
314   
 
315  41 toggle @Override
316    public void endList(ListType listType, Map<String, String> parameters)
317    {
318  41 if (listType == ListType.BULLETED) {
319  36 getXHTMLWikiPrinter().printXMLEndElement("ul");
320    } else {
321  5 getXHTMLWikiPrinter().printXMLEndElement("ol");
322    }
323    }
324   
 
325  52 toggle @Override
326    public void endListItem()
327    {
328  52 getXHTMLWikiPrinter().printXMLEndElement("li");
329    }
330   
 
331  3 toggle @Override
332    public void onId(String name)
333    {
334    // Don't use the "name" attribute (see http://www.w3.org/TR/html4/struct/links.html#h-12.2.3).
335    // If the id s in a paragraph use <span id="..."> and if in a standalone block then use
336    // <div id="...">.
337  3 if (getBlockState().isInLine()) {
338    // Note: We're using <span><span/> and not <span/> since some browsers do not support the
339    // <span/> syntax (FF3) when the content type is set to HTML instead of XHTML.
340  2 getXHTMLWikiPrinter().printXMLStartElement("span", new String[][] {{"id", name}});
341  2 getXHTMLWikiPrinter().printXMLEndElement("span");
342    } else {
343  1 getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] {{"id", name}});
344  1 getXHTMLWikiPrinter().printXMLEndElement("div");
345    }
346    }
347   
 
348  11 toggle @Override
349    public void onHorizontalLine(Map<String, String> parameters)
350    {
351  11 getXHTMLWikiPrinter().printXMLElement("hr", parameters);
352    }
353   
 
354  22 toggle @Override
355    public void onVerbatim(String protectedString, boolean isInline, Map<String, String> parameters)
356    {
357  22 if (isInline) {
358    // Note: We generate a tt element rather than a pre element since pre elements cannot be located inside
359    // paragraphs for example. There also no tag in XHTML that has a semantic of preserving inline content so
360    // tt is the closed to pre for inline.
361    // The class is what is expected by wikimodel to understand the tt as meaning a verbatim and not a Monospace
362    // element.
363  12 getXHTMLWikiPrinter().printXMLStartElement("tt", new String[][] {{"class", "wikimodel-verbatim"}});
364  12 getXHTMLWikiPrinter().printXML(protectedString);
365  12 getXHTMLWikiPrinter().printXMLEndElement("tt");
366    } else {
367  10 getXHTMLWikiPrinter().printXMLStartElement("pre", parameters);
368  10 getXHTMLWikiPrinter().printXML(protectedString);
369  10 getXHTMLWikiPrinter().printXMLEndElement("pre");
370    }
371    }
372   
 
373  6 toggle @Override
374    public void onEmptyLines(int count)
375    {
376    // We need to use a special tag for empty lines since in XHTML the BR tag cannot be used outside of content
377    // tags.
378    // Note: We're using <div><div/> and not <div/> since some browsers do not support the <div/> syntax (FF3)
379    // when the content type is set to HTML instead of XHTML.
380  15 for (int i = 0; i < count; ++i) {
381  9 getXHTMLWikiPrinter().printXMLStartElement("div", new String[][] {{"class", "wikimodel-emptyline"}});
382  9 getXHTMLWikiPrinter().printXMLEndElement("div");
383    }
384    }
385   
386    /**
387    * {@inheritDoc}
388    * @since 2.0RC1
389    */
 
390  19 toggle @Override
391    public void beginDefinitionList(Map<String, String> parameters)
392    {
393  19 getXHTMLWikiPrinter().printXMLStartElement("dl", parameters);
394    }
395   
396    /**
397    * {@inheritDoc}
398    * @since 2.0RC1
399    */
 
400  19 toggle @Override
401    public void endDefinitionList(Map<String, String> parameters)
402    {
403  19 getXHTMLWikiPrinter().printXMLEndElement("dl");
404    }
405   
 
406  13 toggle @Override
407    public void beginDefinitionTerm()
408    {
409  13 getXHTMLWikiPrinter().printXMLStartElement("dt");
410    }
411   
 
412  17 toggle @Override
413    public void beginDefinitionDescription()
414    {
415  17 getXHTMLWikiPrinter().printXMLStartElement("dd");
416    }
417   
 
418  13 toggle @Override
419    public void endDefinitionTerm()
420    {
421  13 getXHTMLWikiPrinter().printXMLEndElement("dt");
422    }
423   
 
424  17 toggle @Override
425    public void endDefinitionDescription()
426    {
427  17 getXHTMLWikiPrinter().printXMLEndElement("dd");
428    }
429   
 
430  7 toggle @Override
431    public void beginQuotation(Map<String, String> parameters)
432    {
433  7 if (getBlockState().isInQuotationLine()) {
434  2 getXHTMLWikiPrinter().printXMLEndElement("p");
435    }
436   
437  7 getXHTMLWikiPrinter().printXMLStartElement("blockquote", parameters);
438   
439  7 getXHTMLWikiPrinter().printXMLStartElement("p");
440    }
441   
 
442  7 toggle @Override
443    public void endQuotation(Map<String, String> parameters)
444    {
445  7 getXHTMLWikiPrinter().printXMLEndElement("p");
446   
447  7 getXHTMLWikiPrinter().printXMLEndElement("blockquote");
448   
449  7 if (getBlockState().isInQuotationLine()) {
450  2 getXHTMLWikiPrinter().printXMLStartElement("p");
451    }
452    }
453   
 
454  12 toggle @Override
455    public void beginQuotationLine()
456    {
457    // Send a new line if the previous event was endQuotationLine since we need to separate each quotation line
458    // or they'll printed next to each other and not on a new line each.
459  12 if (getBlockState().isInQuotation() && getBlockState().getPreviousEvent() == Event.QUOTATION_LINE) {
460  5 onNewLine();
461    }
462    }
463   
 
464  14 toggle @Override
465    public void beginTable(Map<String, String> parameters)
466    {
467  14 getXHTMLWikiPrinter().printXMLStartElement("table", parameters);
468    }
469   
 
470  27 toggle @Override
471    public void beginTableRow(Map<String, String> parameters)
472    {
473  27 getXHTMLWikiPrinter().printXMLStartElement("tr", parameters);
474    }
475   
 
476  34 toggle @Override
477    public void beginTableCell(Map<String, String> parameters)
478    {
479  34 getXHTMLWikiPrinter().printXMLStartElement("td", parameters);
480    }
481   
 
482  22 toggle @Override
483    public void beginTableHeadCell(Map<String, String> parameters)
484    {
485    // Find proper scope attribute value
486  22 Map<String, String> parametersWithScope;
487  22 if (!parameters.containsKey("scope")) {
488  21 parametersWithScope = new LinkedHashMap<String, String>(parameters);
489   
490  21 if (getBlockState().getCellRow() == 0 || getBlockState().getCellCol() > 0) {
491  17 parametersWithScope.put("scope", "col");
492    } else {
493  4 parametersWithScope.put("scope", "row");
494    }
495    } else {
496  1 parametersWithScope = parameters;
497    }
498   
499    // Write th element
500  22 getXHTMLWikiPrinter().printXMLStartElement("th", parametersWithScope);
501    }
502   
 
503  14 toggle @Override
504    public void endTable(Map<String, String> parameters)
505    {
506  14 getXHTMLWikiPrinter().printXMLEndElement("table");
507    }
508   
 
509  27 toggle @Override
510    public void endTableRow(Map<String, String> parameters)
511    {
512  27 getXHTMLWikiPrinter().printXMLEndElement("tr");
513    }
514   
 
515  34 toggle @Override
516    public void endTableCell(Map<String, String> parameters)
517    {
518  34 getXHTMLWikiPrinter().printXMLEndElement("td");
519    }
520   
 
521  22 toggle @Override
522    public void endTableHeadCell(Map<String, String> parameters)
523    {
524  22 getXHTMLWikiPrinter().printXMLEndElement("th");
525    }
526   
527    /**
528    * {@inheritDoc}
529    * @since 2.5RC1
530    */
 
531  34 toggle @Override
532    public void onImage(ResourceReference reference, boolean isFreeStandingURI, Map<String, String> parameters)
533    {
534    // Ensure the image renderer is using the latest printer since the original printer used could have been
535    // superseded by another one in the printer stack.
536  34 this.imageRenderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter());
537   
538    // If the ResourceReference doesn't have a base reference specified, then look for one in previously sent
539    // events (it's sent in begin/endMetaData events).
540  34 List<String> baseReferences = reference.getBaseReferences();
541  34 if (baseReferences.isEmpty()) {
542  33 reference.addBaseReferences(getMetaDataState().<String> getAllMetaData(MetaData.BASE));
543    }
544   
545  34 this.imageRenderer.onImage(reference, isFreeStandingURI, parameters);
546    }
547   
 
548  14 toggle @Override
549    public void onRawText(String text, Syntax syntax)
550    {
551    // Directly inject the HTML content in the wiki printer (bypassing the XHTML printer)
552  14 if ((syntax.getType() == SyntaxType.XHTML) || (syntax.getType() == SyntaxType.HTML)) {
553  14 getXHTMLWikiPrinter().printRaw(text);
554    }
555    }
556    }