/* * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.ks.bbcode.core; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.lang.StringUtils; import org.exoplatform.ks.bbcode.api.BBCode; import org.exoplatform.ks.bbcode.spi.BBCodeData; import org.exoplatform.ks.bbcode.spi.BBCodeProvider; import org.exoplatform.ks.rendering.api.Renderer; import org.exoplatform.ks.rendering.core.SupportedSyntaxes; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; /** * Renderer for BBCode markup. * BBCode lookup is delegated to {@link BBCodeProvider}. By default, this implementation will use a {@link BuiltinBBCodeProvider} * @author <a href="mailto:patrice.lamarque@exoplatform.com">Patrice Lamarque</a> * @version $Revision$ */ public class BBCodeRenderer implements Renderer { public static final String BBCODE_SYNTAX_ID = "bbcode"; protected BBCodeProvider bbCodeProvider; private static final Log log = ExoLogger.getLogger(BBCodeRenderer.class); public BBCodeRenderer() { bbCodeProvider = new BuiltinBBCodeProvider(); } public String getSyntax() { return SupportedSyntaxes.bbcode.name(); } /* * (non-Javadoc) * @see org.exoplatform.ks.rendering.api.Renderer#render(java.lang.String) */ public String render(String s) { for (BBCode bbcode : getBbcodes()) { s = processReplace(s, bbcode); } return s; } public String processReplace(String s, BBCode bbcode) { String bbc = bbcode.getTagName(); if (bbc.equals("URL")) { s = StringUtils.replace(s, "[link", "[URL"); s = StringUtils.replace(s, "[/link]", "[/URL]"); s = StringUtils.replace(s, "[LINK", "[URL"); s = StringUtils.replace(s, "[/LINK]", "[/URL]"); } if (!bbc.equals("LIST")) { if (Boolean.valueOf(bbcode.isOption())) { s = processOptionedTag(s, bbcode); } else { s = processTag(s, bbcode); } } else { s = processList(s); } return s; } String processTag(String s, BBCode bbcode) { String bbc = bbcode.getTagName(); int clsIndex; String start; String end; String str; String param; int lastIndex = 0, tagIndex = 0; start = "[" + bbc + "]"; end = "[/" + bbc + "]"; s = StringUtils.replace(s, start.toLowerCase(), start); s = StringUtils.replace(s, end.toLowerCase(), end); while ((tagIndex = s.indexOf(start, lastIndex)) != -1) { lastIndex = tagIndex + 1; try { clsIndex = s.indexOf(end, tagIndex); str = s.substring(tagIndex + start.length(), clsIndex); param = StringUtils.replace(bbcode.getReplacement(), "{param}", str); s = StringUtils.replace(s, start + str + end, param); } catch (Exception e) { continue; } } return s; } String processOptionedTag(String markup, BBCode bbcode) { String bbc = bbcode.getTagName(); int clsIndex; String start; String end; String str; String param; String option; int lastIndex = 0, tagIndex = 0; start = "[" + bbc + "="; end = "[/" + bbc + "]"; markup = StringUtils.replace(markup, start.toLowerCase(), start); markup = StringUtils.replace(markup, end.toLowerCase(), end); while ((tagIndex = markup.indexOf(start, lastIndex)) != -1) { lastIndex = tagIndex + 1; try { clsIndex = markup.indexOf(end, tagIndex); str = markup.substring(tagIndex + start.length(), clsIndex); option = str.substring(0, str.indexOf("]")); if (option.indexOf("+") == 0) option = option.replaceFirst("\\+", ""); if (option.indexOf("\"") == 0) option = option.replaceAll("\"", ""); if (option.indexOf("'") == 0) option = option.replaceAll("'", ""); if (option.indexOf(""") == 0) option = option.replaceAll(""", ""); param = str.substring(str.indexOf("]") + 1); while (bbc.equals("CODE") && (param.indexOf("<br") >= 0)) { param = param.replaceAll("<br\\s*\\/?>", "\n"); } while (bbc.equals("CODE") && param.indexOf("<p>") >= 0 && param.indexOf("</p>") >= 0) { param = StringUtils.replace(param, "<p>", ""); param = StringUtils.replace(param, "</p>", "\n"); } param = StringUtils.replace(bbcode.getReplacement(), "{param}", param); param = StringUtils.replace(param, "{option}", option.trim()); markup = StringUtils.replace(markup, start + str + end, param); } catch (Exception e) { continue; } } return markup; } String processList(String s) { int lastIndex; int tagIndex; int clsIndex; String str; lastIndex = 0; tagIndex = 0; s = StringUtils.replace(s, "[LIST", "[list"); s = StringUtils.replace(s, "[/LIST]", "[/list]"); while ((tagIndex = s.indexOf("[list]", lastIndex)) != -1) { lastIndex = tagIndex + 1; try { clsIndex = s.indexOf("[/list]", tagIndex); str = s.substring(tagIndex + 6, clsIndex); String str_ = ""; str_ = StringUtils.replaceOnce(str, "[*]", "<li>"); str_ = StringUtils.replace(str_, "[*]", "</li><li>"); if (str_.lastIndexOf("</li><li>") > 0) { str_ = str_ + "</li>"; } if (str_.indexOf("<br/>") >= 0) { str_ = StringUtils.replace(str_, "<br/>", ""); } if (str_.indexOf("<p>") >= 0) { str_ = StringUtils.replace(str_, "<p>", ""); str_ = StringUtils.replace(str_, "</p>", ""); } s = StringUtils.replace(s, "[list]" + str + "[/list]", "<ul>" + str_ + "</ul>"); } catch (Exception e) { continue; } } lastIndex = 0; tagIndex = 0; while ((tagIndex = s.indexOf("[list=", lastIndex)) != -1) { lastIndex = tagIndex + 1; try { clsIndex = s.indexOf("[/list]", tagIndex); String content = s.substring(tagIndex + 6, clsIndex); int clsType = content.indexOf("]"); String type = content.substring(0, clsType); type = type.replaceAll("\"", "").replaceAll("'", ""); str = content.substring(clsType + 1); String str_ = ""; str_ = StringUtils.replaceOnce(str, "[*]", "<li>"); str_ = StringUtils.replace(str_, "[*]", "</li><li>"); if (str_.lastIndexOf("</li><li>") > 0) { str_ = str_ + "</li>"; } if (str_.indexOf("<br/>") >= 0) { str_ = StringUtils.replace(str_, "<br/>", ""); } if (str_.indexOf("<p>") >= 0) { str_ = StringUtils.replace(str_, "<p>", ""); str_ = StringUtils.replace(str_, "</p>", ""); } if (" 1 i I a A ".indexOf(type) > 0) { s = StringUtils.replace(s, "[list=" + content + "[/list]", "<ol type=\"" + type + "\">" + str_ + "</ol>"); } else { str_ = StringUtils.replace(str_, "<li>", "<li type=\"" + type + "\">"); s = StringUtils.replace(s, "[list=" + content + "[/list]", "<ul>" + str_ + "</ul>"); } } catch (Exception e) { continue; } } return s; } public List<BBCode> getBbcodes() { List<BBCode> result = new ArrayList<BBCode>(); Collection<String> supported = getBbCodeProvider().getSupportedBBCodes(); if (supported == null) { log.warn("No BBCode supported by this renderer"); return result; } for (String tag : supported) { result.add(getBbCodeProvider().getBBCode(tag)); } return result; } private List<BBCode> convert(List<BBCodeData> bbc) { List<BBCode> bbcodes = new ArrayList<BBCode>(); for (BBCodeData bbCodeData : bbc) { BBCode bbCode = new BBCode(); bbCode.setActive(Boolean.valueOf(bbCodeData.getIsActive())); bbCode.setDescription(bbCodeData.getDescription()); bbCode.setExample(bbCodeData.getExample()); bbCode.setOption(Boolean.valueOf(bbCodeData.getIsOption())); bbCode.setReplacement(bbCodeData.getReplacement()); bbCode.setTagName(bbCodeData.getTagName()); bbcodes.add(bbCode); } return bbcodes; } public BBCodeProvider getBbCodeProvider() { return bbCodeProvider; } public void setBbCodeProvider(BBCodeProvider bbCodeProvider) { this.bbCodeProvider = bbCodeProvider; } public String renderExample(String s, BBCode bbco) { List<BBCode> bbcodes = new ArrayList<BBCode>(); bbcodes.add(bbco); bbcodes.addAll(getBbcodes()); for (BBCode bbcode : bbcodes) { if (bbcode.getId().equals(bbco.getId())) { s = processReplace(s, bbco); } else { s = processReplace(s, bbcode); } } return s; } }