1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.rendering.internal.parser.xhtml.wikimodel

File XWikiCommentHandler.java

 

Coverage histogram

../../../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

16
61
7
1
211
122
22
0.36
8.71
7
3.14

Classes

Class Line # Actions
XWikiCommentHandler 51 61 0% 22 0
1.0100%
 

Contributing tests

This file is covered by 282 tests. .

Source view

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