Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/remove.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ Terms can also be selected from the set based on their annotations. This can be
- `CURIE=<IRI>`, e.g. `rdfs:seeAlso=<http://purl.obolibrary.org/obo/EX_123>`
- `CURIE='literal'`, e.g. `rdfs:label='example label'`
- `CURIE='literal'^^datatype`, e.g. `rdfs:label='example label'^^xsd:string`
- `CURIE='literal'@language`, e.g. `rdfs:label='example label'@en`
- `CURIE=^^datatype`, e.g. `rdfs:label=^^xsd:string`
- `CURIE=@language`, e.g. `rdfs:label=@en`
- `CURIE=~'regex pattern'`, e.g. `rdfs:label=~'example.*'`

It is also possible to select terms based on parts of their IRI. You may include an IRI pattern using one or more wildcard characters (`*` and/or `?`) enclosed in angle brackets. This MUST be enclosed in quotes to work on the command line.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public RemoveCommand() {
o.addOption("T", "term-file", true, "load terms from a file");
o.addOption("s", "select", true, "select a set of terms based on relations");
o.addOption("a", "axioms", true, "filter only for given axiom types");
o.addOption(null, "include-term", true, "include term");
o.addOption("r", "trim", true, "if true, remove axioms containing any selected object");
o.addOption(
"S",
Expand Down Expand Up @@ -186,6 +187,14 @@ public CommandState execute(CommandState state, String[] args) throws Exception
// Use the select statements to get a set of objects to remove
Set<OWLObject> relatedObjects =
RelatedObjectsHelper.selectGroups(ontology, ioHelper, objects, selectGroups);
// Add all the include terms
if (line.hasOption("include-term") || line.hasOption("include-terms")) {
Set<IRI> includeIRIs =
CommandLineHelper.getTerms(ioHelper, line, "include-term", "include-terms");
Set<OWLObject> includeObjects =
new HashSet<>(OntologyHelper.getEntities(ontology, includeIRIs));
relatedObjects.addAll(includeObjects);
}

// Use these two options to determine which axioms to remove
boolean trim = CommandLineHelper.getBooleanValue(line, "trim", true);
Expand All @@ -199,8 +208,6 @@ public CommandState execute(CommandState state, String[] args) throws Exception
// Handle gaps
boolean preserveStructure = CommandLineHelper.getBooleanValue(line, "preserve-structure", true);
if (preserveStructure) {
// Since we are preserving the structure between the objects that were NOT removed, we need to
// get the complement of the removed object set and build relationships between those objects.
relatedObjects = RelatedObjectsHelper.select(ontology, ioHelper, objects, "complement");
manager.addAxioms(ontology, RelatedObjectsHelper.spanGaps(copy, relatedObjects));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import org.semanticweb.owlapi.search.EntitySearcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.ac.manchester.cs.owl.owlapi.OWLLiteralImplPlain;
import uk.ac.manchester.cs.owl.owlapi.OWLLiteralImplString;

/**
* Convenience methods to get related entities for a set of IRIs. Allowed relation options are: -
Expand Down Expand Up @@ -834,18 +832,30 @@ public static Set<OWLAxiom> spanGaps(OWLOntology ontology, Set<OWLObject> object
protected static Set<OWLAnnotation> getAnnotations(
OWLOntology ontology, IOHelper ioHelper, String annotation) throws Exception {
OWLDataFactory dataFactory = OWLManager.getOWLDataFactory();

// Create an IRI from the CURIE
String propertyID = annotation.split("=")[0];
IRI propertyIRI = ioHelper.createIRI(propertyID);
if (propertyIRI == null) {
throw new IllegalArgumentException(
String.format(invalidIRIError, "annotation property", propertyID));
}

// Get the annotation property and string representation of value
OWLAnnotationProperty annotationProperty = dataFactory.getOWLAnnotationProperty(propertyIRI);
String value = annotation.split("=")[1];
// Based on the value, determine the type of annotation
if (value.contains("<") && value.contains(">")) {
if (value.startsWith("@")) {
String lang = value.substring(1);
return getLangAnnotations(ontology, annotationProperty, lang);

} else if (value.startsWith("^^")) {
String datatypeString = value.substring(2).replace("<", "").replace(">", "");
IRI datatypeIRI = ioHelper.createIRI(datatypeString);
OWLDatatype datatype = dataFactory.getOWLDatatype(datatypeIRI);
return getTypedAnnotations(ontology, annotationProperty, datatype);

} else if (value.contains("<") && value.contains(">") && !value.contains("^^")) {
// Return an IRI annotation
String valueID = value.substring(1, value.length() - 1);
IRI valueIRI = ioHelper.createIRI(valueID);
Expand All @@ -854,24 +864,75 @@ protected static Set<OWLAnnotation> getAnnotations(
String.format(invalidIRIError, "annotation value (IRI)", valueID));
}
return Sets.newHashSet(dataFactory.getOWLAnnotation(annotationProperty, valueIRI));

} else if (value.contains("~'")) {
// Return a set of annotations in the ontology that match a regex pattern
return getPatternAnnotations(ontology, annotationProperty, value);

} else if (value.contains("'")) {
// Return a literal (string, boolean, double, integer, float) annotation
return Sets.newHashSet(
getLiteralAnnotation(ioHelper, dataFactory, annotationProperty, value));

} else {
// Return an IRI annotation based on a CURIE
IRI valueIRI = ioHelper.createIRI(value);
if (valueIRI == null) {
throw new IllegalArgumentException(
String.format(invalidIRIError, "annotation value (CURIE)", value));
}

return Sets.newHashSet(dataFactory.getOWLAnnotation(annotationProperty, valueIRI));
}
}

private static Set<OWLAnnotation> getTypedAnnotations(
OWLOntology ontology, OWLAnnotationProperty property, OWLDatatype datatype) {
Set<OWLAnnotation> annotations = new HashSet<>();
for (OWLAxiom axiom : ontology.getAxioms()) {
if (axiom instanceof OWLAnnotationAssertionAxiom) {
OWLAnnotationAssertionAxiom annAxiom = (OWLAnnotationAssertionAxiom) axiom;
OWLAnnotation ann = annAxiom.getAnnotation();
OWLAnnotationProperty usedProp = ann.getProperty();
if (!usedProp.getIRI().toString().equals(property.getIRI().toString())) {
continue;
}
OWLAnnotationValue value = ann.getValue();
if (value.isLiteral()) {
OWLLiteral lit = value.asLiteral().orNull();
if (lit != null
&& lit.getDatatype().getIRI().toString().equals(datatype.getIRI().toString())) {
annotations.add(ann);
}
}
}
}
return annotations;
}

private static Set<OWLAnnotation> getLangAnnotations(
OWLOntology ontology, OWLAnnotationProperty property, String lang) {
Set<OWLAnnotation> annotations = new HashSet<>();
for (OWLAxiom axiom : ontology.getAxioms()) {
if (axiom instanceof OWLAnnotationAssertionAxiom) {
OWLAnnotationAssertionAxiom annAxiom = (OWLAnnotationAssertionAxiom) axiom;
OWLAnnotation ann = annAxiom.getAnnotation();
OWLAnnotationProperty usedProp = ann.getProperty();
if (!usedProp.getIRI().toString().equals(property.getIRI().toString())) {
continue;
}
OWLAnnotationValue value = ann.getValue();
if (value.isLiteral()) {
OWLLiteral lit = value.asLiteral().orNull();
if (lit != null && lit.hasLang(lang)) {
annotations.add(ann);
}
}
}
}
return annotations;
}

/**
* Given a set of OWLObjects, return the set of IRIs for those objects.
*
Expand Down Expand Up @@ -903,23 +964,22 @@ private static Set<OWLAnnotation> getPatternAnnotations(
Set<OWLAnnotation> annotations = new HashSet<>();
String patternString = value.split("\'")[1];
Pattern pattern = Pattern.compile(patternString);
for (OWLEntity e : OntologyHelper.getEntities(ontology)) {
for (OWLAnnotation a : EntitySearcher.getAnnotations(e, ontology)) {
if (a.getProperty().equals(annotationProperty)) {
for (OWLAxiom axiom : ontology.getAxioms()) {
if (axiom instanceof OWLAnnotationAssertionAxiom) {
OWLAnnotationAssertionAxiom annAxiom = (OWLAnnotationAssertionAxiom) axiom;
OWLAnnotation a = annAxiom.getAnnotation();
if (a.getProperty().getIRI().toString().equals(annotationProperty.getIRI().toString())) {
OWLAnnotationValue av = a.getValue();
String annotationValue;
// The annotation value ONLY expects a plain or string
try {
OWLLiteralImplPlain plain = (OWLLiteralImplPlain) av;
annotationValue = plain.getLiteral();
} catch (ClassCastException ex) {
try {
OWLLiteralImplString str = (OWLLiteralImplString) av;
annotationValue = str.getLiteral();
} catch (ClassCastException ex2) {
continue;
String annotationValue = null;
if (av.isLiteral()) {
OWLLiteral lit = av.asLiteral().orNull();
if (lit != null) {
annotationValue = lit.getLiteral();
}
}
if (annotationValue == null) {
continue;
}
Matcher matcher = pattern.matcher(annotationValue);
if (matcher.matches()) {
annotations.add(a);
Expand Down Expand Up @@ -947,12 +1007,16 @@ private static OWLAnnotation getLiteralAnnotation(
OWLAnnotationProperty annotationProperty,
String value)
throws Exception {
// ioHelper.addPrefix("xsd", "http://www.w3.org/2001/XMLSchema#");
OWLAnnotationValue annotationValue;
if (value.contains("^^")) {
Matcher datatypeMatcher = Pattern.compile("'(.*)'\\^\\^(.*)").matcher(value);
Matcher langMatcher = Pattern.compile("'(.*)'@(.*)").matcher(value);
if (datatypeMatcher.matches()) {
// A datatype is given
String content = value.split("\\^\\^")[0].replace("'", "");
String dataTypeID = value.split("\\^\\^")[1];
String content = datatypeMatcher.group(1);
String dataTypeID = datatypeMatcher.group(2);
if (dataTypeID.startsWith("<") && dataTypeID.endsWith(">")) {
dataTypeID = dataTypeID.replace("<", "").replace(">", "");
}
IRI dataTypeIRI = ioHelper.createIRI(dataTypeID);
if (dataTypeIRI == null) {
throw new IllegalArgumentException(String.format(invalidIRIError, "datatype", dataTypeID));
Expand Down Expand Up @@ -989,8 +1053,13 @@ private static OWLAnnotation getLiteralAnnotation(
} else {
annotationValue = dataFactory.getOWLLiteral(content, dt);
}
} else if (langMatcher.matches()) {
// A language is given - always a string literal
String content = langMatcher.group(1);
String lang = langMatcher.group(2);
annotationValue = dataFactory.getOWLLiteral(content, lang);
} else {
// If a datatype isn't provided, default to string literal
// If a datatype isn't provided, default to string literal with no language
annotationValue = dataFactory.getOWLLiteral(value.replace("'", ""));
}
return dataFactory.getOWLAnnotation(annotationProperty, annotationValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
package org.obolibrary.robot;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;

import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.*;

/** Tests for RelatedObjectsHelper. */
public class RelatedObjectsHelperTest extends CoreTest {

private final OWLDataFactory df = OWLManager.getOWLDataFactory();
private final OWLOntologyManager manager = OWLManager.createOWLOntologyManager();

private final OWLAnnotation annotation1 =
df.getOWLAnnotation(df.getRDFSLabel(), df.getOWLLiteral("English label", "en"));
private final OWLAnnotation annotation2 =
df.getOWLAnnotation(df.getRDFSLabel(), df.getOWLLiteral("French label", "fr"));
private final OWLAnnotation annotation3 =
df.getOWLAnnotation(
df.getRDFSComment(),
df.getOWLLiteral(
"comment 1", df.getOWLDatatype(IRI.create("http://example.com/test-datatype"))));
private final OWLAnnotation annotation4 =
df.getOWLAnnotation(
df.getRDFSComment(),
df.getOWLLiteral(
"comment 2", df.getOWLDatatype(IRI.create("http://example.com/test-datatype-2"))));

/**
* Test getting complete axioms.
Expand Down Expand Up @@ -80,4 +90,81 @@ public void testGetPartialAxioms() throws IOException {
axioms = RelatedObjectsHelper.getPartialAxioms(ontology, objects, axiomTypes);
assertEquals(2, axioms.size());
}

@Test
public void testGetAnnotationByExactLangValue() throws Exception {
IOHelper ioHelper = new IOHelper();
OWLOntology ontology = getOntology();
String select = "rdfs:label='English label'@en";
Set<OWLAnnotation> annotations =
RelatedObjectsHelper.getAnnotations(ontology, ioHelper, select);
assertEquals(1, annotations.size());
assertEquals(annotations.iterator().next(), annotation1);
}

@Test
public void testGetAnnotationByLangTag() throws Exception {
IOHelper ioHelper = new IOHelper();
OWLOntology ontology = getOntology();
String select = "rdfs:label=@en";
Set<OWLAnnotation> annotations =
RelatedObjectsHelper.getAnnotations(ontology, ioHelper, select);
assertEquals(1, annotations.size());
assertEquals(annotations.iterator().next(), annotation1);
}

@Test
public void testGetAnnotationByExactDatatypeValue() throws Exception {
IOHelper ioHelper = new IOHelper();
OWLOntology ontology = getOntology();
String select = "rdfs:comment='comment 1'^^<http://example.com/test-datatype>";
Set<OWLAnnotation> annotations =
RelatedObjectsHelper.getAnnotations(ontology, ioHelper, select);
assertEquals(1, annotations.size());
assertEquals(annotations.iterator().next(), annotation3);
}

@Test
public void testGetAnnotationByDatatype() throws Exception {
IOHelper ioHelper = new IOHelper();
OWLOntology ontology = getOntology();
String select = "rdfs:comment=^^<http://example.com/test-datatype>";
Set<OWLAnnotation> annotations =
RelatedObjectsHelper.getAnnotations(ontology, ioHelper, select);
assertEquals(1, annotations.size());
assertEquals(annotations.iterator().next(), annotation3);
}

@Test
public void testGetAnnotationByRegex() throws Exception {
IOHelper ioHelper = new IOHelper();
OWLOntology ontology = getOntology();
String select = "rdfs:label=~'^.*label$'";
Set<OWLAnnotation> annotations =
RelatedObjectsHelper.getAnnotations(ontology, ioHelper, select);
assertEquals(2, annotations.size());
assertTrue(annotations.contains(annotation1));
assertTrue(annotations.contains(annotation2));
}

/** @throws Exception */
private OWLOntology getOntology() throws Exception {
OWLOntology ontology = manager.createOntology();
OWLAnnotationAssertionAxiom ax =
df.getOWLAnnotationAssertionAxiom(IRI.create("http://example.com/test-class"), annotation1);
manager.addAxiom(ontology, ax);
ax =
df.getOWLAnnotationAssertionAxiom(
IRI.create("http://example.com/test-class-2"), annotation2);
manager.addAxiom(ontology, ax);
ax =
df.getOWLAnnotationAssertionAxiom(
IRI.create("http://example.com/test-class-3"), annotation3);
manager.addAxiom(ontology, ax);
ax =
df.getOWLAnnotationAssertionAxiom(
IRI.create("http://example.com/test-class-4"), annotation4);
manager.addAxiom(ontology, ax);
return ontology;
}
}