package org.kefirsf.bb.proc;
import org.kefirsf.bb.TextProcessorAdapter;
import org.kefirsf.bb.TextProcessorNestingException;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* The bbcode processor. You can use the standard code set or define other.
*
* @author Kefir
*/
public final class BBProcessor extends TextProcessorAdapter {
public static final String LOGGER_CONTEXT = "kefirbb.context";
public static final String LOGGER_PARSE = "kefirbb.parse";
public static final String LOGGER_GENERATE = "kefirbb.generate";
/**
* BB-codes
*/
private ProcScope scope = null;
private ProcTemplate prefix = null;
private ProcTemplate suffix = null;
private Map<String, CharSequence> params = null;
private Set<PatternConstant> constants;
private int nestingLimit = 0;
private boolean propagateNestingException = false;
/**
* Create the bbcode processor
*/
public BBProcessor() {
}
/**
* Process bbcodes
* 1. Escape the xml special symbols
* 2. replace bbcodes to HTML-tags
* 3. replace symbols \r\n to HTML-tag "<br/>"
*
* @param source the source string
* @return result string
* @see org.kefirsf.bb.TextProcessor#process(CharSequence)
*/
public CharSequence process(CharSequence source) {
Context context = new Context();
StringBuilder target = new StringBuilder(source.length());
context.setTarget(target);
Source source1 = new Source(source);
source1.setConstantSet(constants);
context.setSource(source1);
context.setScope(scope);
context.setNestingLimit(nestingLimit*2);
if (params != null) {
for (Map.Entry<String, CharSequence> entry : params.entrySet()) {
context.setAttribute(entry.getKey(), entry.getValue());
}
}
try {
prefix.generate(context);
boolean success = scope.process(context);
suffix.generate(context);
if(!success){
target = new StringBuilder(0);
}
} catch (NestingException e) {
target = new StringBuilder(0);
if(propagateNestingException){
throw new TextProcessorNestingException(nestingLimit);
}
}
return target;
}
/**
* Set the root scope of text processor.
*
* @param scope root code scope
* @throws IllegalStateException if scope already setted
*/
public void setScope(ProcScope scope) throws IllegalStateException {
if (this.scope == null) {
this.scope = scope;
} else {
throw new IllegalStateException("Can't change the root scope.");
}
}
/**
* Set the prefix for text processor
*
* @param prefix template wich uses to create prefix
* @throws IllegalStateException If prefix already setted
*/
public void setPrefix(ProcTemplate prefix) throws IllegalStateException {
if (this.prefix == null) {
this.prefix = prefix;
} else {
throw new IllegalStateException("Can't change the prefix.");
}
}
/**
* Set the suffix for text processor
*
* @param suffix template wich uses to create prefix
* @throws IllegalStateException If suffix already setted
*/
public void setSuffix(ProcTemplate suffix) {
if (this.suffix == null) {
this.suffix = suffix;
} else {
throw new IllegalStateException("Can't change the suffix.");
}
}
/**
* Set text processor parameters map.
*
* @param params parameters
*/
public void setParams(Map<String, CharSequence> params) {
if (this.params == null) {
this.params = Collections.unmodifiableMap(params);
} else {
throw new IllegalStateException("Can't change parameters.");
}
}
public void setConstants(Set<PatternConstant> constants) {
this.constants = constants;
}
public void setNestingLimit(int nestingLimit) {
this.nestingLimit = nestingLimit;
}
public void setPropagateNestingException(boolean propagateNestingException) {
this.propagateNestingException = propagateNestingException;
}
}