/**
*
*/
package se.liu.imt.mi.snomedct.expression.tools;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAxiom;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.search.EntitySearcher;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionLexer;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser;
import se.liu.imt.mi.snomedct.parser.OWLVisitor;
/**
* Wrapper class for the SNOMED CT ANTLR parser and OWL converter.
*
* @author Daniel Karlsson, daniel.karlsson@liu.se
*
*/
public class SNOMEDCTParserUtil {
public static final String PC_IRI = "http://snomed.info/expid/";
public static class ThrowingErrorListener extends BaseErrorListener {
public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();
@Override
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e)
throws ParseCancellationException {
// List<String> stack = ((Parser)
// recognizer).getRuleInvocationStack();
// Collections.reverse(stack);
String message = "line " + line + ", pos " + charPositionInLine
+ ": " + msg;
throw new ParseCancellationException(message);
}
}
/**
* Wrapper method for parsing an SNOMED CT expression from an InputStream
*
* @param is
* an InputStream
* @return parse tree resulting from parsing
* @throws ExpressionSyntaxError
* thrown when syntax error in expression string
*/
public static ParseTree parseFile(InputStream is)
throws ParseCancellationException, ExpressionSyntaxError,
IOException {
ParseTree tree = null;
ANTLRInputStream input = new ANTLRInputStream(is);
SNOMEDCTExpressionLexer lexer = new SNOMEDCTExpressionLexer(input);
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SNOMEDCTExpressionParser parser = new SNOMEDCTExpressionParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE);
try {
tree = parser.statements();
} catch (Exception e) {
throw new ExpressionSyntaxError(e);
}
if (tree == null)
throw new ExpressionSyntaxError(
"Parse result is null. Should not happen ever!");
return tree;
}
/**
* Wrapper method for parsing an SNOMED CT expression from a string
*
* @param expression
* string representation of a SNOMED CT expression
* @return parse tree resulting from parsing
* @throws ExpressionSyntaxError
* thrown when syntax error in expression string
*/
public static ParseTree parseExpression(String expression)
throws ParseCancellationException, ExpressionSyntaxError {
ParseTree tree = null;
// parse string and throw ExpressionSyntaxError if unparsable
ANTLRInputStream input = new ANTLRInputStream(expression);
SNOMEDCTExpressionLexer lexer = new SNOMEDCTExpressionLexer(input);
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SNOMEDCTExpressionParser parser = new SNOMEDCTExpressionParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE);
try {
tree = parser.expression();
} catch (Exception e) {
throw new ExpressionSyntaxError(e);
}
if (tree == null)
throw new ExpressionSyntaxError(
"Parse result is null. Should not happen ever!");
return tree;
}
/**
* Wrapper method for parsing an SNOMED CT statement from a string
*
* @param statement
* string representation of a SNOMED CT statement
* @return parse tree resulting from parsing
* @throws ExpressionSyntaxError
* thrown when syntax error in statement string
*/
public static ParseTree parseStatement(String statement)
throws ExpressionSyntaxError {
ParseTree tree = null;
// parse string and throw ExpressionSyntaxError if unparsable
ANTLRInputStream input = new ANTLRInputStream(statement);
SNOMEDCTExpressionLexer lexer = new SNOMEDCTExpressionLexer(input);
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);
CommonTokenStream tokens = new CommonTokenStream(lexer);
SNOMEDCTExpressionParser parser = new SNOMEDCTExpressionParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE);
try {
tree = parser.statement();
} catch (Exception e) {
throw new ExpressionSyntaxError(e);
}
if (tree == null)
throw new ExpressionSyntaxError(
"Parse result is null. Should not happen ever!");
return tree;
}
/**
* Parses expression, converts to an OWLAxiom and adds it to ontology,
* including any descriptions as rdfs:label annotations
*
* @param expression
* the expression to parse
* @param ontology
* the ontology to which the parsed, converted expression is
* added
*
* @return the resulting OWLAxiom
* @throws ExpressionSyntaxError
*/
public static OWLAxiom parseExpressionToOWLAxiom(String expression,
OWLOntology ontology) throws ExpressionSyntaxError {
return parseExpressionToOWLAxiom(expression, ontology, (OWLClass) null,
false);
}
/**
* Parses expression, converts to an OWLAxiom and adds it to ontology,
* including any descriptions as rdfs:label annotations
*
* @param expression
* the expression to parse
* @param ontology
* the ontology to which the parsed, converted expression is
* added
* @param subj
* a string, if not null, a new class is created which is the
* definiendum of the new axiom
* @param defaultToPrimitive
* make subclassOf axiom if no definitions status in expression
*
* @return the resulting OWLAxiom
* @throws ExpressionSyntaxError
*/
public static OWLAxiom parseExpressionToOWLAxiom(String expression,
OWLOntology ontology, String subj, boolean defaultToPrimitive)
throws ExpressionSyntaxError {
final OWLOntologyManager manager = ontology.getOWLOntologyManager();
if (subj == null)
return parseExpressionToOWLAxiom(expression, ontology,
(OWLClass) null, defaultToPrimitive);
OWLClass newClass = manager.getOWLDataFactory().getOWLClass(
IRI.create(PC_IRI + subj));
return parseExpressionToOWLAxiom(expression, ontology, newClass,
defaultToPrimitive);
}
/**
* Parses expression, converts to an OWLAxiom and adds it to ontology,
* including any descriptions as rdfs:label annotations
*
* @param expression
* the expression to parse
* @param ontology
* the ontology to which the parsed, converted expression is
* added
* @param definiendum
* an OWLClass which will be the definiendum of the new axiom
*
* @return the resulting OWLAxiom
* @throws ExpressionSyntaxError
*/
public static OWLAxiom parseExpressionToOWLAxiom(String expression,
OWLOntology ontology, OWLClass definiendum)
throws ExpressionSyntaxError {
return parseExpressionToOWLAxiom(expression, ontology, definiendum,
false);
}
public static OWLAxiom parseExpressionToOWLAxiom(ParseTree tree,
OWLOntology ontology, String subj,
boolean defaultToPrimitive) {
if (subj == null)
return parseExpressionToOWLAxiom(tree, ontology,
(OWLClass) null, defaultToPrimitive);
final OWLOntologyManager manager = ontology.getOWLOntologyManager();
OWLClass newClass = manager.getOWLDataFactory().getOWLClass(
IRI.create(PC_IRI + subj));
return parseExpressionToOWLAxiom(tree, ontology, newClass,
defaultToPrimitive);
}
public static OWLAxiom parseExpressionToOWLAxiom(ParseTree tree,
OWLOntology ontology, OWLClass definiendum,
boolean defaultToPrimitive) {
OWLAxiom owlAxiom = null;
final OWLOntologyManager manager = ontology.getOWLOntologyManager();
final OWLDataFactory dataFactory = manager.getOWLDataFactory();
OWLVisitor visitor = new OWLVisitor(ontology, definiendum);
// convert from parse tree to OWLAxiom
owlAxiom = (OWLClassAxiom) visitor.visit(tree);
// add axiom to ontology
manager.addAxiom(ontology, owlAxiom);
// labels for expression parts are kept in a map
Map<IRI, OWLAnnotation> annotations = visitor.getLabels();
// add labels, if any
for (Entry<IRI, OWLAnnotation> label : annotations.entrySet()) {
if (EntitySearcher.getAnnotations(label.getKey(), ontology).isEmpty())
manager.addAxiom(
ontology,
dataFactory.getOWLAnnotationAssertionAxiom(
label.getKey(), label.getValue()));
}
return owlAxiom;
}
/**
* Parses expression, converts to an OWLAxiom and adds it to ontology,
* including any descriptions as rdfs:label annotations
*
* @param expression
* the expression to parse
* @param ontology
* the ontology to which the parsed, converted expression is
* added
* @param definiendum
* an OWLClass which will be the definiendum of the new axiom
* @param defaultToPrimitive
* make subclassOf axiom if no definitions status in expression
*
* @return the resulting OWLAxiom
* @throws ExpressionSyntaxError
*/
public static OWLAxiom parseExpressionToOWLAxiom(String expression,
OWLOntology ontology, OWLClass definiendum,
boolean defaultToPrimitive) throws ExpressionSyntaxError {
ParseTree tree = null;
if (expression.startsWith("("))
tree = parseStatement(expression);
else
tree = parseExpression(expression);
return parseExpressionToOWLAxiom(tree, ontology, definiendum,
defaultToPrimitive);
}
}