001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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 attachmentLink = searchLinkInAttachments(linkNode);
229    
230                    if (attachmentLink != null) {
231    
232                            // Attachment links take precedence over pages
233    
234                            append(_attachmentURLPrefix + attachmentLink);
235    
236                            return;
237                    }
238    
239                    String pageTitle = linkNode.getLink();
240    
241                    if ((page != null) && (_viewPageURL != null)) {
242                            _viewPageURL.setParameter("title", pageTitle);
243    
244                            append(_viewPageURL.toString());
245    
246                            _viewPageURL.setParameter("title", _wikiPage.getTitle());
247                    }
248                    else if (_editPageURL != null) {
249                            _editPageURL.setParameter("title", pageTitle);
250    
251                            append(_editPageURL.toString());
252    
253                            _editPageURL.setParameter("title", _wikiPage.getTitle());
254                    }
255            }
256    
257            protected String getHeadingMarkup(String prefix, String text) {
258                    StringBundler sb = new StringBundler(5);
259    
260                    sb.append(_HEADING_ANCHOR_PREFIX);
261                    sb.append(prefix);
262                    sb.append(StringPool.DASH);
263                    sb.append(text.trim());
264    
265                    return StringUtil.replace(
266                            sb.toString(), StringPool.SPACE, StringPool.PLUS);
267            }
268    
269            protected String getUnformattedHeadingText(HeadingNode headingNode) {
270                    UnformattedHeadingTextVisitor unformattedHeadingTextVisitor =
271                            new UnformattedHeadingTextVisitor();
272    
273                    return unformattedHeadingTextVisitor.getUnformattedText(headingNode);
274            }
275    
276            protected String searchLinkInAttachments(LinkNode linkNode) {
277                    String[] attachments = null;
278    
279                    try {
280                            attachments = _wikiPage.getAttachmentsFiles();
281                    }
282                    catch (Exception e) {
283                            return null;
284                    }
285    
286                    String link =
287                            StringPool.SLASH + _wikiPage.getAttachmentsDir() +
288                                    StringPool.SLASH + linkNode.getLink();
289    
290                    for (String attachment : attachments) {
291                            if (attachment.equals(link)) {
292                                    int pos = attachment.lastIndexOf(StringPool.SLASH);
293    
294                                    return attachment.substring(pos + 1);
295                            }
296                    }
297    
298                    return null;
299            }
300    
301            private static final String _HEADING_ANCHOR_PREFIX = "section-";
302    
303            private static Log _log = LogFactoryUtil.getLog(XhtmlTranslator.class);
304    
305            private String _attachmentURLPrefix;
306            private PortletURL _editPageURL;
307            private WikiPageNode _rootWikiPageNode;
308            private PortletURL _viewPageURL;
309            private WikiPage _wikiPage;
310    
311    }