001    /**
002     * Copyright (c) 2000-2012 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.util.HtmlUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.TreeNode;
024    import com.liferay.portal.parsers.creole.ast.CollectionNode;
025    import com.liferay.portal.parsers.creole.ast.HeadingNode;
026    import com.liferay.portal.parsers.creole.ast.ImageNode;
027    import com.liferay.portal.parsers.creole.ast.WikiPageNode;
028    import com.liferay.portal.parsers.creole.ast.extension.TableOfContentsNode;
029    import com.liferay.portal.parsers.creole.ast.link.LinkNode;
030    import com.liferay.portal.parsers.creole.visitor.impl.XhtmlTranslationVisitor;
031    import com.liferay.portlet.wiki.NoSuchPageException;
032    import com.liferay.portlet.wiki.engines.antlrwiki.translator.internal.UnformattedHeadingTextVisitor;
033    import com.liferay.portlet.wiki.engines.antlrwiki.translator.internal.UnformattedLinksTextVisitor;
034    import com.liferay.portlet.wiki.model.WikiPage;
035    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
036    
037    import java.util.List;
038    
039    import javax.portlet.PortletURL;
040    
041    /**
042     * @author Miguel Pastor
043     */
044    public class XhtmlTranslator extends XhtmlTranslationVisitor {
045    
046            public String translate(
047                    WikiPage wikiPage, PortletURL viewPageURL, PortletURL editPageURL,
048                    String attachmentURLPrefix, WikiPageNode wikiPageNode) {
049    
050                    _wikiPage = wikiPage;
051                    _viewPageURL = viewPageURL;
052                    _editPageURL = editPageURL;
053                    _attachmentURLPrefix = attachmentURLPrefix;
054                    _rootWikiPageNode = wikiPageNode;
055    
056                    return super.translate(wikiPageNode);
057            }
058    
059            @Override
060            public void visit(HeadingNode headingNode) {
061                    append("<h");
062                    append(headingNode.getLevel());
063    
064                    String unformattedText = getUnformattedHeadingText(headingNode);
065    
066                    String markup = getHeadingMarkup(_wikiPage.getTitle(), unformattedText);
067    
068                    append(" id=\"");
069                    append(markup);
070                    append("\">");
071    
072                    traverse(headingNode.getChildASTNodes());
073    
074                    append("<a class=\"hashlink\" href=\"");
075    
076                    if (_viewPageURL != null) {
077                            append(_viewPageURL.toString());
078                    }
079    
080                    append(StringPool.POUND);
081                    append(markup);
082                    append("\">#</a></h");
083                    append(headingNode.getLevel());
084                    append(">");
085            }
086    
087            @Override
088            public void visit(ImageNode imageNode) {
089                    append("<img");
090    
091                    if (imageNode.hasAltCollectionNode()) {
092                            append(" alt=\"");
093    
094                            CollectionNode altCollectionNode = imageNode.getAltNode();
095    
096                            traverse(altCollectionNode.getASTNodes());
097    
098                            append(StringPool.QUOTE);
099                    }
100    
101                    append(" src=\"");
102    
103                    if (imageNode.isAbsoluteLink()) {
104                            append(imageNode.getLink());
105                    }
106                    else {
107                            append(_attachmentURLPrefix);
108                            append(imageNode.getLink());
109                    }
110    
111                    append("\" />");
112            }
113    
114            @Override
115            public void visit(LinkNode linkNode) {
116                    append("<a href=\"");
117    
118                    appendHref(linkNode);
119    
120                    append("\">");
121    
122                    if (linkNode.hasAltCollectionNode()) {
123                            CollectionNode altCollectionNode = linkNode.getAltCollectionNode();
124    
125                            traverse(altCollectionNode.getASTNodes());
126                    }
127                    else {
128                            append(HtmlUtil.escape(linkNode.getLink()));
129                    }
130    
131                    append("</a>");
132            }
133    
134            @Override
135            public void visit(TableOfContentsNode tableOfContentsNode) {
136                    TableOfContentsVisitor tableOfContentsVisitor =
137                            new TableOfContentsVisitor();
138    
139                    TreeNode<HeadingNode> tableOfContents = tableOfContentsVisitor.compose(
140                            _rootWikiPageNode);
141    
142                    append("<div class=\"toc\">");
143                    append("<div class=\"collapsebox\">");
144                    append("<h4>Table of Contents");
145                    append(StringPool.NBSP);
146                    append("<a class=\"toc-trigger\" href=\"javascript:;\">[-]</a></h4>");
147                    append("<div class=\"toc-index\">");
148    
149                    appendTableOfContents(tableOfContents, 1);
150    
151                    append("</div>");
152                    append("</div>");
153                    append("</div>");
154            }
155    
156            protected void appendAbsoluteHref(LinkNode linkNode) {
157                    append(HtmlUtil.escape(linkNode.getLink()));
158            }
159    
160            protected void appendHref(LinkNode linkNode) {
161                    if (linkNode.getLink() == null) {
162                            UnformattedLinksTextVisitor unformattedLinksTextVisitor =
163                                    new UnformattedLinksTextVisitor();
164    
165                            linkNode.setLink(
166                                    unformattedLinksTextVisitor.getUnformattedText(linkNode));
167                    }
168    
169                    if (linkNode.isAbsoluteLink()) {
170                            appendAbsoluteHref(linkNode);
171                    }
172                    else {
173                            appendWikiHref(linkNode);
174                    }
175            }
176    
177            protected void appendTableOfContents(
178                    TreeNode<HeadingNode> tableOfContents, int depth) {
179    
180                    append("<ol>");
181    
182                    List<TreeNode<HeadingNode>> treeNodes = tableOfContents.getChildNodes();
183    
184                    if (treeNodes != null) {
185                            for (TreeNode<HeadingNode> treeNode : treeNodes) {
186                                    append("<li class=\"toc-level-");
187                                    append(depth);
188                                    append("\">");
189    
190                                    HeadingNode headingNode = treeNode.getValue();
191    
192                                    String content = getUnformattedHeadingText(headingNode);
193    
194                                    append("<a class=\"wikipage\" href=\"");
195    
196                                    if (_viewPageURL != null) {
197                                            append(_viewPageURL.toString());
198                                    }
199    
200                                    append(StringPool.POUND);
201                                    append(getHeadingMarkup(_wikiPage.getTitle(), content));
202                                    append("\">");
203                                    append(content);
204                                    append("</a>");
205    
206                                    appendTableOfContents(treeNode, depth + 1);
207    
208                                    append("</li>");
209                            }
210                    }
211    
212                    append("</ol>");
213            }
214    
215            protected void appendWikiHref(LinkNode linkNode) {
216                    WikiPage page = null;
217    
218                    try {
219                            page = WikiPageLocalServiceUtil.getPage(
220                                    _wikiPage.getNodeId(), linkNode.getLink());
221                    }
222                    catch (NoSuchPageException nspe) {
223                    }
224                    catch (Exception e) {
225                            _log.error(e, e);
226                    }
227    
228                    String pageTitle = linkNode.getLink();
229    
230                    if ((page != null) && (_viewPageURL != null)) {
231                            _viewPageURL.setParameter("title", pageTitle);
232    
233                            append(_viewPageURL.toString());
234    
235                            _viewPageURL.setParameter("title", _wikiPage.getTitle());
236                    }
237                    else if (_editPageURL != null) {
238                            _editPageURL.setParameter("title", pageTitle);
239    
240                            append(_editPageURL.toString());
241    
242                            _editPageURL.setParameter("title", _wikiPage.getTitle());
243                    }
244            }
245    
246            protected String getHeadingMarkup(String prefix, String text) {
247                    StringBundler sb = new StringBundler(5);
248    
249                    sb.append(_HEADING_ANCHOR_PREFIX);
250                    sb.append(prefix);
251                    sb.append(StringPool.DASH);
252                    sb.append(text.trim());
253    
254                    return StringUtil.replace(
255                            sb.toString(), StringPool.SPACE, StringPool.PLUS);
256            }
257    
258            protected String getUnformattedHeadingText(HeadingNode headingNode) {
259                    UnformattedHeadingTextVisitor unformattedHeadingTextVisitor =
260                            new UnformattedHeadingTextVisitor();
261    
262                    return unformattedHeadingTextVisitor.getUnformattedText(headingNode);
263            }
264    
265            private static final String _HEADING_ANCHOR_PREFIX = "section-";
266    
267            private static Log _log = LogFactoryUtil.getLog(XhtmlTranslator.class);
268    
269            private String _attachmentURLPrefix;
270            private PortletURL _editPageURL;
271            private WikiPageNode _rootWikiPageNode;
272            private PortletURL _viewPageURL;
273            private WikiPage _wikiPage;
274    
275    }