org.obolibrary.obo2owl.OWLAPIOwl2Obo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of owlapi-oboformat Show documentation
Show all versions of owlapi-oboformat Show documentation
A java library for converting obo format documents to OWL, and for converting (a subset of) OWL to obo format. This version has been slightly modified to be included directly in the OWL API.
The upstream code for this module and its authors can be found at https://code.google.com/p/oboformat/.
The newest version!
package org.obolibrary.obo2owl;
import static org.semanticweb.owlapi.search.EntitySearcher.getAnnotationObjects;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.checkNotNull;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.emptyOptional;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.optional;
import static org.semanticweb.owlapi.util.OWLAPIPreconditions.verifyNotNull;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.asList;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.asSet;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.obolibrary.obo2owl.Obo2OWLConstants.Obo2OWLVocabulary;
import org.obolibrary.oboformat.model.Clause;
import org.obolibrary.oboformat.model.Frame;
import org.obolibrary.oboformat.model.Frame.FrameType;
import org.obolibrary.oboformat.model.OBODoc;
import org.obolibrary.oboformat.model.QualifierValue;
import org.obolibrary.oboformat.model.Xref;
import org.obolibrary.oboformat.parser.OBOFormatConstants;
import org.obolibrary.oboformat.parser.OBOFormatConstants.OboFormatTag;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLAnnotationValue;
import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLAxiomVisitor;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNamedObject;
import org.semanticweb.owlapi.model.OWLNaryPropertyAxiom;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectCardinalityRestriction;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLQuantifiedObjectRestriction;
import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLRuntimeException;
import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
import org.semanticweb.owlapi.rdf.rdfxml.parser.RDFConstants;
import org.semanticweb.owlapi.vocab.Namespaces;
import org.semanticweb.owlapi.vocab.OWL2Datatype;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class OWLAPIOwl2Obo.
*/
public class OWLAPIOwl2Obo {
private static final String MAX_CARDINALITY = "maxCardinality";
private static final String MIN_CARDINALITY = "minCardinality";
/**
* The annotation property map.
*/
public static final Map ANNOTATIONPROPERTYMAP = initAnnotationPropertyMap();
private static final String TOP_BOTTOM_NONTRANSLATEABLE =
"Assertions using owl:Thing or owl:Nothing are not translateable OBO";
/**
* The log.
*/
private static final Logger LOG = LoggerFactory.getLogger(OWLAPIOwl2Obo.class);
private static final String IRI_CLASS_SYNONYMTYPEDEF =
Obo2OWLConstants.DEFAULT_IRI_PREFIX + "IAO_synonymtypedef";
private static final String IRI_CLASS_SUBSETDEF =
Obo2OWLConstants.DEFAULT_IRI_PREFIX + "IAO_subsetdef";
// RDF_TYPE added to guard against scenario when a syntactic triple is
// accidentally interpreted as an annotation.
// See https://github.com/ontodev/robot/issues/1089 for context
private static final Set SKIPPED_QUALIFIERS =
new HashSet<>(Arrays.asList("gci_relation", "gci_filler", "cardinality", MIN_CARDINALITY,
MAX_CARDINALITY, "all_some", "all_only", RDFConstants.RDF_TYPE));
protected final Pattern absoluteURLPattern = Pattern.compile("<\\s*http.*?>");
protected final Set untranslatableAxioms = new HashSet<>();
protected final Map idSpaceMap = new HashMap<>();
protected final Set apToDeclare = new HashSet<>();
private final OWLDataFactory df;
protected OWLOntologyManager manager;
protected OWLOntology owlOntology;
protected OBODoc obodoc;
protected String ontologyId;
protected boolean strictConversion;
protected boolean discardUntranslatable = false;
/**
* Mute untranslatable axiom warnings.
*/
private boolean muteUntranslatableAxioms = false;
/**
* @param translationManager the translation manager
*/
public OWLAPIOwl2Obo(OWLOntologyManager translationManager) {
manager = translationManager;
df = manager.getOWLDataFactory();
init();
}
/**
* Inits the annotation property map.
*
* @return the hash map
*/
protected static Map initAnnotationPropertyMap() {
Map map = new HashMap<>();
for (String key : OWLAPIObo2Owl.ANNOTATIONPROPERTYMAP.keySet()) {
IRI propIRI = OWLAPIObo2Owl.ANNOTATIONPROPERTYMAP.get(key);
map.put(propIRI.toString(), key);
}
return map;
}
protected static boolean shorthand(@Nullable String propId) {
return "shorthand".equals(propId);
}
/**
* Adds the qualifiers.
*
* @param c the c
* @param qualifiers the qualifiers
*/
protected static void addQualifiers(Clause c, Stream qualifiers) {
qualifiers.forEach(a -> addQualifiers(c, a));
}
/**
* Adds the qualifiers.
*
* @param c the c
* @param qualifier the qualifier
*/
protected static void addQualifiers(Clause c, OWLAnnotation qualifier) {
String prop = owlObjectToTag(qualifier.getProperty());
if (prop == null) {
prop = qualifier.getProperty().getIRI().toString();
}
if (SKIPPED_QUALIFIERS.contains(prop)) {
return;
}
String value = qualifier.getValue().toString();
if (qualifier.getValue() instanceof OWLLiteral) {
value = ((OWLLiteral) qualifier.getValue()).getLiteral();
} else if (qualifier.getValue().isIRI()) {
value = getIdentifier((IRI) qualifier.getValue());
}
QualifierValue qv = new QualifierValue(prop, value);
c.addQualifierValue(qv);
}
/**
* E.g. http://purl.obolibrary.org/obo/go.owl to "go"
* if does not match this pattern, then retain original IRI
*
* @param ontology the ontology
* @return The OBO ID of the ontology
*/
public static String getOntologyId(OWLOntology ontology) {
Optional ontologyIRI = ontology.getOntologyID().getOntologyIRI();
if (!ontologyIRI.isPresent()) {
return "";
}
return getOntologyId(ontologyIRI.get());
}
/**
* Gets the ontology id.
*
* @param iriObj the iri
* @return the ontology id
*/
public static String getOntologyId(IRI iriObj) {
String iri = iriObj.toString();
String id;
if (iri.startsWith("http://purl.obolibrary.org/obo/")) {
id = iri.replace("http://purl.obolibrary.org/obo/", "");
if (id.endsWith(".owl")) {
id = id.replaceFirst(".owl$", "");
}
} else {
id = iri;
}
return id;
}
/**
* Gets the data version.
*
* @param ontology the ontology
* @return the data version
*/
@Nullable
public static String getDataVersion(OWLOntology ontology) {
String oid = getOntologyId(ontology);
Optional v = ontology.getOntologyID().getVersionIRI();
if (v.isPresent()) {
String vs = v.get().toString().replace("http://purl.obolibrary.org/obo/", "");
vs = vs.replaceFirst(oid + '/', "");
vs = vs.replace('/' + oid + ".owl", "");
return vs;
}
return null;
}
/**
* Check the entity annotations for axioms declaring it to be an obsolete entity, with
* 'obsolescence reason' being 'term merge', and a non-empty 'replaced by' literal. This
* corresponds to an OBO alternate identifier. Track non related annotations.
*
* @param annotations set of annotations for the entity @return replaced_by if it is an alt_id
* @return alternate id check result
*/
private static Optional checkForOboAltId(
Collection annotations) {
String replacedBy = null;
boolean isMerged = false;
boolean isDeprecated = false;
final Set unrelatedAxioms = new HashSet<>();
for (OWLAnnotationAssertionAxiom axiom : annotations) {
OWLAnnotationProperty prop = axiom.getProperty();
if (prop.isDeprecated()) {
isDeprecated = true;
} else if (Obo2OWLConstants.IRI_IAO_0000231.equals(prop.getIRI())) {
isMerged = handleIAO227(isMerged, unrelatedAxioms, axiom);
} else if (Obo2OWLVocabulary.IRI_IAO_0100001.iri.equals(prop.getIRI())) {
replacedBy = handleIAO10001(replacedBy, unrelatedAxioms, axiom);
} else {
unrelatedAxioms.add(axiom);
}
}
Optional result;
if (replacedBy != null && isMerged && isDeprecated) {
result = optional(new OboAltIdCheckResult(replacedBy, unrelatedAxioms));
} else {
result = emptyOptional();
}
return result;
}
protected static boolean handleIAO227(boolean isMerged,
final Set unrelatedAxioms, OWLAnnotationAssertionAxiom axiom) {
OWLAnnotationValue value = axiom.getValue();
Optional asIRI = value.asIRI();
if (asIRI.isPresent()) {
return Obo2OWLConstants.IRI_IAO_0000227.equals(asIRI.get());
}
unrelatedAxioms.add(axiom);
return isMerged;
}
@Nullable
protected static String handleIAO10001(@Nullable String replacedBy,
final Set unrelatedAxioms, OWLAnnotationAssertionAxiom axiom) {
OWLAnnotationValue value = axiom.getValue();
Optional asLiteral = value.asLiteral();
if (asLiteral.isPresent()) {
return asLiteral.get().getLiteral();
}
// fallback: also check for an IRI
Optional asIRI = value.asIRI();
if (asIRI.isPresent()) {
// translate IRI to OBO style ID
return getIdentifier(asIRI.get());
}
unrelatedAxioms.add(axiom);
return replacedBy;
}
/**
* Retrieve the identifier for a given {@link OWLObject}. This methods uses also shorthand hints
* to resolve the identifier. Should the translation process encounter a problem or not find an
* identifier the defaultValue is returned.
*
* @param obj the {@link OWLObject} to resolve
* @param ont the target ontology
* @param defaultValue the value to return in case of an error or no id
* @return identifier or the default value
*/
public static String getIdentifierFromObject(OWLObject obj, OWLOntology ont,
String defaultValue) {
String id = defaultValue;
try {
id = getIdentifierFromObject(obj, ont);
if (id == null) {
id = defaultValue;
}
} catch (UntranslatableAxiomException e) {
LOG.error(e.getMessage(), e);
}
return id;
}
/**
* Retrieve the identifier for a given {@link OWLObject}. This methods uses also shorthand hints
* to resolve the identifier. Should the translation process encounter an unexpected axiom an
*
* @param obj the {@link OWLObject} to resolve
* @param ont the target ontology
* @return identifier or null
* @throws UntranslatableAxiomException the untranslatable axiom exception
* {@link UntranslatableAxiomException} is thrown.
*/
@Nullable
public static String getIdentifierFromObject(OWLObject obj, OWLOntology ont)
throws UntranslatableAxiomException {
if (obj instanceof OWLObjectProperty || obj instanceof OWLAnnotationProperty) {
OWLEntity entity = (OWLEntity) obj;
for (OWLAnnotationAssertionAxiom ax : asList(
ont.annotationAssertionAxioms(entity.getIRI()))) {
String propId = getIdentifierFromObject(ax.getProperty().getIRI(), ont);
// see BFOROXrefTest
// 5.9.3. Special Rules for Relations
if (shorthand(propId)) {
OWLAnnotationValue value = ax.getValue();
if (value instanceof OWLLiteral) {
return ((OWLLiteral) value).getLiteral();
}
throw new UntranslatableAxiomException(
"Untranslatable axiom, expected literal value, but was: " + value
+ " in axiom: " + ax);
}
}
}
if (obj instanceof OWLEntity) {
return getIdentifier(((OWLEntity) obj).getIRI());
}
if (obj.isIRI()) {
return getIdentifier((IRI) obj);
}
return null;
}
/**
* See table 5.9.2. Translation of identifiers
*
* @param iriId the iri id
* @return obo identifier
*/
public static String getIdentifier(IRI iriId) {
String iri = iriId.toString();
// canonical IRIs
String id = getId(iri);
String[] s = id.split("#_");
// table 5.9.2 row 2 - NonCanonical-Prefixed-ID
if (s.length > 1) {
return s[0] + ':' + s[1];
}
// row 3 - Unprefixed-ID
s = id.split("#");
if (s.length > 1) {
String prefix = "";
if ("owl".equals(s[0]) || "rdf".equals(s[0]) || "rdfs".equals(s[0])) {
prefix = s[0] + ':';
}
return prefix + s[1];
}
// row 1 - Canonical-Prefixed-ID
s = id.split("_");
if (s.length == 2 && !id.contains("#") && !s[1].contains("_")) {
String localId;
try {
localId = URLDecoder.decode(s[1], "UTF-8");
return s[0] + ':' + localId;
} catch (UnsupportedEncodingException e) {
throw new OWLRuntimeException("UTF-8 not supported, JRE corrupted?", e);
}
}
if (s.length > 2 && !id.contains("#")
&& s[s.length - 1].replaceAll("[0-9]", "").isEmpty()) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length; i++) {
if (i > 0) {
if (i == s.length - 1) {
sb.append(':');
} else {
sb.append('_');
}
}
sb.append(s[i]);
}
return sb.toString();
}
return iri;
}
protected static String getId(String iri) {
int indexSlash = iri.lastIndexOf('/');
if (indexSlash > -1) {
return iri.substring(indexSlash + 1);
}
return iri;
}
/**
* Owl object to tag.
*
* @param obj the object
* @return the string
*/
@Nullable
public static String owlObjectToTag(OWLObject obj) {
IRI iriObj = null;
if (obj instanceof OWLNamedObject) {
iriObj = ((OWLNamedObject) obj).getIRI();
} else if (obj.isIRI()) {
iriObj = (IRI) obj;
}
if (iriObj == null) {
return null;
}
String iri = iriObj.toString();
String tag = ANNOTATIONPROPERTYMAP.get(iri);
if (tag == null) {
// hard coded values for legacy annotation properties: (TEMPORARY)
if (iri.startsWith(Obo2OWLConstants.DEFAULT_IRI_PREFIX + "IAO_")) {
String legacyId = iri.replace(Obo2OWLConstants.DEFAULT_IRI_PREFIX, "");
if ("IAO_xref".equals(legacyId)) {
return OboFormatTag.TAG_XREF.getTag();
}
if ("IAO_id".equals(legacyId)) {
return OboFormatTag.TAG_ID.getTag();
}
if ("IAO_namespace".equals(legacyId)) {
return OboFormatTag.TAG_NAMESPACE.getTag();
}
}
String prefix = Obo2OWLConstants.OIOVOCAB_IRI_PREFIX;
if (iri.startsWith(prefix)) {
tag = iri.substring(prefix.length());
} else {
tag = getIdentifier(iriObj);
}
}
return tag;
}
/**
* Join clauses and its {@link QualifierValue} which have the same relationship type and target.
* Try to resolve conflicts for multiple statements. E.g., min=2 and min=3 is resolved to min=2,
* or max=2 and max=4 is resolved to max=4. It will not merge conflicting exact cardinality
* statements. TODO How to merge "all_some", and "all_only"?
*
* @param clauses the clauses
* @return normalized list of {@link Clause}
*/
public static List normalizeRelationshipClauses(List clauses) {
List normalized = new ArrayList<>();
while (!clauses.isEmpty()) {
Clause target = clauses.remove(0);
List similar = findSimilarClauses(clauses, target);
normalized.add(target);
mergeSimilarIntoTarget(target, similar);
}
return normalized;
}
/**
* Find similar clauses.
*
* @param clauses the clauses
* @param target the target
* @return the list
*/
static List findSimilarClauses(List clauses, Clause target) {
String targetTag = target.getTag();
List similar = new ArrayList<>();
if (targetTag == null) {
return similar;
}
int size = target.getValues().size();
Object targetValue = target.getValue();
Object targetValue2 = null;
if (size > 1) {
targetValue2 = target.getValue2();
}
Iterator iterator = clauses.iterator();
while (iterator.hasNext()) {
Clause current = iterator.next();
int sizeCurrent = current.getValues().size();
Object currentValue = current.getValue();
Object currentValue2 = null;
if (sizeCurrent > 1) {
currentValue2 = current.getValue2();
}
if (targetTag.equals(current.getTag()) && targetValue.equals(currentValue)
&& Objects.equals(targetValue2, currentValue2)) {
similar.add(current);
iterator.remove();
}
}
return similar;
}
/**
* Merge similar into target.
*
* @param target the target
* @param similar the similar
*/
static void mergeSimilarIntoTarget(Clause target, List similar) {
if (similar.isEmpty()) {
return;
}
Collection targetQVs = target.getQualifierValues();
for (Clause current : similar) {
Collection newQVs = current.getQualifierValues();
for (QualifierValue newQV : newQVs) {
String newQualifier = newQV.getQualifier();
// if min or max cardinality check for possible merges
if (MIN_CARDINALITY.equals(newQualifier) || MAX_CARDINALITY.equals(newQualifier)) {
QualifierValue match = findMatchingQualifierValue(newQV, targetQVs);
if (match != null) {
mergeQualifierValues(match, newQV);
} else {
target.addQualifierValue(newQV);
}
} else {
target.addQualifierValue(newQV);
}
}
}
}
/**
* Find matching qualifier value.
*
* @param query the query
* @param list the list
* @return the qualifier value
*/
@Nullable
static QualifierValue findMatchingQualifierValue(QualifierValue query,
Collection list) {
String queryQualifier = query.getQualifier();
for (QualifierValue qv : list) {
if (queryQualifier.equals(qv.getQualifier())) {
return qv;
}
}
return null;
}
/**
* Merge qualifier values.
*
* @param target the target
* @param newQV the new qv
*/
static void mergeQualifierValues(QualifierValue target, QualifierValue newQV) {
// do nothing, if they are equal
if (!target.getValue().equals(newQV.getValue())) {
if (MIN_CARDINALITY.equals(target.getQualifier())) {
// try to merge, parse as integers
int currentValue = Integer.parseInt(target.getValue());
int newValue = Integer.parseInt(newQV.getValue());
int mergedValue = Math.min(currentValue, newValue);
target.setValue(Integer.toString(mergedValue));
} else if (MAX_CARDINALITY.equals(target.getQualifier())) {
// try to merge, parse as integers
int currentValue = Integer.parseInt(target.getValue());
int newValue = Integer.parseInt(newQV.getValue());
int mergedValue = Math.max(currentValue, newValue);
target.setValue(Integer.toString(mergedValue));
}
}
}
protected final void init() {
idSpaceMap.clear();
// legacy:
idSpaceMap.put("http://www.obofoundry.org/ro/ro.owl#", "OBO_REL");
untranslatableAxioms.clear();
apToDeclare.clear();
}
/**
* Gets the strict conversion.
*
* @return the strict conversion
*/
public boolean getStrictConversion() {
return strictConversion;
}
/**
* Sets the strict conversion.
*
* @param b the new strict conversion
*/
public void setStrictConversion(boolean b) {
strictConversion = b;
}
/**
* Checks if is discard untranslatable.
*
* @return the discard untranslatable flag
*/
public boolean isDiscardUntranslatable() {
return discardUntranslatable;
}
/**
* Sets the discard untranslatable.
*
* @param discardUntranslatable the new value for discard untranslatable to set
*/
public void setDiscardUntranslatable(boolean discardUntranslatable) {
this.discardUntranslatable = discardUntranslatable;
}
/**
* Gets the manager.
*
* @return the manager
*/
public OWLOntologyManager getManager() {
return manager;
}
/**
* Sets the manager.
*
* @param manager the new manager
*/
public void setManager(OWLOntologyManager manager) {
this.manager = manager;
}
/**
* Gets the obodoc.
*
* @return the obodoc
*/
public OBODoc getObodoc() {
return verifyNotNull(obodoc);
}
/**
* Sets the obodoc.
*
* @param obodoc the new obodoc
*/
public void setObodoc(OBODoc obodoc) {
this.obodoc = obodoc;
}
/**
* Convert.
*
* @param ont the ontology
* @return the OBO doc
*/
public OBODoc convert(OWLOntology ont) {
owlOntology = ont;
ontologyId = getOntologyId(ont);
init();
return tr();
}
protected OWLOntology getOWLOntology() {
return verifyNotNull(owlOntology);
}
/**
* Gets the untranslatable axioms.
*
* @return the untranslatable axioms
*/
public Collection getUntranslatableAxioms() {
return untranslatableAxioms;
}
/**
* Translate to obo document.
*
* @return the OBO doc
*/
protected OBODoc tr() {
setObodoc(new OBODoc());
preProcess();
tr(getOWLOntology());
// declarations need to be sorted - otherwise there is a risk of id being processed before
// altId, which causes spurious clauses.
accept(getOWLOntology().axioms(AxiomType.DECLARATION).sorted());
AxiomType.skipDeclarations().forEach(t -> accept(getOWLOntology().axioms(t)));
if (!untranslatableAxioms.isEmpty() && !discardUntranslatable) {
String axiomString = OwlStringTools.translate(untranslatableAxioms);
if (!axiomString.isEmpty()) {
Frame headerFrame = getObodoc().getHeaderFrame();
if (headerFrame == null) {
headerFrame = new Frame(FrameType.HEADER);
getObodoc().setHeaderFrame(headerFrame);
}
headerFrame.addClause(new Clause(OboFormatTag.TAG_OWL_AXIOMS, axiomString));
}
}
return getObodoc();
}
private void accept(Stream extends OWLAxiom> axioms) {
OWLAxiomVisitor visitor = new Translator();
axioms.forEach(ax -> ax.accept(visitor));
}
/**
* Preprocess.
*/
protected void preProcess() {
// converse of postProcess in obo2owl
String viewRel = null;
OWLAnnotationProperty logicalDef = manager.getOWLDataFactory().getOWLAnnotationProperty(
Obo2OWLVocabulary.IRI_OIO_LogicalDefinitionViewRelation.getIRI());
List collect = asList(getOWLOntology().annotations(logicalDef));
if (!collect.isEmpty()) {
OWLAnnotationValue v = collect.get(0).getValue();
if (v instanceof OWLLiteral) {
viewRel = ((OWLLiteral) v).getLiteral();
} else if (v.isIRI()) {
viewRel = getIdentifier((IRI) v);
}
}
if (viewRel == null) {
return;
}
String view = viewRel;
Set rmAxioms = new HashSet<>();
Set newAxioms = new HashSet<>();
getOWLOntology().axioms(AxiomType.EQUIVALENT_CLASSES)
.forEach(eca -> preprocessEquivalents(view, rmAxioms, newAxioms, eca));
getOWLOntology().remove(rmAxioms);
getOWLOntology().add(newAxioms);
}
protected void preprocessEquivalents(String view, Set rmAxioms,
Set newAxioms, OWLEquivalentClassesAxiom eca) {
AtomicInteger numNamed = new AtomicInteger();
Set xs = new HashSet<>();
eca.classExpressions().forEach(x -> {
if (x instanceof OWLClass) {
xs.add(x);
numNamed.incrementAndGet();
} else if (x instanceof OWLObjectSomeValuesFrom) {
OWLObjectProperty p =
(OWLObjectProperty) ((OWLObjectSomeValuesFrom) x).getProperty();
if (!view.equals(getIdentifier(p))) {
LOG.error("Expected: {} got: {} in {}", view, p, eca);
}
xs.add(((OWLObjectSomeValuesFrom) x).getFiller());
} else {
LOG.error("Unexpected: {}", eca);
}
});
if (numNamed.get() == 1) {
rmAxioms.add(eca);
newAxioms.add(df.getOWLEquivalentClassesAxiom(xs));
} else {
LOG.error("ECA did not fit expected pattern: {}", eca);
}
}
protected void add(@Nullable Frame f) {
if (f != null) {
try {
getObodoc().addFrame(f);
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
}
}
}
/**
* Translate object property.
*
* @param prop the prop
* @param tag the tag
* @param value the value
* @param annotations the annotations
* @return true, if successful
*/
protected boolean trObjectProperty(@Nullable OWLObjectProperty prop, @Nullable String tag,
@Nullable String value, Stream annotations) {
if (prop == null || value == null) {
return false;
}
addQualifiers(clause(prop, tag, value), annotations);
return true;
}
protected Clause clause(OWLObjectProperty prop, @Nullable String tag, String value) {
Frame f = getTypedefFrame(prop);
if (OboFormatTag.TAG_ID.getTag().equals(tag)) {
Clause clause = f.getClause(tag);
assert clause != null;
clause.setValue(value);
return clause;
} else {
Clause clause = new Clause(tag, value);
f.addClause(clause);
return clause;
}
}
/**
* Translate object property.
*
* @param prop the prop
* @param tag the tag
* @param value the value
* @param annotations the annotations
* @return true, if successful
*/
protected boolean trObjectProperty(@Nullable OWLObjectProperty prop, String tag,
@Nullable Boolean value, Stream annotations) {
if (prop == null || value == null) {
return false;
}
Frame f = getTypedefFrame(prop);
Clause clause = new Clause(tag);
clause.addValue(value);
f.addClause(clause);
addQualifiers(clause, annotations);
return true;
}
/**
* Translate nary property axiom.
*
* @param ax the ax
* @param tag the tag
*/
protected void trNaryPropertyAxiom(OWLNaryPropertyAxiom ax,
String tag) {
List set = asList(ax.properties());
if (set.size() > 1) {
boolean first = true;
OWLObjectProperty prop = null;
String disjointFrom = null;
for (OWLObjectPropertyExpression ex : set) {
if (ex.isBottomEntity() || ex.isTopEntity()) {
error(tag + " using Top or Bottom entities are not supported in OBO.", ax,
false);
return;
}
if (first) {
first = false;
if (ex.isOWLObjectProperty()) {
prop = ex.asOWLObjectProperty();
}
} else {
disjointFrom = getIdentifier(ex);
}
}
if (trObjectProperty(prop, tag, disjointFrom, ax.annotations())) {
return;
}
}
error(ax, true);
}
/**
* Translate.
*
* @param ax the ax
*/
protected void tr(OWLSubPropertyChainOfAxiom ax) {
OWLObjectPropertyExpression pEx = ax.getSuperProperty();
if (pEx.isAnonymous()) {
error(ax, false);
return;
}
OWLObjectProperty p = pEx.asOWLObjectProperty();
if (p.isBottomEntity() || p.isTopEntity()) {
error("Property chains using Top or Bottom entities are not supported in OBO.", ax,
false);
return;
}
List list = ax.getPropertyChain();
if (list.size() != 2) {
error(ax, false);
return;
}
OWLObjectPropertyExpression exp1 = list.get(0);
OWLObjectPropertyExpression exp2 = list.get(1);
if (exp1.isBottomEntity() || exp1.isTopEntity() || exp2.isBottomEntity()
|| exp2.isTopEntity()) {
error("Property chains using Top or Bottom entities are not supported in OBO.", ax,
false);
return;
}
String rel1 = getIdentifier(exp1);
String rel2 = getIdentifier(exp2);
if (rel1 == null || rel2 == null) {
error(ax, false);
return;
}
// set of unprocessed annotations
List unprocessedAnnotations = asList(ax.annotations());
Frame f = getTypedefFrame(p);
Clause clause;
if (rel1.equals(f.getId())) {
clause = new Clause(OboFormatTag.TAG_TRANSITIVE_OVER, rel2);
} else {
OboFormatTag tag = OboFormatTag.TAG_HOLDS_OVER_CHAIN;
List collect = asList(ax.annotations());
for (OWLAnnotation ann : collect) {
if (OWLAPIObo2Owl.IRI_PROP_ISREVERSIBLEPROPERTYCHAIN
.equals(ann.getProperty().getIRI().toString())) {
tag = OboFormatTag.TAG_EQUIVALENT_TO_CHAIN;
// remove annotation from unprocessed set.
unprocessedAnnotations.remove(ann);
break;
}
}
clause = new Clause(tag);
clause.addValue(rel1);
clause.addValue(rel2);
}
f.addClause(clause);
addQualifiers(clause, unprocessedAnnotations.stream());
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLEquivalentObjectPropertiesAxiom ax) {
trNaryPropertyAxiom(ax, OboFormatTag.TAG_EQUIVALENT_TO.getTag());
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLTransitiveObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_TRANSITIVE.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLDisjointObjectPropertiesAxiom ax) {
trNaryPropertyAxiom(ax, OboFormatTag.TAG_DISJOINT_FROM.getTag());
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLReflexiveObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_REFLEXIVE.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLInverseFunctionalObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_INVERSE_FUNCTIONAL.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLInverseObjectPropertiesAxiom ax) {
OWLObjectPropertyExpression prop1 = ax.getFirstProperty();
OWLObjectPropertyExpression prop2 = ax.getSecondProperty();
if (prop1.isOWLObjectProperty() && prop2.isOWLObjectProperty()
&& trObjectProperty(prop1.asOWLObjectProperty(), OboFormatTag.TAG_INVERSE_OF.getTag(),
getIdentifier(prop2), ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLObjectPropertyDomainAxiom ax) {
OWLObjectPropertyExpression propEx = ax.getProperty();
if (propEx.isAnonymous()) {
error(ax, true);
return;
}
OWLObjectProperty prop = propEx.asOWLObjectProperty();
OWLClassExpression domain = ax.getDomain();
if (domain.isBottomEntity() || domain.isTopEntity()) {
// at least get the type def frame
getTypedefFrame(prop);
// now throw the error
error("domains using top or bottom entities are not translatable to OBO.", ax, false);
return;
}
String range = getIdentifier(domain);
if (range != null) {
if (trObjectProperty(prop, OboFormatTag.TAG_DOMAIN.getTag(), range, ax.annotations())) {
return;
} else {
error("trObjectProperty failed for " + prop, ax, true);
}
} else {
error("no range translatable for " + ax, false);
}
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLAsymmetricObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_ASYMMETRIC.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLSymmetricObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_SYMMETRIC.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLFunctionalObjectPropertyAxiom ax) {
OWLObjectPropertyExpression prop = ax.getProperty();
if (prop.isOWLObjectProperty() && trObjectProperty(prop.asOWLObjectProperty(),
OboFormatTag.TAG_IS_FUNCTIONAL.getTag(), Boolean.TRUE, ax.annotations())) {
return;
}
error(ax, true);
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLObjectPropertyRangeAxiom ax) {
OWLClassExpression owlRange = ax.getRange();
OWLObjectPropertyExpression propEx = ax.getProperty();
if (propEx.isAnonymous()) {
error(ax, false);
}
OWLObjectProperty prop = propEx.asOWLObjectProperty();
if (owlRange.isBottomEntity() || owlRange.isTopEntity()) {
// at least create the property frame
getTypedefFrame(prop);
// error message
error("ranges using top or bottom entities are not translatable to OBO.", ax, false);
return;
}
String range = getIdentifier(owlRange);
if (range != null
&& trObjectProperty(prop, OboFormatTag.TAG_RANGE.getTag(), range, ax.annotations())) {
return;
}
error(ax, false);
}
protected void tr(OWLSubObjectPropertyOfAxiom ax) {
OWLObjectPropertyExpression sup = ax.getSuperProperty();
OWLObjectPropertyExpression sub = ax.getSubProperty();
if (sub.isBottomEntity() || sub.isTopEntity() || sup.isBottomEntity()
|| sup.isTopEntity()) {
error("SubProperties using Top or Bottom entites are not supported in OBO.", false);
return;
}
if (sub.isOWLObjectProperty() && sup.isOWLObjectProperty()) {
String supId = checkNotNull(getIdentifier(sup));
if (supId.startsWith("owl:")) {
return;
}
Frame f = getTypedefFrame((OWLObjectProperty) sub);
Clause clause = new Clause(OboFormatTag.TAG_IS_A, supId);
f.addClause(clause);
addQualifiers(clause, ax.annotations());
} else {
error(ax, true);
}
}
protected void tr(OWLSubAnnotationPropertyOfAxiom ax) {
OWLAnnotationProperty sup = ax.getSuperProperty();
OWLAnnotationProperty sub = ax.getSubProperty();
if (sub.isBottomEntity() || sub.isTopEntity() || sup.isBottomEntity()
|| sup.isTopEntity()) {
error("SubAnnotationProperties using Top or Bottom entites are not supported in OBO.",
false);
return;
}
String tagObject = owlObjectToTag(sup);
if (OboFormatTag.TAG_SYNONYMTYPEDEF.getTag().equals(tagObject)) {
String name = "";
String scope = null;
for (OWLAnnotationAssertionAxiom axiom : asList(
getOWLOntology().annotationAssertionAxioms(sub.getIRI()))) {
String tg = owlObjectToTag(axiom.getProperty());
if (OboFormatTag.TAG_NAME.getTag().equals(tg)) {
name = ((OWLLiteral) axiom.getValue()).getLiteral();
} else if (OboFormatTag.TAG_SCOPE.getTag().equals(tg)) {
scope = owlObjectToTag(axiom.getValue());
}
}
Frame hf = checkNotNull(getObodoc().getHeaderFrame());
assert hf != null;
Clause clause = new Clause(OboFormatTag.TAG_SYNONYMTYPEDEF);
clause.addValue(getIdentifier(sub));
clause.addValue(name);
if (scope != null) {
clause.addValue(scope);
}
addQualifiers(clause, ax.annotations());
if (!hf.getClauses().contains(clause)) {
hf.addClause(clause);
} else {
LOG.error("duplicate clause: {} in header", clause);
}
return;
} else if (OboFormatTag.TAG_SUBSETDEF.getTag().equals(tagObject)) {
String comment = "";
for (OWLAnnotationAssertionAxiom axiom : asList(
getOWLOntology().annotationAssertionAxioms(sub.getIRI()))) {
String tg = owlObjectToTag(axiom.getProperty());
if (OboFormatTag.TAG_COMMENT.getTag().equals(tg)) {
comment = ((OWLLiteral) axiom.getValue()).getLiteral();
break;
}
}
Frame hf = checkNotNull(getObodoc().getHeaderFrame());
assert hf != null;
Clause clause = new Clause(OboFormatTag.TAG_SUBSETDEF);
clause.addValue(getIdentifier(sub));
clause.addValue(comment);
if (!hf.getClauses().contains(clause)) {
hf.addClause(clause);
} else {
LOG.error("duplicate clause: {} in header", clause);
}
addQualifiers(clause, ax.annotations());
return;
}
if (sub.isOWLObjectProperty() && sup.isOWLObjectProperty()) {
String supId = getIdentifier(sup);
if (supId == null || supId.startsWith("owl:")) {
return;
}
Frame f = getTypedefFrame(sub);
Clause clause = new Clause(OboFormatTag.TAG_IS_A, supId);
f.addClause(clause);
addQualifiers(clause, ax.annotations());
} else {
error(ax, true);
}
}
/**
* Translate axiom.
*
* @param ax annotation assertion axiom
* @param frame the frame
*/
protected void tr(OWLAnnotationAssertionAxiom ax, Frame frame) {
boolean success = tr(ax.getProperty(), ax.getValue(), asList(ax.annotations()), frame);
if (!success) {
untranslatableAxioms.add(ax);
}
}
/**
* Translate annotation.
*
* @param prop the prop
* @param annVal annotation value
* @param qualifiers the qualifiers
* @param frame the frame
* @return true, if successful
*/
protected boolean tr(OWLAnnotationProperty prop, OWLAnnotationValue annVal,
Collection qualifiers, Frame frame) {
String tagString = owlObjectToTag(prop);
OboFormatTag tag = null;
if (tagString != null) {
tag = OBOFormatConstants.getTag(tagString);
}
if (tag == null) {
if (annVal.isIRI() && FrameType.TERM.equals(frame.getType()) && isMetadataTag(prop)) {
String propId = this.getIdentifier(prop);
if (propId != null) {
Clause clause = new Clause(OboFormatTag.TAG_RELATIONSHIP);
clause.addValue(propId);
clause.addValue(getIdentifier((IRI) annVal));
addQualifiers(clause, qualifiers.stream());
frame.addClause(clause);
return true;
}
}
// annotation property does not correspond to a mapping to a tag in
// the OBO syntax -
// use the property_value tag
return trGenericPropertyValue(prop, annVal, qualifiers.stream(), frame);
}
Object value = getValue(annVal, tagString);
String valueString = value.toString().trim();
if (!valueString.isEmpty()) {
if (tag == OboFormatTag.TAG_ID) {
if (!value.equals(frame.getId())) {
warn("Conflicting id definitions: 1) " + frame.getId() + " 2)" + valueString);
return false;
}
return true;
}
Clause clause = new Clause(tag);
if (tag == OboFormatTag.TAG_DATE) {
try {
clause.addValue(OBOFormatConstants.headerDateFormat().parseObject(valueString));
} catch (@SuppressWarnings("unused") ParseException e) {
error("Could not parse date string: " + value, true);
return false;
}
} else {
clause.addValue(value);
}
Set unprocessedQualifiers = new HashSet<>(qualifiers);
if (tag == OboFormatTag.TAG_DEF) {
for (OWLAnnotation aan : qualifiers) {
String propId = owlObjectToTag(aan.getProperty());
if ("xref".equals(propId)) {
OWLAnnotationValue v = aan.getValue();
String xrefValue;
if (v.isIRI()) {
xrefValue = v.toString();
} else {
xrefValue = ((OWLLiteral) v).getLiteral();
}
Xref xref = new Xref(xrefValue);
clause.addXref(xref);
unprocessedQualifiers.remove(aan);
}
}
} else if (tag == OboFormatTag.TAG_XREF) {
Xref xref = new Xref(valueString);
for (OWLAnnotation annotation : qualifiers) {
if (df.getRDFSLabel().equals(annotation.getProperty())) {
OWLAnnotationValue owlAnnotationValue = annotation.getValue();
if (owlAnnotationValue instanceof OWLLiteral) {
unprocessedQualifiers.remove(annotation);
String xrefAnnotation = ((OWLLiteral) owlAnnotationValue).getLiteral();
xrefAnnotation = xrefAnnotation.trim();
if (!xrefAnnotation.isEmpty()) {
xref.setAnnotation(xrefAnnotation);
}
}
}
}
clause.setValue(xref);
} else if (tag == OboFormatTag.TAG_EXACT || tag == OboFormatTag.TAG_NARROW
|| tag == OboFormatTag.TAG_BROAD || tag == OboFormatTag.TAG_RELATED) {
handleSynonym(qualifiers, tag.getTag(), clause, unprocessedQualifiers);
} else if (tag == OboFormatTag.TAG_SYNONYM) {
// This should never happen.
// All synonyms need to be qualified with a type.
String synonymType = null;
handleSynonym(qualifiers, synonymType, clause, unprocessedQualifiers);
}
addQualifiers(clause, unprocessedQualifiers.stream());
// before adding the clause check for redundant clauses
boolean redundant = false;
for (Clause frameClause : frame.getClauses()) {
if (clause.equals(frameClause)) {
redundant = handleDuplicateClause(frame, frameClause);
}
}
if (!redundant) {
frame.addClause(clause);
}
} else {
return false;
}
return true;
}
private boolean isMetadataTag(OWLAnnotationProperty p) {
final IRI metadataTagIRI = IRI.create(Obo2OWLConstants.OIOVOCAB_IRI_PREFIX,
OboFormatTag.TAG_IS_METADATA_TAG.getTag());
return owlOntology.annotationAssertionAxioms(p.getIRI())
.anyMatch(ax -> metadataTagIRI.equals(ax.getProperty().getIRI()));
}
/**
* Handle synonym.
*
* @param qualifiers the qualifiers
* @param scope the scope
* @param clause the clause
* @param unprocessedQualifiers the unprocessed qualifiers
*/
protected void handleSynonym(Collection qualifiers, @Nullable String scope,
Clause clause, Set unprocessedQualifiers) {
clause.setTag(OboFormatTag.TAG_SYNONYM.getTag());
String type = null;
clause.setXrefs(new ArrayList());
for (OWLAnnotation aan : qualifiers) {
String propId = owlObjectToTag(aan.getProperty());
if (OboFormatTag.TAG_XREF.getTag().equals(propId)) {
OWLAnnotationValue v = aan.getValue();
String xrefValue;
if (v.isIRI()) {
xrefValue = v.toString();
} else {
xrefValue = ((OWLLiteral) v).getLiteral();
}
Xref xref = new Xref(xrefValue);
clause.addXref(xref);
unprocessedQualifiers.remove(aan);
} else if (OboFormatTag.TAG_HAS_SYNONYM_TYPE.getTag().equals(propId)) {
type = getIdentifier(aan.getValue());
unprocessedQualifiers.remove(aan);
}
}
if (scope != null) {
clause.addValue(scope);
if (type != null) {
clause.addValue(type);
}
}
}
/**
* Handle a duplicate clause in a frame during translation.
*
* @param frame the frame
* @param clause the clause
* @return true if the clause is to be marked as redundant and will not be added to the
*/
protected boolean handleDuplicateClause(Frame frame, Clause clause) {
// default is to report it via the logger and remove it.
LOG.error("Duplicate clause '{}' generated in frame: {}", clause, frame.getId());
return true;
}
/**
* Translate generic property value.
*
* @param prop the prop
* @param annVal annotation value
* @param qualifiers the qualifiers
* @param frame the frame
* @return true, if successful
*/
protected boolean trGenericPropertyValue(OWLAnnotationProperty prop, OWLAnnotationValue annVal,
Stream qualifiers, Frame frame) {
// no built-in obo tag for this: use the generic property_value tag
Clause clause = new Clause(OboFormatTag.TAG_PROPERTY_VALUE.getTag());
String propId = getIdentifier(prop);
addQualifiers(clause, qualifiers);
if (!shorthand(propId)) {
clause.addValue(propId);
if (annVal instanceof OWLLiteral) {
OWLLiteral owlLiteral = (OWLLiteral) annVal;
clause.addValue(owlLiteral.getLiteral());
OWLDatatype datatype = owlLiteral.getDatatype();
IRI dataTypeIri = datatype.getIRI();
if (!OWL2Datatype.isBuiltIn(dataTypeIri)) {
error("Untranslatable axiom due to unknown data type: " + annVal, true);
return false;
}
if (Namespaces.XSD.inNamespace(dataTypeIri)) {
clause.addValue(dataTypeIri.prefixedBy("xsd:"));
} else if (dataTypeIri.isPlainLiteral()) {
clause.addValue(OWL2Datatype.XSD_STRING.getPrefixedName());
} else {
clause.addValue(dataTypeIri.toString());
}
} else if (annVal.isIRI()) {
clause.addValue(getIdentifier((IRI) annVal));
}
frame.addClause(clause);
}
return true;
}
/**
* Gets the value.
*
* @param annVal annotation value
* @param tag the tag
* @return the value
*/
protected Object getValue(OWLAnnotationValue annVal, @Nullable String tag) {
Object value = annVal.toString();
if (annVal instanceof OWLLiteral) {
OWLLiteral l = (OWLLiteral) annVal;
value = l.isBoolean() ? Boolean.valueOf(l.parseBoolean()) : l.getLiteral();
} else if (annVal.isIRI()) {
value = getIdentifier((IRI) annVal);
}
if (OboFormatTag.TAG_EXPAND_EXPRESSION_TO.getTag().equals(tag)) {
String s = value.toString();
Matcher matcher = absoluteURLPattern.matcher(s);
while (matcher.find()) {
String m = matcher.group();
m = m.replace("<", "");
m = m.replace(">", "");
int i = m.lastIndexOf('/');
m = m.substring(i + 1);
s = s.replace(matcher.group(), m);
}
value = s;
}
return value;
}
/**
* Translate ontology.
*
* @param ontology the ontology
*/
protected void tr(OWLOntology ontology) {
Frame f = new Frame(FrameType.HEADER);
getObodoc().setHeaderFrame(f);
ontology.directImportsDocuments().forEach(iri -> f
.addClause(new Clause(OboFormatTag.TAG_IMPORT.getTag()).withValue(iri.toString())));
String id = getOntologyId(ontology);
Clause c = new Clause(OboFormatTag.TAG_ONTOLOGY.getTag());
c.setValue(id);
f.addClause(c);
String vid = getDataVersion(ontology);
if (vid != null) {
Clause c2 = new Clause(OboFormatTag.TAG_DATA_VERSION.getTag());
c2.setValue(vid);
f.addClause(c2);
}
List collect = asList(ontology.annotations());
for (OWLAnnotation ann : collect) {
OWLAnnotationProperty property = ann.getProperty();
String tagString = owlObjectToTag(property);
if (OboFormatTag.TAG_COMMENT.getTag().equals(tagString)) {
property = df.getOWLAnnotationProperty(
OWLAPIObo2Owl.trTagToIRI(OboFormatTag.TAG_REMARK.getTag()));
}
tr(property, ann.getValue(), asList(ann.annotations()), f);
}
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLEquivalentClassesAxiom ax) {
/*
* Assumption: the underlying data structure is a set The order is not guaranteed to be
* preserved.
*/
// handle expression list with size other than two elements as error
if (ax.classExpressions().count() != 2) {
error(ax, false);
return;
}
Iterator it = ax.classExpressions().iterator();
OWLClassExpression ce1 = it.next();
OWLClassExpression ce2 = it.next();
if (ce1.isBottomEntity() || ce1.isTopEntity() || ce2.isBottomEntity()
|| ce2.isTopEntity()) {
error(
"Equivalent classes axioms using Top or Bottom entities are not supported in OBO.",
ax, false);
return;
}
if (!(ce1 instanceof OWLClass)) {
// check whether ce2 is the actual OWLEntity
if (ce2 instanceof OWLClass) {
// three way exchange
OWLClassExpression temp = ce2;
ce2 = ce1;
ce1 = temp;
} else {
// this might happen for some GCI axioms, which are not
// expressible in OBO
error("GCI axioms are not expressible in OBO.", ax, false);
return;
}
}
Frame f = getTermFrame(ce1.asOWLClass());
boolean isUntranslateable = false;
List equivalenceAxiomClauses = new ArrayList<>();
String cls2 = getIdentifier(ce2);
if (cls2 != null) {
Clause c = new Clause(OboFormatTag.TAG_EQUIVALENT_TO.getTag());
c.setValue(cls2);
f.addClause(c);
addQualifiers(c, ax.annotations());
} else if (ce2 instanceof OWLObjectUnionOf) {
List extends OWLClassExpression> list2 = ((OWLObjectUnionOf) ce2).getOperandsAsList();
for (OWLClassExpression oce : list2) {
String id = getIdentifier(oce);
if (id == null) {
error(ax, true);
return;
}
Clause c = new Clause(OboFormatTag.TAG_UNION_OF.getTag());
c.setValue(id);
equivalenceAxiomClauses.add(c);
addQualifiers(c, ax.annotations());
}
} else if (ce2 instanceof OWLObjectIntersectionOf) {
List extends OWLClassExpression> list2 =
((OWLObjectIntersectionOf) ce2).getOperandsAsList();
for (OWLClassExpression ce : list2) {
String r = null;
cls2 = getIdentifier(ce);
Integer exact = null; // cardinality
Integer min = null; // minCardinality
Integer max = null; // maxCardinality
Boolean allSome = null; // all_some
Boolean allOnly = null; // all_only
if (ce instanceof OWLObjectSomeValuesFrom) {
OWLObjectSomeValuesFrom ristriction = (OWLObjectSomeValuesFrom) ce;
r = getIdentifier(ristriction.getProperty());
cls2 = getIdentifier(ristriction.getFiller());
} else if (ce instanceof OWLObjectExactCardinality) {
OWLObjectExactCardinality card = (OWLObjectExactCardinality) ce;
r = getIdentifier(card.getProperty());
cls2 = getIdentifier(card.getFiller());
exact = Integer.valueOf(card.getCardinality());
} else if (ce instanceof OWLObjectMinCardinality) {
OWLObjectMinCardinality card = (OWLObjectMinCardinality) ce;
r = getIdentifier(card.getProperty());
cls2 = getIdentifier(card.getFiller());
min = Integer.valueOf(card.getCardinality());
} else if (ce instanceof OWLObjectMaxCardinality) {
OWLObjectMaxCardinality card = (OWLObjectMaxCardinality) ce;
r = getIdentifier(card.getProperty());
cls2 = getIdentifier(card.getFiller());
max = Integer.valueOf(card.getCardinality());
} else if (ce instanceof OWLObjectAllValuesFrom) {
OWLObjectAllValuesFrom all = (OWLObjectAllValuesFrom) ce;
OWLClassExpression filler = all.getFiller();
if (filler instanceof OWLClass) {
r = getIdentifier(all.getProperty());
cls2 = getIdentifier(filler);
allOnly = Boolean.TRUE;
} else if (filler instanceof OWLObjectComplementOf) {
OWLObjectComplementOf restriction = (OWLObjectComplementOf) filler;
r = getIdentifier(all.getProperty());
cls2 = getIdentifier(restriction.getOperand());
exact = Integer.valueOf(0);
}
} else if (ce instanceof OWLObjectIntersectionOf) {
// either a min-max or a some-all combination
Set operands =
asSet(((OWLObjectIntersectionOf) ce).operands(), OWLClassExpression.class);
if (operands.size() == 2) {
for (OWLClassExpression operand : operands) {
if (operand instanceof OWLObjectMinCardinality) {
OWLObjectMinCardinality card = (OWLObjectMinCardinality) operand;
r = getIdentifier(card.getProperty());
cls2 = getIdentifier(card.getFiller());
min = Integer.valueOf(card.getCardinality());
} else if (operand instanceof OWLObjectMaxCardinality) {
OWLObjectMaxCardinality card = (OWLObjectMaxCardinality) operand;
r = getIdentifier(card.getProperty());
cls2 = getIdentifier(card.getFiller());
max = Integer.valueOf(card.getCardinality());
} else if (operand instanceof OWLObjectAllValuesFrom) {
OWLObjectAllValuesFrom all = (OWLObjectAllValuesFrom) operand;
r = getIdentifier(all.getProperty());
cls2 = getIdentifier(all.getFiller());
allOnly = Boolean.TRUE;
} else if (operand instanceof OWLObjectSomeValuesFrom) {
OWLObjectSomeValuesFrom all = (OWLObjectSomeValuesFrom) operand;
r = getIdentifier(all.getProperty());
cls2 = getIdentifier(all.getFiller());
allSome = Boolean.TRUE;
}
}
}
}
if (cls2 != null) {
Clause c = new Clause(OboFormatTag.TAG_INTERSECTION_OF.getTag());
if (r != null) {
c.addValue(r);
}
c.addValue(cls2);
equivalenceAxiomClauses.add(c);
if (exact != null) {
String string = exact.toString();
c.addQualifierValue(new QualifierValue("cardinality", string));
}
if (min != null) {
String string = min.toString();
c.addQualifierValue(new QualifierValue(MIN_CARDINALITY, string));
}
if (max != null) {
String string = max.toString();
c.addQualifierValue(new QualifierValue(MAX_CARDINALITY, string));
}
if (allSome != null) {
String string = allSome.toString();
c.addQualifierValue(new QualifierValue("all_some", string));
}
if (allOnly != null) {
String string = allOnly.toString();
c.addQualifierValue(new QualifierValue("all_only", string));
}
addQualifiers(c, ax.annotations());
} else if (!f.getClauses(OboFormatTag.TAG_INTERSECTION_OF).isEmpty()) {
error(
"The axiom is not translated (maximimum one IntersectionOf EquivalenceAxiom)",
ax, false);
} else {
isUntranslateable = true;
error(ax, false);
}
}
} else {
isUntranslateable = true;
error(ax, false);
}
// Only add clauses if the *entire* equivalence axiom can be translated
if (!isUntranslateable) {
equivalenceAxiomClauses.forEach(f::addClause);
}
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLDisjointClassesAxiom ax) {
// use set, the OWL-API does not provide an order
if (ax.classExpressions().count() != 2) {
error("Expected two classes in a disjoin classes axiom.", ax, false);
}
Iterator it = ax.classExpressions().iterator();
OWLClassExpression ce1 = it.next();
OWLClassExpression ce2 = it.next();
if (ce1.isBottomEntity() || ce1.isTopEntity() || ce2.isBottomEntity()
|| ce2.isTopEntity()) {
error("Disjoint classes axiom using Top or Bottom entities are not supported.", ax,
false);
}
String cls2 = getIdentifier(ce2);
if (cls2 == null) {
error(ax, true);
return;
}
if (ce1.isAnonymous()) {
error(ax, false);
return;
}
OWLClass cls1 = ce1.asOWLClass();
Frame f = getTermFrame(cls1);
Clause c = new Clause(OboFormatTag.TAG_DISJOINT_FROM.getTag());
c.setValue(cls2);
f.addClause(c);
addQualifiers(c, ax.annotations());
}
/**
* Translate axiom.
*
* @param axiom the axiom
*/
protected void tr(OWLDeclarationAxiom axiom) {
OWLEntity entity = axiom.getEntity();
if (entity.isBottomEntity() || entity.isTopEntity()) {
return;
}
List set =
asList(owlOntology.annotationAssertionAxioms(entity.getIRI()));
if (set.isEmpty()) {
return;
}
boolean isClass = entity.isOWLClass();
boolean isObjectProperty = entity.isOWLObjectProperty();
// check whether the entity is an alt_id
Optional altIdOptional = checkForOboAltId(set);
if (altIdOptional.isPresent()) {
// the entity will not be translated
// instead create the appropriate alt_id in the replaced_by frame
String currentId = getIdentifier(entity.getIRI());
addAltId(altIdOptional.get().replacedBy, currentId, isClass, isObjectProperty);
// add unrelated annotations to untranslatableAxioms axioms
untranslatableAxioms.addAll(altIdOptional.get().unrelated);
return;
}
// translate
Frame f = null;
if (isClass) {
f = getTermFrame(entity.asOWLClass());
} else if (isObjectProperty) {
f = getTypedefFrame(entity.asOWLObjectProperty());
} else if (entity.isOWLAnnotationProperty()) {
for (OWLAnnotationAssertionAxiom ax : set) {
OWLAnnotationProperty prop = ax.getProperty();
String tag = owlObjectToTag(prop);
if (OboFormatTag.TAG_IS_METADATA_TAG.getTag().equals(tag)) {
f = getTypedefFrame(entity);
break;
}
}
}
if (f != null) {
Frame f1 = f;
set.forEach(a -> tr(a, f1));
add(f);
}
}
private void addAltId(String replacedBy, String altId, boolean isClass, boolean isProperty) {
Frame replacedByFrame = null;
if (isClass) {
replacedByFrame = getTermFrame(replacedBy);
} else if (isProperty) {
replacedByFrame = getTypedefFrame(replacedBy);
}
if (replacedByFrame != null) {
boolean addClause = true;
// check existing alt_ids to avoid duplicate clauses
Collection existing = replacedByFrame.getClauses(OboFormatTag.TAG_ALT_ID);
for (Clause clause : existing) {
if (altId.equals(clause.getValue(String.class))) {
addClause = false;
}
}
if (addClause) {
replacedByFrame.addClause(new Clause(OboFormatTag.TAG_ALT_ID, altId));
}
}
}
/**
* Gets the identifier.
*
* @param obj the object
* @return the identifier
*/
@Nullable
public String getIdentifier(OWLObject obj) {
try {
return getIdentifierFromObject(obj, getOWLOntology());
} catch (UntranslatableAxiomException e) {
error(e.getMessage(), true);
}
return null;
}
/**
* @return true if untranslatable axioms should not be logged
*/
public boolean isMuteUntranslatableAxioms() {
return muteUntranslatableAxioms;
}
/**
* @param muteUntranslatableAxioms true disables logging
*/
public void setMuteUntranslatableAxioms(boolean muteUntranslatableAxioms) {
this.muteUntranslatableAxioms = muteUntranslatableAxioms;
}
/**
* Gets the term frame.
*
* @param entity the entity
* @return the term frame
*/
protected Frame getTermFrame(OWLClass entity) {
String id = getIdentifier(entity.getIRI());
return getTermFrame(id);
}
private Frame getTermFrame(String id) {
Frame f = getObodoc().getTermFrame(id);
if (f == null) {
f = new Frame(FrameType.TERM);
f.setId(id);
f.addClause(new Clause(OboFormatTag.TAG_ID, id));
add(f);
}
return f;
}
/**
* Gets the typedef frame.
*
* @param entity the entity
* @return the typedef frame
*/
protected Frame getTypedefFrame(OWLEntity entity) {
String id = getIdentifier(entity);
return getTypedefFrame(checkNotNull(id));
}
private Frame getTypedefFrame(String id) {
Frame f = getObodoc().getTypedefFrame(id);
if (f == null) {
f = new Frame(FrameType.TYPEDEF);
f.setId(id);
f.addClause(new Clause(OboFormatTag.TAG_ID, id));
add(f);
}
return f;
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLClassAssertionAxiom ax) {
OWLObject cls = ax.getClassExpression();
if (!(cls instanceof OWLClass)) {
return;
}
String clsIRI = ((OWLClass) cls).getIRI().toString();
Frame f = checkNotNull(getObodoc().getHeaderFrame());
assert f != null;
if (IRI_CLASS_SYNONYMTYPEDEF.equals(clsIRI)) {
Clause c = new Clause(OboFormatTag.TAG_SYNONYMTYPEDEF.getTag());
OWLNamedIndividual indv = (OWLNamedIndividual) ax.getIndividual();
String indvId = checkNotNull(getIdentifier(indv));
// TODO: full specify this in the spec document.
// we may want to allow full IDs for subsets in future.
// here we would have a convention that an unprefixed
// subsetdef/synonymtypedef
// gets placed in a temp ID space, and only this id space is
// stripped
indvId = indvId.replaceFirst(".*:", "");
c.addValue(indvId);
c.addValue(indvId);
String nameValue = "";
String scopeValue = null;
Optional a =
getAnnotationObjects(indv, getOWLOntology(), df.getRDFSLabel()).findFirst();
if (a.isPresent()) {
nameValue = '"' + a.get().getValue().asLiteral().get().getLiteral() + '"';
}
a = getAnnotationObjects(indv, getOWLOntology())
.filter(ann -> !ann.getProperty().equals(df.getRDFSLabel())).findFirst();
if (a.isPresent()) {
scopeValue = a.get().getValue().asLiteral().get().getLiteral();
}
c.addValue(nameValue);
if (scopeValue != null && !scopeValue.isEmpty()) {
c.addValue(scopeValue);
}
f.addClause(c);
} else if (IRI_CLASS_SUBSETDEF.equals(clsIRI)) {
Clause c = new Clause(OboFormatTag.TAG_SUBSETDEF.getTag());
OWLNamedIndividual indv = (OWLNamedIndividual) ax.getIndividual();
String indvId = checkNotNull(getIdentifier(indv));
// TODO: full specify this in the spec document.
// we may want to allow full IDs for subsets in future.
// here we would have a convention that an unprefixed
// subsetdef/synonymtypedef
// gets placed in a temp ID space, and only this id space is
// stripped
indvId = indvId.replaceFirst(".*:", "");
c.addValue(indvId);
String nameValue = "";
Optional value =
getAnnotationObjects(indv, getOWLOntology(), df.getRDFSLabel()).findFirst();
if (value.isPresent()) {
nameValue = '"' + value.get().getValue().asLiteral().get().getLiteral() + '"';
}
c.addValue(nameValue);
f.addClause(c);
} else {
// TODO: individual
}
}
/**
* Translate axiom.
*
* @param ax the ax
*/
protected void tr(OWLSubClassOfAxiom ax) {
OWLClassExpression sub = ax.getSubClass();
OWLClassExpression sup = ax.getSuperClass();
if (sub.isOWLNothing() || sub.isTopEntity() || sup.isTopEntity() || sup.isOWLNothing()) {
error(TOP_BOTTOM_NONTRANSLATEABLE, ax, false);
return;
}
// 5.2.2
Set qvs = new HashSet<>();
if (sub instanceof OWLObjectIntersectionOf) {
Set xs =
asSet(((OWLObjectIntersectionOf) sub).operands(), OWLClassExpression.class);
// obo-format is limited to very restricted GCIs - the LHS of the
// axiom
// must correspond to ObjectIntersectionOf(cls
// ObjectSomeValuesFrom(p filler))
if (xs.size() == 2) {
OWLClass c = null;
OWLObjectProperty p = null;
OWLClass filler = null;
for (OWLClassExpression x : xs) {
if (x instanceof OWLClass) {
c = (OWLClass) x;
}
if (x instanceof OWLObjectSomeValuesFrom) {
OWLObjectSomeValuesFrom r = (OWLObjectSomeValuesFrom) x;
if (r.getProperty().isOWLObjectProperty()
&& r.getFiller() instanceof OWLClass) {
p = r.getProperty().asOWLObjectProperty();
filler = (OWLClass) r.getFiller();
}
}
}
if (c != null && p != null && filler != null) {
sub = c;
qvs.add(new QualifierValue("gci_relation", checkNotNull(getIdentifier(p))));
qvs.add(new QualifierValue("gci_filler", checkNotNull(getIdentifier(filler))));
}
}
}
if (sub instanceof OWLClass) {
Frame f = getTermFrame((OWLClass) sub);
if (sup instanceof OWLClass) {
Clause c = new Clause(OboFormatTag.TAG_IS_A.getTag());
c.setValue(checkNotNull(getIdentifier(sup)));
c.setQualifierValues(qvs);
f.addClause(c);
addQualifiers(c, ax.annotations());
} else if (sup instanceof OWLObjectCardinalityRestriction) {
// OWLObjectExactCardinality
// OWLObjectMinCardinality
// OWLObjectMaxCardinality
OWLObjectCardinalityRestriction cardinality = (OWLObjectCardinalityRestriction) sup;
OWLClassExpression filler = cardinality.getFiller();
if (filler.isBottomEntity() || filler.isTopEntity()) {
error(TOP_BOTTOM_NONTRANSLATEABLE, ax, false);
return;
}
String fillerId = getIdentifier(filler);
if (fillerId == null) {
error(ax, true);
return;
}
f.addClause(
createRelationshipClauseWithCardinality(cardinality, fillerId, qvs, ax));
} else if (sup instanceof OWLQuantifiedObjectRestriction) {
// OWLObjectSomeValuesFrom
// OWLObjectAllValuesFrom
OWLQuantifiedObjectRestriction r = (OWLQuantifiedObjectRestriction) sup;
OWLClassExpression filler = r.getFiller();
if (filler.isBottomEntity() || filler.isTopEntity()) {
error(TOP_BOTTOM_NONTRANSLATEABLE, ax, false);
return;
}
String fillerId = getIdentifier(filler);
if (fillerId == null) {
error(ax, true);
return;
}
if (r instanceof OWLObjectAllValuesFrom) {
qvs.add(new QualifierValue("all_only", "true"));
}
f.addClause(createRelationshipClauseWithRestrictions(r, fillerId, qvs, ax));
} else if (sup instanceof OWLObjectIntersectionOf) {
OWLObjectIntersectionOf i = (OWLObjectIntersectionOf) sup;
List clauses = new ArrayList<>();
List extends OWLClassExpression> collect = asList(i.operands());
for (OWLClassExpression operand : collect) {
if (operand instanceof OWLObjectCardinalityRestriction) {
OWLObjectCardinalityRestriction restriction =
(OWLObjectCardinalityRestriction) operand;
OWLClassExpression filler = restriction.getFiller();
if (filler.isBottomEntity() || filler.isTopEntity()) {
error(TOP_BOTTOM_NONTRANSLATEABLE, ax, false);
return;
}
String fillerId = getIdentifier(filler);
if (fillerId == null) {
error(ax, true);
return;
}
clauses.add(createRelationshipClauseWithCardinality(restriction, fillerId,
new HashSet<>(qvs), ax));
} else if (operand instanceof OWLQuantifiedObjectRestriction) {
OWLQuantifiedObjectRestriction restriction =
(OWLQuantifiedObjectRestriction) operand;
OWLClassExpression filler = restriction.getFiller();
if (filler.isBottomEntity() || filler.isTopEntity()) {
error(TOP_BOTTOM_NONTRANSLATEABLE, ax, false);
return;
}
String fillerId = getIdentifier(filler);
if (fillerId == null) {
error(ax, true);
return;
}
clauses.add(createRelationshipClauseWithRestrictions(restriction, fillerId,
new HashSet<>(qvs), ax));
} else {
error(ax, true);
return;
}
}
if (clauses.isEmpty()) {
error(ax, true);
return;
}
clauses = normalizeRelationshipClauses(clauses);
clauses.forEach(f::addClause);
} else {
error(ax, true);
return;
}
} else {
error(ax, true);
return;
}
}
/**
* Creates the relationship clause with restrictions.
*
* @param r the r
* @param fillerId the filler id
* @param qvs the qvs
* @param ax the ax
* @return the clause
*/
protected Clause createRelationshipClauseWithRestrictions(OWLQuantifiedObjectRestriction r,
String fillerId, Set qvs, OWLSubClassOfAxiom ax) {
Clause c = new Clause(OboFormatTag.TAG_RELATIONSHIP.getTag());
c.addValue(getIdentifier(r.getProperty()));
c.addValue(fillerId);
c.setQualifierValues(qvs);
addQualifiers(c, ax.annotations());
return c;
}
/**
* Creates the relationship clause with cardinality.
*
* @param restriction the restriction
* @param fillerId the filler id
* @param qvs the qvs
* @param ax the ax
* @return the clause
*/
protected Clause createRelationshipClauseWithCardinality(
OWLObjectCardinalityRestriction restriction, String fillerId, Set qvs,
OWLSubClassOfAxiom ax) {
Clause c = new Clause(OboFormatTag.TAG_RELATIONSHIP.getTag());
c.addValue(getIdentifier(restriction.getProperty()));
c.addValue(fillerId);
c.setQualifierValues(qvs);
String q = "cardinality";
if (restriction instanceof OWLObjectMinCardinality) {
q = MIN_CARDINALITY;
} else if (restriction instanceof OWLObjectMaxCardinality) {
q = MAX_CARDINALITY;
}
c.addQualifierValue(new QualifierValue(q, Integer.toString(restriction.getCardinality())));
addQualifiers(c, ax.annotations());
return c;
}
protected void error(String message, OWLAxiom ax, boolean shouldLogComplaint) {
untranslatableAxioms.add(ax);
error(message + ax, shouldLogComplaint);
}
protected void error(OWLAxiom ax, boolean shouldLogComplaint) {
untranslatableAxioms.add(ax);
error("the axiom is not translated : " + ax, shouldLogComplaint);
}
protected void error(String message, boolean shouldLogComplaint) {
if (strictConversion) {
throw new OWLRuntimeException("The conversion is halted: " + message);
} else {
if (!muteUntranslatableAxioms && shouldLogComplaint) {
LOG.error("MASKING ERROR «{}»", message, new Exception());
}
}
}
protected void warn(String message) {
if (strictConversion) {
throw new OWLRuntimeException("The conversion is halted: " + message);
} else {
LOG.warn("MASKING ERROR «{}»", message);
}
}
/**
* Helper class: allow to return two values for the alternate id check.
*/
private static class OboAltIdCheckResult {
final String replacedBy;
final Set unrelated;
OboAltIdCheckResult(String replacedBy, Set unrelated) {
this.replacedBy = replacedBy;
this.unrelated = unrelated;
}
}
/**
* The Class UntranslatableAxiomException.
*/
public static class UntranslatableAxiomException extends Exception {
/**
* Instantiates a new untranslatable axiom exception.
*
* @param message the message
* @param cause the cause
*/
public UntranslatableAxiomException(String message, Throwable cause) {
super(message, cause);
}
/**
* Instantiates a new untranslatable axiom exception.
*
* @param message the message
*/
public UntranslatableAxiomException(String message) {
super(message);
}
}
class Translator implements OWLAxiomVisitor {
@Override
public void visit(OWLDeclarationAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLSubClassOfAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLDisjointClassesAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLEquivalentClassesAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLClassAssertionAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLEquivalentObjectPropertiesAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLSubAnnotationPropertyOfAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLSubObjectPropertyOfAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLObjectPropertyRangeAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLFunctionalObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLSymmetricObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLAsymmetricObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLObjectPropertyDomainAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLInverseFunctionalObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLInverseObjectPropertiesAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLDisjointObjectPropertiesAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLReflexiveObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLTransitiveObjectPropertyAxiom ax) {
tr(ax);
}
@Override
public void visit(OWLSubPropertyChainOfAxiom ax) {
tr(ax);
}
@Override
public void doDefault(Object o) {
if (!(o instanceof OWLAnnotationAssertionAxiom)) {
error((OWLAxiom) o, false);
}
}
}
}