org.obolibrary.obo2owl.OWLAPIOwl2Obo Maven / Gradle / Ivy
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);
}
}
}
}