/**
* SPINdle (version 2.2.2)
* Copyright (C) 2009-2012 NICTA Ltd.
*
* This file is part of SPINdle project.
*
* SPINdle 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 3 of the License, or
* (at your option) any later version.
*
* SPINdle 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 SPINdle. If not, see <http://www.gnu.org/licenses/>.
*
* @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory
*/
package spindle.io.parser;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import spindle.core.dom.Conclusion;
import spindle.core.dom.ConclusionType;
import spindle.core.dom.DomUtilities;
import spindle.core.dom.Literal;
import spindle.core.dom.LiteralVariable;
import spindle.core.dom.Mode;
import spindle.core.dom.Rule;
import spindle.core.dom.RuleType;
import spindle.core.dom.Superiority;
import spindle.core.dom.Theory;
import spindle.core.dom.TheoryException;
import spindle.io.ParserException;
import spindle.io.outputter.DflTheoryConst;
import spindle.io.outputter.XmlTheoryOutputter;
import spindle.io.outputter.XmlTag.Attribute;
import spindle.io.outputter.XmlTag.Tag;
import spindle.sys.AppLogger;
import spindle.sys.message.ErrorMessage;
/**
* Defeasible theory and conclusions parser for theory represented using XML.
*
* @deprecated As of version 2.2.2, the XML theory parser class {@link spindle.io.parser.XmlTheoryParser} is replaced by {@link spindle.io.parser.XmlTheoryParser2}.
* @author H.-P. Lam (oleklam@gmail.com), National ICT Australia - Queensland Research Laboratory
* @since version 1.0.0
* @version Last modified 2013.05.30
* @see spindle.io.parser.XmlTheoryParser2
*/
@Deprecated
public class XmlTheoryParser extends AbstractTheoryParser {
public static final String PARSER_TYPE = XmlTheoryOutputter.OUTPUTTER_TYPE;
private static XmlTheoryParser INSTANCE = null;
public static Theory getTheory(String xmlString, AppLogger logger) throws ParserException {
if (null == INSTANCE) INSTANCE = new XmlTheoryParser();
try {
InputStream ins = new ByteArrayInputStream(xmlString.replaceAll("[\t\r\n]", "").getBytes());
if (null != logger) INSTANCE.setAppLogger(logger);
return INSTANCE.getTheory(ins);
} catch (Exception e) {
throw new ParserException(e);
} finally {
INSTANCE.resetAppLogger();
}
}
public static Map<Literal, Map<ConclusionType, Conclusion>> getConclusions(String xmlString, AppLogger logger) throws ParserException {
if (null == INSTANCE) INSTANCE = new XmlTheoryParser();
try {
InputStream ins = new ByteArrayInputStream(xmlString.replaceAll("[\t\r\n]", "").getBytes());
if (null != logger) INSTANCE.setAppLogger(logger);
return INSTANCE.getConclusions(ins);
} catch (Exception e) {
throw new ParserException(e);
} finally {
INSTANCE.resetAppLogger();
}
}
private XMLStreamReader reader = null;
private Tag currTag = null;
private int ruleCounter = 0;
public XmlTheoryParser() {
super(PARSER_TYPE);
}
@Override
protected void generateTheory(InputStream ins) throws ParserException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
try {
reader = inputFactory.createXMLStreamReader(ins);
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_DOCUMENT:
break;
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (null == currTag) throw new ParserException("unknown element found in the theory file: " + reader.getLocalName());
switch (currTag) {
case DOC_ROOT:
break;
case LITERAL_VARIABLE:
extractLiteralVariable(Tag.LITERAL_VARIABLE);
break;
case LITERAL_BOOLEAN_FUNCTION:
extractLiteralVariable(Tag.LITERAL_BOOLEAN_FUNCTION);
break;
case FACT:
Rule fact = extractFact();
if (fact.getLabel().startsWith(TEMP_RULE_LABEL)) addPendingRule(fact);
else addRule(fact);
break;
case RULE:
Rule rule = extractRule();
if (rule.getLabel().startsWith(TEMP_RULE_LABEL)) addPendingRule(rule);
else addRule(rule);
break;
case SUPERIORITY:
Superiority superiority = extractSuperiority();
addSuperiority(superiority);
break;
case MODE_CONVERSION:
extractModeConversionRule();
break;
case MODE_CONFLICT:
extractModeConflictRule();
break;
default:
}
break;
case XMLStreamConstants.CHARACTERS:
break;
case XMLStreamConstants.END_ELEMENT:
break;
case XMLStreamConstants.END_DOCUMENT:
break;
case XMLStreamConstants.COMMENT:
}
}
} catch (ParserException e) {
throw e;
} catch (Exception e) {
throw new ParserException("exception throw while parsing document", e);
} finally {
if (null != reader) {
try {
reader.close();
} catch (XMLStreamException e) {
}
reader = null;
}
}
}
private void extractLiteralVariable(Tag elementType) throws ParserException {
LiteralVariable literalVariableName = null;
LiteralVariable literalVariableValue = null;
LiteralVariable currLiteralVariable = null;
try {
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.LITERAL_VARIABLE_NAME.equals(currTag)) {
// currentTag=Tag.LITERAL_VARIABLE_NAME;
} else if (Tag.LITERAL_VARIABLE_VALUE.equals(currTag)) {
// currentTag=Tag.LITERAL_BOOLEAN_FUNCTION;
} else if (Tag.LITERAL_BOOLEAN_FUNCTION_FORMULA.equals(currTag)) {
currLiteralVariable = DomUtilities.getLiteralVariable(extractLiteral(Tag.LITERAL_BOOLEAN_FUNCTION_FORMULA));
// currentTag=Tag.LITERAL_BOOLEAN_FUNCTION_FORMULA;
} else if (Tag.LITERAL.equals(currTag)) {
currLiteralVariable = DomUtilities.getLiteralVariable(extractLiteral(Tag.LITERAL));
} else {
throw new ParserException("Illegal element appeared in rule: " + currTag + ":" + elementType + "::" + literalVariableName + ":::"
+ literalVariableValue);
}
break;
case XMLStreamConstants.END_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.LITERAL_VARIABLE_NAME.equals(currTag)) {
literalVariableName = currLiteralVariable;
} else if (Tag.LITERAL_VARIABLE_VALUE.equals(currTag)) {
literalVariableValue = currLiteralVariable;
} else if (Tag.LITERAL_BOOLEAN_FUNCTION_FORMULA.equals(currTag)) {
literalVariableValue = currLiteralVariable;
} else if (elementType.equals(currTag)) {
if (null == literalVariableName) throw new ParserException("literal variable name not defined");
if (null == literalVariableValue) throw new ParserException("literal variable name not defined");
addLiteralVariable(literalVariableName, literalVariableValue);
return;
} else throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
}
} catch (ParserException e) {
throw e;
} catch (Exception e) {
throw new ParserException(e);
}
throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
private Rule extractFact() throws ParserException {
return extractRule(RuleType.FACT);
}
private Rule extractRule() throws ParserException {
RuleType ruleType = null;
for (int i = 0; i < reader.getAttributeCount() && null == ruleType; i++) {
String attributeName = reader.getAttributeLocalName(i);
String attributeValue = reader.getAttributeValue(i);
if (Attribute.RULE_TYPE_STRICT_RULE.getAttributeName().equals(attributeName)) {
ruleType = getRuleType_xml(attributeValue);
}
}
return extractRule(ruleType);
}
private Rule extractRule(RuleType ruleType) throws ParserException {
String ruleLabel = "";
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attributeName = reader.getAttributeLocalName(i);
String attributeValue = reader.getAttributeValue(i);
if (Attribute.RULE_LABEL.getAttributeName().equals(attributeName)) {
ruleLabel = attributeValue;
}
}
if ("".equals(ruleLabel)) ruleLabel = TEMP_RULE_LABEL + Theory.formatter.format(ruleCounter++);
Rule rule = DomUtilities.getRule(ruleLabel, ruleType);
List<Literal> bodyLiterals = null;
List<Literal> headLiterals = null;
Mode mode = null;
try {
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.BODY.equals(currTag)) {
bodyLiterals = extractLiteralList(reader.getLocalName());
} else if (Tag.HEAD.equals(currTag)) {
headLiterals = extractLiteralList(reader.getLocalName());
} else if (Tag.LITERAL.equals(currTag) && RuleType.FACT.equals(ruleType)) {
Literal literal = extractLiteral(Tag.LITERAL);
headLiterals = new ArrayList<Literal>();
headLiterals.add(literal);
} else if (Tag.MODE.equals(currTag) || Tag.NOT.equals(currTag)) {
mode = extractRuleMode();
} else {
throw new ParserException("Illegal element appeared in rule: " + reader.getLocalName());
}
break;
case XMLStreamConstants.END_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.RULE.equals(currTag) || Tag.FACT.equals(currTag)) {
if (null == headLiterals || headLiterals.size() == 0) throw new ParserException("rule [" + ruleLabel + "] contains no heads");
for (Literal literal : headLiterals) {
rule.addHeadLiteral(literal);
}
if (null != bodyLiterals) {
for (Literal literal : bodyLiterals) {
rule.addBodyLiteral(literal);
}
}
if (null != mode) rule.setMode(mode);
return rule;
}
break;
}
}
} catch (Exception e) {
throw new ParserException(e);
}
throw new ParserException("unexpected end of document");
}
private List<Literal> extractLiteralList(String endElement) throws XMLStreamException, ParserException {
List<Literal> literals = new ArrayList<Literal>();
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.AND.equals(currTag)) {
} else if (Tag.LITERAL.equals(currTag)) {
Literal literal = extractLiteral(Tag.LITERAL);
literals.add(literal);
}
break;
case XMLStreamConstants.END_ELEMENT:
if (endElement.equals(reader.getLocalName())) return literals;
}
}
throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
private Mode extractRuleMode() throws XMLStreamException, ParserException {
String modeName = "";
boolean isModeNegation = false;
Tag startTag = currTag;
if (Tag.NOT.equals(currTag)) isModeNegation = true;
do {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
break;
case XMLStreamConstants.END_ELEMENT:
if (startTag.equals(currTag)) return new Mode(modeName.trim(), isModeNegation);
break;
case XMLStreamConstants.CHARACTERS:
if (Tag.MODE.equals(currTag)) {
modeName += reader.getText();
}
break;
}
} while (reader.hasNext());
throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
private Literal extractLiteral(Tag xmlRootTag) throws XMLStreamException, ParserException {
String literalName = "";
boolean isNegation = false;
boolean isModeNegation = false;
String modeName = "";
String predicates = "";
boolean currTagNegation = false;
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.ATOM.equals(currTag)) {
isNegation = currTagNegation;
} else if (Tag.MODE.equals(currTag)) {
isModeNegation = currTagNegation;
} else if (Tag.NOT.equals(currTag)) {
currTagNegation = true;
} else if (Tag.PREDICATE.equals(currTag)) {
} else {
throw new ParserException("Illegal element appeared in theory file: " + reader.getLocalName());
}
break;
case XMLStreamConstants.END_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.NOT.equals(currTag)) {
currTagNegation = false;
} else if (Tag.PREDICATE.equals(currTag)) {
// System.out.println("predicate=" + predicates);
} else if (xmlRootTag.equals(currTag)) {
Literal literal = DomUtilities.getLiteral(literalName, isNegation, //
modeName, isModeNegation,//
null,
predicates.split("" + DflTheoryConst.LITERAL_SEPARATOR));
return literal;
}
break;
case XMLStreamConstants.CHARACTERS:
if (Tag.ATOM.equals(currTag)) {
literalName += reader.getText();
literalName = literalName.trim();
} else if (Tag.MODE.equals(currTag)) {
modeName += reader.getText();
modeName = modeName.trim();
} else if (Tag.PREDICATE.equals(currTag)) {
predicates += reader.getText();
}
break;
}
}
throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
private Superiority extractSuperiority() {
String superior = null;
String inferior = null;
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attributeName = reader.getAttributeLocalName(i);
String attributeValue = reader.getAttributeValue(i);
if (Attribute.SUPERIORITY_SUPERIOR.getAttributeName().equals(attributeName)) {
superior = attributeValue;
} else if (Attribute.SUPERIORITY_INFERIOR.getAttributeName().equals(attributeName)) {
inferior = attributeValue;
}
}
return new Superiority(superior, inferior);
}
private void extractModeConversionRule() throws XMLStreamException, TheoryException {
String mode = "";
List<String> conversionList = new ArrayList<String>();
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
break;
case XMLStreamConstants.CHARACTERS:
if (Tag.MODE_CONVERSION_FROM.equals(currTag)) {
String v = reader.getText().trim();
if (!"".equals(v)) mode += v;
} else if (Tag.MODE_CONVERSION_TO.equals(currTag)) {
String v = reader.getText().trim();
if (!"".equals(v)) conversionList.add(reader.getText());
}
break;
case XMLStreamConstants.END_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.MODE_CONVERSION.equals(currTag)) {
String[] modes = new String[conversionList.size()];
addModeConversionRule(mode, conversionList.toArray(modes));
return;
}
}
}
}
private void extractModeConflictRule() throws XMLStreamException, ParserException, TheoryException {
String mode = "";
List<String> conflictList = new ArrayList<String>();
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.MODE_CONFLICT_MODE.equals(currTag)) {
} else if (Tag.MODE_CONFLICT_WITH.equals(currTag)) {
} else throw new ParserException("unexpected mode found, currTag=" + currTag);
break;
case XMLStreamConstants.CHARACTERS:
if (Tag.MODE_CONFLICT_MODE.equals(currTag)) {
String v = reader.getText().trim();
if (!"".equals(v)) mode += v;
} else if (Tag.MODE_CONFLICT_WITH.equals(currTag)) {
String v = reader.getText().trim();
if (!"".equals(v)) conflictList.add(reader.getText());
}
break;
case XMLStreamConstants.END_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.MODE_CONFLICT.equals(currTag)) {
String[] modes = new String[conflictList.size()];
addModeConflictRule(mode, conflictList.toArray(modes));
return;
}
}
}
}
// ===========================================
// conclusions
@Override
protected Map<Literal, Map<ConclusionType, Conclusion>> generateConclusions(InputStream ins) throws ParserException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
Map<Literal, Map<ConclusionType, Conclusion>> conclusions = new TreeMap<Literal, Map<ConclusionType, Conclusion>>();
try {
reader = inputFactory.createXMLStreamReader(ins);
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_DOCUMENT:
break;
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (null == currTag) throw new ParserException("unknown element found in the theory file: " + reader.getLocalName());
switch (currTag) {
case DOC_ROOT:
break;
case CONCLUSION:
Conclusion conclusion = extractConclusion(currTag.getXmlTag());
Literal literal = conclusion.getLiteral();
Map<ConclusionType, Conclusion> conclusionList = null;
if (conclusions.containsKey(literal)) {
conclusionList = conclusions.get(literal);
} else {
conclusionList = new TreeMap<ConclusionType, Conclusion>();
conclusions.put(literal, conclusionList);
}
conclusionList.put(conclusion.getConclusionType(), conclusion);
break;
default:
}
break;
case XMLStreamConstants.CHARACTERS:
break;
case XMLStreamConstants.END_ELEMENT:
break;
case XMLStreamConstants.END_DOCUMENT:
break;
case XMLStreamConstants.COMMENT:
}
}
} catch (Exception e) {
throw new ParserException("exception throw while parsing document", e);
} finally {
if (null != reader) {
try {
reader.close();
} catch (XMLStreamException e) {
}
reader = null;
}
}
return conclusions;
}
private Conclusion extractConclusion(String endElement) throws ParserException, XMLStreamException {
ConclusionType conclusionType = null;
Literal literal = null;
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attributeName = reader.getAttributeLocalName(i);
String attributeValue = reader.getAttributeValue(i);
if (Attribute.CONCLUSION_TYPE.getAttributeName().equals(attributeName)) {
conclusionType = getConclusionType_xml(attributeValue);
}
}
while (reader.hasNext()) {
int event = reader.next();
switch (event) {
case XMLStreamConstants.START_ELEMENT:
currTag = getXmlTag(reader.getLocalName());
if (Tag.LITERAL.equals(currTag)) literal = extractLiteral(Tag.LITERAL);
break;
case XMLStreamConstants.END_ELEMENT:
if (endElement.equals(reader.getLocalName())) return new Conclusion(conclusionType, literal);
}
}
throw new ParserException(ErrorMessage.IO_UNEXPECTED_END_OF_FILE);
}
}