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