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