/**
*
*/
package se.liu.imt.mi.snomedct.parser;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Map.Entry;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.semanticweb.elk.util.collections.ArraySet;
import org.semanticweb.owlapi.model.ClassExpressionType;
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.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.search.EntitySearcher;
import org.semanticweb.owlapi.vocab.OWLRDFVocabulary;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionLexer;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeGroupContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeSetContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.ConceptReferenceContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.ExpressionContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.FocusConceptContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.NonGroupedAttributeSetContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.RefinementContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.StatementContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.StatementsContext;
import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.SubExpressionContext;
/**
* @author Daniel Karlsson, Linköping University, daniel.karlsson@liu.se
*
*/
public class OWLVisitor extends SNOMEDCTExpressionBaseVisitor<OWLObject> {
private static final String PC_IRI = "http://snomed.org/postcoord/";
private static final String SCTID_IRI = "http://snomed.info/id/";
private static final String ROLEGROUP_IRI = "http://snomed.info/id/609096000";
private static final String[] neverGrouped = { SCTID_IRI + "123005000",
SCTID_IRI + "272741003", SCTID_IRI + "127489000",
SCTID_IRI + "411116001" };
static Logger logger = Logger.getLogger(OWLVisitor.class);
private OWLOntology ontology;
private OWLOntologyManager manager;
private OWLDataFactory dataFactory;
private OWLClass definiendum;
private Map<IRI, OWLAnnotation> labels;
private boolean defaultToPrimitive;
public OWLVisitor(OWLOntology ontology) {
this(ontology, null);
}
public OWLVisitor(OWLOntology ontology, OWLClass c) {
this(ontology, c, false);
}
public OWLVisitor(OWLOntology ontology, OWLClass c,
boolean defaultToPrimitive) {
super();
this.ontology = ontology;
this.manager = ontology.getOWLOntologyManager();
this.dataFactory = manager.getOWLDataFactory();
this.definiendum = c;
this.labels = new HashMap<IRI, OWLAnnotation>();
this.defaultToPrimitive = defaultToPrimitive;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitStatement
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.
* StatementContext)
*/
@Override
public OWLObject visitStatement(StatementContext ctx) {
// ctx.subExpression().size() == 2
// ctx.definitionStatus() != null
// logger.info("visitStatement: " + ctx.getText());
OWLObject subExpression1 = visit(ctx.subExpression(0));
OWLObject subExpression2 = visit(ctx.subExpression(1));
OWLAxiom axiom = null;
if ((ctx.definitionStatus() == null && defaultToPrimitive == false)
|| ctx.definitionStatus().start.getType() == SNOMEDCTExpressionLexer.EQ_TO) {
// logger.info("equivalentTo");
axiom = dataFactory.getOWLEquivalentClassesAxiom(
(OWLClassExpression) subExpression1,
(OWLClassExpression) subExpression2);
} else if ((ctx.definitionStatus() == null && defaultToPrimitive == true)
|| ctx.definitionStatus().start.getType() == SNOMEDCTExpressionLexer.SC_OF) {
// logger.info("subClassOf");
axiom = dataFactory.getOWLSubClassOfAxiom(
(OWLClassExpression) subExpression1,
(OWLClassExpression) subExpression2);
}
return axiom;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitExpression
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .ExpressionContext)
*/
@Override
public OWLObject visitExpression(ExpressionContext ctx) {
// logger.info("visitExpression: " + ctx.getText());
OWLObject subExpression = visit(ctx.subExpression());
OWLAxiom axiom = null;
if (definiendum == null)
definiendum = dataFactory.getOWLClass(IRI.create(PC_IRI
+ UUID.randomUUID().toString()));
if ((ctx.definitionStatus() == null && defaultToPrimitive == false)
|| ctx.definitionStatus().start.getType() == SNOMEDCTExpressionLexer.EQ_TO) {
// logger.info("equivalentTo");
axiom = dataFactory.getOWLEquivalentClassesAxiom(definiendum,
(OWLClassExpression) subExpression);
} else if ((ctx.definitionStatus() == null && defaultToPrimitive == true)
|| ctx.definitionStatus().start.getType() == SNOMEDCTExpressionLexer.SC_OF) {
// logger.info("subClassOf");
axiom = dataFactory.getOWLSubClassOfAxiom(definiendum,
(OWLClassExpression) subExpression);
}
return axiom;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitRefinement
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .RefinementContext)
*/
@Override
public OWLObject visitRefinement(RefinementContext ctx) {
// logger.info("visitRefinement: " + ctx.getText());
OWLClassExpression expression = null;
Set<OWLClassExpression> expressionSet = new HashSet<OWLClassExpression>();
if (ctx.nonGroupedAttributeSet() != null) {
expressionSet
.add((OWLClassExpression) visitNonGroupedAttributeSet(ctx
.nonGroupedAttributeSet()));
}
if (ctx.attributeGroup() != null) {
for (SNOMEDCTExpressionParser.AttributeGroupContext attrGroupCtx : ctx
.attributeGroup()) {
expressionSet
.add((OWLClassExpression) visitAttributeGroup(attrGroupCtx));
}
}
if (expressionSet.size() > 1)
expression = dataFactory.getOWLObjectIntersectionOf(expressionSet);
else
expression = expressionSet.iterator().next();
return expression;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitSubExpression
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .SubExpressionContext)
*/
@Override
public OWLObject visitSubExpression(SubExpressionContext ctx) {
// logger.info("visitSubExpression: " + ctx.getText());
OWLClassExpression expression = null;
if (ctx.getChildCount() > 1) {
Set<OWLClassExpression> totalSet = new HashSet<OWLClassExpression>();
OWLClassExpression focusConcept = (OWLClassExpression) visitFocusConcept(ctx.focusConcept());
if(focusConcept.getClassExpressionType() == ClassExpressionType.OBJECT_INTERSECTION_OF)
totalSet.addAll(((OWLObjectIntersectionOf)focusConcept).getOperands());
else
totalSet.add(focusConcept);
OWLClassExpression refinement = (OWLClassExpression) visitRefinement(ctx.refinement());
if(refinement.getClassExpressionType() == ClassExpressionType.OBJECT_INTERSECTION_OF)
totalSet.addAll(((OWLObjectIntersectionOf)refinement).getOperands());
else
totalSet.add(refinement);
expression = dataFactory.getOWLObjectIntersectionOf(totalSet);
}
else
expression = (OWLClassExpression) visitFocusConcept(ctx
.focusConcept());
return expression;
}
/**
* @return the labels
*/
public Map<IRI, OWLAnnotation> getLabels() {
return labels;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitFocusConcept
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .FocusConceptContext)
*/
@Override
public OWLObject visitFocusConcept(FocusConceptContext ctx) {
// logger.info("visitFocusConcept: " + ctx.getText());
OWLClassExpression expression = null;
if (ctx.getChildCount() > 1) {
Set<OWLClassExpression> expressionSet = new HashSet<OWLClassExpression>();
for (SNOMEDCTExpressionParser.ConceptReferenceContext focusConceptCtx : ctx
.getRuleContexts(SNOMEDCTExpressionParser.ConceptReferenceContext.class))
expressionSet
.add((OWLClassExpression) visitConceptReference(focusConceptCtx));
expression = dataFactory.getOWLObjectIntersectionOf(expressionSet);
} else
expression = (OWLClassExpression) visitConceptReference(ctx
.conceptReference(0));
return expression;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitConceptReference
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .ConceptReferenceContext)
*/
@Override
public OWLObject visitConceptReference(ConceptReferenceContext ctx) {
// logger.info("visitConceptReference: " + ctx.getText());
OWLObject entity = null;
// concept reference may be to a object or data property or a class
// depending on
// the parent parse rule context
IRI iri = IRI.create(SCTID_IRI + ctx.SCTID().getText());
if (ctx.getParent().getClass() == SNOMEDCTExpressionParser.AttributeContext.class)
// return the IRI as we do not know here if it is an object or data
// property
entity = iri;
else if (ctx.getParent().getClass() == SNOMEDCTExpressionParser.FocusConceptContext.class
|| ctx.getParent().getClass() == SNOMEDCTExpressionParser.AttributeValueContext.class)
entity = dataFactory.getOWLClass(iri);
if (ctx.TERM() != null) {
labels.put(iri, dataFactory.getOWLAnnotation(dataFactory
.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL
.getIRI()), dataFactory
.getOWLLiteral(removeCharacter(ctx.TERM().getText(), "|"))));
}
return entity;
}
// TODO: let the grammar handle vertical bars instead! Only semi-possible?
private String removeCharacter(String input, String c) {
if (input.startsWith(c))
input = input.substring(1);
if (input.endsWith(c))
input = input.substring(0, input.length() - 1);
return input;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitAttribute
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.
* AttributeContext)
*/
@Override
public OWLObject visitAttribute(
se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeContext ctx) {
// logger.info("visitAttribute: " + ctx.getText());
OWLClassExpression expression = null;
// if property filler is a concept reference
if (ctx.attributeValue().getChild(0).getClass() == SNOMEDCTExpressionParser.ConceptReferenceContext.class) {
OWLObjectProperty property = dataFactory
.getOWLObjectProperty((IRI) visitConceptReference(ctx
.conceptReference()));
OWLClassExpression filler = (OWLClassExpression) visitAttributeValue(ctx
.attributeValue());
expression = dataFactory.getOWLObjectSomeValuesFrom(property,
filler);
} else // if the property filler is a number
if (ctx.attributeValue().start.getType() == SNOMEDCTExpressionLexer.NUMBER) {
String stringValue = ctx.attributeValue().getText();
OWLLiteral literal;
if (stringValue.indexOf('.') > 0) {
double value = Double.parseDouble(stringValue.substring(1));
literal = dataFactory.getOWLLiteral(value);
} else {
int value = Integer.parseInt(stringValue.substring(1));
literal = dataFactory.getOWLLiteral(value);
}
OWLDataProperty property = dataFactory
.getOWLDataProperty((IRI) visitConceptReference(ctx
.conceptReference()));
expression = dataFactory.getOWLDataHasValue(property, literal);
} else // if the property filler is a string
if (ctx.attributeValue().start.getType() == SNOMEDCTExpressionLexer.STRING) {
String stringValue = StringEscapeUtils
.unescapeJava(removeCharacter(ctx.attributeValue()
.getText(), "\""));
OWLDataProperty property = dataFactory
.getOWLDataProperty((IRI) visitConceptReference(ctx
.conceptReference()));
OWLLiteral literal = dataFactory.getOWLLiteral(stringValue);
expression = dataFactory.getOWLDataHasValue(property, literal);
} else // a subexpression
if (ctx.attributeValue().getChild(0).getClass() == SNOMEDCTExpressionParser.NestedExpressionContext.class) {
OWLObjectProperty property = dataFactory
.getOWLObjectProperty((IRI) visitConceptReference(ctx
.conceptReference()));
OWLClassExpression filler = (OWLClassExpression) visitSubExpression(ctx
.attributeValue().nestedExpression().subExpression());
expression = dataFactory.getOWLObjectSomeValuesFrom(property,
filler);
} else
logger.info("Shouldn't ever get here");
return expression;
}
/*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitAttributeGroup
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .AttributeGroupContext)
*/
@Override
public OWLObject visitAttributeGroup(AttributeGroupContext ctx) {
// logger.info("visitAttributeGroup: " + ctx.getText());
OWLClassExpression expression = null;
OWLClassExpression attrSet = (OWLClassExpression) visitAttributeSet(ctx
.attributeSet());
OWLObjectProperty attrGroup = dataFactory.getOWLObjectProperty(IRI
.create(ROLEGROUP_IRI));
expression = dataFactory.getOWLObjectSomeValuesFrom(attrGroup, attrSet);
return expression;
}
/*
* This method does not insert attribute groups for non-grouped attributes!
* TODO: remove magic transforms from Compositional Grammar specification
*
* (non-Javadoc)
*
* @see se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor#
* visitAttributeSet
* (se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser
* .AttributeSetContext)
*/
@Override
public OWLObject visitAttributeSet(AttributeSetContext ctx) {
OWLClassExpression expression = null;
if (ctx.getChildCount() > 1) {
Set<OWLClassExpression> expressionSet = new HashSet<OWLClassExpression>();
for (SNOMEDCTExpressionParser.AttributeContext attrCtx : ctx
.getRuleContexts(SNOMEDCTExpressionParser.AttributeContext.class))
expressionSet.add((OWLClassExpression) visitAttribute(attrCtx));
expression = dataFactory.getOWLObjectIntersectionOf(expressionSet);
} else
expression = (OWLClassExpression) visitAttribute(ctx.attribute(0));
return expression;
}
@Override
public OWLObject visitNonGroupedAttributeSet(
NonGroupedAttributeSetContext ctx) {
OWLClassExpression expression = null;
if (ctx.getChildCount() > 1) {
Set<OWLClassExpression> groupedExpressionSet = new HashSet<OWLClassExpression>();
Set<OWLClassExpression> shouldNotBeGroupedExpressionSet = new HashSet<OWLClassExpression>();
Set<OWLClassExpression> totalSet = new HashSet<OWLClassExpression>();
for (SNOMEDCTExpressionParser.AttributeContext attrCtx : ctx
.getRuleContexts(SNOMEDCTExpressionParser.AttributeContext.class)) {
OWLClassExpression attr = (OWLClassExpression) visitAttribute(attrCtx);
if (attr.getClassExpressionType() == ClassExpressionType.OBJECT_SOME_VALUES_FROM) {
if (isNeverGrouped(((OWLObjectSomeValuesFrom) attr)
.getProperty())) {
shouldNotBeGroupedExpressionSet.add(attr);
} else {
OWLObjectProperty group = dataFactory
.getOWLObjectProperty(IRI.create(ROLEGROUP_IRI));
OWLClassExpression groupExpression = dataFactory
.getOWLObjectSomeValuesFrom(group, attr);
groupedExpressionSet.add(groupExpression);
}
} else
groupedExpressionSet.add(attr);
}
totalSet.addAll(shouldNotBeGroupedExpressionSet);
totalSet.addAll(groupedExpressionSet);
if(totalSet.size() > 1)
expression = dataFactory.getOWLObjectIntersectionOf(totalSet);
else
expression = totalSet.iterator().next();
} else { // i.e. only ony child
OWLClassExpression attr = (OWLClassExpression) visitAttribute((AttributeContext) ctx
.getChild(0));
if (attr.getClassExpressionType() == ClassExpressionType.OBJECT_SOME_VALUES_FROM
&& isNeverGrouped(((OWLObjectSomeValuesFrom) attr)
.getProperty()))
expression = attr;
else {
OWLObjectProperty attrGroup = dataFactory
.getOWLObjectProperty(IRI.create(ROLEGROUP_IRI));
expression = dataFactory.getOWLObjectSomeValuesFrom(attrGroup,
attr);
}
}
return expression;
}
private boolean isNeverGrouped(OWLObjectPropertyExpression property) {
IRI iri = property.getNamedProperty().getIRI();
String iriString = iri.toString();
for (String nonGroupedIri : neverGrouped) {
if (iriString.equals(nonGroupedIri))
return true;
}
return false;
}
@Override
public OWLObject visitStatements(StatementsContext ctx) {
ArraySet<OWLAxiom> axioms = new ArraySet<OWLAxiom>();
OWLAxiom owlAxiom = null;
for (StatementContext statement : ctx
.getRuleContexts(SNOMEDCTExpressionParser.StatementContext.class)) {
owlAxiom = (OWLClassAxiom) visitStatement(statement);
axioms.add(owlAxiom);
}
manager.addAxioms(ontology, axioms);
// labels for expression parts are kept in a map
Map<IRI, OWLAnnotation> annotations = this.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;
}
}