package info.ephyra.questionanalysis.atype.classifier;
import info.ephyra.questionanalysis.atype.AnswerType;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import edu.cmu.minorthird.classify.Feature;
import edu.cmu.minorthird.classify.Instance;
import edu.cmu.minorthird.classify.MutableInstance;
/**
* A rule used for rule-based classification of answer type.
*
* @author Justin Betteridge
* @version 2008-02-10
*/
public class Rule {
private String atype;
private double confidence;
private List<RuleElement> elements;
/**
* Instantiates a Rule object from an XML Element.
* @param ruleElement the Element to construct a Rule from
*/
public Rule (Element ruleElement) {
NamedNodeMap ruleAttributes = ruleElement.getAttributes();
this.atype = ruleAttributes.getNamedItem("atype").getNodeValue().toString();
this.confidence = Double.parseDouble(ruleAttributes.getNamedItem("conf").getNodeValue().toString());
this.elements = new ArrayList<RuleElement>();
NodeList ruleElementList = ruleElement.getChildNodes();
for (int j = 0; j < ruleElementList.getLength(); j++) {
Node ruleElementElement = ruleElementList.item(j);
if (!ruleElementElement.getNodeName().equals("RULE_ELEMENT")) continue;
elements.add(new RuleElement((Element)ruleElementElement));
}
}
/**
* Tells whether a given Instance matches this Rule by returning
* the appropriate answer type if it does match, and <code>null</code>
* if it does not.
*
* @param instance the Instance to consider
* @return the answer type and subtype formed by matching this Rule to the
* given Instance, or <code>null</code> if this Rule does not match the Instance.
* @throws IllegalStateException if this Rule has not been compiled yet
*/
public AnswerType matches (Instance instance) {
if (elements == null)
throw new IllegalStateException("Must compile rule before using it");
String retAtype = atype;
AnswerType res = null;
// All elements of the rule must match in order for the rule to match
for (RuleElement element : elements) {
String result = element.matches(instance);
if (result == null) {
return null;
} else if (element.getFeature().equals("FOCUS_TYPE")) {
result = result.toUpperCase();
if (!result.equals(atype) && result != "")
retAtype = atype + "." + result;
}
}
res = AnswerType.constructFromString(retAtype);
res.setConfidence(confidence);
return res;
}
/**
* @param atype the atype to set
*/
public void setAtype(String atype) {
this.atype = atype;
}
/**
* @return the elements
*/
public List<RuleElement> getElements() {
return elements;
}
/**
* @param elements the elements to set
*/
public void setElements(List<RuleElement> elements) {
this.elements = elements;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Atype: " + atype + "\n");
if (elements == null) sb.append("null");
else {
for (RuleElement re : elements) {
sb.append("Element:\n" + re.toString() + "\n");
}
}
return sb.toString();
}
/**
* Tests Rule creation, compilation and matching.
*
* @param args
*/
public static void main(String[] args) {
String test = "<RULE atype=\"TEST_TYPE\">" +
"<RULE_ELEMENT feature_name=\"TEST_FEATURE1\">" +
"<FEATURE_VALUE>value1</FEATURE_VALUE>" +
"<FEATURE_VALUE>value2</FEATURE_VALUE>" +
"<FEATURE_VALUE>value3</FEATURE_VALUE>" +
"</RULE_ELEMENT>" +
"<RULE_ELEMENT feature_name=\"FOCUS_TYPE\">" +
"<FEATURE_VALUE>value3=</FEATURE_VALUE>" +
"<FEATURE_VALUE>value4=new</FEATURE_VALUE>" +
"</RULE_ELEMENT>" +
"</RULE>";
Document ruleDocument;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setNamespaceAware(true);
DocumentBuilder db = factory.newDocumentBuilder();
ruleDocument = db.parse(new InputSource(new StringReader(test)));
Rule r = new Rule(ruleDocument.getDocumentElement());
System.out.println("Test input: " + test);
System.out.println(r.toString());
MutableInstance testInstance = new MutableInstance(test);
testInstance.addBinary(new Feature("TEST_FEATURE1.value1"));
testInstance.addBinary(new Feature("FOCUS_TYPE.value4"));
System.out.println("Test instance: " + testInstance);
System.out.println("matches test rule?: " + r.matches(testInstance));
testInstance = new MutableInstance(test);
testInstance.addBinary(new Feature("TEST_FEATURE1.value1"));
testInstance.addBinary(new Feature("FOCUS_TYPE.value3"));
System.out.println("Test instance: " + testInstance);
System.out.println("matches test rule?: " + r.matches(testInstance));
} catch (Exception e) {
throw new RuntimeException("Failed to parse XML string", e);
}
}
}