From 0c053f5e037116787041bc042ae7fe6950f5e0be Mon Sep 17 00:00:00 2001 From: Becky Jackson Date: Mon, 10 Oct 2022 15:25:20 -0700 Subject: [PATCH 1/2] Add support for domain and range --- docs/export.md | 2 + .../org/obolibrary/robot/ExportOperation.java | 214 +++++++----------- 2 files changed, 84 insertions(+), 132 deletions(-) diff --git a/docs/export.md b/docs/export.md index e0566ea7f..94a1d0a8a 100644 --- a/docs/export.md +++ b/docs/export.md @@ -61,6 +61,8 @@ Various `--header` types are supported: * `Equivalent Property`: creates an "Equivalent Properties" column based on `owl:equivalentProperty` * `Disjoint With`: creates a "Disjoint With" column based on `owl:disjointWith` * `Type`: creates an "Instance Of" column based on `rdf:type` for named individuals or the OWL EntityType for all others (e.g., `Class`) + * `Domain`: creates a "Domain" column based on `rdfs:domain` + * `Range`: creates a "Range" column based on `rdfs:range` * **Property CURIES**: you can always reference a property by the short form of the unique identifier (e.g. `oboInOwl:hasDbXref`). Any prefix used [must be defined](global#prefixes). * **Property Labels**: as long as a property label is defined in the input ontology, you can reference a property by label (e.g. `database_cross_reference`). This label will also be used as the column header. diff --git a/robot-core/src/main/java/org/obolibrary/robot/ExportOperation.java b/robot-core/src/main/java/org/obolibrary/robot/ExportOperation.java index 43fa01e57..aed7c468f 100644 --- a/robot-core/src/main/java/org/obolibrary/robot/ExportOperation.java +++ b/robot-core/src/main/java/org/obolibrary/robot/ExportOperation.java @@ -344,72 +344,6 @@ public static void saveTable(Table table, String exportPath, Map } } - /** - * Given a label function, a collection of class expressions, and a boolean indicating to include - * anonymous classes, return the classes as a string. Multiple values are separated by the pipe - * character. Use labels when possible. Return null if no values exist. - * - * @param rt RendererType to use to render Manchester - * @param provider ShortFormProvider to resolve entities - * @param classes Set of class expressions to convert to string - * @param includeNamed if true, include named classes in output - * @param includeAnonymous if true, include anonymous classes in output - * @return String of class expressions or null - */ - private static List classExpressionsToString( - RendererType rt, - ShortFormProvider provider, - Collection classes, - boolean includeNamed, - boolean includeAnonymous) { - List strings = new ArrayList<>(); - for (OWLClassExpression expr : classes) { - if (expr.isAnonymous() && includeAnonymous) { - // Get a Manchester string using labels - String manString = OntologyHelper.renderManchester(expr, provider, rt); - strings.add(manString); - } else if (!expr.isAnonymous() && includeNamed) { - OWLClass sc = expr.asOWLClass(); - strings.add(OntologyHelper.renderManchester(sc, provider, rt)); - } - } - return strings; - } - - /** - * Return a Cell containing class expressions. - * - * @param exprs Collection of OWLClassExpressions to render in property cell - * @param column Column for this Cell - * @param displayRendererType RendererType for display value - * @param sortRendererType RendererType for sort value - * @param provider ShortFormProvider to resolve entities - * @param includeNamed if true, include named classes in output - * @param includeAnonymous if true, include anonymous classes in output - * @return Cell for this Column containing class expressions - */ - private static Cell getClassCell( - Collection exprs, - Column column, - RendererType displayRendererType, - RendererType sortRendererType, - ShortFormProvider provider, - boolean includeNamed, - boolean includeAnonymous) { - List displays = - classExpressionsToString( - displayRendererType, provider, exprs, includeNamed, includeAnonymous); - List sorts; - if (sortRendererType != null) { - sorts = - classExpressionsToString( - sortRendererType, provider, exprs, includeNamed, includeAnonymous); - } else { - sorts = displays; - } - return (new Cell(column, displays, sorts)); - } - /** * Given an OWLOntology and a map of options for which types of entities to included return a set * of entities in the ontology. @@ -505,19 +439,19 @@ private static Cell getEntityTypeCell(EntityType type, Column column) { } /** - * Return a Cell containing property expressions. + * Return a Cell containing rendered OWL objects (e.g., class expressions) * - * @param exprs Collection of OWLPropertyExpressions to render in property cell + * @param objects Collection of OWLObjects to render in cell * @param column Column for this Cell * @param displayRendererType RendererType for display value * @param sortRendererType RendererType for sort value * @param provider ShortFormProvider to resolve entities * @param includeNamed if true, include named classes in output * @param includeAnonymous if true, include anonymous classes in output - * @return Cell for this Column containing property expressions + * @return Cell for this Column containing class expressions */ - private static Cell getPropertyCell( - Collection exprs, + private static Cell getObjectCell( + Collection objects, Column column, RendererType displayRendererType, RendererType sortRendererType, @@ -525,17 +459,15 @@ private static Cell getPropertyCell( boolean includeNamed, boolean includeAnonymous) { List displays = - propertyExpressionsToString( - displayRendererType, provider, exprs, includeNamed, includeAnonymous); + owlObjectsToString(displayRendererType, provider, objects, includeNamed, includeAnonymous); List sorts; if (sortRendererType != null) { sorts = - propertyExpressionsToString( - sortRendererType, provider, exprs, includeNamed, includeAnonymous); + owlObjectsToString(sortRendererType, provider, objects, includeNamed, includeAnonymous); } else { sorts = displays; } - return new Cell(column, displays, sorts); + return (new Cell(column, displays, sorts)); } /** @@ -985,7 +917,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection subclasses = EntitySearcher.getSubClasses(entity.asOWLClass(), ontology); row.add( - getClassCell( + getObjectCell( subclasses, col, displayRendererType, @@ -1091,7 +1023,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t // owl:Thing should not be included in the subclass of column supers.remove(dataFactory.getOWLThing()); row.add( - getClassCell( + getObjectCell( supers, col, displayRendererType, @@ -1108,7 +1040,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection supers = EntitySearcher.getSuperProperties(entity.asOWLAnnotationProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( supers, col, displayRendererType, @@ -1121,7 +1053,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection supers = EntitySearcher.getSuperProperties(entity.asOWLDataProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( supers, col, displayRendererType, @@ -1134,7 +1066,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection supers = EntitySearcher.getSuperProperties(entity.asOWLObjectProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( supers, col, displayRendererType, @@ -1150,7 +1082,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection eqs = EntitySearcher.getEquivalentClasses(entity.asOWLClass(), ontology); row.add( - getClassCell( + getObjectCell( eqs, col, displayRendererType, @@ -1166,7 +1098,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection eqs = EntitySearcher.getEquivalentProperties(entity.asOWLAnnotationProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( eqs, col, displayRendererType, @@ -1179,7 +1111,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection eqs = EntitySearcher.getEquivalentProperties(entity.asOWLDataProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( eqs, col, displayRendererType, @@ -1192,7 +1124,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection eqs = EntitySearcher.getEquivalentProperties(entity.asOWLObjectProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( eqs, col, displayRendererType, @@ -1208,7 +1140,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection disjoints = EntitySearcher.getDisjointClasses(entity.asOWLClass(), ontology); row.add( - getClassCell( + getObjectCell( disjoints, col, displayRendererType, @@ -1221,7 +1153,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection disjoints = EntitySearcher.getDisjointProperties(entity.asOWLAnnotationProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( disjoints, col, displayRendererType, @@ -1234,7 +1166,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection disjoints = EntitySearcher.getDisjointProperties(entity.asOWLDataProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( disjoints, col, displayRendererType, @@ -1247,7 +1179,7 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t Collection disjoints = EntitySearcher.getDisjointProperties(entity.asOWLObjectProperty(), ontology); row.add( - getPropertyCell( + getObjectCell( disjoints, col, displayRendererType, @@ -1258,13 +1190,13 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t } break; case "http://www.w3.org/1999/02/22-rdf-syntax-ns#type": - // Class Assertioons + // Class Assertions if (entity.isOWLNamedIndividual()) { Collection types = EntitySearcher.getTypes(entity.asOWLNamedIndividual(), ontology); if (!types.isEmpty()) { row.add( - getClassCell( + getObjectCell( types, col, displayRendererType, @@ -1282,6 +1214,48 @@ private static Row getRow(OWLOntology ontology, Table table, OWLEntity entity) t row.add(getEntityTypeCell(entity.getEntityType(), col)); } break; + case "http://www.w3.org/2000/01/rdf-schema#domain": + Collection domains = null; + if (entity.isOWLObjectProperty()) { + domains = EntitySearcher.getDomains(entity.asOWLObjectProperty(), ontology); + } else if (entity.isOWLDataProperty()) { + domains = EntitySearcher.getDomains(entity.asOWLDataProperty(), ontology); + } else if (entity.isOWLAnnotationProperty()) { + domains = EntitySearcher.getDomains(entity.asOWLAnnotationProperty(), ontology); + } + if (domains != null) { + row.add( + getObjectCell( + domains, + col, + displayRendererType, + sortRendererType, + provider, + includeNamed, + includeAnonymous)); + } + break; + case "http://www.w3.org/2000/01/rdf-schema#range": + Collection ranges = null; + if (entity.isOWLObjectProperty()) { + ranges = EntitySearcher.getRanges(entity.asOWLObjectProperty(), ontology); + } else if (entity.isOWLDataProperty()) { + ranges = EntitySearcher.getRanges(entity.asOWLDataProperty(), ontology); + } else if (entity.isOWLAnnotationProperty()) { + ranges = EntitySearcher.getRanges(entity.asOWLAnnotationProperty(), ontology); + } + if (ranges != null) { + row.add( + getObjectCell( + ranges, + col, + displayRendererType, + sortRendererType, + provider, + includeNamed, + includeAnonymous)); + } + break; default: throw new Exception(String.format(invalidColumnError, colName)); } @@ -1314,58 +1288,30 @@ private static List getSynonyms(OWLOntology ontology, OWLEntity entity) } /** - * Given a label function, a collection of property expressions, and a boolean indicating to - * include anonymous expressions, return the parent properties as a string. Multiple values are - * separated by the pipe character. Use labels when possible. Return null if no values exist. + * Given a label function, a collection of OWL objects, and a boolean indicating to include + * anonymous objects, return the objects as a string. Multiple values are separated by the pipe + * character. Use labels when possible. Return null if no values exist. * * @param rt RendererType to use to render Manchester * @param provider ShortFormProvider to resolve entities - * @param props Set of property expressions to convert to string + * @param objects Set of OWL objects to convert to string * @param includeNamed if true, include named classes in output * @param includeAnonymous if true, include anonymous classes in output - * @return String of property expressions or null + * @return String of class expressions or null */ - private static List propertyExpressionsToString( + private static List owlObjectsToString( RendererType rt, ShortFormProvider provider, - Collection props, + Collection objects, boolean includeNamed, boolean includeAnonymous) { - // Try to convert to object property expressions - Collection opes = - props.stream() - .map(p -> (OWLPropertyExpression) p) - .filter(OWLPropertyExpression::isObjectPropertyExpression) - .map(p -> (OWLObjectPropertyExpression) p) - .collect(Collectors.toList()); - // Try to convert to data property expressions - Collection dpes = - props.stream() - .map(p -> (OWLPropertyExpression) p) - .filter(OWLPropertyExpression::isDataPropertyExpression) - .map(p -> (OWLDataPropertyExpression) p) - .collect(Collectors.toList()); - List strings = new ArrayList<>(); - // Only one of the above collections will have entries - // Maybe process object property expressions - for (OWLObjectPropertyExpression expr : opes) { - if (expr.isAnonymous() && includeAnonymous) { - String manString = OntologyHelper.renderManchester(expr, provider, rt); - strings.add(manString); - } else if (!expr.isAnonymous() && includeNamed) { - OWLObjectProperty op = expr.asOWLObjectProperty(); - strings.add(OntologyHelper.renderManchester(op, provider, rt)); - } - } - // Maybe process data property expressions - for (OWLDataPropertyExpression expr : dpes) { - if (expr.isAnonymous() && includeAnonymous) { - String manString = OntologyHelper.renderManchester(expr, provider, rt); - strings.add(manString); - } else if (!expr.isAnonymous() && includeNamed) { - OWLDataProperty dp = expr.asOWLDataProperty(); - strings.add(OntologyHelper.renderManchester(dp, provider, rt)); + for (OWLObject o : objects) { + if (o.isAnonymous() && includeAnonymous) { + // Get a Manchester string using labels + strings.add(OntologyHelper.renderManchester(o, provider, rt)); + } else if (!o.isAnonymous() && includeNamed) { + strings.add(OntologyHelper.renderManchester(o, provider, rt)); } } return strings; @@ -1429,6 +1375,8 @@ private static void updateLabelMap(Map labelMap) { labelMap.put( "EquivalentProperties", IRI.create("http://www.w3.org/2002/07/owl#equivalentProperty")); labelMap.put("DisjointWith", IRI.create("http://www.w3.org/2002/07/owl#disjointWith")); + labelMap.put("Domain", IRI.create("http://www.w3.org/2000/01/rdf-schema#domain")); + labelMap.put("Range", IRI.create("http://www.w3.org/2000/01/rdf-schema#range")); // Camel case labelMap.put("subClassOf", IRI.create("http://www.w3.org/2000/01/rdf-schema#subClassOf")); @@ -1464,5 +1412,7 @@ private static void updateLabelMap(Map labelMap) { labelMap.put( "equivalentproperties", IRI.create("http://www.w3.org/2002/07/owl#equivalentProperty")); labelMap.put("disjointwith", IRI.create("http://www.w3.org/2002/07/owl#disjointWith")); + labelMap.put("domain", IRI.create("http://www.w3.org/2000/01/rdf-schema#domain")); + labelMap.put("range", IRI.create("http://www.w3.org/2000/01/rdf-schema#range")); } } From b0021aeae50f9255ddb296733ea34e28061aae2a Mon Sep 17 00:00:00 2001 From: Becky Jackson Date: Mon, 10 Oct 2022 15:28:28 -0700 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85a8a9bd5..696c866f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Checking for empty strings in addition to missing ones in `missing_label.rq` [#1017] +- Add "domain" and "range" support to export [#1061] ### Fixed - Fix missing labels in [`diff`] output. [#1026] @@ -323,6 +324,7 @@ First official release of ROBOT! [`template`]: http://robot.obolibrary.org/template [`validate`]: http://robot.obolibrary.org/validate +[#1061]: https://github.com/ontodev/robot/issues/1061 [#1009]: https://github.com/ontodev/robot/issues/1009 [#979]: https://github.com/ontodev/robot/pull/979 [#978]: https://github.com/ontodev/robot/pull/978