001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.wiki.engines.antlrwiki.translator;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.repository.model.FileEntry;
020    import com.liferay.portal.kernel.util.HtmlUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.TreeNode;
025    import com.liferay.portal.parsers.creole.ast.CollectionNode;
026    import com.liferay.portal.parsers.creole.ast.HeadingNode;
027    import com.liferay.portal.parsers.creole.ast.ImageNode;
028    import com.liferay.portal.parsers.creole.ast.WikiPageNode;
029    import com.liferay.portal.parsers.creole.ast.extension.TableOfContentsNode;
030    import com.liferay.portal.parsers.creole.ast.link.LinkNode;
031    import com.liferay.portal.parsers.creole.visitor.impl.XhtmlTranslationVisitor;
032    import com.liferay.portlet.wiki.NoSuchPageException;
033    import com.liferay.portlet.wiki.engines.antlrwiki.translator.internal.UnformattedHeadingTextVisitor;
034    import com.liferay.portlet.wiki.engines.antlrwiki.translator.internal.UnformattedLinksTextVisitor;
035    import com.liferay.portlet.wiki.model.WikiPage;
036    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
037    
038    import java.util.List;
039    
040    import javax.portlet.PortletURL;
041    
042    /**
043     * @author Miguel Pastor
044     */
045    public class XhtmlTranslator extends XhtmlTranslationVisitor {
046    
047            public String translate(
048                    WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
049                    String attachmentURLPrefix, WikiPageNode wikiPageNode) {
050    
051                    _page = page;
052                    _viewPageURL = viewPageURL;
053                    _editPageURL = editPageURL;
054                    _attachmentURLPrefix = attachmentURLPrefix;
055                    _rootWikiPageNode = wikiPageNode;
056    
057                    return super.translate(wikiPageNode);
058            }
059    
060            @Override
061            public void visit(HeadingNode headingNode) {
062                    append("<h");
063                    append(headingNode.getLevel());
064    
065                    String unformattedText = getUnformattedHeadingText(headingNode);
066    
067                    String markup = getHeadingMarkup(_page.getTitle(), unformattedText);
068    
069                    append(" id=\"");
070                    append(markup);
071                    append("\">");
072    
073                    traverse(headingNode.getChildASTNodes());
074    
075                    append("</h");
076                    append(headingNode.getLevel());
077                    append(">");
078            }
079    
080            @Override
081            public void visit(ImageNode imageNode) {
082                    append("<img");
083    
084                    if (imageNode.hasAltCollectionNode()) {
085                            append(" alt=\"");
086    
087                            CollectionNode altCollectionNode = imageNode.getAltNode();
088    
089                            traverse(altCollectionNode.getASTNodes());
090    
091                            append(StringPool.QUOTE);
092                    }
093    
094                    append(" src=\"");
095    
096                    if (imageNode.isAbsoluteLink()) {
097                            append(imageNode.getLink());
098                    }
099                    else {
100                            append(_attachmentURLPrefix);
101                            append(imageNode.getLink());
102                    }
103    
104                    append("\" />");
105            }
106    
107            @Override
108            public void visit(LinkNode linkNode) {
109                    append("<a href=\"");
110    
111                    appendHref(linkNode);
112    
113                    append("\">");
114    
115                    if (linkNode.hasAltCollectionNode()) {
116                            CollectionNode altCollectionNode = linkNode.getAltCollectionNode();
117    
118                            traverse(altCollectionNode.getASTNodes());
119                    }
120                    else {
121                            append(HtmlUtil.escape(linkNode.getLink()));
122                    }
123    
124                    append("</a>");
125            }
126    
127            @Override
128            public void visit(TableOfContentsNode tableOfContentsNode) {
129                    TableOfContentsVisitor tableOfContentsVisitor =
130                            new TableOfContentsVisitor();
131    
132                    TreeNode<HeadingNode> tableOfContents = tableOfContentsVisitor.compose(
133                            _rootWikiPageNode);
134    
135                    append("<div class=\"toc\">");
136                    append("<div class=\"collapsebox\">");
137                    append("<h4>");
138    
139                    String title = tableOfContentsNode.getTitle();
140    
141                    if (title == null) {
142                            title = "Table of Contents";
143                    }
144    
145                    append(title);
146    
147                    append(StringPool.NBSP);
148                    append("<a class=\"toc-trigger\" href=\"javascript:;\">[-]</a></h4>");
149                    append("<div class=\"toc-index\">");
150    
151                    appendTableOfContents(tableOfContents, 1);
152    
153                    append("</div>");
154                    append("</div>");
155                    append("</div>");
156            }
157    
158            protected void appendAbsoluteHref(LinkNode linkNode) {
159                    append(HtmlUtil.escape(linkNode.getLink()));
160            }
161    
162            protected void appendHref(LinkNode linkNode) {
163                    if (linkNode.getLink() == null) {
164                            UnformattedLinksTextVisitor unformattedLinksTextVisitor =
165                                    new UnformattedLinksTextVisitor();
166    
167                            linkNode.setLink(
168                                    unformattedLinksTextVisitor.getUnformattedText(linkNode));
169                    }
170    
171                    if (linkNode.isAbsoluteLink()) {
172                            appendAbsoluteHref(linkNode);
173                    }
174                    else {
175                            appendWikiHref(linkNode);
176                    }
177            }
178    
179            protected void appendTableOfContents(
180                    TreeNode<HeadingNode> tableOfContents, int depth) {
181    
182                    List<TreeNode<HeadingNode>> treeNodes = tableOfContents.getChildNodes();
183    
184                    if ((treeNodes == null) || treeNodes.isEmpty()) {
185                            return;
186                    }
187    
188                    append("<ol>");
189    
190                    for (TreeNode<HeadingNode> treeNode : treeNodes) {
191                            append("<li class=\"toc-level-");
192                            append(depth);
193                            append("\">");
194    
195                            HeadingNode headingNode = treeNode.getValue();
196    
197                            String content = getUnformattedHeadingText(headingNode);
198    
199                            append("<a class=\"wikipage\" href=\"");
200    
201                            if (_viewPageURL != null) {
202                                    append(_viewPageURL.toString());
203                            }
204    
205                            append(StringPool.POUND);
206                            append(getHeadingMarkup(_page.getTitle(), content));
207                            append("\">");
208                            append(content);
209                            append("</a>");
210    
211                            appendTableOfContents(treeNode, depth + 1);
212    
213                            append("</li>");
214                    }
215    
216                    append("</ol>");
217            }
218    
219            protected void appendWikiHref(LinkNode linkNode) {
220                    WikiPage page = null;
221    
222                    try {
223                            page = WikiPageLocalServiceUtil.getPage(
224                                    _page.getNodeId(), linkNode.getLink());
225                    }
226                    catch (NoSuchPageException nspe) {
227                    }
228                    catch (Exception e) {
229                            _log.error(e, e);
230                    }
231    
232                    String attachmentLink = searchLinkInAttachments(linkNode);
233    
234                    if (attachmentLink != null) {
235    
236                            // Attachment links take precedence over pages
237    
238                            append(_attachmentURLPrefix + attachmentLink);
239    
240                            return;
241                    }
242    
243                    String pageTitle = linkNode.getLink();
244    
245                    if ((page != null) && (_viewPageURL != null)) {
246                            _viewPageURL.setParameter("title", pageTitle);
247    
248                            append(_viewPageURL.toString());
249    
250                            _viewPageURL.setParameter("title", _page.getTitle());
251                    }
252                    else if (_editPageURL != null) {
253                            _editPageURL.setParameter("title", pageTitle);
254    
255                            append(_editPageURL.toString());
256    
257                            _editPageURL.setParameter("title", _page.getTitle());
258                    }
259            }
260    
261            protected String getHeadingMarkup(String prefix, String text) {
262                    StringBundler sb = new StringBundler(5);
263    
264                    sb.append(_HEADING_ANCHOR_PREFIX);
265                    sb.append(prefix);
266                    sb.append(StringPool.DASH);
267                    sb.append(text.trim());
268    
269                    return StringUtil.replace(
270                            sb.toString(), StringPool.SPACE, StringPool.PLUS);
271            }
272    
273            protected String getUnformattedHeadingText(HeadingNode headingNode) {
274                    UnformattedHeadingTextVisitor unformattedHeadingTextVisitor =
275                            new UnformattedHeadingTextVisitor();
276    
277                    return unformattedHeadingTextVisitor.getUnformattedText(headingNode);
278            }
279    
280            protected String searchLinkInAttachments(LinkNode linkNode) {
281                    try {
282                            for (FileEntry fileEntry : _page.getAttachmentsFileEntries()) {
283                                    String title = fileEntry.getTitle();
284    
285                                    if (title.equals(linkNode.getLink())) {
286                                            return title;
287                                    }
288                            }
289                    }
290                    catch (Exception e) {
291                    }
292    
293                    return null;
294            }
295    
296            private static final String _HEADING_ANCHOR_PREFIX = "section-";
297    
298            private static final Log _log = LogFactoryUtil.getLog(
299                    XhtmlTranslator.class);
300    
301            private String _attachmentURLPrefix;
302            private PortletURL _editPageURL;
303            private WikiPage _page;
304            private WikiPageNode _rootWikiPageNode;
305            private PortletURL _viewPageURL;
306    
307    }