Skip to content

Commit

Permalink
reification refactoring, don't merge axioms together, fixes issues wi…
Browse files Browse the repository at this point in the history
…th obo xrefs
  • Loading branch information
jamesamcl committed Dec 30, 2022
1 parent 6fdf0de commit 8d46102
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 121 deletions.
8 changes: 8 additions & 0 deletions apitester4/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@
import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.*;
import java.util.Map.Entry;

import com.google.gson.*;
Expand Down Expand Up @@ -379,16 +375,11 @@ public JsonElement deepSort(JsonElement element) {
elems[i] = deepSort(arr.get(i));
}

Arrays.sort(elems, new Comparator<JsonElement>() {

public int compare(JsonElement a, JsonElement b) {
return gson.toJson(a).compareTo(gson.toJson(b));
}
});
Arrays.sort(elems, Comparator.comparing(elem -> gson.toJson(elem)));

JsonArray res = new JsonArray();

for(int i = 0; i < arr.size(); ++ i) {
for(int i = 0; i < elems.length; ++ i) {
res.add(elems[i]);
}

Expand All @@ -398,11 +389,7 @@ public int compare(JsonElement a, JsonElement b) {

JsonObject obj = element.getAsJsonObject();

TreeSet<String> sortedKeys = new TreeSet<String>();

for(String key : obj.keySet()) {
sortedKeys.add(key);
}
TreeSet<String> sortedKeys = new TreeSet<String>(obj.keySet());

JsonObject res = new JsonObject();

Expand Down
53 changes: 38 additions & 15 deletions backend/src/main/java/uk/ac/ebi/spot/ols/model/v1/V1OboSynonym.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import uk.ac.ebi.spot.ols.service.OboDatabaseUrlService;
import uk.ac.ebi.spot.ols.service.OntologyEntity;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand All @@ -21,47 +23,68 @@ public static List<V1OboSynonym> extractFromEntity(OntologyEntity entity, OboDat

List<V1OboSynonym> synonyms =
exact.stream().map(synonym -> fromSynonymObject(synonym, "hasExactSynonym", oboDbUrls))
.flatMap(Collection::stream)
.filter(synonym -> synonym.type != null || synonym.xrefs != null)
.collect(Collectors.toList());

synonyms.addAll(
related.stream().map(synonym -> fromSynonymObject(synonym, "hasRelatedSynonym", oboDbUrls))
.flatMap(Collection::stream)
.filter(synonym -> synonym.type != null || synonym.xrefs != null)
.collect(Collectors.toList())
);

return synonyms.size() > 0 ? synonyms : null;
}

private static V1OboSynonym fromSynonymObject(Object synonymObj, String scope, OboDatabaseUrlService oboDbUrls) {
private static List<V1OboSynonym> fromSynonymObject(Object synonymObj, String scope, OboDatabaseUrlService oboDbUrls) {

if(synonymObj instanceof String) {
V1OboSynonym synonym = new V1OboSynonym();
synonym.name = (String)synonymObj;
synonym.scope = scope;
return synonym;
return List.of(synonym);
}

List<V1OboSynonym> synonyms = new ArrayList<>();

Map<String,Object> synonymMap = (Map<String,Object>) synonymObj;
V1OboSynonym synonym = new V1OboSynonym();

synonym.name = (String)synonymMap.get("value");
synonym.scope = scope;
synonym.type = (String)synonymMap.get("oboSynonymTypeName");
List<Object> axioms = (List<Object>) synonymMap.get("axioms");

Object xrefs = synonymMap.get("http://www.geneontology.org/formats/oboInOwl#hasDbXref");
if(axioms == null) {
throw new RuntimeException("axioms were null");
}

if(xrefs != null) {
if(! (xrefs instanceof List)) {
xrefs = List.of(xrefs);
}
for(Object axiomObj : axioms) {

Map<String,Object> axiom = (Map<String,Object>) axiomObj;

Object xrefs = axiom.get("http://www.geneontology.org/formats/oboInOwl#hasDbXref");

if(xrefs != null) {
if(! (xrefs instanceof List)) {
xrefs = List.of(xrefs);
}

synonym.xrefs =
((List<Object>) xrefs).stream().map(xref -> V1OboXref.fromString((String) xref, oboDbUrls))
.collect(Collectors.toList());
List<V1OboXref> xrefObjs =
((List<Object>) xrefs).stream().map(xref -> V1OboXref.fromString((String) xref, oboDbUrls))
.collect(Collectors.toList());

for(V1OboXref xrefObj : xrefObjs) {
V1OboSynonym synonym = new V1OboSynonym();

synonym.name = (String)synonymMap.get("value");
synonym.scope = scope;
synonym.type = (String)axiom.get("oboSynonymTypeName");
synonym.xrefs = List.of(xrefObj);

synonyms.add(synonym);
}
}
}

return synonym;
return synonyms;
}

}
Expand Down
41 changes: 29 additions & 12 deletions dataload/json2neo/src/main/java/OntologyScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ public static Result scanOntology(JsonReader reader) throws IOException {

private static void visitValue(String predicate, Object value, Set<String> outProps, Set<String> outEdgeProps) {

if(predicate.equals("iriToLabels")) {
return;
}

if(value instanceof String) {

} else if(value instanceof List) {
Expand All @@ -140,14 +144,20 @@ private static void visitValue(String predicate, Object value, Set<String> outPr

} else if(value instanceof Map) {

// either reification, or a bnode (anon. class or restriction)
// could be a typed literal, a relatedTo object, reification, or a bnode

Map<String, Object> mapValue = new TreeMap<String,Object>((Map<String, Object>) value);

if(mapValue.containsKey("value")) {
List<String> types = (List<String>) mapValue.get("type");

if(types == null) {
// bnode (anon. class)
return;
}

// either reification (an owl axiom) OR a langString
if(types.contains("literal")) {

// is this a localization?
if(mapValue.containsKey("lang")) {

String lang = (String)mapValue.get("lang");
Expand All @@ -159,27 +169,34 @@ private static void visitValue(String predicate, Object value, Set<String> outPr
if(!lang.equals("en")) {
outProps.add(lang + "+" + predicate);
}
}

} else if(types.contains("related")) {

visitValue(predicate, mapValue.get("value"), outProps, outEdgeProps);

} else {
} else if(types.contains("reification")) {

List<Object> axioms = (List<Object>) mapValue.get("axioms");

for(Object axiomObj : axioms) {

Map<String,Object> axiom = (Map<String,Object>) axiomObj;

// reification (owl:Axiom or relatedTo)

// predicates used to describe the edge itself
for(String edgePredicate : mapValue.keySet()) {
for(String edgePredicate : axiom.keySet()) {

if(edgePredicate.equals("value"))
if(edgePredicate.equals("type"))
continue;

outEdgeProps.add(edgePredicate);
}
}
}

visitValue(predicate, mapValue.get("value"), outProps, outEdgeProps);

} else {

// bnode (anon. class or restriction)

throw new RuntimeException("???");
}

}
Expand Down
28 changes: 18 additions & 10 deletions dataload/json2neo/src/main/java/OntologyWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,32 @@ public void maybeWriteEdges(String subject, String property, Object value) throw
for(Object v : values) {

if (v instanceof Map) {
// maybe axiom

Map<String, Object> mapValue = (Map<String, Object>) v;
if (mapValue.containsKey("value") && !mapValue.containsKey("lang")) {
// axiom
Object axiomValue = mapValue.get("value");
assert (axiomValue instanceof String);
List<String> types = (List<String>) mapValue.get("type");

if(types != null && types.contains("reification")) {

// reification
Object reifiedValue = mapValue.get("value");
assert (reifiedValue instanceof String);

List<Map<String,Object>> axioms = (List<Map<String,Object>>) mapValue.get("axioms");
assert(axioms != null);

// is the value the URI of something that exists in the ontology?
if (ontologyScannerResult.uriToTypes.containsKey(axiomValue)) {
printEdge(ontologyId, subject, property, axiomValue, mapValue);
if (ontologyScannerResult.uriToTypes.containsKey(reifiedValue)) {
// create one edge for each axiom
for(Map<String,Object> axiom : axioms) {
printEdge(ontologyId, subject, property, reifiedValue, axiom);
}
}
}
} else if (v instanceof String) {

// is the value the URI of something that exists in the ontology?
if (ontologyScannerResult.uriToTypes.containsKey(v)) {
printEdge(ontologyId, subject, property, v, new TreeMap<>());
printEdge(ontologyId, subject, property, v, Map.of());
}

} else {
Expand Down Expand Up @@ -209,8 +218,7 @@ private void printEdge(String ontologyId, String aUri, String predicate, Object
// In the hacky approach below, we just make multiple edges: in the above example,
// one edge would point to the Class and another would point to the Individual.
//
// TODO: We should instead look up "predicate" and find out what the semantics
// of the property are.
// TODO: fix
//
Set<OntologyScanner.NodeType> aTypes = ontologyScannerResult.uriToTypes.get(aUri);
Set<OntologyScanner.NodeType> bTypes = ontologyScannerResult.uriToTypes.get(bUri);
Expand Down
37 changes: 27 additions & 10 deletions dataload/json2solr/src/main/java/JSON2Solr.java
Original file line number Diff line number Diff line change
Expand Up @@ -284,19 +284,19 @@ static private void flattenProperties(Map<String,Object> properties, Map<String,

// There are 4 cases when the object can be a Map {} instead of a literal.
//
// (1) It's a value with type information { datatype: ..., value: ... }
// (1) It's a literal with type information { datatype: ..., value: ... }
//
// (2) It's a class expression
//
// (3) It's a localization, which is a specific case of (1) where a
// language and localized value are provided.
//
// (4) It's reification { type: Axiom|Restriction, ...., value: ... }
// (4) It's reification { type: reification|related, ...., value: ... }
//
// In the case of (1), we discard the datatype and keep the value
//
// In the case of (2), we don't store anything in solr fields. Class
// expressions should // already have been evaluated into separate "related"
// expressions should already have been evaluated into separate "related"
// fields by the RelatedAnnotator in owl2json.
//
// In the case of (3), we create a Solr document for each language (see
Expand All @@ -310,8 +310,17 @@ static private void flattenProperties(Map<String,Object> properties, Map<String,
public static Object discardMetadata(Object obj, String lang) {

if (obj instanceof Map) {

Map<String, Object> dict = (Map<String, Object>) obj;
if (dict.containsKey("value")) {
List<String> types = (List<String>) dict.get("type");

if(types == null) {
// (2) class expression
return null;
}

if(types.contains("literal")) {

if(dict.containsKey("lang")) {
// (3) localisation
String valLang = (String)dict.get("lang");
Expand All @@ -320,15 +329,23 @@ public static Object discardMetadata(Object obj, String lang) {
return null;
}
}
// (1) datatyped or (4) reification

// (1) typed literal
return discardMetadata(dict.get("value"), lang);
} else {
// (2) class expression
return null;

} else if(types.contains("reification") || types.contains("related")) {

// (4) reification
return discardMetadata(dict.get("value"), lang);

} else {
throw new RuntimeException("???");
}
}

return obj;
} else {

return obj;
}
}

// Gather all of the lang: attributes from an object and all of its descendants
Expand Down
Loading

0 comments on commit 8d46102

Please sign in to comment.