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.portal.parsers.creole.visitor.impl;
016    
017    import com.liferay.portal.kernel.util.HtmlUtil;
018    import com.liferay.portal.kernel.util.StringBundler;
019    import com.liferay.portal.kernel.util.StringPool;
020    import com.liferay.portal.parsers.creole.ast.ASTNode;
021    import com.liferay.portal.parsers.creole.ast.BoldTextNode;
022    import com.liferay.portal.parsers.creole.ast.CollectionNode;
023    import com.liferay.portal.parsers.creole.ast.ForcedEndOfLineNode;
024    import com.liferay.portal.parsers.creole.ast.FormattedTextNode;
025    import com.liferay.portal.parsers.creole.ast.HeadingNode;
026    import com.liferay.portal.parsers.creole.ast.HorizontalNode;
027    import com.liferay.portal.parsers.creole.ast.ImageNode;
028    import com.liferay.portal.parsers.creole.ast.ItalicTextNode;
029    import com.liferay.portal.parsers.creole.ast.LineNode;
030    import com.liferay.portal.parsers.creole.ast.NoWikiSectionNode;
031    import com.liferay.portal.parsers.creole.ast.OrderedListItemNode;
032    import com.liferay.portal.parsers.creole.ast.OrderedListNode;
033    import com.liferay.portal.parsers.creole.ast.ParagraphNode;
034    import com.liferay.portal.parsers.creole.ast.ScapedNode;
035    import com.liferay.portal.parsers.creole.ast.UnformattedTextNode;
036    import com.liferay.portal.parsers.creole.ast.UnorderedListItemNode;
037    import com.liferay.portal.parsers.creole.ast.UnorderedListNode;
038    import com.liferay.portal.parsers.creole.ast.WikiPageNode;
039    import com.liferay.portal.parsers.creole.ast.extension.TableOfContentsNode;
040    import com.liferay.portal.parsers.creole.ast.link.LinkNode;
041    import com.liferay.portal.parsers.creole.ast.table.TableDataNode;
042    import com.liferay.portal.parsers.creole.ast.table.TableHeaderNode;
043    import com.liferay.portal.parsers.creole.ast.table.TableNode;
044    import com.liferay.portal.parsers.creole.visitor.ASTVisitor;
045    
046    import java.util.List;
047    
048    /**
049     * @author Miguel Pastor
050     */
051    public class XhtmlTranslationVisitor implements ASTVisitor {
052    
053            public String translate(WikiPageNode wikiPageNode) {
054                    _sb.setIndex(0);
055    
056                    visit(wikiPageNode);
057    
058                    return _sb.toString();
059            }
060    
061            public void visit(BoldTextNode boldTextNode) {
062                    append("<strong>");
063    
064                    if (boldTextNode.hasContent()) {
065                            traverse(boldTextNode.getChildASTNodes());
066                    }
067    
068                    append("</strong>");
069            }
070    
071            public void visit(CollectionNode collectionNode) {
072                    for (ASTNode astNode : collectionNode.getASTNodes()) {
073                            astNode.accept(this);
074                    }
075            }
076    
077            public void visit(ForcedEndOfLineNode forcedEndOfLineNode) {
078                    append("<br/>");
079            }
080    
081            public void visit(FormattedTextNode formattedTextNode) {
082                    if (formattedTextNode.getContent() != null) {
083                            append(HtmlUtil.escape(formattedTextNode.getContent()));
084                    }
085                    else {
086                            traverse(formattedTextNode.getChildASTNodes());
087                    }
088            }
089    
090            public void visit(HeadingNode headingNode) {
091                    int level = headingNode.getLevel();
092    
093                    append("<h");
094                    append(level);
095                    append(">");
096    
097                    traverse(headingNode.getChildASTNodes());
098    
099                    append("</h");
100                    append(level);
101                    append(">");
102            }
103    
104            public void visit(HorizontalNode horizontalNode) {
105                    append("<hr/>");
106            }
107    
108            public void visit(ImageNode imageNode) {
109                    append("<img src=\"");
110                    append(HtmlUtil.escape(imageNode.getLink()));
111                    append("\" ");
112    
113                    if (imageNode.hasAltCollectionNode()) {
114                            append("alt=\"");
115    
116                            CollectionNode altCollectionNode = imageNode.getAltNode();
117    
118                            traverse(altCollectionNode.getASTNodes());
119    
120                            append("\"");
121                    }
122    
123                    append("/>");
124            }
125    
126            public void visit(ItalicTextNode italicTextNode) {
127                    append("<em>");
128    
129                    if (italicTextNode.hasContent()) {
130                            traverse(italicTextNode.getChildASTNodes());
131                    }
132    
133                    append("</em>");
134            }
135    
136            public void visit(LineNode lineNode) {
137                    traverse(lineNode.getChildASTNodes(), null, StringPool.SPACE);
138            }
139    
140            public void visit(LinkNode linkNode) {
141                    append("<a href=\"");
142                    append(HtmlUtil.escape(linkNode.getLink()));
143                    append("\">");
144    
145                    if (linkNode.hasAltCollectionNode()) {
146                            CollectionNode altCollectionNode = linkNode.getAltCollectionNode();
147    
148                            traverse(altCollectionNode.getASTNodes());
149                    }
150                    else {
151                            append(HtmlUtil.escape(linkNode.getLink()));
152                    }
153    
154                    append("</a>");
155            }
156    
157            public void visit(NoWikiSectionNode noWikiSectionNode) {
158                    append("<pre>");
159                    append(HtmlUtil.escape(noWikiSectionNode.getContent()));
160                    append("</pre>");
161            }
162    
163            public void visit(OrderedListItemNode orderedListItemNode) {
164                    appendLevelTags(orderedListItemNode.getLevel(), true);
165    
166                    traverse(orderedListItemNode.getChildASTNodes(), "<li>", "</li>");
167            }
168    
169            public void visit(OrderedListNode orderedListNode) {
170                    _currentNodeLevel = 0;
171    
172                    traverse(orderedListNode.getChildASTNodes());
173    
174                    appendLevelTags(0, true);
175            }
176    
177            public void visit(ParagraphNode paragraphNode) {
178                    traverse(paragraphNode.getChildASTNodes(), "<p>", "</p>");
179            }
180    
181            public void visit(ScapedNode scapedNode) {
182                    append(HtmlUtil.escape(scapedNode.getContent()));
183            }
184    
185            public void visit(TableDataNode tableDataNode) {
186                    traverse(tableDataNode.getChildASTNodes(), "<td>", "</td>");
187            }
188    
189            public void visit(TableHeaderNode tableHeaderNode) {
190                    traverse(tableHeaderNode.getChildASTNodes(), "<th>", "</th>");
191            }
192    
193            public void visit(TableNode tableNode) {
194                    append("<table>");
195    
196                    traverseAndWriteForEach(tableNode.getChildASTNodes(), "<tr>", "</tr>");
197    
198                    append("</table>");
199            }
200    
201            public void visit(TableOfContentsNode tableOfContentsNode) {
202            }
203    
204            public void visit(UnformattedTextNode unformattedTextNode) {
205                    if (unformattedTextNode.hasContent()) {
206                            append(HtmlUtil.escape(unformattedTextNode.getContent()));
207                    }
208                    else {
209                            traverse(unformattedTextNode.getChildASTNodes());
210                    }
211            }
212    
213            public void visit(UnorderedListItemNode unorderedListItemNode) {
214                    appendLevelTags(unorderedListItemNode.getLevel(), false);
215    
216                    traverse(unorderedListItemNode.getChildASTNodes(), "<li>", "</li>");
217            }
218    
219            public void visit(UnorderedListNode unorderedListNode) {
220                    _currentNodeLevel = 0;
221    
222                    traverse(unorderedListNode.getChildASTNodes());
223    
224                    appendLevelTags(0, false);
225            }
226    
227            public void visit(WikiPageNode wikiPageNode) {
228                    traverse(wikiPageNode.getChildASTNodes());
229            }
230    
231            protected void append(Object object) {
232                    if (object != null) {
233                            _sb.append(object);
234                    }
235            }
236    
237            protected void appendLevelTags(int nodeLevel, boolean ordered) {
238                    int diff = nodeLevel - _currentNodeLevel;
239    
240                    if (diff > 0) {
241                            for (int i = 0; i < diff; i++) {
242                                    if (ordered) {
243                                            append("<ol>");
244                                    }
245                                    else {
246                                            append("<ul>");
247                                    }
248                            }
249                    }
250                    else if (diff < 0) {
251                            for (int i = 0; i > diff; i--) {
252                                    if (ordered) {
253                                            append("</ol>");
254                                    }
255                                    else {
256                                            append("</ul>");
257                                    }
258                            }
259                    }
260    
261                    _currentNodeLevel = nodeLevel;
262            }
263    
264            protected void traverse(List<ASTNode> astNodes) {
265                    if (astNodes != null) {
266                            for (ASTNode astNode : astNodes) {
267                                    astNode.accept(this);
268                            }
269                    }
270            }
271    
272            protected void traverse(List<ASTNode> astNodes, String open, String close) {
273                    append(open);
274    
275                    traverse(astNodes);
276    
277                    append(close);
278            }
279    
280            protected void traverseAndWriteForEach(
281                    List<ASTNode> astNodes, String open, String close) {
282    
283                    for (ASTNode curNode : astNodes) {
284                            append(open);
285    
286                            curNode.accept(this);
287    
288                            append(close);
289                    }
290            }
291    
292            private int _currentNodeLevel;
293            private StringBundler _sb = new StringBundler();
294    
295    }