Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.obolibrary.obo2owl.OboInOwlCardinalityTools Maven / Gradle / Ivy
package org.obolibrary.obo2owl;
import static org.semanticweb.owlapi.model.parameters.Imports.INCLUDED;
import java.util.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.obolibrary.oboformat.model.Frame;
import org.obolibrary.oboformat.parser.OBOFormatConstants.OboFormatTag;
import org.semanticweb.owlapi.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Tools for checking and fixing cardinality constrains for OBO ontologies in
* OWL.
*/
public final class OboInOwlCardinalityTools {
protected static final Logger LOGGER = LoggerFactory.getLogger(OboInOwlCardinalityTools.class);
private OboInOwlCardinalityTools() {}
/**
* Functor for resolving conflicts for an annotation property and its
* cardinality constraint.
*/
public interface AnnotationCardinalityConfictHandler {
/**
* Resolve a conflict for a given annotation property and axioms. The
* result is either a list of resolved axioms or an exception thrown by
* this method.
*
* @param entity
* entity
* @param property
* property
* @param axioms
* axioms
* @return list of resolved axioms
* @throws AnnotationCardinalityException
* AnnotationCardinalityException
*/
@Nonnull
List handleConflict(@Nonnull OWLEntity entity,
@Nonnull OWLAnnotationProperty property, @Nonnull Collection axioms)
throws AnnotationCardinalityException;
/**
* Resolve a conflict for a given annotation property and ontology
* annotations. The result is either a list of resolved annotations or
* an exception thrown by this method.
*
* @param property
* property
* @param ontologyAnnotations
* ontologyAnnotations
* @return list of resolved annotations
* @throws AnnotationCardinalityException
* AnnotationCardinalityException
*/
@Nonnull
List handleConflict(@Nonnull OWLAnnotationProperty property,
@Nonnull Collection ontologyAnnotations) throws AnnotationCardinalityException;
}
/**
* Functor for reporting conflicts for an annotation property and its
* cardinality constraint.
*/
public interface AnnotationCardinalityReporter {
/**
* Report a conflict for a given annotation property and axioms.
*
* @param entity
* entity
* @param property
* property
* @param axioms
* axioms
*/
void reportConflict(@Nonnull OWLEntity entity, @Nonnull OWLAnnotationProperty property,
@Nonnull Collection axioms);
/**
* Report a conflict for a given annotation property and ontology
* annotations.
*
* @param property
* property
* @param ontologyAnnotations
* ontologyAnnotations
*/
void reportConflict(@Nonnull OWLAnnotationProperty property,
@Nonnull Collection ontologyAnnotations);
}
/**
* Exception indication a non-resolvable conflict for an annotation property
* and its cardinality constraint.
*/
public static class AnnotationCardinalityException extends Exception {
// generated
private static final long serialVersionUID = 40000L;
/**
* Create a new Exception.
*
* @param message
* message
* @param cause
* cause
*/
public AnnotationCardinalityException(@Nonnull String message, @Nonnull Throwable cause) {
super(message, cause);
}
/**
* Create a new Exception.
*
* @param message
* message
*/
public AnnotationCardinalityException(@Nonnull String message) {
super(message);
}
}
/**
* Check the annotations for cardinality violations. Try to resolve
* conflicts with the given handler.
*
* @param ontology
* the target ontology
* @param reporter
* reporter
* @param handler
* the conflict handler
* @throws AnnotationCardinalityException
* throws exception in case a conflict cannot be resolved by the
* handler
* @see Frame#check() for implementation in OBO
*/
public static void checkAnnotationCardinality(@Nonnull OWLOntology ontology,
@Nullable AnnotationCardinalityReporter reporter, @Nullable AnnotationCardinalityConfictHandler handler)
throws AnnotationCardinalityException {
OWLOntologyManager manager = ontology.getOWLOntologyManager();
OWLDataFactory factory = manager.getOWLDataFactory();
Set headerProperties = getProperties(factory, OboFormatTag.TAG_ONTOLOGY,
OboFormatTag.TAG_FORMAT_VERSION, OboFormatTag.TAG_DATE, OboFormatTag.TAG_DEFAULT_NAMESPACE,
OboFormatTag.TAG_SAVED_BY, OboFormatTag.TAG_AUTO_GENERATED_BY);
checkOntologyAnnotations(headerProperties, ontology, reporter, handler, manager);
Set properties = getProperties(factory, OboFormatTag.TAG_IS_ANONYMOUS,
OboFormatTag.TAG_NAME, OboFormatTag.TAG_NAMESPACE, OboFormatTag.TAG_DEF, OboFormatTag.TAG_COMMENT,
OboFormatTag.TAG_DOMAIN, OboFormatTag.TAG_RANGE, OboFormatTag.TAG_IS_ANTI_SYMMETRIC,
OboFormatTag.TAG_IS_CYCLIC, OboFormatTag.TAG_IS_REFLEXIVE, OboFormatTag.TAG_IS_SYMMETRIC,
OboFormatTag.TAG_IS_TRANSITIVE, OboFormatTag.TAG_IS_FUNCTIONAL, OboFormatTag.TAG_IS_INVERSE_FUNCTIONAL,
OboFormatTag.TAG_IS_OBSELETE, OboFormatTag.TAG_CREATED_BY, OboFormatTag.TAG_CREATION_DATE);
for (OWLClass owlClass : ontology.getClassesInSignature(INCLUDED)) {
assert owlClass != null;
checkOwlEntity(owlClass, properties, ontology, reporter, handler, manager);
}
for (OWLObjectProperty owlProperty : ontology.getObjectPropertiesInSignature(INCLUDED)) {
assert owlProperty != null;
checkOwlEntity(owlProperty, properties, ontology, reporter, handler, manager);
}
}
@Nonnull
private static Set getProperties(@Nonnull OWLDataFactory factory,
@Nonnull OboFormatTag... tags) {
Set set = new HashSet<>();
for (OboFormatTag tag : tags) {
IRI iri = OWLAPIObo2Owl.trTagToIRI(tag.getTag());
OWLAnnotationProperty property = factory.getOWLAnnotationProperty(iri);
set.add(property);
}
return set;
}
private static void checkOntologyAnnotations(@Nonnull Set properties,
@Nonnull OWLOntology ontology, @Nullable AnnotationCardinalityReporter reporter,
@Nullable AnnotationCardinalityConfictHandler handler, @Nonnull OWLOntologyManager manager)
throws AnnotationCardinalityException {
Set annotations = ontology.getAnnotations();
Map> groupedAnnotations = new HashMap<>();
for (OWLAnnotation annotation : annotations) {
OWLAnnotationProperty current = annotation.getProperty();
if (properties.contains(current)) {
Set set = groupedAnnotations.get(current);
if (set == null) {
groupedAnnotations.put(current, Collections.singleton(annotation));
} else if (set.size() == 1) {
set = new HashSet<>(set);
set.add(annotation);
groupedAnnotations.put(current, set);
} else {
set.add(annotation);
}
}
}
// check cardinality constraint
for (OWLAnnotationProperty property : groupedAnnotations.keySet()) {
assert property != null;
Set group = groupedAnnotations.get(property);
if (group.size() > 1) {
if (reporter != null) {
// report conflict
reporter.reportConflict(property, group);
}
if (handler != null) {
// handle conflict
// if conflict is not resolvable, throws exception
List changed = handler.handleConflict(property, group);
for (OWLAnnotation annotation : group) {
assert annotation != null;
manager.applyChange(new RemoveOntologyAnnotation(ontology, annotation));
}
for (OWLAnnotation annotation : changed) {
assert annotation != null;
manager.applyChange(new AddOntologyAnnotation(ontology, annotation));
}
}
}
}
}
private static void checkOwlEntity(@Nonnull OWLEntity owlClass, @Nonnull Set properties,
@Nonnull OWLOntology ontology, @Nullable AnnotationCardinalityReporter reporter,
@Nullable AnnotationCardinalityConfictHandler handler, @Nonnull OWLOntologyManager manager)
throws AnnotationCardinalityException {
Set axioms = ontology.getAnnotationAssertionAxioms(owlClass.getIRI());
Map> groupedAxioms = new HashMap<>();
for (OWLAnnotationAssertionAxiom axiom : axioms) {
OWLAnnotationProperty current = axiom.getProperty();
if (properties.contains(current)) {
Set set = groupedAxioms.get(current);
if (set == null) {
groupedAxioms.put(current, Collections.singleton(axiom));
} else if (set.size() == 1) {
set = new HashSet<>(set);
set.add(axiom);
groupedAxioms.put(current, set);
} else {
set.add(axiom);
}
}
}
// check cardinality constraint
for (OWLAnnotationProperty property : groupedAxioms.keySet()) {
assert property != null;
Set group = groupedAxioms.get(property);
if (group.size() > 1) {
if (reporter != null) {
// report conflict
reporter.reportConflict(owlClass, property, group);
}
if (handler != null) {
// handle conflict
// if conflict is not resolvable, throws exception
List changed = handler.handleConflict(owlClass, property, group);
for (OWLAnnotationAssertionAxiom axiom : group) {
assert axiom != null;
manager.removeAxiom(ontology, axiom);
}
for (OWLAnnotationAssertionAxiom axiom : changed) {
assert axiom != null;
manager.addAxiom(ontology, axiom);
}
}
}
}
}
/**
* Check the annotations for cardinality violations. Try to resolve
* conflicts with the default handler.
*
* @param ontology
* the target ontology
* @throws AnnotationCardinalityException
* throws exception in case a conflict cannot be resolved by the
* handler
* @see #DEFAULT_HANDLER
*/
public static void checkAnnotationCardinality(@Nonnull OWLOntology ontology) throws AnnotationCardinalityException {
checkAnnotationCardinality(ontology, null, DEFAULT_HANDLER);
}
/**
* Check the annotations for cardinality violations. Only report violations
* via the given reporter
*
* @param ontology
* the target ontology
* @param reporter
* used to report violations
*/
public static void checkAnnotationCardinality(@Nonnull OWLOntology ontology,
AnnotationCardinalityReporter reporter) {
try {
checkAnnotationCardinality(ontology, reporter, null);
} catch (AnnotationCardinalityException e) {
// this will not happen as no handler is registered
LOGGER.error("Cardinality exception during report: This isn't supposed to happen.", e);
}
}
/** default handler */
@Nonnull
public static final AnnotationCardinalityConfictHandler DEFAULT_HANDLER = new AnnotationCardinalityConfictHandler() {
@Nonnull
@Override
public List handleConflict(@Nonnull OWLEntity entity,
@Nonnull OWLAnnotationProperty property, @Nonnull Collection axioms)
throws AnnotationCardinalityException {
if (axioms.size() > 1) {
String tag = OWLAPIOwl2Obo.owlObjectToTag(property);
if (tag == null) {
tag = property.getIRI().toString();
}
// take the first one in the collection
// (may be random)
LOGGER.info("Fixing multiple {} tags for entity: {}", tag, entity.getIRI());
return listOfFirst(axioms);
}
throw new AnnotationCardinalityException("Could not resolve conflict for property: " + property);
}
@Nonnull
@Override
public List handleConflict(@Nonnull OWLAnnotationProperty property,
@Nonnull Collection ontologyAnnotations) throws AnnotationCardinalityException {
if (ontologyAnnotations.size() > 1) {
String tag = OWLAPIOwl2Obo.owlObjectToTag(property);
if (tag == null) {
tag = property.getIRI().toString();
}
// take the first one in the collection
// (may be random)
LOGGER.info("Fixing multiple ontolgy annotations with, tag: {}", tag);
return listOfFirst(ontologyAnnotations);
}
throw new AnnotationCardinalityException("Could not resolve conflict for property: " + property);
}
};
@Nonnull
static List listOfFirst(Collection t) {
return Collections.singletonList(t.iterator().next());
}
}