package org.kefirsf.bb;
import org.kefirsf.bb.conf.*;
import org.kefirsf.bb.proc.*;
import java.util.*;
class ProcessorBuilder {
private final PatternElementFactory patternElementFactory = new PatternElementFactory(this);
private final TemplateElementFactory templateElementFactory = new TemplateElementFactory();
private final Configuration conf;
private Map<Scope, ProcScope> scopes;
private Map<Code, ProcCode> codes;
/**
* @param conf text processor configuration
*/
ProcessorBuilder(Configuration conf) {
this.conf = conf;
}
/**
* Build an processor.
*/
public BBProcessor build() {
this.scopes = new HashMap<Scope, ProcScope>();
this.codes = new HashMap<Code, ProcCode>();
patternElementFactory.cleanConstants();
BBProcessor processor = new BBProcessor();
processor.setScope(createScope(conf.getRootScope()));
processor.setPrefix(createTemplate(conf.getPrefix()));
processor.setSuffix(createTemplate(conf.getSuffix()));
processor.setParams(conf.getParams());
processor.setConstants(patternElementFactory.getConstants());
processor.setNestingLimit(conf.getNestingLimit());
processor.setPropagateNestingException(conf.isPropagateNestingException());
// Init scopes
for (ProcScope scope : scopes.values()) {
scope.init();
}
return processor;
}
/**
* Find or create the scope.
*
* @param scope the scope configuration
* @return scope scope
*/
ProcScope createScope(Scope scope) {
ProcScope created = scopes.get(scope);
if (created == null) {
created = new ProcScope(scope.getName());
scopes.put(scope, created);
created.setStrong(scope.isStrong());
created.setIgnoreText(scope.isIgnoreText());
if (scope.getParent() != null) {
created.setParent(createScope(scope.getParent()));
}
Set<ProcCode> scopeCodes = new HashSet<ProcCode>();
for (Code code : scope.getCodes()) {
scopeCodes.add(createCode(code));
}
created.setScopeCodes(scopeCodes);
created.setMin(scope.getMin());
created.setMax(scope.getMax());
}
return created;
}
/**
* Create code from this definition
*
* @param defCode code definition
* @return code object
*/
private ProcCode createCode(Code defCode) {
if (!defCode.hasPatterns()) {
throw new IllegalStateException("Field pattern can't be null.");
}
if (defCode.getTemplate() == null) {
throw new IllegalStateException("Field template can't be null.");
}
ProcCode code = codes.get(defCode);
if (code == null) {
List<Pattern> confPatterns = defCode.getPatterns();
List<ProcPattern> procPatterns = new ArrayList<ProcPattern>(confPatterns.size());
for (Pattern confPattern : confPatterns) {
procPatterns.add(createPattern(confPattern));
}
code = new ProcCode(
procPatterns,
createTemplate(defCode.getTemplate()),
defCode.getName(),
defCode.getPriority(),
defCode.isTransparent()
);
codes.put(defCode, code);
}
return code;
}
/**
* Create a template from definition
*
* @param template the template definition
* @return template
*/
private ProcTemplate createTemplate(Template template) {
if (!template.isEmpty()) {
return new ProcTemplate(templateElementFactory.createTemplateList(template.getElements()));
} else {
return ProcTemplate.EMPTY;
}
}
/**
* Create a pattern for text parsing
*
* @param pattern pattern definition
* @return pattern pattern
*/
private ProcPattern createPattern(Pattern pattern) {
if (pattern.isEmpty()) {
throw new IllegalStateException("Pattern elements list can't be empty.");
}
List<ProcPatternElement> elements = new ArrayList<ProcPatternElement>();
for (PatternElement element : pattern.getElements()) {
elements.add(patternElementFactory.create(element));
}
return new ProcPattern(elements);
}
}