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
61   209   22   8.71
16   120   0.36   7
7     3.14  
1    
 
  XWikiCommentHandler       Line # 50 61 0% 22 0 100% 1.0
 
  (219)
 
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.xhtml.wikimodel;
21   
22    import java.util.Stack;
23   
24    import org.xwiki.rendering.wikimodel.WikiParameter;
25    import org.xwiki.rendering.wikimodel.WikiParameters;
26    import org.xwiki.rendering.wikimodel.WikiReference;
27    import org.xwiki.rendering.wikimodel.xhtml.handler.CommentHandler;
28    import org.xwiki.rendering.wikimodel.xhtml.impl.XhtmlHandler.TagStack;
29    import org.xwiki.component.manager.ComponentLookupException;
30    import org.xwiki.component.manager.ComponentManager;
31    import org.xwiki.rendering.internal.parser.wikimodel.XWikiGeneratorListener;
32    import org.xwiki.rendering.internal.parser.xhtml.XHTMLParser;
33    import org.xwiki.rendering.listener.MetaData;
34    import org.xwiki.rendering.listener.reference.ResourceReference;
35    import org.xwiki.rendering.parser.ResourceReferenceParser;
36    import org.xwiki.rendering.renderer.PrintRenderer;
37    import org.xwiki.rendering.renderer.PrintRendererFactory;
38    import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
39    import org.xwiki.rendering.renderer.reference.link.URILabelGenerator;
40    import org.xwiki.xml.XMLUtils;
41   
42    /**
43    * Handle Link and Macro definitions in comments (we store links in a comment since otherwise there are situations where
44    * it's not possible to reconstruct the original reference from the rendered HTML value and for macros it wouldn't be
45    * possible at all to reconstruct the macro).
46    *
47    * @version $Id: b85e067a75389318e5ed4e663c456bb8d428b390 $
48    * @since 1.7M1
49    */
 
