/**
* Copyright (C) 2011 JTalks.org Team
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jtalks.jcommune.service.nontransactional;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.jtalks.jcommune.model.entity.JCUser;
import org.jtalks.jcommune.plugin.api.service.PluginBbCodeService;
import org.jtalks.jcommune.service.bb2htmlprocessors.TextPostProcessor;
import org.kefirsf.bb.BBProcessorFactory;
import org.kefirsf.bb.TextProcessor;
import java.util.ArrayList;
import java.util.List;
/**
* Provides various helper methods for encoding/decoding BB codes. This class is used by our JSTL tags on JSP pages.
*
* @author Evgeniy Naumenko
*/
public class BBCodeService implements PluginBbCodeService {
private static final String QUOTE_PATEERN = "[quote=\"%s\"]%s[/quote]";
/** Processor is thread safe as it's explicitly stated in documentation */
private final TextProcessor processor = BBProcessorFactory.getInstance().create();
/** Processor to strip bb-codes */
private final TextProcessor stripBBCodesProcessor = BBProcessorFactory.getInstance().createFromResource("kefirbb-strip-config.xml");
/** Preprocessors of BB encoded text used before actual BB2HTML converter */
private final List<TextProcessor> preprocessors = new ArrayList<>();
/**
* Postprocessors of BB decoded text used after actual BB2HTML converter. This is needed for instance in case of
* Code Reviews when we first change user's input to get rid of extra bb-codes, and then put them back after bb
* codes has been processed.
*/
private final List<TextPostProcessor> postprocessors = new ArrayList<>();
/**
* Quotes text given as a valid BB-coded quote. Such a quotes are rendered automatically in posts or forum messages.
* On UI you can find Quote button near each post.
*
* @param source text to quote, not null
* @param author text author, not null
* @return well formed BB qoute
*/
public String quote(String source, JCUser author) {
Validate.notNull(source, "Source cannot be null");
Validate.notNull(author, "Author cannot be null");
return String.format(QUOTE_PATEERN, author.getUsername(), source);
}
/**
* <p>Converts BB-encoded text into HTML-encoded one. Actual transformation result depends on kefirBB.xml
* configuration and the CSS styles mentioned in it's patterns. Uses pre-processors to do some work on input text,
* like closing un-closed tags. Also it uses post-processors e.g. for code reviews to return back [code] tag after
* it was removed in the pre-processors.</p> If input text contains <i>no</i> BB-compatible tags it's returned as
* is.
*
* @param bbEncodedText string with BB-style markup
* @return the same text with HTML markup to be shown
*/
public String convertBbToHtml(String bbEncodedText) {
for (TextProcessor preprocessor : preprocessors) {
bbEncodedText = preprocessor.process(bbEncodedText);
}
if (isUserbbCode(bbEncodedText)){
bbEncodedText = processUserbbCode(bbEncodedText);
} else {
bbEncodedText = processor.process(bbEncodedText);
}
for (TextPostProcessor postpreprocessor : postprocessors) {
bbEncodedText = postpreprocessor.postProcess(bbEncodedText);
}
return bbEncodedText;
}
/**
* if it's [user]-tag processing, use method
* "processUserbbCode"
* @param bbEncodedText line with bb-codes
*/
private boolean isUserbbCode(String bbEncodedText) {
return bbEncodedText.startsWith("[user=/") && bbEncodedText.endsWith("[/user]");
}
/** @param preprocessors objects that process input text from users post before the actual bb-converting is
* started */
public void setPreprocessors(List<TextProcessor> preprocessors) {
this.preprocessors.addAll(preprocessors);
}
/**
* @param postprocessors objects that process input text from users' posts after it was processed by {@link
* TextProcessor}, this is useful for instance for code reviews when we need to do some
* clean-up work.
*/
public void setPostprocessors(List<TextPostProcessor> postprocessors) {
this.postprocessors.addAll(postprocessors);
}
/**
* Remove bb-codes from the specified string.
* It remove ONLY VALID bb-codes. So, something like [zzz][/zzz] is unchanged.
* Also it doesn't strip open bb-code when there are no appropriate close tag.
* @param bbCode text with bb-codes
* @return text without bb-codes
*/
public String stripBBCodes(String bbCode) {
return stripBBCodesProcessor.process(bbCode);
}
/**
* In case when bb code contains tag [user], text processing execute with help
* this method because KefirrBB does not work properly
* with eg "[user=/jcommune/users/16][user]user[/user][/user]" i.e user name contains tag [user]
* @param bbEncodedText line with nested [user] bb-codes
* @return formatted text with link
*/
private String processUserbbCode(String bbEncodedText) {
String openTag = "<a href=\"";
String closeTag = "</a>";
String classInfo = "\" class=\"mentioned-user\" >";
String[] array = StringUtils.substringsBetween(bbEncodedText, "[", "]");
String userLink = array[0];
String userName = bbEncodedText.substring(userLink.length() + 2, bbEncodedText.length() - 7);
String result = openTag + userLink.substring(5, userLink.length()) + classInfo + userName + closeTag;
return result;
}
}