package edu.cmu.sphinx.jsgf;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import edu.cmu.sphinx.jsgf.rule.JSGFRule;
import edu.cmu.sphinx.jsgf.rule.JSGFRuleAlternatives;
import edu.cmu.sphinx.jsgf.rule.JSGFRuleCount;
import edu.cmu.sphinx.jsgf.rule.JSGFRuleSequence;
import edu.cmu.sphinx.jsgf.rule.JSGFRuleToken;
public class GrXMLHandler extends DefaultHandler {
protected final Map<String, JSGFRule> topRuleMap;
Logger logger;
JSGFRule currentRule;
URL baseURL;
public GrXMLHandler(URL baseURL, Map<String, JSGFRule> rules, Logger logger) {
this.baseURL = baseURL;
this.topRuleMap = rules;
this.logger = logger;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
JSGFRule newRule = null;
JSGFRule topRule = null;
logger.fine("Starting element " + qName);
if (qName.equals("rule")) {
String id = attributes.getValue("id");
if (id != null) {
newRule = new JSGFRuleSequence(new ArrayList<JSGFRule>());
topRuleMap.put(id, newRule);
topRule = newRule;
}
}
if (qName.equals("item")) {
String repeat = attributes.getValue("repeat");
if (repeat != null) {
newRule = new JSGFRuleSequence(new ArrayList<JSGFRule>());
JSGFRuleCount ruleCount = new JSGFRuleCount(newRule, JSGFRuleCount.ONCE_OR_MORE);
topRule = ruleCount;
} else {
newRule = new JSGFRuleSequence(new ArrayList<JSGFRule>());
topRule = newRule;
}
}
if (qName.equals("one-of")) {
newRule = new JSGFRuleAlternatives(new ArrayList<JSGFRule>());
topRule = newRule;
}
addToCurrent(newRule, topRule);
}
@Override
public void characters(char buf[], int offset, int len)throws SAXException {
String item = new String(buf, offset, len).trim();
if (item.length() == 0)
return;
logger.fine ("Processing text " + item);
JSGFRuleToken newRule = new JSGFRuleToken(item);
addToCurrent(newRule, newRule);
// Don't shift current
currentRule = newRule.parent;
}
private void addToCurrent(JSGFRule newRule, JSGFRule topRule) {
if (newRule == null)
return;
if (currentRule == null) {
currentRule = newRule;
return;
}
if (currentRule instanceof JSGFRuleSequence) {
JSGFRuleSequence ruleSequence = (JSGFRuleSequence) currentRule;
ruleSequence.append(topRule);
newRule.parent = currentRule;
currentRule = newRule;
} else if (currentRule instanceof JSGFRuleAlternatives) {
JSGFRuleAlternatives ruleAlternatives = (JSGFRuleAlternatives) currentRule;
ruleAlternatives.append(topRule);
newRule.parent = currentRule;
currentRule = newRule;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXParseException {
logger.fine ("Ending element " + qName);
if (qName.equals("item") || qName.equals("one-of") || qName.equals("rule"))
currentRule = currentRule.parent;
}
}