50    public class XWikiCommentHandler extends CommentHandler
51    {
52    private XHTMLParser parser;
53   
54    private PrintRendererFactory xwikiSyntaxPrintRendererFactory;
55   
56    private ComponentManager componentManager;
57   
58    private ResourceReferenceParser xhtmlMarkerResourceReferenceParser;
59   
60    /**
61    * We're using a stack so that we can have nested comment handling. For example when we have a link to an image we
62    * need nested comment support.
63    */
64    private Stack<String> commentContentStack = new Stack<String>();
65   
66    /**
67    * @since 2.5RC1
68    * @todo Remove the need to pass a Parser when WikiModel implements support for wiki syntax in links. See
69    * http://code.google.com/p/wikimodel/issues/detail?id=87
70    */
 
71  219 toggle public XWikiCommentHandler(ComponentManager componentManager, XHTMLParser parser,
72    PrintRendererFactory xwikiSyntaxPrintRendererFactory, ResourceReferenceParser xhtmlMarkerResourceReferenceParser)
73    {
74  219 this.componentManager = componentManager;
75  219 this.parser = parser;
76  219 this.xwikiSyntaxPrintRendererFactory = xwikiSyntaxPrintRendererFactory;
77  219 this.xhtmlMarkerResourceReferenceParser = xhtmlMarkerResourceReferenceParser;
78    }
79   
 
80  193 toggle @Override
81    public void onComment(String content, TagStack stack)
82    {
83    // if ignoreElements is true it means we are inside a macro or another block we don't want to parse content
84  193 boolean ignoreElements = (Boolean) stack.getStackParameter("ignoreElements");
85   
86    // If the comment starts with "startwikilink" then we need to gather all XHTML tags inside
87    // the A tag, till we get a "stopwikilink" comment.
88    // Same for "startimage" and "stopimage".
89  193 if (!ignoreElements && content.startsWith("startwikilink:")) {
90  45 handleLinkCommentStart(XMLUtils.unescapeXMLComment(content), stack);
91  148 } else if (!ignoreElements && content.startsWith("stopwikilink")) {
92  45 handleLinkCommentStop(XMLUtils.unescapeXMLComment(content), stack);
93  103 } else if (!ignoreElements && content.startsWith("startimage:")) {
94  15 handleImageCommentStart(XMLUtils.unescapeXMLComment(content), stack);
95  88 } else if (!ignoreElements && content.startsWith("stopimage")) {
96  15 handleImageCommentStop(XMLUtils.unescapeXMLComment(content), stack);
97  73 } else if (!ignoreElements && content.startsWith("startmacro")) {
98  27 super.onComment(XMLUtils.unescapeXMLComment(content), stack);
99    } else {
100  46 super.onComment(content, stack);
101    }
102    }
103   
 
104  45 toggle private void handleLinkCommentStart(String content, TagStack stack)
105    {
106    // Since wikimodel does not support wiki syntax in link labels we need to pass the link label "as is" (as it
107    // originally appears in the parsed source) and handle it specially in DefaultXWikiGeneratorListener, with the
108    // parser passed as the first parameter in the DefaultXWikiGeneratorListener constructor.
109    // Since we cannot get this label as it originally appeared in the HTML source ( we are doing a SAX-like
110    // parsing), we should render the XDOM as HTML to get an HTML label.
111    // Since any syntax would do it, as long as this renderer matches the corresponding
112    // DefaultXWikiGeneratorListener
113    // parser, we use an xwiki 2.1 renderer for it is less complex (no context needed to render xwiki 2.1, no url
114    // resolution needed, no reference validity tests).
115    // see DefaultXWikiGeneratorListener#DefaultXWikiGeneratorListener(Parser, ResourceReferenceParser, ImageParser)
116    // see WikiModelXHTMLParser#getLinkLabelParser()
117    // see http://code.google.com/p/wikimodel/issues/detail?id=87
118    // TODO: remove this workaround when wiki syntax in link labels will be supported by wikimodel
119  45 DefaultWikiPrinter printer = new DefaultWikiPrinter();
120   
121  45 PrintRenderer linkLabelRenderer = this.xwikiSyntaxPrintRendererFactory.createRenderer(printer);
122    // Make sure to flush whatever the renderer implementation
123  45 linkLabelRenderer.beginDocument(MetaData.EMPTY);
124   
125  45 XWikiGeneratorListener xwikiListener = this.parser.createXWikiGeneratorListener(linkLabelRenderer, null);
126   
127  45 stack.pushStackParameter("linkListener", xwikiListener);
128   
129  45 stack.pushStackParameter("isInLink", true);
130  45 stack.pushStackParameter("isFreeStandingLink", false);
131  45 stack.pushStackParameter("linkParameters", WikiParameters.EMPTY);
132   
133  45 this.commentContentStack.push(content.substring("startwikilink:".length()));
134    }
135   
 
136  45 toggle private void handleLinkCommentStop(String content, TagStack stack)
137    {
138  45 XWikiGeneratorListener xwikiListener = (XWikiGeneratorListener) stack.popStackParameter("linkListener");
139  45 PrintRenderer linkLabelRenderer = (PrintRenderer) xwikiListener.getListener();
140   
141    // Make sure to flush whatever the renderer implementation
142  45 linkLabelRenderer.endDocument(MetaData.EMPTY);
143   
144  45 boolean isFreeStandingLink = (Boolean) stack.getStackParameter("isFreeStandingLink");
145   
146  45 ResourceReference linkReference = this.xhtmlMarkerResourceReferenceParser.parse(this.commentContentStack.pop());
147  45 WikiParameters linkParams = WikiParameters.EMPTY;
148  45 String label = null;
149  45 if (!isFreeStandingLink) {
150  38 label = linkLabelRenderer.getPrinter().toString();
151   
152    // Add the Link reference parameters to the link parameters.
153  38 linkParams = (WikiParameters) stack.getStackParameter("linkParameters");
154    }
155   
156  45 WikiReference wikiReference = new XWikiWikiReference(linkReference, label, linkParams, isFreeStandingLink);
157  45 stack.getScannerContext().onReference(wikiReference);
158   
159  45 stack.popStackParameter("isInLink");
160  45 stack.popStackParameter("isFreeStandingLink");
161  45 stack.popStackParameter("linkParameters");
162    }
163   
 
164  15 toggle private void handleImageCommentStart(String content, TagStack stack)
165    {
166  15 stack.setStackParameter("isInImage", true);
167  15 this.commentContentStack.push(content.substring("startimage:".length()));
168    }
169   
 
170  15 toggle private void handleImageCommentStop(String content, TagStack stack)
171    {
172  15 boolean isFreeStandingImage = (Boolean) stack.getStackParameter("isFreeStandingImage");
173   
174  15 ResourceReference imageReference =
175    this.xhtmlMarkerResourceReferenceParser.parse(this.commentContentStack.pop());
176   
177  15 WikiParameters imageParams = WikiParameters.EMPTY;
178  15 if (!isFreeStandingImage) {
179    // Remove the ALT attribute if the content has the same value as the original image location
180    // This is because the XHTML renderer automatically adds an ALT attribute since it is mandatory
181    // in the XHTML specifications.
182  8 imageParams = (WikiParameters) stack.getStackParameter("imageParameters");
183  8 WikiParameter alt = imageParams.getParameter("alt");
184  8 if (alt != null && alt.getValue().equals(computeAltAttributeValue(imageReference))) {
185  6 imageParams = imageParams.remove("alt");
186    }
187    }
188   
189  15 WikiReference reference = new XWikiWikiReference(imageReference, null, imageParams, isFreeStandingImage);
190  15 stack.getScannerContext().onImage(reference);
191   
192  15 stack.setStackParameter("isInImage", false);
193  15 stack.setStackParameter("isFreeStandingImage", false);
194  15 stack.setStackParameter("imageParameters", WikiParameters.EMPTY);
195    }
196   
 
197  6 toggle private String computeAltAttributeValue(ResourceReference reference)
198    {
199  6 String label;
200  6 try {
201  6 URILabelGenerator uriLabelGenerator =
202    this.componentManager.lookup(URILabelGenerator.class, reference.getType().getScheme());
203  5 label = uriLabelGenerator.generateLabel(reference);
204    } catch (ComponentLookupException e) {
205  1 label = reference.getReference();
206    }
207  6 return label;
208    }
209    }