();
+ map.put(OboFormatTag.TAG_IS_OBSELETE.getTag(),OWLRDFVocabulary.OWL_DEPRECATED.getIRI());
+ map.put(OboFormatTag.TAG_NAME.getTag(),OWLRDFVocabulary.RDFS_LABEL.getIRI());
+ map.put(OboFormatTag.TAG_COMMENT.getTag(),OWLRDFVocabulary.RDFS_COMMENT.getIRI());
+
+ for(Obo2OWLVocabulary vac: Obo2OWLVocabulary.values()){
+ map.put(vac.getMappedTag(), vac.getIRI());
+ }
+
+ /* map.put("expand_expression_to",Obo2OWLVocabulary.IRI_IAO_0000424.getIRI());
+ map.put("expand_assertion_to",Obo2OWLVocabulary.IRI_IAO_0000425.getIRI());
+ map.put("def",Obo2OWLVocabulary.IRI_IAO_0000115.getIRI());
+ map.put("synonym",Obo2OWLVocabulary.IRI_IAO_0000118.getIRI());
+ map.put("is_anti_symmetric",Obo2OWLVocabulary.IRI_IAO_0000427.getIRI());
+ map.put("replaced_by", Obo2OWLVocabulary.IRI_IAO_0100001.getIRI());*/
+
+ return map;
+ }
+
+ /**
+ * Returns an OWLClass given an IRI
+ *
+ * the class must be declared in either the source ontology, or in a support ontology,
+ * otherwise null is returned
+ *
+ * @param iri
+ * @return {@link OWLClass}
+ */
+ public OWLClass getOWLClass(IRI iri) {
+ OWLClass c = getDataFactory().getOWLClass(iri);
+ for (OWLOntology o : getAllOntologies()) {
+ if (o.getDeclarationAxioms(c).size() > 0) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Returns the OWLObjectProperty with this IRI
+ *
+ * Must have been declared in one of the ontologies
+ *
+ * @param iri
+ * @return {@link OWLObjectProperty}
+ */
+ public OWLObjectProperty getOWLObjectProperty(String iri) {
+ return getOWLObjectProperty(IRI.create(iri));
+ }
+
+ public OWLObjectProperty getOWLObjectProperty(IRI iri) {
+ OWLObjectProperty p = getDataFactory().getOWLObjectProperty(iri);
+ for (OWLOntology o : getAllOntologies()) {
+ if (o.getDeclarationAxioms(p).size() > 0) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * fetches the rdfs:label for an OWLObject
+ *
+ * assumes zero or one rdfs:label
+ *
+ * @param c
+ * @return label
+ */
+ public String getLabel(OWLObject c) {
+ return getAnnotationValue(c, getDataFactory().getRDFSLabel());
+ }
+
+ /**
+ * fetches the value of a single-valued annotation property for an OWLObject
+ *
+ * TODO: provide a flag that determines behavior in the case of >1 value
+ *
+ * @param c
+ * @param lap
+ * @return value
+ */
+ public String getAnnotationValue(OWLObject c, OWLAnnotationProperty lap) {
+ Setanns = new HashSet();
+ if (c instanceof OWLEntity) {
+ for (OWLOntology ont : getAllOntologies()) {
+ anns.addAll(OwlHelper.getAnnotations((OWLEntity) c, lap, ont));
+ }
+ }
+ else {
+ return null;
+ }
+ for (OWLAnnotation a : anns) {
+ if (a.getValue() instanceof OWLLiteral) {
+ OWLLiteral val = (OWLLiteral) a.getValue();
+ return (String) SerializationUtils.clone(val.getLiteral()); // return first - TODO - check zero or one
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Every OWLGraphWrapper objects wraps zero or one source ontologies.
+ *
+ * @return ontology
+ */
+ public OWLOntology getSourceOntology() {
+ return sourceOntology;
+ }
+
+ public void setSourceOntology(OWLOntology sourceOntology) {
+ this.sourceOntology = sourceOntology;
+ }
+
+
+ public OWLOntologyManager getManager() {
+ return sourceOntology.getOWLOntologyManager();
+ }
+
+
+ public void addSupportOntology(OWLOntology o) {
+ this.supportOntologySet.add(o);
+ }
+ public void removeSupportOntology(OWLOntology o) {
+ this.supportOntologySet.remove(o);
+ }
+
+
+ /**
+ * in general application code need not call this - it is mostly used internally
+ *
+ * @return union of source ontology plus all supporting ontologies plus their import closures
+ */
+ public Set getAllOntologies() {
+ Set all = new HashSet(getSupportOntologySet());
+ for (OWLOntology o : getSupportOntologySet()) {
+ all.addAll(o.getImportsClosure());
+ }
+ all.add(getSourceOntology());
+ all.addAll(getSourceOntology().getImportsClosure());
+ return all;
+ }
+
+ /**
+ * all operations are over a set of ontologies - the source ontology plus
+ * any number of supporting ontologies. The supporting ontologies may be drawn
+ * from the imports closure of the source ontology, although this need not be the case.
+ *
+ * @return set of support ontologies
+ */
+ public Set getSupportOntologySet() {
+ return supportOntologySet;
+ }
+
+// @Override
+ public synchronized void close() throws IOException {
+// if (reasoner != null) {
+// reasoner.dispose();
+// reasoner = null;
+// isSynchronized = false;
+// }
+// neighborAxioms = null;
+ }
+
+
+ /**
+ * Fetch all {@link OWLClass} objects from all ontologies.
+ * This set is a copy. Changes are not reflected in the ontologies.
+ *
+ * @return set of all {@link OWLClass}
+ */
+ public Set getAllOWLClasses() {
+ Set owlClasses = new THashSet();
+ for (OWLOntology o : getAllOntologies()) {
+ owlClasses.addAll(o.getClassesInSignature());
+ }
+ return owlClasses;
+ }
+
+
+ /**
+ * Given an OBO-style ID, return the corresponding OWLClass, if it is declared - otherwise null
+ *
+ * @param id - e.g. GO:0008150
+ * @return OWLClass with id or null
+ */
+ public OWLClass getOWLClassByIdentifier(String id) {
+ return getOWLClassByIdentifier(id, false);
+ }
+
+ /**
+ *
+ * As {@link #getOWLClassByIdentifier(String)} but include pre-resolution step
+ * using altId map.
+ *
+ * Currently this additional boolean option is obo-format specific; in OBO,
+ * when a class A is merged into B, the OBO-ID of A is preserved with an hasAlternateId
+ * annotation on the IRI of B. Using this method, with isAutoResolve=true, a query for
+ * the OBO ID of A will return class B.
+ *
+ * In future, analogous options will be added to IRI-based access to classes.
+ *
+ * @param id
+ * @param isAutoResolve
+ * @return OWLClass with id or null
+ */
+ public OWLClass getOWLClassByIdentifier(String id, boolean isAutoResolve) {
+ IRI iri = getIRIByIdentifier(id, isAutoResolve);
+ if (iri != null)
+ return getOWLClass(iri);
+ return null;
+ }
+
+ public IRI getIRIByIdentifier(String id, boolean isAutoResolve) {
+ if (isAutoResolve) {
+ OWLObject obj = this.getObjectByAltId(id);
+ if (obj != null) {
+ return ((OWLNamedObject) obj).getIRI();
+ }
+ }
+
+ // special magic for finding IRIs from a non-standard identifier
+ // This is the case for relations (OWLObject properties) with a short hand
+ // or for relations with a non identifiers with-out a colon, e.g. negative_regulation
+ // we first collect all candidate matching properties in candIRISet.
+ Set candIRISet = Sets.newHashSet();
+ if (!id.contains(":")) {
+ final OWLAnnotationProperty shortHand = getDataFactory().getOWLAnnotationProperty(Obo2OWLVocabulary.IRI_OIO_shorthand.getIRI());
+ final OWLAnnotationProperty oboIdInOwl = getDataFactory().getOWLAnnotationProperty(trTagToIRI(OboFormatTag.TAG_ID.getTag()));
+ for (OWLOntology o : getAllOntologies()) {
+ for(OWLObjectProperty p : o.getObjectPropertiesInSignature()) {
+ // check for short hand or obo ID in owl
+ Set annotations = OwlHelper.getAnnotations(p, o);
+ if (annotations != null) {
+ for (OWLAnnotation owlAnnotation : annotations) {
+ OWLAnnotationProperty property = owlAnnotation.getProperty();
+ if ((shortHand != null && shortHand.equals(property))
+ || (oboIdInOwl != null && oboIdInOwl.equals(property)))
+ {
+ OWLAnnotationValue value = owlAnnotation.getValue();
+ if (value != null && value instanceof OWLLiteral) {
+ OWLLiteral literal = (OWLLiteral) value;
+ String shortHandLabel = literal.getLiteral();
+ if (id.equals(shortHandLabel)) {
+ candIRISet.add(p.getIRI());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // In the case where we find multiple candidate IRIs, we give priorities for IRIs from BFO or RO ontologies.
+ IRI returnIRI = null;
+ for (IRI iri: candIRISet) {
+ String iriStr = iri.toString();
+ if (iriStr.contains("BFO") || iriStr.contains("RO")) {
+ returnIRI = iri;
+ }
+ }
+
+ // If we were not able to find RO/BFO candidate IRIs for id
+ if (returnIRI == null) {
+ // We return it only if we have only one candidate.
+ if (candIRISet.size() == 1)
+ return new ArrayList(candIRISet).get(0);
+ // This is the unexpected case. Multiple non-RO/BPO properties are mapped to given id and it's not clear what to return.
+ else if (candIRISet.size() > 1)
+ throw new RuntimeException("Multiple candidate IRIs are found for id: " + id + ". None of them are from BFO or RO.");
+ }
+ // If we were able to find the property from RO/BFO, just return it.
+ else {
+ return returnIRI;
+ }
+
+ // otherwise use the obo2owl method
+ //Obo2Owl b = new Obo2Owl(getManager()); // re-use manager, creating a new one can be expensive as this is a highly used code path
+ //b.setObodoc(new OBODoc());
+ return oboIdToIRI(id);
+ }
+
+ public static IRI trTagToIRI(String tag){
+ IRI iri = null;
+ if (annotationPropertyMap.containsKey(tag)) {
+ iri = annotationPropertyMap.get(tag);
+ }
+ else {
+ //iri = IRI.create(Obo2OWLConstants.DEFAULT_IRI_PREFIX+"IAO_"+tag);
+ iri = IRI.create(Obo2OWLConstants.OIOVOCAB_IRI_PREFIX+tag);
+
+ }
+
+ return iri;
+
+ }
+
+ public IRI oboIdToIRI(String id) {
+ if (id.contains(" ")) {
+ LOG.error("id contains space: \""+id+"\"");
+ //throw new UnsupportedEncodingException();
+ return null;
+ }
+
+ // No conversion is required if this is already an IRI (ID-as-URI rule)
+ if (id.startsWith("http:")) { // TODO - roundtrip from other schemes
+ return IRI.create(id);
+ }
+ else if (id.startsWith("https:")) { // TODO - roundtrip from other schemes
+ return IRI.create(id);
+ }
+ else if (id.startsWith("ftp:")) { // TODO - roundtrip from other schemes
+ return IRI.create(id);
+ }
+ else if (id.startsWith("urn:")) { // TODO - roundtrip from other schemes
+ return IRI.create(id);
+ }
+
+ // TODO - treat_xrefs_as_equivalent
+ // special case rule for relation xrefs:
+ // 5.9.3. Special Rules for Relations
+ if (!id.contains(":")) {
+ String xid = translateShorthandIdToExpandedId(id);
+ if (!xid.equals(id))
+ return oboIdToIRI(xid);
+ }
+
+ String[] idParts = id.split(":", 2);
+ String db;
+ String localId;
+ if (idParts.length > 1) {
+ db = idParts[0];
+ localId = idParts[1];
+ if(localId.contains("_")){
+ db += "#_"; // NonCanonical-Prefixed-ID
+ }else
+ db += "_";
+ }
+ else if (idParts.length == 0) {
+ db = getDefaultIDSpace()+"#";
+ localId = id;
+ }
+ else { // == 1
+ // todo use owlOntology IRI
+ db = getDefaultIDSpace()+"#";
+ // if(id.contains("_"))
+ // db += "_";
+
+ localId = idParts[0]; // Unprefixed-ID
+ }
+
+
+ String uriPrefix = Obo2OWLConstants.DEFAULT_IRI_PREFIX+db;
+ if (idSpaceMap.containsKey(db)) {
+ uriPrefix = idSpaceMap.get(db);
+ }
+
+ String safeId;
+ try {
+ safeId = java.net.URLEncoder.encode(localId,"US-ASCII");
+ } catch (UnsupportedEncodingException e1) {
+ // TODO Auto-generated catch block
+ return null;
+ }
+
+ if (safeId.contains(" "))
+ safeId = safeId.replace(" ", "_");
+ IRI iri = null;
+ try {
+ iri = IRI.create(uriPrefix + safeId);
+ } catch (IllegalArgumentException e) {
+ // TODO - define new exception class for this
+ // throw new UnsupportedEncodingException();
+ return null;
+ }
+
+ return iri;
+ }
+
+ // 5.9.3. Special Rules for Relations
+ private String translateShorthandIdToExpandedId(String id) {
+ if (id.contains(":")) {
+ return id;
+ }else {
+ System.err.println("line 467 translateShorthandIdToExpandedId fail on need for obo");
+ System.exit(-1);
+ }
+ return null;
+/* Frame tdf = obodoc.getTypedefFrame(id);
+ if (tdf == null)
+ return id;
+ Collection xrefs = tdf.getTagValues(OboFormatTag.TAG_XREF, Xref.class);
+ String matchingExpandedId = null;
+ for (Xref xref : xrefs) {
+ //System.err.println("ID:"+id+" xref:"+xref);
+
+ if (xref != null) {
+ String xid = xref.getIdref();
+ //System.err.println(" ID:"+id+" xid:"+xid);
+ if (xid.equals(id))
+ continue;
+ if (matchingExpandedId == null) {
+ matchingExpandedId = xid;
+ }
+ else {
+ // RO and BFO take precedence over others
+ if ((xid.startsWith("RO") ||
+ xid.startsWith("BFO"))) {
+ matchingExpandedId = xid;
+ }
+ }
+ }
+ }
+ if (matchingExpandedId == null)
+ return id;
+ //System.err.println(" ID:"+id+" matching:"+matchingExpandedId);
+ return matchingExpandedId;
+ */
+ }
+
+ private String getDefaultIDSpace() {
+ return defaultIDSpace;
+ }
+
+ /**
+ * @param altId
+ * @return OWLObject that has matching altId, or null if not found
+ */
+ public OWLObject getObjectByAltId(String altId) {
+ Map m = getAltIdMap(false);
+ if (m.containsKey(altId))
+ return m.get(altId);
+ else
+ return null;
+ }
+
+ private Map getAltIdMap(boolean isReset) {
+ if (isReset)
+ altIdMap = null;
+ if (altIdMap == null) {
+ altIdMap = getAllOWLObjectsByAltId();
+ }
+ return altIdMap;
+ }
+
+ /**
+ * Given an OBO-style ID, return the corresponding OWLObject, if it is declared - otherwise null
+ *
+ * @param id - e.g. GO:0008150
+ * @return object with id or null
+ */
+ public OWLObject getOWLObjectByIdentifier(String id) {
+ IRI iri = getIRIByIdentifier(id);
+ if (iri != null)
+ return getOWLObject(iri);
+ return null;
+ }
+
+ /**
+ * Returns the OWLObject with this IRI
+ *
+ * Must have been declared in one of the ontologies
+ *
+ * Currently OWLObject must be one of OWLClass, OWLObjectProperty or OWLNamedIndividual
+ *
+ * If the ontology employs punning and there different entities with the same IRI, then
+ * the order of precedence is OWLClass then OWLObjectProperty then OWLNamedIndividual
+ *
+ * @param s entity IRI
+ * @return {@link OWLObject}
+ */
+ public OWLObject getOWLObject(IRI s) {
+ OWLObject o;
+ o = getOWLClass(s);
+ if (o == null) {
+ o = getOWLIndividual(s);
+ }
+ if (o == null) {
+ o = getOWLObjectProperty(s);
+ }
+ if (o == null) {
+ o = getOWLAnnotationProperty(s);
+ }
+ return o;
+ }
+
+ public OWLAnnotationProperty getOWLAnnotationProperty(IRI iri) {
+ OWLAnnotationProperty p = getDataFactory().getOWLAnnotationProperty(iri);
+ for (OWLOntology o : getAllOntologies()) {
+ if (o.getDeclarationAxioms(p).size() > 0) {
+ return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns an OWLNamedIndividual with this IRI if it has been declared
+ * in the source or support ontologies. Returns null otherwise.
+ *
+ * @param iri
+ * @return {@link OWLNamedIndividual}
+ */
+ public OWLNamedIndividual getOWLIndividual(IRI iri) {
+ OWLNamedIndividual c = getDataFactory().getOWLNamedIndividual(iri);
+ for (OWLOntology o : getAllOntologies()) {
+ for (OWLDeclarationAxiom da : o.getDeclarationAxioms(c)) {
+ if (da.getEntity() instanceof OWLNamedIndividual) {
+ return (OWLNamedIndividual) da.getEntity();
+ }
+ }
+ }
+ return null;
+ }
+
+ public OWLDataFactory getDataFactory() {
+ return getManager().getOWLDataFactory();
+ }
+
+
+ /**
+ * Given an OBO-style ID, return the corresponding OWLObjectProperty, if it is declared - otherwise null
+ *
+ * @param id - e.g. GO:0008150
+ * @return OWLObjectProperty with id or null
+ */
+ public OWLObjectProperty getOWLObjectPropertyByIdentifier(String id) {
+ IRI iri = getIRIByIdentifier(id);
+ if (iri != null)
+ return getOWLObjectProperty(iri);
+ return null;
+ }
+
+
+// public void mergeImportClosure(boolean b) {
+// // TODO Auto-generated method stub
+//
+// }
+
+
+ /**
+ * Find all corresponding {@link OWLObject}s with an OBO-style alternate identifier.
+ *
+ * WARNING: This methods scans all object annotations in all ontologies.
+ * This is an expensive method.
+ *
+ * @return map of altId to OWLObject (never null)
+ */
+ public Map getAllOWLObjectsByAltId() {
+ final Map results = new HashMap();
+ final OWLAnnotationProperty altIdProperty = getAnnotationProperty(OboFormatTag.TAG_ALT_ID.getTag());
+ if (altIdProperty == null) {
+ return Collections.emptyMap();
+ }
+ for (OWLOntology o : getAllOntologies()) {
+ Set aas = o.getAxioms(AxiomType.ANNOTATION_ASSERTION);
+ for (OWLAnnotationAssertionAxiom aa : aas) {
+ OWLAnnotationValue v = aa.getValue();
+ OWLAnnotationProperty property = aa.getProperty();
+ if (altIdProperty.equals(property) && v instanceof OWLLiteral) {
+ String altId = ((OWLLiteral)v).getLiteral();
+ OWLAnnotationSubject subject = aa.getSubject();
+ if (subject instanceof IRI) {
+ OWLObject obj = getOWLObject((IRI) subject);
+ if (obj != null) {
+ results.put(altId, obj);
+ }
+ }
+ }
+ }
+ }
+ return results;
+ }
+
+ /**
+ * It translates a oboformat tag into an OWL annotation property
+ *
+ * @param tag
+ * @return {@link OWLAnnotationProperty}
+ */
+ public OWLAnnotationProperty getAnnotationProperty(String tag){
+ return getDataFactory().getOWLAnnotationProperty(trTagToIRI(tag));
+ }
+
+ /**
+ * fetches an OWL Object by rdfs:label
+ *
+ * if there is >1 match, return the first one encountered
+ *
+ * @param label
+ * @return object or null
+ */
+ public OWLObject getOWLObjectByLabel(String label) {
+ IRI iri = getIRIByLabel(label);
+ if (iri != null)
+ return getOWLObject(iri);
+ return null;
+ }
+
+ /**
+ * fetches an OWL IRI by rdfs:label
+ *
+ * @param label
+ * @return IRI or null
+ */
+ public IRI getIRIByLabel(String label) {
+ try {
+ return getIRIByLabel(label, false);
+ } catch (Exception e) {
+ // note that it should be impossible to reach this point
+ // if getIRIByLabel is called with isEnforceUnivocal = false
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * fetches an OWL IRI by rdfs:label, optionally testing for uniqueness
+ *
+ * TODO: index labels. This currently scans all labels in the ontology, which is expensive
+ *
+ * @param label
+ * @param isEnforceUnivocal
+ * @return IRI or null
+ * @throws SharedLabelException if >1 IRI shares input label
+ */
+ public IRI getIRIByLabel(String label, boolean isEnforceUnivocal) throws Exception {
+ IRI iri = null;
+ for (OWLOntology o : getAllOntologies()) {
+ Set aas = o.getAxioms(AxiomType.ANNOTATION_ASSERTION);
+ for (OWLAnnotationAssertionAxiom aa : aas) {
+ OWLAnnotationValue v = aa.getValue();
+ OWLAnnotationProperty property = aa.getProperty();
+ if (property.isLabel() && v instanceof OWLLiteral) {
+ if (label.equals( ((OWLLiteral)v).getLiteral())) {
+ OWLAnnotationSubject subject = aa.getSubject();
+ if (subject instanceof IRI) {
+ if (isEnforceUnivocal) {
+ if (iri != null && !iri.equals((IRI)subject)) {
+ throw new Exception();
+ }
+ iri = (IRI)subject;
+ }
+ else {
+ return (IRI)subject;
+ }
+ }
+ else {
+ //return null;
+ }
+ }
+ }
+ }
+ }
+ return iri;
+ }
+
+ public IRI getIRIByIdentifier(String id) {
+ return getIRIByIdentifier(id, false);
+ }
+
+
+}
+
diff --git a/minerva-core/src/main/java/org/geneontology/minerva/MolecularModelManager.java b/minerva-core/src/main/java/org/geneontology/minerva/MolecularModelManager.java
index fff4a812..0c4c9c7a 100644
--- a/minerva-core/src/main/java/org/geneontology/minerva/MolecularModelManager.java
+++ b/minerva-core/src/main/java/org/geneontology/minerva/MolecularModelManager.java
@@ -24,7 +24,7 @@
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
-import owltools.graph.OWLGraphWrapper;
+//import owltools.graph.OWLGraphWrapper;
import owltools.vocab.OBOUpperVocabulary;
/**
@@ -291,15 +291,15 @@ public OWLNamedIndividual getIndividual(IRI iri, ModelContainer model) {
return individual;
}
private OWLClass getClass(String cid, ModelContainer model) throws UnknownIdentifierException {
- OWLGraphWrapper graph = new OWLGraphWrapper(model.getAboxOntology());
- return getClass(cid, graph);
+ MinervaOWLGraphWrapper graph = new MinervaOWLGraphWrapper(model.getAboxOntology());
+ return getClass(cid, graph);
}
- private OWLClass getClass(String cid, OWLGraphWrapper graph) throws UnknownIdentifierException {
+ private OWLClass getClass(String cid, MinervaOWLGraphWrapper graph) throws UnknownIdentifierException {
IRI iri = getCuriHandler().getIRI(cid);
return graph.getOWLClass(iri);
}
public OWLObjectProperty getObjectProperty(String pid, ModelContainer model) throws UnknownIdentifierException {
- OWLGraphWrapper graph = new OWLGraphWrapper(model.getAboxOntology());
+ MinervaOWLGraphWrapper graph = new MinervaOWLGraphWrapper(model.getAboxOntology());
IRI iri = getCuriHandler().getIRI(pid);
return graph.getOWLObjectProperty(iri);
}
diff --git a/minerva-core/src/main/java/org/geneontology/minerva/UndoAwareMolecularModelManager.java b/minerva-core/src/main/java/org/geneontology/minerva/UndoAwareMolecularModelManager.java
index 051e0f1e..f8ca354b 100644
--- a/minerva-core/src/main/java/org/geneontology/minerva/UndoAwareMolecularModelManager.java
+++ b/minerva-core/src/main/java/org/geneontology/minerva/UndoAwareMolecularModelManager.java
@@ -20,8 +20,6 @@
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
-import owltools.graph.OWLGraphWrapper;
-
/**
* Provide undo and redo operations for the {@link MolecularModelManager}.
*/
diff --git a/minerva-core/src/main/java/org/geneontology/minerva/json/MolecularModelJsonRenderer.java b/minerva-core/src/main/java/org/geneontology/minerva/json/MolecularModelJsonRenderer.java
index 47dec5dd..13de176b 100644
--- a/minerva-core/src/main/java/org/geneontology/minerva/json/MolecularModelJsonRenderer.java
+++ b/minerva-core/src/main/java/org/geneontology/minerva/json/MolecularModelJsonRenderer.java
@@ -15,6 +15,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.log4j.Logger;
+import org.geneontology.minerva.MinervaOWLGraphWrapper;
import org.geneontology.minerva.ModelContainer;
import org.geneontology.minerva.MolecularModelManager;
import org.geneontology.minerva.curie.CurieHandler;
@@ -52,7 +53,6 @@
import owltools.gaf.eco.EcoMapper;
import owltools.gaf.eco.EcoMapperFactory;
import owltools.gaf.eco.EcoMapperFactory.OntologyMapperPair;
-import owltools.graph.OWLGraphWrapper;
import owltools.util.OwlHelper;
/**
@@ -67,7 +67,7 @@ public class MolecularModelJsonRenderer {
private final String modelId;
private final OWLOntology ont;
- private final OWLGraphWrapper graph;
+ private final MinervaOWLGraphWrapper graph;
private final CurieHandler curieHandler;
private final InferenceProvider inferenceProvider;
@@ -83,19 +83,19 @@ protected DateFormat initialValue() {
public MolecularModelJsonRenderer(ModelContainer model, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
this(curieHandler.getCuri(model.getModelId()),
model.getAboxOntology(),
- new OWLGraphWrapper(model.getAboxOntology()),
+ new MinervaOWLGraphWrapper(model.getAboxOntology()),
inferenceProvider, curieHandler);
}
public MolecularModelJsonRenderer(String modelId, OWLOntology ontology, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
- this(modelId, ontology, new OWLGraphWrapper(ontology), inferenceProvider, curieHandler);
+ this(modelId, ontology, new MinervaOWLGraphWrapper(ontology), inferenceProvider, curieHandler);
}
- public MolecularModelJsonRenderer(String modelId, OWLGraphWrapper graph, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
+ public MolecularModelJsonRenderer(String modelId, MinervaOWLGraphWrapper graph, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
this(modelId, graph.getSourceOntology(), graph, inferenceProvider, curieHandler);
}
- private MolecularModelJsonRenderer(String modelId, OWLOntology ont, OWLGraphWrapper graph, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
+ private MolecularModelJsonRenderer(String modelId, OWLOntology ont, MinervaOWLGraphWrapper graph, InferenceProvider inferenceProvider, CurieHandler curieHandler) {
super();
this.modelId = modelId;
this.ont = ont;
@@ -370,7 +370,7 @@ public static Pair,List> renderProperti
*/
// retrieve (or load) all ontologies
// put in a new wrapper
- OWLGraphWrapper wrapper = new OWLGraphWrapper(mmm.getOntology());
+ MinervaOWLGraphWrapper wrapper = new MinervaOWLGraphWrapper(mmm.getOntology());
Collection imports = mmm.getImports();
OWLOntologyManager manager = wrapper.getManager();
for (IRI iri : imports) {
@@ -460,7 +460,7 @@ public static List renderEvidences(OWLOntologyManager manager,
}
pair = eco;
}
- final OWLGraphWrapper graph = pair.getGraph();
+ final MinervaOWLGraphWrapper graph = pair.getGraph();
final EcoMapper mapper = pair.getMapper();
Set ecoClasses = graph.getAllOWLClasses();
Map codesForEcoClasses = mapper.getCodesForEcoClasses();
diff --git a/minerva-core/src/main/java/org/geneontology/minerva/util/ManchesterSyntaxTool.java b/minerva-core/src/main/java/org/geneontology/minerva/util/ManchesterSyntaxTool.java
deleted file mode 100644
index 8fc8b306..00000000
--- a/minerva-core/src/main/java/org/geneontology/minerva/util/ManchesterSyntaxTool.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.geneontology.minerva.util;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
-import org.semanticweb.owlapi.OWLAPIConfigProvider;
-import org.semanticweb.owlapi.expression.OWLEntityChecker;
-import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntaxParserImpl;
-import org.semanticweb.owlapi.manchestersyntax.renderer.ParserException;
-import org.semanticweb.owlapi.model.IRI;
-import org.semanticweb.owlapi.model.OWLAnnotationProperty;
-import org.semanticweb.owlapi.model.OWLClass;
-import org.semanticweb.owlapi.model.OWLClassExpression;
-import org.semanticweb.owlapi.model.OWLDataFactory;
-import org.semanticweb.owlapi.model.OWLDataProperty;
-import org.semanticweb.owlapi.model.OWLDatatype;
-import org.semanticweb.owlapi.model.OWLNamedIndividual;
-import org.semanticweb.owlapi.model.OWLObject;
-import org.semanticweb.owlapi.model.OWLObjectProperty;
-import org.semanticweb.owlapi.util.mansyntax.ManchesterOWLSyntaxParser;
-
-import owltools.graph.OWLGraphWrapper;
-
-
-/**
- * Wrapper for parsing OWL Manchester Syntax using a {@link OWLGraphWrapper}.
- * This is a simplified re-implementation.
- */
-public class ManchesterSyntaxTool {
-
- private static final OWLAPIConfigProvider CONFIGURATION_PROVIDER = new OWLAPIConfigProvider();
-
- private final OWLDataFactory dataFactory;
- private final OWLEntityChecker entityChecker;
- private final Map createdClassesMap;
-
- /**
- * Create new instance.
- *
- * @param graph
- * @param createClasses if set to true, classes are generated even if they are not declared.
- */
- public ManchesterSyntaxTool(OWLGraphWrapper graph, boolean createClasses) {
- super();
- this.dataFactory = graph.getDataFactory();
- createdClassesMap = new HashMap();
- entityChecker = new AdvancedEntityChecker(graph, createClasses, createdClassesMap);
- }
-
- /**
- * @return the createdClasses
- */
- public Map getCreatedClasses() {
- return Collections.unmodifiableMap(createdClassesMap);
- }
-
- /**
- * Parse a class expression in Manchester syntax.
- *
- * @param expression
- * @return {@link OWLClassExpression}
- * @throws ParserException
- */
- public OWLClassExpression parseManchesterExpression(String expression) throws ParserException {
- ManchesterOWLSyntaxParser parser = createParser();
- OWLClassExpression ce = parser.parseClassExpression(expression);
- return ce;
- }
-
-
- private ManchesterOWLSyntaxParser createParser() {
- ManchesterOWLSyntaxParserImpl parser = new ManchesterOWLSyntaxParserImpl(CONFIGURATION_PROVIDER, dataFactory);
- parser.setOWLEntityChecker(entityChecker);
- return parser;
- }
-
- static class AdvancedEntityChecker implements OWLEntityChecker {
-
- private final OWLGraphWrapper graph;
- private final boolean createClasses;
- private final Map createdClassesMap;
-
- AdvancedEntityChecker(OWLGraphWrapper graph, boolean createClasses,
- Map createdClassesMap) {
- super();
- this.graph = graph;
- this.createClasses = createClasses;
- this.createdClassesMap = createdClassesMap;
- }
-
- public OWLClass getOWLClass(String name) {
- if (name.length() < 2) {
- return null;
- }
- OWLObject owlObject;
- if (name.charAt(0) == '\'') {
- name = trimQuotes(name);
- owlObject = graph.getOWLObjectByLabel(name);
- }
- else {
- owlObject = graph.getOWLObjectByIdentifier(name);
- if (owlObject == null) {
- owlObject = graph.getOWLObjectByLabel(name);
- }
- }
- if (owlObject != null) {
- if (owlObject instanceof OWLClass) {
- return (OWLClass) owlObject;
- }
- return null;
- }
- if (name.startsWith("http:")) {
- IRI iri = IRI.create(name);
- owlObject = graph.getOWLObject(iri);
- if (owlObject != null) {
- if (owlObject instanceof OWLClass) {
- return (OWLClass) owlObject;
- }
- return null;
- }
- OWLClass c = null;
- if (createClasses) {
- String id = graph.getIdentifier(iri);
- c = createdClassesMap.get(id);
- if (c == null) {
- c = graph.getDataFactory().getOWLClass(iri);
- createdClassesMap.put(name, c);
- }
- }
- return c;
- }
- else {
- if (createClasses && !StringUtils.contains(name, ' ')) {
- OWLClass c = createdClassesMap.get(name);
- if (c == null) {
- IRI iri = graph.getIRIByIdentifier(name);
- c = graph.getDataFactory().getOWLClass(iri);
- createdClassesMap.put(name, c);
- }
- return c;
- }
- }
- return null;
- }
-
- public OWLObjectProperty getOWLObjectProperty(String name) {
- if (name.length() < 2) {
- return null;
- }
- name = trimQuotes(name);
- OWLObjectProperty p = null;
- if (StringUtils.contains(name, ' ') == false) {
- p = graph.getOWLObjectPropertyByIdentifier(name);
- if (p == null) {
- p = graph.getOWLObjectProperty(name);
- }
- }
- if (p == null) {
- graph.getIRIByLabel(name);
- OWLObject owlObject = graph.getOWLObjectByLabel(name);
- if (owlObject != null && owlObject instanceof OWLObjectProperty) {
- p = (OWLObjectProperty) owlObject;
- }
- }
- return p;
- }
-
- private String trimQuotes(String s) {
- if (s.startsWith("'") && s.endsWith("'")) {
- s = s.substring(1, s.length() - 1);
- }
- return s;
- }
-
- public OWLDataProperty getOWLDataProperty(String name) {
- return null;
- }
-
- public OWLNamedIndividual getOWLIndividual(String name) {
- OWLNamedIndividual i = graph.getOWLIndividualByIdentifier(name);
- if (i == null) {
- i = graph.getOWLIndividual(name);
- }
- return i;
- }
-
- public OWLDatatype getOWLDatatype(String name) {
- return null;
- }
-
- public OWLAnnotationProperty getOWLAnnotationProperty(String name) {
- return null;
- }
-
- }
-}
diff --git a/minerva-core/src/main/java/org/geneontology/minerva/validation/OWLValidationReport.java b/minerva-core/src/main/java/org/geneontology/minerva/validation/OWLValidationReport.java
index 20c3d48e..86d15721 100644
--- a/minerva-core/src/main/java/org/geneontology/minerva/validation/OWLValidationReport.java
+++ b/minerva-core/src/main/java/org/geneontology/minerva/validation/OWLValidationReport.java
@@ -12,4 +12,11 @@ public OWLValidationReport() {
super(report_type_id, tracker, rulefile);
}
+
+
+ public String getAsText() {
+ String e = "A human readable explanation of any OWL inconsistencies ought to go here.";
+ return e;
+ }
+
}
diff --git a/minerva-core/src/main/java/owltools/cli/Opts.java b/minerva-core/src/main/java/owltools/cli/Opts.java
new file mode 100644
index 00000000..50135c18
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/cli/Opts.java
@@ -0,0 +1,178 @@
+package owltools.cli;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+
+/**
+ * Helper for easy handling of command line parameters and input.
+ */
+public class Opts {
+
+ private int i = 0;
+ private String[] args;
+ private boolean helpMode = false;
+
+ /**
+ * Create a new instance for the given command-line parameters.
+ *
+ * @param args command-line parameter array
+ */
+ public Opts(String[] args) {
+ super();
+ this.i = 0;
+ this.args = args;
+ }
+
+ /**
+ * Create a new instance for the given command-line parameters.
+ *
+ * @param args list of command-line parameters
+ */
+ public Opts(List args) {
+ this(args.toArray(new String[args.size()]));
+ }
+
+ /**
+ * @param helpMode the helpMode to set
+ */
+ public void setHelpMode(boolean helpMode) {
+ this.helpMode = helpMode;
+ }
+
+ /**
+ * @return the helpMode
+ */
+ public boolean isHelpMode() {
+ return helpMode;
+ }
+
+ /**
+ * @return true, if there are further parameters to handle.
+ */
+ public boolean hasArgs() {
+ return i < args.length;
+ }
+
+ /**
+ * @return if there is a next parameter, which is an option flag
+ */
+ public boolean hasOpts() {
+ return hasArgs() && args[i].startsWith("-");
+ }
+
+ /**
+ * Check if the option flag is in the remaining parameters
+ *
+ * @param opt
+ * @return true, if one of the remaining parameters equals the given string.
+ */
+ public boolean hasOpt(String opt) {
+ for (int j=i; j eqs) {
+ for (String eq : eqs) {
+ if (nextEq(eq))
+ return true;
+ }
+ return false;
+ }
+ public List nextList() {
+ ArrayList sl = new ArrayList();
+ while (hasArgs()) {
+ if (args[i].equals("//")) {
+ i++;
+ break;
+ }
+ if (args[i].startsWith("-"))
+ break;
+ sl.add(args[i]);
+ i++;
+ }
+ return sl;
+ }
+ public String nextOpt() {
+ String opt = args[i];
+ i++;
+ return opt;
+ }
+ public File nextFile() {
+ String opt = args[i];
+ i++;
+ File f = FileUtils.getFile(opt);
+ return f;
+ }
+ public String peekArg() {
+ if (hasArgs())
+ return args[i];
+ return null;
+ }
+ public boolean nextArgIsHelp() {
+ if (hasArgs() && (args[i].equals("-h")
+ || args[i].equals("--help"))) {
+ nextOpt();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Send a fail. WARNING: This will terminate the VM.
+ * Do NOT use in a framework.
+ *
+ * Uses System.err to print the error message.
+ */
+ public void fail() {
+ System.err.println("cannot process: "+args[i]);
+ System.exit(1);
+
+ }
+
+ /**
+ * Write an info. WARNING: This will terminate the VM.
+ * Do NOT use in a framework.
+ *
+ * Uses System.out to print the message.
+ *
+ * @param params
+ * @param desc
+ */
+ public void info(String params, String desc) {
+ if (this.nextArgIsHelp()) {
+ System.out.println(args[i-2]+" "+params+"\t "+desc);
+ System.exit(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/EcoMapper.java b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapper.java
new file mode 100644
index 00000000..1c727678
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapper.java
@@ -0,0 +1,66 @@
+package owltools.gaf.eco;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLClass;
+
+public interface EcoMapper {
+
+ /**
+ * Permanent URL for the evidence code ontology (ECO) owl file.
+ */
+ public static final String ECO_PURL = "http://purl.obolibrary.org/obo/eco.owl";
+
+ /**
+ * IRI for the evidence code ontology (ECO) owl file.
+ */
+ public static final IRI ECO_PURL_IRI = IRI.create(ECO_PURL);
+
+ /**
+ * Permanent URL for the mapping of GO evidence codes to ECO classes
+ */
+ public static final String ECO_MAPPING_PURL = "http://purl.obolibrary.org/obo/eco/gaf-eco-mapping.txt";
+
+ /**
+ * Retrieve the equivalent ECO class for the given GO evidence code. Assume, that the reference is 'default'.
+ *
+ * @param code
+ * @return {@link OWLClass} or null
+ */
+ public OWLClass getEcoClassForCode(String code);
+
+ /**
+ * Retrieve the ECO classes for the given GO evidence code. Include the classes to be used with more specific references.
+ *
+ * @param code
+ * @return set of classes, never null
+ */
+ public Set getAllEcoClassesForCode(String code);
+
+ /**
+ * Retrieve the ECO class for the given GO evidence code and reference. If reference is null, assume default.
+ *
+ * @param code
+ * @param refCode
+ * @return {@link OWLClass} or null
+ */
+ public OWLClass getEcoClassForCode(String code, String refCode);
+
+
+ /**
+ * Check that the given GO code is a valid code with an existing mapping to ECO
+ *
+ * @param code
+ * @return true if the code is a valid
+ */
+ public boolean isGoEvidenceCode(String code);
+
+ /**
+ * Retrieve the mapping from ECO classes to GO evidence codes.
+ *
+ * @return mapping
+ */
+ public Map getCodesForEcoClasses();
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperFactory.java b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperFactory.java
new file mode 100644
index 00000000..0b6e95ca
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperFactory.java
@@ -0,0 +1,575 @@
+package owltools.gaf.eco;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.geneontology.minerva.MinervaOWLGraphWrapper;
+import org.semanticweb.elk.owlapi.ElkReasonerFactory;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLException;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyID;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
+
+import com.google.common.base.Optional;
+
+import owltools.io.ParserWrapper;
+
+/**
+ * Factory to create instances of {@link EcoMapper} and {@link TraversingEcoMapper}.
+ */
+public class EcoMapperFactory {
+
+ private static final OWLReasonerFactory reasonerFactor = new ElkReasonerFactory();
+
+ private EcoMapperFactory() {
+ // private constructor, no instances allowed
+ }
+
+ public static class OntologyMapperPair {
+
+ private final MinervaOWLGraphWrapper graph;
+ private final MAPPER mapper;
+
+ /**
+ * @param graph
+ * @param mapper
+ */
+ OntologyMapperPair(MinervaOWLGraphWrapper graph, MAPPER mapper) {
+ this.graph = graph;
+ this.mapper = mapper;
+ }
+
+ /**
+ * @return the graph
+ */
+ public MinervaOWLGraphWrapper getGraph() {
+ return graph;
+ }
+
+ /**
+ * @return the mapper
+ */
+ public MAPPER getMapper() {
+ return mapper;
+ }
+ }
+
+ /**
+ * Create a new {@link SimpleEcoMapper} with from the mapping loaded from
+ * the PURL.
+ *
+ * @return mapper
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static SimpleEcoMapper createSimple() throws IOException {
+ return createSimple(EcoMapper.ECO_MAPPING_PURL);
+ }
+
+ /**
+ * Create a new {@link SimpleEcoMapper} with from the mapping loaded from
+ * the given source.
+ *
+ * @param source
+ * @return mapper
+ * @throws IOException
+ */
+ public static SimpleEcoMapper createSimple(String source) throws IOException {
+ return createSimpleMapper(createReader(source));
+ }
+
+ /**
+ * Create an instance of a {@link EcoMapper}. Uses a separate parser. Load
+ * the ECO and mappings using their PURLs.
+ *
+ * @return mapper pair
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_PURL
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createEcoMapper() throws OWLException, IOException {
+ return createEcoMapper(new ParserWrapper());
+ }
+
+ /**
+ * Create an instance of a {@link EcoMapper}. Uses a the manager to load ECO via the
+ * PURL. Load mappings using the PURL.
+ * @param m
+ *
+ * @return mapper pair
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_PURL
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createEcoMapper(OWLOntologyManager m) throws OWLException, IOException {
+ ParserWrapper p = new ParserWrapper();
+ p.setManager(m);
+ return createEcoMapper(p);
+ }
+
+ /**
+ * Create an instance of a {@link EcoMapper}. Uses the given
+ * {@link ParserWrapper} to load the ontology. Retrieves ECO and the
+ * mappings using their PURLs.
+ *
+ * @param p
+ * @return mapper pair
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_PURL
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createEcoMapper(ParserWrapper p) throws OWLException, IOException {
+ return createEcoMapper(p, EcoMapper.ECO_PURL);
+ }
+
+ /**
+ * Create an instance of a {@link EcoMapper}. Uses the given
+ * {@link ParserWrapper} to load the ontology. Retrieves ECO from the given location and the
+ * mapping from the PURL.
+ *
+ * @param p
+ * @param location
+ * @return mapper pair
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createEcoMapper(ParserWrapper p, String location) throws OWLException, IOException {
+ final OWLOntology eco = p.parseOWL(location);
+ final MinervaOWLGraphWrapper graph = new MinervaOWLGraphWrapper(eco);
+ final EcoMapper mapper = createEcoMapper(graph);
+ final OntologyMapperPair pair = new OntologyMapperPair(graph, mapper);
+ return pair ;
+ }
+
+ /**
+ * Create an instance of a {@link EcoMapper}. Retrieves the mappings using
+ * the PURL.
+ *
+ * @param graph graph containing ECO
+ * @return mapper
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static EcoMapper createEcoMapper(MinervaOWLGraphWrapper graph) throws IOException {
+ Reader reader = null;
+ try {
+ reader = createReader(EcoMapper.ECO_MAPPING_PURL);
+ EcoMappings mappings = loadEcoMappings(reader, graph);
+ return createEcoMapper(mappings);
+ }
+ finally {
+ IOUtils.closeQuietly(reader);
+ }
+ }
+
+ static EcoMapper createEcoMapper(EcoMappings mappings) {
+ return new EcoMapperImpl(mappings);
+ }
+
+ /**
+ * Create a {@link TraversingEcoMapper} instance using a new
+ * {@link ParserWrapper} to load ECO. ECO and the mappings are retrieved
+ * using their PURLs.
+ *
+ * Creates an ELK reasoner to be used in the traversal methods. Use
+ * {@link TraversingEcoMapper#dispose()} to ensure proper cleanup of the ELK
+ * worker thread pool.
+ *
+ * @return mapper pair
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_PURL
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createTraversingEcoMapper() throws OWLException, IOException {
+ return createTraversingEcoMapper(new ParserWrapper());
+ }
+
+ /**
+ * Create a {@link TraversingEcoMapper} instance using the given
+ * {@link ParserWrapper} to load ECO. ECO and the mappings are retrieved
+ * using their PURLs.
+ *
+ * Creates an ELK reasoner to be used in the traversal methods. Use
+ * {@link TraversingEcoMapper#dispose()} to ensure proper cleanup of the ELK
+ * worker thread pool.
+ *
+ * @param p
+ * @return mapper
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_PURL
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createTraversingEcoMapper(ParserWrapper p) throws OWLException, IOException {
+ return createTraversingEcoMapper(p, EcoMapper.ECO_PURL);
+ }
+
+ /**
+ * Create a {@link TraversingEcoMapper} instance using the given
+ * {@link ParserWrapper} to load ECO from the given location. The mappings
+ * are retrieved using the PURL.
+ *
+ * Creates an ELK reasoner to be used in the traversal methods. Use
+ * {@link TraversingEcoMapper#dispose()} to ensure proper cleanup of the ELK
+ * worker thread pool.
+ *
+ * @param p
+ * @param location
+ * @return mapper
+ * @throws OWLException
+ * @throws IOException
+ *
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static OntologyMapperPair createTraversingEcoMapper(ParserWrapper p, String location) throws OWLException, IOException {
+ OWLOntology eco = p.parseOWL(EcoMapper.ECO_PURL_IRI);
+ OWLReasoner reasoner = reasonerFactor.createReasoner(eco);
+ Reader reader = null;
+ try {
+ MinervaOWLGraphWrapper ecoGraph = new MinervaOWLGraphWrapper(eco);
+ reader = createReader(EcoMapper.ECO_MAPPING_PURL);
+ final TraversingEcoMapper mapper = createTraversingEcoMapper(reader, ecoGraph, reasoner, true);
+ return new OntologyMapperPair(ecoGraph, mapper);
+ }
+ finally {
+ IOUtils.closeQuietly(reader);
+ }
+ }
+
+ /**
+ * Create a {@link TraversingEcoMapper} instance using the given
+ * {@link MinervaOWLGraphWrapper}. It is assumed that ECO can be retrieved from the
+ * graph using its default IRI. The mappings are retrieved using the PURL.
+ *
+ * Uses the given reasoner in the traversal methods. If disposeReasoner is
+ * set to true, dispose also the reasoner, while calling
+ * {@link TraversingEcoMapper#dispose()}.
+ *
+ * @param all
+ * graph containing all ontologies, including ECO
+ * @param reasoner
+ * reasoner capable of traversing ECO
+ * @param disposeReasoner
+ * set to true if the reasoner should be disposed, when calling
+ * {@link TraversingEcoMapper#dispose()}
+ * @return mapper
+ * @throws IOException
+ * @throws OWLException
+ * @throws IllegalArgumentException
+ * throw when the reasoner is null, or the
+ * {@link MinervaOWLGraphWrapper} does not contain ECO.
+ *
+ * @see EcoMapper#ECO_PURL_IRI
+ * @see EcoMapper#ECO_MAPPING_PURL
+ */
+ public static TraversingEcoMapper createTraversingEcoMapper(MinervaOWLGraphWrapper all, OWLReasoner reasoner, boolean disposeReasoner) throws IOException, OWLException {
+
+ // This has bitten me, so let's try and be specific...
+ if( reasoner == null ) {
+ throw new IllegalArgumentException("No reasoner was specified for use with the EcoTools. Add a reasoner for the command line");
+ }
+
+ OWLOntology eco = null;
+
+ // assume the graph wrapper is more than eco
+ // try to find ECO by its purl
+ Set allOntologies = all.getAllOntologies();
+ for (OWLOntology owlOntology : allOntologies) {
+ OWLOntologyID id = owlOntology.getOntologyID();
+ Optional ontologyIRI = id.getOntologyIRI();
+ if (ontologyIRI.isPresent()) {
+ if (EcoMapper.ECO_PURL_IRI.equals(ontologyIRI.get())) {
+ eco = owlOntology;
+ }
+ }
+ }
+ if (eco == null) {
+ throw new IllegalArgumentException("The specified graph did not contain ECO with the IRI: "+EcoMapper.ECO_PURL_IRI);
+ }
+
+ MinervaOWLGraphWrapper ecoGraph = new MinervaOWLGraphWrapper(eco);
+ Reader reader = null;
+ try {
+ reader = createReader(EcoMapper.ECO_MAPPING_PURL);
+ EcoMappings mappings = loadEcoMappings(reader, ecoGraph);
+ return new TraversingEcoMapperImpl(mappings, reasoner, disposeReasoner);
+ }
+ finally {
+ IOUtils.closeQuietly(reader);
+ }
+ }
+
+ static Reader createReader(String src) throws IOException {
+ if (src.indexOf(':') > 0) {
+ // assume its an url
+ URL url = new URL(src);
+ return loadUrl(url);
+ }
+
+ // treat as file
+ File file = new File(src);
+ return new FileReader(file);
+ }
+
+ private static Reader loadUrl(URL url) throws IOException {
+ final HttpURLConnection connection;
+ InputStream response = null;
+ // setup and open (actual connection)
+ try {
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(true); // warning does not follow redirects from http to https
+ response = connection.getInputStream(); // opens the connection to the server
+ }
+ catch (IOException e) {
+ IOUtils.closeQuietly(response);
+ throw e;
+ }
+ // check status code
+ final int status;
+ try {
+ status = connection.getResponseCode();
+ } catch (IOException e) {
+ IOUtils.closeQuietly(response);
+ throw e;
+ }
+ if (HttpURLConnection.HTTP_MOVED_PERM == status || HttpURLConnection.HTTP_MOVED_TEMP == status) {
+ String location;
+ try {
+ location = connection.getHeaderField("Location");
+ } finally {
+ IOUtils.closeQuietly(response);
+ }
+ if (location == null) {
+ throw new IOException("Could not follow redirect, missing header/no value for header 'Location'");
+ }
+ URL next = new URL(url, location); // Deal with relative URLs
+
+ return loadUrl(next);
+ }
+ // handle unexpected status code
+ if (status != 200) {
+ // try to check error stream
+ String errorMsg = getErrorMsg(connection);
+
+ // construct message for exception
+ StringBuilder sb = new StringBuilder("Unexpected HTTP status code: "+status);
+
+ if (errorMsg != null) {
+ sb.append(" Details: ");
+ sb.append(errorMsg);
+ }
+ throw new IOException(sb.toString());
+ }
+
+ // try to detect charset
+ String contentType = connection.getHeaderField("Content-Type");
+ String charset = null;
+
+ if (contentType != null) {
+ for (String param : contentType.replace(" ", "").split(";")) {
+ if (param.startsWith("charset=")) {
+ charset = param.split("=", 2)[1];
+ break;
+ }
+ }
+ }
+
+ // get string response from stream
+ String string;
+ try {
+ if (charset != null) {
+ string = IOUtils.toString(response, charset);
+ }
+ else {
+ string = IOUtils.toString(response);
+ }
+ } catch (IOException e) {
+ throw e;
+ }
+ finally {
+ IOUtils.closeQuietly(response);
+ }
+ return new StringReader(string);
+ }
+
+ private static String getErrorMsg(HttpURLConnection connection) {
+ String errorMsg = null;
+ InputStream errorStream = null;
+ try {
+ errorStream = connection.getErrorStream();
+ if (errorStream != null) {
+ errorMsg =IOUtils.toString(errorStream);
+ }
+ errorMsg = StringUtils.trimToNull(errorMsg);
+ }
+ catch (IOException e) {
+ // ignore errors, while trying to retrieve the error message
+ }
+ finally {
+ IOUtils.closeQuietly(errorStream);
+ }
+ return errorMsg;
+ }
+
+ static TraversingEcoMapper createTraversingEcoMapper(Reader mappingsReader, MinervaOWLGraphWrapper eco, OWLReasoner reasoner, boolean disposeReasoner) throws IOException, OWLException {
+ EcoMappings mappings = loadEcoMappings(mappingsReader, eco);
+ return new TraversingEcoMapperImpl(mappings, reasoner, disposeReasoner);
+ }
+
+ private static EcoMappings loadEcoMappings(Reader mappingsReader, MinervaOWLGraphWrapper eco) throws IOException {
+ EcoMappings mappings = new EcoMappings();
+ List lines = IOUtils.readLines(mappingsReader);
+ for (String line : lines) {
+ line = StringUtils.trimToNull(line);
+ if (line != null) {
+ char c = line.charAt(0);
+ if ('#' != c) {
+ String[] split = StringUtils.split(line, '\t');
+ if (split.length == 3) {
+ String code = split[0];
+ String ref = split[1];
+ String ecoId = split[2];
+ OWLClass cls = eco.getOWLClassByIdentifier(ecoId);
+ if (cls != null) {
+ mappings.add(code, ref, cls);
+ }
+ }
+ }
+ }
+ }
+ return mappings;
+ }
+
+ private static SimpleEcoMapper createSimpleMapper(Reader mappingsReader) throws IOException {
+ EcoMappings mappings = loadEcoMappings(mappingsReader);
+ return new SimpleEcoMapperImpl(mappings);
+ }
+
+ private static EcoMappings loadEcoMappings(Reader mappingsReader) throws IOException {
+ EcoMappings mappings = new EcoMappings();
+ List lines = IOUtils.readLines(mappingsReader);
+ for (String line : lines) {
+ line = StringUtils.trimToNull(line);
+ if (line != null) {
+ char c = line.charAt(0);
+ if ('#' != c) {
+ String[] split = StringUtils.split(line, '\t');
+ if (split.length == 3) {
+ String code = split[0];
+ String ref = split[1];
+ String ecoId = split[2];
+ mappings.add(code, ref, ecoId);
+ }
+ }
+ }
+ }
+ return mappings;
+ }
+
+ /**
+ * Helper to access the mapping for ECO codes. ECO codes should always have
+ * a 'Default' mapping. Optionally, they have additional mappings for
+ * specific annotation references.
+ *
+ * @param
+ */
+ static class EcoMappings {
+
+ static final String DEFAULT_REF = "Default";
+
+ private final Map> allMappings = new HashMap>();
+
+ void add(String code, String ref, T cls) {
+ Map codeMap = allMappings.get(code);
+ if (codeMap == null) {
+ codeMap = new HashMap();
+ allMappings.put(code, codeMap);
+ }
+ if (ref == null) {
+ ref = DEFAULT_REF;
+ }
+ codeMap.put(ref, cls);
+ }
+
+ T get(String code, String ref) {
+ T result = null;
+ if (code != null) {
+ Map codeMap = allMappings.get(code);
+ if (codeMap != null) {
+ if (ref == null) {
+ ref = DEFAULT_REF;
+ }
+ result = codeMap.get(ref);
+ }
+ }
+ return result;
+ }
+
+ T get(String code) {
+ return get(code, DEFAULT_REF);
+ }
+
+ Set getAll(String code) {
+ Set result = new HashSet();
+ if (code != null) {
+ Map codeMap = allMappings.get(code);
+ if (codeMap != null) {
+ result.addAll(codeMap.values());
+ }
+ }
+ return result;
+ }
+
+ boolean hasCode(String code) {
+ return allMappings.containsKey(code);
+ }
+
+ Map> getReverseMap() {
+ Map> reverseMap = new HashMap>();
+ for(Entry> e : allMappings.entrySet()) {
+ Map codeMap = e.getValue();
+ for(Entry codeEntry : codeMap.entrySet()) {
+ T eco = codeEntry.getValue();
+ String ref = codeEntry.getKey();
+ if (DEFAULT_REF.equals(ref)) {
+ ref = null;
+ }
+ reverseMap.put(eco, Pair.of(e.getKey(), ref));
+ }
+ }
+ return reverseMap;
+ }
+ }
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperImpl.java b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperImpl.java
new file mode 100644
index 00000000..bd597737
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/EcoMapperImpl.java
@@ -0,0 +1,53 @@
+package owltools.gaf.eco;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.semanticweb.owlapi.model.OWLClass;
+
+public class EcoMapperImpl implements EcoMapper {
+
+ private final EcoMapperFactory.EcoMappings mappings;
+
+ EcoMapperImpl(EcoMapperFactory.EcoMappings mappings) {
+ this.mappings = mappings;
+ }
+
+ @Override
+ public OWLClass getEcoClassForCode(String code) {
+ return mappings.get(code);
+ }
+
+ @Override
+ public Set getAllEcoClassesForCode(String code) {
+ return mappings.getAll(code);
+ }
+
+ @Override
+ public OWLClass getEcoClassForCode(String code, String refCode) {
+ return mappings.get(code, refCode);
+ }
+
+ @Override
+ public boolean isGoEvidenceCode(String code) {
+ return mappings.hasCode(code);
+ }
+
+ @Override
+ public Map getCodesForEcoClasses() {
+ Map> fullReverseMap = mappings.getReverseMap();
+ Map simpleReverseMap = new HashMap();
+ for(Entry> e : fullReverseMap.entrySet()) {
+ String ref = e.getValue().getRight();
+ if (ref == null) {
+ simpleReverseMap.put(e.getKey(), e.getValue().getLeft());
+ }
+
+ }
+ return simpleReverseMap;
+ }
+
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapper.java b/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapper.java
new file mode 100644
index 00000000..61b82bcf
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapper.java
@@ -0,0 +1,14 @@
+package owltools.gaf.eco;
+
+import java.util.Collection;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+public interface SimpleEcoMapper {
+
+ public String getEco(String goCode, String ref);
+
+ public String getEco(String goCode, Collection allRefs);
+
+ public Pair getGoCode(String eco);
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapperImpl.java b/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapperImpl.java
new file mode 100644
index 00000000..939c2c09
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/SimpleEcoMapperImpl.java
@@ -0,0 +1,42 @@
+package owltools.gaf.eco;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import owltools.gaf.eco.EcoMapperFactory.EcoMappings;
+
+public class SimpleEcoMapperImpl implements SimpleEcoMapper {
+
+ private final EcoMapperFactory.EcoMappings mappings;
+ private final Map> reverseMap;
+
+ SimpleEcoMapperImpl(EcoMappings mappings) {
+ this.mappings = mappings;
+ reverseMap = mappings.getReverseMap();
+ }
+
+ @Override
+ public String getEco(String goCode, String ref) {
+ return mappings.get(goCode, ref);
+ }
+
+ @Override
+ public String getEco(String goCode, Collection allRefs) {
+ String eco = null;
+ for (String ref : allRefs) {
+ eco = mappings.get(goCode, ref);
+ if (eco != null) {
+ break;
+ }
+ }
+ return eco;
+ }
+
+ @Override
+ public Pair getGoCode(String eco) {
+ return reverseMap.get(eco);
+ }
+
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapper.java b/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapper.java
new file mode 100644
index 00000000..f8f632fe
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapper.java
@@ -0,0 +1,70 @@
+package owltools.gaf.eco;
+
+import java.util.Set;
+
+import org.semanticweb.owlapi.model.OWLClass;
+
+public interface TraversingEcoMapper extends EcoMapper {
+
+ /**
+ * Traversing method for the ECO ontology.
+ *
+ * @param sources
+ * @param reflexive
+ * @return set of super classes
+ */
+ public Set getAncestors(Set sources, boolean reflexive);
+
+ /**
+ * Traversing method for the ECO ontology.
+ *
+ * @param source
+ * @param reflexive
+ * @return set of super classes
+ */
+ public Set getAncestors(OWLClass source, boolean reflexive);
+
+ /**
+ * Traversing method for the ECO ontology.
+ *
+ * @param sources
+ * @param reflexive
+ * @return set of sub classes
+ */
+ public Set getDescendents(Set sources, boolean reflexive);
+
+ /**
+ * Traversing method for the ECO ontology.
+ *
+ * @param source
+ * @param reflexive
+ * @return set of sub classes
+ */
+ public Set getDescendents(OWLClass source, boolean reflexive);
+
+
+ /**
+ * Get all strings which are valid identifiers for a given evidence code.
+ * This includes, the the codes itself and valid OBO-style identifier from ECO.
+ *
+ * @param code
+ * @param includeChildren
+ * @return set of ids
+ */
+ public Set getAllValidEvidenceIds(String code, boolean includeChildren);
+
+ /**
+ * Get all strings which are valid identifiers for the given evidence codes.
+ * This includes, the the codes itself and valid OBO-style identifier from ECO.
+ *
+ * @param codes
+ * @param includeChildren
+ * @return set of ids
+ */
+ public Set getAllValidEvidenceIds(Set codes, boolean includeChildren);
+
+ /**
+ * Dispose this instance
+ */
+ public void dispose();
+}
diff --git a/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapperImpl.java b/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapperImpl.java
new file mode 100644
index 00000000..4b0064f3
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/gaf/eco/TraversingEcoMapperImpl.java
@@ -0,0 +1,125 @@
+package owltools.gaf.eco;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+//import org.obolibrary.obo2owl.Owl2Obo;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+
+import owltools.gaf.eco.EcoMapperFactory.EcoMappings;
+import owltools.util.OwlHelper;
+
+public class TraversingEcoMapperImpl extends EcoMapperImpl implements TraversingEcoMapper {
+
+ private final OWLReasoner reasoner;
+ private final boolean disposeReasoner;
+
+ private final Map> mappingCache = new HashMap>();
+
+ TraversingEcoMapperImpl(EcoMappings mappings, OWLReasoner reasoner, boolean disposeReasoner) {
+ super(mappings);
+ this.reasoner = reasoner;
+ this.disposeReasoner = disposeReasoner;
+ }
+
+ @Override
+ public Set getAncestors(Set sources, boolean reflexive) {
+ if (sources == null || sources.isEmpty()) {
+ return Collections.emptySet();
+ }
+ Set result = new HashSet();
+ for (OWLClass source : sources) {
+ Set set = reasoner.getSuperClasses(source, false).getFlattened();
+ for (OWLClass cls : set) {
+ if (cls.isBuiltIn() == false) {
+ result.add(cls);
+ }
+ }
+ }
+ if (reflexive) {
+ result.addAll(sources);
+ }
+ if (result.isEmpty()) {
+ return Collections.emptySet();
+ }
+ return result;
+ }
+
+ @Override
+ public Set getAncestors(OWLClass source, boolean reflexive) {
+ return getAncestors(Collections.singleton(source), reflexive);
+ }
+
+ @Override
+ public Set getDescendents(Set sources, boolean reflexive) {
+ if (sources == null || sources.isEmpty()) {
+ return Collections.emptySet();
+ }
+ Set result = new HashSet();
+ for (OWLClass source : sources) {
+ Set set = reasoner.getSubClasses(source, false).getFlattened();
+ for (OWLClass cls : set) {
+ if (cls.isBuiltIn() == false) {
+ result.add(cls);
+ }
+ }
+ }
+ if (reflexive) {
+ result.addAll(sources);
+ }
+ if (result.isEmpty()) {
+ return Collections.emptySet();
+ }
+ return result;
+ }
+
+ @Override
+ public Set getDescendents(OWLClass source, boolean reflexive) {
+ return getDescendents(Collections.singleton(source), reflexive);
+ }
+
+ @Override
+ public Set getAllValidEvidenceIds(String code, boolean includeChildren) {
+ return getAllValidEvidenceIds(Collections.singleton(code), includeChildren);
+ }
+
+ @Override
+ public Set getAllValidEvidenceIds(Set codes, boolean includeChildren) {
+ if (codes == null || codes.isEmpty()) {
+ return Collections.emptySet();
+ }
+ Set result = new HashSet();
+ for(String code : codes) {
+ Set classes = getAllEcoClassesForCode(code);
+ for (OWLClass owlClass : classes) {
+ result.add(getId(owlClass));
+ }
+ if (includeChildren) {
+ Set descendents = getDescendents(classes, false);
+ for (OWLClass owlClass : descendents) {
+ result.add(getId(owlClass));
+ }
+ }
+ }
+ result.addAll(codes);
+ return result;
+ }
+
+ private String getId(OWLClass cls) {
+ //return Owl2Obo.getIdentifier(cls.getIRI());
+ return OwlHelper.getIdentifier(cls.getIRI(), null);
+ }
+
+ @Override
+ public void dispose() {
+ mappingCache.clear();
+ if (disposeReasoner) {
+ reasoner.dispose();
+ }
+ }
+
+}
diff --git a/minerva-core/src/main/java/owltools/io/CatalogXmlIRIMapper.java b/minerva-core/src/main/java/owltools/io/CatalogXmlIRIMapper.java
new file mode 100644
index 00000000..4aa45e21
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/io/CatalogXmlIRIMapper.java
@@ -0,0 +1,187 @@
+package owltools.io;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.log4j.Logger;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLOntologyIRIMapper;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * {@link OWLOntologyIRIMapper} using the mappings from a catalog.xml file.
+ */
+public class CatalogXmlIRIMapper implements OWLOntologyIRIMapper {
+
+ private static final Logger logger = Logger.getLogger(CatalogXmlIRIMapper.class);
+
+ private final Map mappings;
+
+ CatalogXmlIRIMapper(Map mappings) {
+ this.mappings = mappings;
+ }
+
+ /**
+ * Create an CatalogXmlIRIMapper from the given catalog.xml file.
+ * Assume, that relative paths are relative to the catalog file location.
+ *
+ * @param catalogFile
+ * @throws IOException
+ */
+ public CatalogXmlIRIMapper(String catalogFile) throws IOException {
+ this(new File(catalogFile).getAbsoluteFile());
+ }
+
+ /**
+ * Create an CatalogXmlIRIMapper from the given catalog.xml file.
+ * Assume, that relative paths are relative to the catalog file location.
+ *
+ * @param catalogFile
+ * @throws IOException
+ */
+ public CatalogXmlIRIMapper(File catalogFile) throws IOException {
+ this(catalogFile, catalogFile.getAbsoluteFile().getParentFile());
+ }
+
+ /**
+ * Create an CatalogXmlIRIMapper from the given catalog.xml file.
+ * Use the parentFolder to resolve relative paths from the catalog file.
+ *
+ * @param catalogFile
+ * @param parentFolder
+ * @throws IOException
+ */
+ public CatalogXmlIRIMapper(File catalogFile, File parentFolder) throws IOException {
+ this(parseCatalogXml(new FileInputStream(catalogFile), parentFolder));
+ }
+
+ /**
+ * Create an CatalogXmlIRIMapper from the given catalog URL.
+ * Assume, there are no relative paths in the catalog file.
+ *
+ * @param catalogURL
+ * @throws IOException
+ */
+ public CatalogXmlIRIMapper(URL catalogURL) throws IOException {
+ if ("file".equals(catalogURL.getProtocol())) {
+ try {
+ File catalogFile = new File(catalogURL.toURI());
+ mappings = parseCatalogXml(new FileInputStream(catalogFile), catalogFile.getParentFile());
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+ }
+ else {
+ mappings = parseCatalogXml(catalogURL.openStream(), null);
+ }
+ }
+
+ /**
+ * Create an CatalogXmlIRIMapper from the given catalog URL.
+ * Use the parentFolder to resolve relative paths from the catalog file.
+ *
+ * @param catalogURL
+ * @param parentFolder
+ * @throws IOException
+ */
+ public CatalogXmlIRIMapper(URL catalogURL, File parentFolder) throws IOException {
+ this(parseCatalogXml(catalogURL.openStream(), parentFolder));
+ }
+
+ @Override
+ public IRI getDocumentIRI(IRI ontologyIRI) {
+ return mappings.get(ontologyIRI);
+ }
+
+ public Map getMappings() {
+ return Collections.unmodifiableMap(mappings);
+ }
+
+ /**
+ * Parse the inputStream as a catalog.xml file and extract IRI mappings.
+ *
+ * Optional: Resolve relative file paths with the given parent folder.
+ *
+ * @param inputStream input stream (never null)
+ * @param parentFolder folder or null
+ * @return mappings
+ * @throws IOException
+ * @throws IllegalArgumentException if input stream is null
+ */
+ static Map parseCatalogXml(InputStream inputStream, final File parentFolder) throws IOException {
+ if (inputStream == null) {
+ throw new IllegalArgumentException("InputStream should never be null, missing resource?");
+ }
+
+ // use the Java built-in SAX parser
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+
+ try {
+ final Map mappings = new HashMap();
+ SAXParser saxParser = factory.newSAXParser();
+ saxParser.parse(inputStream, new DefaultHandler(){
+
+ @Override
+ public void startElement(String uri, String localName,
+ String qName, Attributes attributes)
+ throws SAXException
+ {
+ // only look at 'uri' tags
+ // does not check any parent tags
+ if ("uri".equals(qName)) {
+ IRI original = null;
+ IRI mapped = null;
+ String nameString = attributes.getValue("name");
+ if (nameString != null) {
+ original = IRI.create(nameString);
+ }
+ String mappedString = attributes.getValue("uri");
+ if (mappedString != null) {
+ if (parentFolder != null && mappedString.indexOf(":") < 0) {
+ // there is a parent folder and the mapping is not an IRI or URL
+ File file = new File(mappedString);
+ if (!file.isAbsolute()) {
+ file = new File(parentFolder, mappedString);
+ }
+ try {
+ file = file.getCanonicalFile();
+ mapped = IRI.create(file);
+ } catch (IOException e) {
+ logger.warn("Skipping mapping: "+nameString+" "+mappedString, e);
+ }
+ }
+ else {
+ mapped = IRI.create(mappedString);
+ }
+ }
+
+ if (original != null && mapped != null) {
+ mappings.put(original, mapped);
+ }
+ }
+ }
+ });
+ return mappings;
+ } catch (ParserConfigurationException e) {
+ throw new IOException(e);
+ } catch (SAXException e) {
+ throw new IOException(e);
+ } finally {
+ inputStream.close();
+ }
+ }
+}
diff --git a/minerva-core/src/main/java/owltools/io/ParserWrapper.java b/minerva-core/src/main/java/owltools/io/ParserWrapper.java
new file mode 100644
index 00000000..002ee1e9
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/io/ParserWrapper.java
@@ -0,0 +1,383 @@
+package owltools.io;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.apache.log4j.lf5.util.StreamUtils;
+import org.geneontology.minerva.MinervaOWLGraphWrapper;
+import org.obolibrary.oboformat.model.Frame;
+import org.obolibrary.oboformat.model.OBODoc;
+import org.obolibrary.oboformat.parser.OBOFormatConstants.OboFormatTag;
+import org.obolibrary.oboformat.writer.OBOFormatWriter;
+import org.obolibrary.oboformat.writer.OBOFormatWriter.NameProvider;
+import org.obolibrary.oboformat.writer.OBOFormatWriter.OBODocNameProvider;
+import org.semanticweb.owlapi.apibinding.OWLManager;
+import org.semanticweb.owlapi.formats.OBODocumentFormat;
+import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLDocumentFormat;
+import org.semanticweb.owlapi.model.OWLObject;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyAlreadyExistsException;
+import org.semanticweb.owlapi.model.OWLOntologyCreationException;
+import org.semanticweb.owlapi.model.OWLOntologyDocumentAlreadyExistsException;
+import org.semanticweb.owlapi.model.OWLOntologyID;
+import org.semanticweb.owlapi.model.OWLOntologyIRIMapper;
+import org.semanticweb.owlapi.model.OWLOntologyLoaderListener;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.model.OWLOntologyStorageException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.google.common.base.Optional;
+
+/**
+ * Convenience class wrapping org.oboformat that abstracts away underlying details of ontology format or location
+ * @author cjm
+ *
+ */
+public class ParserWrapper {
+
+ private static Logger LOG = Logger.getLogger(ParserWrapper.class);
+ OWLOntologyManager manager;
+ private final List mappers = new ArrayList();
+ OBODoc obodoc;
+ boolean isCheckOboDoc = true;
+
+
+ public ParserWrapper() {
+ manager = OWLManager.createOWLOntologyManager();
+ OWLOntologyLoaderListener listener = new OWLOntologyLoaderListener() {
+
+ // generated
+ private static final long serialVersionUID = 8475800207882525640L;
+
+ @Override
+ public void startedLoadingOntology(LoadingStartedEvent event) {
+ IRI id = event.getOntologyID().getOntologyIRI().orNull();
+ IRI source = event.getDocumentIRI();
+ LOG.info("Start loading ontology: "+id+" from: "+source);
+ }
+
+ @Override
+ public void finishedLoadingOntology(LoadingFinishedEvent event) {
+ IRI id = event.getOntologyID().getOntologyIRI().orNull();
+ IRI source = event.getDocumentIRI();
+ LOG.info("Finished loading ontology: "+id+" from: "+source);
+ }
+ };
+ manager.addOntologyLoaderListener(listener);
+ }
+
+ public OWLOntologyManager getManager() {
+ return manager;
+ }
+ public void setManager(OWLOntologyManager manager) {
+ this.manager = manager;
+ }
+
+ public boolean isCheckOboDoc() {
+ return isCheckOboDoc;
+ }
+
+ public void setCheckOboDoc(boolean isCheckOboDoc) {
+ this.isCheckOboDoc = isCheckOboDoc;
+ }
+
+ public void addIRIMapper(OWLOntologyIRIMapper mapper) {
+ manager.getIRIMappers().add(mapper);
+ mappers.add(0, mapper);
+ }
+ public void removeIRIMapper(OWLOntologyIRIMapper mapper) {
+ manager.getIRIMappers().remove(mapper);
+ mappers.remove(mapper);
+ }
+ public List getIRIMappers() {
+ return Collections.unmodifiableList(mappers);
+ }
+ public void addIRIMappers(List mappers) {
+ List reverse = new ArrayList(mappers);
+ Collections.reverse(reverse);
+ for (OWLOntologyIRIMapper mapper : reverse) {
+ addIRIMapper(mapper);
+ }
+ }
+
+ public MinervaOWLGraphWrapper parseToOWLGraph(String iriString) throws OWLOntologyCreationException, IOException {
+ return new MinervaOWLGraphWrapper(parse(iriString));
+ }
+
+ public OWLOntology parse(String iriString) throws OWLOntologyCreationException, IOException {
+ return parseOWL(iriString);
+ }
+
+ public OWLOntology parseOBO(String source) throws IOException, OWLOntologyCreationException {
+ return parseOWL(source);
+ }
+
+ public OWLOntology parseOWL(String iriString) throws OWLOntologyCreationException {
+ IRI iri;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("parsing: "+iriString);
+ }
+ if (isIRI(iriString)) {
+ iri = IRI.create(iriString);
+ }
+ else {
+ iri = IRI.create(new File(iriString));
+ }
+ return parseOWL(iri);
+ }
+
+ private boolean isIRI(String iriString) {
+ return iriString.startsWith("file:") || iriString.startsWith("http:") || iriString.startsWith("https:");
+ }
+
+ public OWLOntology parseOWL(IRI iri) throws OWLOntologyCreationException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("parsing: "+iri.toString()+" using "+manager);
+ }
+ OWLOntology ont;
+ try {
+ ont = manager.loadOntology(iri);
+ } catch (OWLOntologyAlreadyExistsException e) {
+ // Trying to recover from exception
+ OWLOntologyID ontologyID = e.getOntologyID();
+ ont = manager.getOntology(ontologyID);
+ if (ont == null) {
+ // throw original exception, if no ontology could be found
+ // never return null ontology
+ throw e;
+ }
+ LOG.info("Skip already loaded ontology: "+iri);
+ } catch (OWLOntologyDocumentAlreadyExistsException e) {
+ // Trying to recover from exception
+ IRI duplicate = e.getOntologyDocumentIRI();
+ ont = manager.getOntology(duplicate);
+ if (ont == null) {
+ for(OWLOntology managed : manager.getOntologies()) {
+ Optional managedIRI = managed.getOntologyID().getOntologyIRI();
+ if(managedIRI.isPresent() && duplicate.equals(managedIRI.get())) {
+ LOG.info("Skip already loaded ontology: "+iri);
+ ont = managed;
+ break;
+ }
+ }
+ }
+ if (ont == null) {
+ // throw original exception, if no ontology could be found
+ // never return null ontology
+ throw e;
+ }
+ }
+ return ont;
+ }
+
+// public void saveOWL(OWLOntology ont, String file) throws OWLOntologyStorageException, IOException {
+// OWLDocumentFormat owlFormat = new RDFXMLDocumentFormat();
+// saveOWL(ont, owlFormat, file);
+// }
+// public void saveOWL(OWLOntology ont, OWLDocumentFormat owlFormat, String file) throws OWLOntologyStorageException, IOException {
+// if ((owlFormat instanceof OBODocumentFormat) ||
+// (owlFormat instanceof OWLOboGraphsFormat) ||
+// (owlFormat instanceof OWLOboGraphsYamlFormat) ||
+// (owlFormat instanceof OWLJSONFormat) ||
+// (owlFormat instanceof OWLJsonLDFormat)){
+// try {
+// FileOutputStream os = new FileOutputStream(new File(file));
+// saveOWL(ont, owlFormat, os);
+// } catch (FileNotFoundException e) {
+// throw new OWLOntologyStorageException("Could not open file: "+file, e);
+// }
+// }
+// else {
+// IRI iri;
+// if (file.startsWith("file://")) {
+// iri = IRI.create(file);
+// }
+// else {
+// iri = IRI.create(new File(file));
+// }
+// manager.saveOntology(ont, owlFormat, iri);
+// }
+// }
+// public void saveOWL(OWLOntology ont, OWLDocumentFormat owlFormat,
+// OutputStream outputStream) throws OWLOntologyStorageException, IOException {
+// if (owlFormat instanceof OBODocumentFormat && this.isCheckOboDoc == false) {
+// // special work-around for skipping the OBO validation before write
+// // see also OWL-API issue: https://github.com/owlcs/owlapi/issues/290
+// // see also saveOWL(OWLOntology, OWLOntologyFormat, String) for redundant code
+// Owl2Obo bridge = new Owl2Obo();
+// OBODoc doc;
+// BufferedWriter bw = null;
+// try {
+// doc = bridge.convert(ont);
+// OBOFormatWriter oboWriter = new OBOFormatWriter();
+// oboWriter.setCheckStructure(isCheckOboDoc);
+// bw = new BufferedWriter(new OutputStreamWriter(outputStream));
+// oboWriter.write(doc, bw);
+// } catch (IOException e) {
+// throw new OWLOntologyStorageException("Could not write ontology to output stream.", e);
+// }
+// finally {
+// IOUtils.closeQuietly(bw);
+// }
+// }
+// else if (owlFormat instanceof OWLJSONFormat) {
+//
+// BufferedWriter bw = null;
+// try {
+// bw = new BufferedWriter(new OutputStreamWriter(outputStream));
+// OWLGsonRenderer gr = new OWLGsonRenderer(new PrintWriter(outputStream));
+// gr.render(ont);
+// gr.flush();
+// }
+// finally {
+// IOUtils.closeQuietly(bw);
+// }
+// }
+// else if (owlFormat instanceof OWLOboGraphsFormat || owlFormat instanceof OWLOboGraphsYamlFormat) {
+//
+// // TODO:
+// FromOwl fromOwl = new FromOwl();
+// GraphDocument gd = fromOwl.generateGraphDocument(ont);
+// String out;
+// if (owlFormat instanceof OWLOboGraphsFormat)
+// out = OgJsonGenerator.render(gd);
+// else
+// out = OgYamlGenerator.render(gd);
+// BufferedWriter bw = null;
+// try {
+// bw = new BufferedWriter(new OutputStreamWriter(outputStream));
+// bw.write(out);
+// }
+// finally {
+// IOUtils.closeQuietly(bw);
+// }
+//
+// }
+// else if (owlFormat instanceof OWLJsonLDFormat) {
+//
+// //JsonLdStorer.register(manager); // Needed once per ontologyManager
+//
+// //TODO: fix this after https://github.com/stain/owlapi-jsonld/issues/4
+// //manager.saveOntology(ont, new JsonLdOntologyFormat(), outputStream);
+//
+// }
+// else {
+// manager.saveOntology(ont, owlFormat, outputStream);
+// }
+// }
+//
+// public OBODoc getOBOdoc() {
+// return obodoc;
+// }
+
+ /**
+ * Provide names for the {@link OBOFormatWriter} using an
+ * {@link MinervaOWLGraphWrapper}.
+ *
+ * @see OboAndOwlNameProvider use the {@link OboAndOwlNameProvider}, the
+ * pure OWL lookup is problematic for relations.
+ */
+ public static class OWLGraphWrapperNameProvider implements NameProvider {
+ private final MinervaOWLGraphWrapper graph;
+ private final String defaultOboNamespace;
+
+ /**
+ * @param graph
+ */
+ public OWLGraphWrapperNameProvider(MinervaOWLGraphWrapper graph) {
+ super();
+ this.graph = graph;
+ this.defaultOboNamespace = null;
+
+ }
+
+ /**
+ * @param graph
+ * @param defaultOboNamespace
+ */
+ public OWLGraphWrapperNameProvider(MinervaOWLGraphWrapper graph, String defaultOboNamespace) {
+ super();
+ this.graph = graph;
+ this.defaultOboNamespace = defaultOboNamespace;
+
+ }
+
+ /**
+ * @param graph
+ * @param oboDoc
+ *
+ * If an {@link OBODoc} is available use {@link OboAndOwlNameProvider}.
+ */
+ @Deprecated
+ public OWLGraphWrapperNameProvider(MinervaOWLGraphWrapper graph, OBODoc oboDoc) {
+ super();
+ this.graph = graph;
+ String defaultOboNamespace = null;
+ if (oboDoc != null) {
+ Frame headerFrame = oboDoc.getHeaderFrame();
+ if (headerFrame != null) {
+ defaultOboNamespace = headerFrame.getTagValue(OboFormatTag.TAG_DEFAULT_NAMESPACE, String.class);
+ }
+ }
+ this.defaultOboNamespace = defaultOboNamespace;
+
+ }
+
+ @Override
+ public String getName(String id) {
+ String name = null;
+ OWLObject obj = graph.getOWLObjectByIdentifier(id);
+ if (obj != null) {
+ name = graph.getLabel(obj);
+ }
+ return name;
+ }
+
+ @Override
+ public String getDefaultOboNamespace() {
+ return defaultOboNamespace;
+ }
+ }
+
+ /**
+ * Provide names for the {@link OBOFormatWriter} using an {@link OBODoc}
+ * first and an {@link MinervaOWLGraphWrapper} as secondary.
+ */
+ public static class OboAndOwlNameProvider extends OBODocNameProvider {
+
+ private final MinervaOWLGraphWrapper graph;
+
+ public OboAndOwlNameProvider(OBODoc oboDoc, MinervaOWLGraphWrapper wrapper) {
+ super(oboDoc);
+ this.graph = wrapper;
+ }
+
+ @Override
+ public String getName(String id) {
+ String name = super.getName(id);
+ if (name != null) {
+ return name;
+ }
+ OWLObject owlObject = graph.getOWLObjectByIdentifier(id);
+ if (owlObject != null) {
+ name = graph.getLabel(owlObject);
+ }
+ return name;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/minerva-core/src/main/java/owltools/util/OwlHelper.java b/minerva-core/src/main/java/owltools/util/OwlHelper.java
new file mode 100644
index 00000000..7c90fa5f
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/util/OwlHelper.java
@@ -0,0 +1,373 @@
+package owltools.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+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.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLEntity;
+import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
+import org.semanticweb.owlapi.model.OWLIndividual;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
+import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
+import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
+import org.semanticweb.owlapi.model.OWLSubPropertyAxiom;
+
+public class OwlHelper {
+
+ private OwlHelper() {
+ // no instances
+ }
+
+ public static Set getAnnotations(OWLEntity e, OWLAnnotationProperty property, OWLOntology ont) {
+ Set annotations;
+ if (e != null && property != null && ont != null) {
+ annotations = new HashSet<>();
+ for (OWLAnnotationAssertionAxiom ax : ont.getAnnotationAssertionAxioms(e.getIRI())) {
+ if (property.equals(ax.getProperty())) {
+ annotations.add(ax.getAnnotation());
+ }
+ }
+ }
+ else {
+ annotations = Collections.emptySet();
+ }
+ return annotations;
+ }
+
+ public static Set getAnnotations(OWLEntity e, OWLOntology ont) {
+ Set annotations;
+ if (e != null && ont != null) {
+ Set axioms = ont.getAnnotationAssertionAxioms(e.getIRI());
+ annotations = new HashSet<>(axioms.size());
+ for(OWLAnnotationAssertionAxiom ax : axioms) {
+ annotations.add(ax.getAnnotation());
+ }
+ }
+ else {
+ annotations = Collections.emptySet();
+ }
+ return annotations;
+ }
+
+ public static Set getAnnotations(OWLEntity e, Set ontolgies) {
+ Set annotations;
+ if (e != null && ontolgies != null && !ontolgies.isEmpty()) {
+ annotations = new HashSet<>();
+ for(OWLOntology ont : ontolgies) {
+ annotations.addAll(getAnnotations(e, ont));
+ }
+ }
+ else {
+ annotations = Collections.emptySet();
+ }
+ return annotations;
+ }
+
+ public static Set getEquivalentClasses(OWLClass cls, OWLOntology ont) {
+ Set expressions;
+ if (cls != null && ont != null) {
+ Set axioms = ont.getEquivalentClassesAxioms(cls);
+ expressions = new HashSet<>(axioms.size());
+ for(OWLEquivalentClassesAxiom ax : axioms) {
+ expressions.addAll(ax.getClassExpressions());
+ }
+ expressions.remove(cls); // set should not contain the query cls
+ }
+ else {
+ expressions = Collections.emptySet();
+ }
+ return expressions;
+ }
+
+ public static Set getEquivalentClasses(OWLClass cls, Set ontologies) {
+ Set expressions;
+ if (cls != null && ontologies != null && ontologies.isEmpty() == false) {
+ expressions = new HashSet<>();
+ for(OWLOntology ont : ontologies) {
+ expressions.addAll(getEquivalentClasses(cls, ont));
+ }
+ }
+ else {
+ expressions = Collections.emptySet();
+ }
+ return expressions;
+ }
+
+ public static Set getSuperClasses(OWLClass subCls, OWLOntology ont) {
+ Set result;
+ if (subCls != null && ont != null) {
+ result = new HashSet<>();
+ Set axioms = ont.getSubClassAxiomsForSubClass(subCls);
+ for (OWLSubClassOfAxiom axiom : axioms) {
+ result.add(axiom.getSuperClass());
+ }
+ }
+ else {
+ result = Collections.emptySet();
+ }
+ return result;
+ }
+
+ public static Set getSuperClasses(OWLClass subCls, Set ontologies) {
+ Set result;
+ if (subCls != null && ontologies != null && ontologies.isEmpty() == false) {
+ result = new HashSet<>();
+ for(OWLOntology ont : ontologies) {
+ result.addAll(getSuperClasses(subCls, ont));
+ }
+ }
+ else {
+ result = Collections.emptySet();
+ }
+ return result;
+ }
+
+ public static Set getSubClasses(OWLClass superCls, OWLOntology ont) {
+ Set result;
+ if (superCls != null && ont != null) {
+ result = new HashSet<>();
+ Set axioms = ont.getSubClassAxiomsForSuperClass(superCls);
+ for (OWLSubClassOfAxiom axiom : axioms) {
+ result.add(axiom.getSubClass());
+ }
+ }
+ else {
+ result = Collections.emptySet();
+ }
+ return result;
+ }
+
+ public static Set getSubClasses(OWLClass superCls, Set ontologies) {
+ Set result;
+ if (superCls != null && ontologies != null && ontologies.isEmpty() == false) {
+ result = new HashSet<>();
+ for(OWLOntology ont : ontologies) {
+ result.addAll(getSubClasses(superCls, ont));
+ }
+ }
+ else {
+ result = Collections.emptySet();
+ }
+ return result;
+ }
+
+ public static Set getTypes(OWLIndividual i, OWLOntology ont) {
+ Set types;
+ if (ont != null && i != null && i.isNamed()) {
+ types = getTypes(i.asOWLNamedIndividual(), ont);
+ }
+ else {
+ types = Collections.emptySet();
+ }
+ return types;
+ }
+
+ public static Set getTypes(OWLNamedIndividual i, OWLOntology ont) {
+ Set types;
+ if (i != null && ont != null) {
+ types = new HashSet<>();
+ for (OWLClassAssertionAxiom axiom : ont.getClassAssertionAxioms(i)) {
+ types.add(axiom.getClassExpression());
+ }
+ }
+ else {
+ types = Collections.emptySet();
+ }
+ return types;
+ }
+
+ public static Set getTypes(OWLNamedIndividual i, Set ontologies) {
+ Set types;
+ if (i != null && ontologies != null && ontologies.isEmpty() == false) {
+ types = new HashSet<>();
+ for(OWLOntology ont : ontologies) {
+ types.addAll(getTypes(i, ont));
+ }
+ }
+ else {
+ types = Collections.emptySet();
+ }
+ return types;
+ }
+
+ public static Map> getObjectPropertyValues(OWLIndividual i, OWLOntology ont) {
+ Set axioms = ont.getObjectPropertyAssertionAxioms(i);
+ Map> result = new HashMap<>();
+ for(OWLObjectPropertyAssertionAxiom ax : axioms) {
+ Set inds = result.get(ax.getProperty());
+ if (inds == null) {
+ inds = new HashSet<>();
+ result.put(ax.getProperty(), inds);
+ }
+ inds.add(ax.getObject());
+ }
+ return result;
+ }
+
+ public static boolean isTransitive(OWLObjectPropertyExpression property, OWLOntology ontology) {
+ return !ontology.getTransitiveObjectPropertyAxioms(property).isEmpty();
+ }
+
+ public static boolean isTransitive(OWLObjectPropertyExpression property, Set ontologies) {
+ for (OWLOntology ont : ontologies) {
+ if (isTransitive(property, ont)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static Set getSubProperties(OWLAnnotationProperty superProp, OWLOntology ont) {
+ return getSubProperties(superProp, Collections.singleton(ont));
+ }
+
+ public static Set getSubProperties(OWLAnnotationProperty superProp, Set ontologies) {
+ Set result = new HashSet();
+ for (OWLOntology ont : ontologies) {
+ for (OWLSubAnnotationPropertyOfAxiom ax : ont.getAxioms(AxiomType.SUB_ANNOTATION_PROPERTY_OF)) {
+ if (ax.getSuperProperty().equals(superProp)) {
+ result.add(ax.getSubProperty());
+ }
+ }
+ }
+ return result;
+ }
+
+ public static Set getSuperProperties(OWLAnnotationProperty subProp, OWLOntology ont) {
+ return getSuperProperties(subProp, Collections.singleton(ont));
+ }
+
+ public static Set getSuperProperties(OWLAnnotationProperty subProp, Set ontologies) {
+ Set result = new HashSet();
+ for (OWLOntology ont : ontologies) {
+ for (OWLSubAnnotationPropertyOfAxiom ax : ont.getAxioms(AxiomType.SUB_ANNOTATION_PROPERTY_OF)) {
+ if (ax.getSubProperty().equals(subProp)) {
+ result.add(ax.getSuperProperty());
+ }
+ }
+ }
+ return result;
+ }
+
+ public static Set getSuperProperties(OWLObjectPropertyExpression prop, OWLOntology ont) {
+ Set result = new HashSet<>();
+ Set axioms = ont.getObjectSubPropertyAxiomsForSubProperty(prop);
+ for (OWLSubPropertyAxiom axiom : axioms) {
+ result.add(axiom.getSuperProperty());
+ }
+ return result;
+ }
+
+ public static Set getSubProperties(OWLObjectPropertyExpression prop, OWLOntology ont) {
+ Set results = new HashSet<>();
+ Set axioms = ont.getObjectSubPropertyAxiomsForSuperProperty(prop);
+ for (OWLSubObjectPropertyOfAxiom axiom : axioms) {
+ results.add(axiom.getSubProperty());
+ }
+ return results;
+ }
+
+ public static String getIdentifier(IRI iriId, OWLOntology baseOntology) {
+
+ if(iriId == null)
+ return null;
+
+ String iri = iriId.toString();
+
+ /*
+ // canonical IRIs
+ if (iri.startsWith("http://purl.obolibrary.org/obo/")) {
+ String canonicalId = iri.replace("http://purl.obolibrary.org/obo/", "");
+ }
+ */
+
+ int indexSlash = iri.lastIndexOf("/");
+
+
+ String prefixURI = null;
+ String id = null;
+
+ if(indexSlash>-1){
+ prefixURI = iri.substring(0, indexSlash+1);
+ id = iri.substring(indexSlash+1);
+ }else
+ id = 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){
+ // prefixURI = prefixURI + s[0] + "#";
+
+ // if(!(s[1].contains("#") || s[1].contains("_"))){
+ String prefix = "";
+
+ if("owl".equals(s[0]) || "rdf".equals(s[0]) || "rdfs".equals(s[0])){
+ prefix = s[0] + ":";
+ }
+ // TODO: the following implements behavior in current spec, but this leads to undesirable results
+ /*
+ else if (baseOntology != null) {
+ String oid = getOntologyId(baseOntology); // OBO-style ID
+ if (oid.equals(s[0]))
+ prefix = "";
+ else {
+ return iri;
+ }
+ //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 = java.net.URLDecoder.decode(s[1]);
+ return s[0] + ":" + localId;
+ }
+ if(s.length > 2 && !id.contains("#")) {
+ if (s[s.length-1].replaceAll("[0-9]","").length() == 0) {
+ StringBuffer sb = new StringBuffer();
+ 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;
+ }
+
+}
diff --git a/minerva-core/src/main/java/owltools/version/VersionInfo.java b/minerva-core/src/main/java/owltools/version/VersionInfo.java
new file mode 100644
index 00000000..6e00f473
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/version/VersionInfo.java
@@ -0,0 +1,50 @@
+package owltools.version;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+public class VersionInfo {
+
+ private VersionInfo() {
+ // make constructor private
+ }
+
+ /**
+ * Try to retrieve the value for the given key from a manifest file.
+ * Returns the first match or null, if it does not exist.
+ *
+ * @param key
+ * @return string value or null
+ */
+ public static String getManifestVersion(String key) {
+ Enumeration resEnum;
+ try {
+ resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
+ while (resEnum.hasMoreElements()) {
+ try {
+ URL url = resEnum.nextElement();
+ InputStream is = url.openStream();
+ if (is != null) {
+ Manifest manifest = new Manifest(is);
+ Attributes mainAttribs = manifest.getMainAttributes();
+ String version = mainAttribs.getValue(key);
+ if(version != null) {
+ return version;
+ }
+ }
+ }
+ catch (Exception exception) {
+ // Silently ignore problematic manifests in classpath
+ }
+ }
+ } catch (IOException ioException) {
+ // Silently ignore any IO issues with manifests
+ }
+ return null;
+ }
+}
diff --git a/minerva-core/src/main/java/owltools/vocab/OBONamespaces.java b/minerva-core/src/main/java/owltools/vocab/OBONamespaces.java
new file mode 100644
index 00000000..b816f4f8
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/vocab/OBONamespaces.java
@@ -0,0 +1,13 @@
+package owltools.vocab;
+
+public enum OBONamespaces {
+ GO("GO"),
+ BFO("BFO"),
+ GOREL("GOREL"),
+ RO("RO");
+
+ final String ns;
+ OBONamespaces(String ns) {
+ this.ns = ns;
+ }
+}
diff --git a/minerva-core/src/main/java/owltools/vocab/OBOUpperVocabulary.java b/minerva-core/src/main/java/owltools/vocab/OBOUpperVocabulary.java
new file mode 100644
index 00000000..3fd88ede
--- /dev/null
+++ b/minerva-core/src/main/java/owltools/vocab/OBOUpperVocabulary.java
@@ -0,0 +1,74 @@
+package owltools.vocab;
+
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLOntology;
+
+
+public enum OBOUpperVocabulary {
+
+ /**
+ *
+ */
+ GO_molecular_function(OBONamespaces.GO, "0003674"),
+ GO_biological_process(OBONamespaces.GO, "0008150"),
+ GO_cellular_process(OBONamespaces.GO, "0009987"),
+ BFO_part_of(OBONamespaces.BFO, "0000050"),
+ BFO_has_part(OBONamespaces.BFO, "0000051"),
+ BFO_occurs_in(OBONamespaces.BFO, "0000066"),
+ RO_regulates(OBONamespaces.RO, "0002211"),
+ RO_negatively_regulates(OBONamespaces.RO, "0002212"),
+ RO_positively_regulates(OBONamespaces.RO, "0002213"),
+ RO_starts(OBONamespaces.RO, "0002223"),
+ RO_ends(OBONamespaces.RO, "0002229"),
+ RO_gene_product_of(OBONamespaces.RO, "0002204"),
+ RO_involved_in(OBONamespaces.RO, "0002331"),
+ GOREL_enabled_by(OBONamespaces.RO, "0002333"),
+ GOREL_directly_provides_input_for(OBONamespaces.RO, "0002413");
+
+
+
+
+ final IRI iri;
+ final OBONamespaces namespace;
+ final String id;
+
+ public static final String OBO = "http://purl.obolibrary.org/obo/";
+
+ OBOUpperVocabulary(OBONamespaces ns, String id) {
+ this.namespace = ns;
+ this.id = id;
+ iri = IRI.create(OBO + ns + "_" + id);
+ }
+
+
+
+ public IRI getIRI() {
+ return iri;
+ }
+
+
+ public OWLClass getOWLClass(OWLDataFactory f) {
+ return f.getOWLClass(iri);
+ }
+ public OWLClass getOWLClass(OWLOntology o) {
+ return getOWLClass(o.getOWLOntologyManager().getOWLDataFactory());
+ }
+
+ public OWLObjectProperty getObjectProperty(OWLDataFactory f) {
+ return f.getOWLObjectProperty(iri);
+ }
+ public OWLObjectProperty getObjectProperty(OWLOntology o) {
+ return getObjectProperty(o.getOWLOntologyManager().getOWLDataFactory());
+ }
+
+ @Override
+ public String toString() {
+ return iri.toString();
+ }
+
+
+
+}
diff --git a/minerva-core/src/test/java/org/geneontology/minerva/BlazegraphMolecularModelManagerTest.java b/minerva-core/src/test/java/org/geneontology/minerva/BlazegraphMolecularModelManagerTest.java
index cc21f7fc..bd1a39d5 100644
--- a/minerva-core/src/test/java/org/geneontology/minerva/BlazegraphMolecularModelManagerTest.java
+++ b/minerva-core/src/test/java/org/geneontology/minerva/BlazegraphMolecularModelManagerTest.java
@@ -18,7 +18,7 @@
import org.openrdf.query.TupleQueryResult;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.*;
-import owltools.OWLToolsTestBasics;
+//import owltools.OWLToolsTestBasics;
import java.io.File;
import java.io.FileInputStream;
@@ -27,7 +27,7 @@
import static org.junit.Assert.*;
-public class BlazegraphMolecularModelManagerTest extends OWLToolsTestBasics {
+public class BlazegraphMolecularModelManagerTest {
private final CurieHandler curieHandler = DefaultCurieHandler.getDefaultHandler();
@Rule
diff --git a/minerva-core/src/test/java/org/geneontology/minerva/UndoAwareMolecularModelManagerTest.java b/minerva-core/src/test/java/org/geneontology/minerva/UndoAwareMolecularModelManagerTest.java
index d3755651..3e472e62 100644
--- a/minerva-core/src/test/java/org/geneontology/minerva/UndoAwareMolecularModelManagerTest.java
+++ b/minerva-core/src/test/java/org/geneontology/minerva/UndoAwareMolecularModelManagerTest.java
@@ -24,13 +24,12 @@
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLOntology;
-import owltools.OWLToolsTestBasics;
-import owltools.graph.OWLGraphWrapper;
+
import owltools.io.ParserWrapper;
-public class UndoAwareMolecularModelManagerTest extends OWLToolsTestBasics {
+public class UndoAwareMolecularModelManagerTest {
- static OWLGraphWrapper g = null;
+ static MinervaOWLGraphWrapper g = null;
static CurieHandler curieHandler = DefaultCurieHandler.getDefaultHandler();
static UndoAwareMolecularModelManager m3 = null;
diff --git a/minerva-core/src/test/java/org/geneontology/minerva/json/MolecularModelJsonRendererTest.java b/minerva-core/src/test/java/org/geneontology/minerva/json/MolecularModelJsonRendererTest.java
index 6d1ea938..0e8d2f9a 100644
--- a/minerva-core/src/test/java/org/geneontology/minerva/json/MolecularModelJsonRendererTest.java
+++ b/minerva-core/src/test/java/org/geneontology/minerva/json/MolecularModelJsonRendererTest.java
@@ -10,6 +10,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
+import org.geneontology.minerva.MinervaOWLGraphWrapper;
import org.geneontology.minerva.MolecularModelManager.UnknownIdentifierException;
import org.geneontology.minerva.curie.CurieHandler;
import org.geneontology.minerva.curie.DefaultCurieHandler;
@@ -35,12 +36,11 @@
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
-import owltools.graph.OWLGraphWrapper;
import owltools.io.ParserWrapper;
public class MolecularModelJsonRendererTest {
- private static OWLGraphWrapper g = null;
+ private static MinervaOWLGraphWrapper g = null;
private static CurieHandler curieHandler = DefaultCurieHandler.getDefaultHandler();
private static OWLOntologyManager m = null;
private static OWLDataFactory f = null;
@@ -51,7 +51,7 @@ public static void setUpBeforeClass() throws Exception {
ParserWrapper pw = new ParserWrapper();
File file = new File("src/test/resources/mgi-go.obo").getCanonicalFile();
OWLOntology ont = pw.parseOWL(IRI.create(file));
- g = new OWLGraphWrapper(ont);
+ g = new MinervaOWLGraphWrapper(ont);
f = g.getDataFactory();
m = g.getManager();
partOf = g.getOWLObjectPropertyByIdentifier("BFO:0000050");
@@ -162,7 +162,7 @@ private void testSimpleClassExpression(OWLClassExpression ce, String expectedJso
assertNotNull(jsonOwlIndividualParse);
assertEquals(jsonOwlIndividualOriginal, jsonOwlIndividualParse);
- Set ces = TestJsonOwlObjectParser.parse(new OWLGraphWrapper(o), jsonOwlIndividualParse.type);
+ Set ces = TestJsonOwlObjectParser.parse(new MinervaOWLGraphWrapper(o), jsonOwlIndividualParse.type);
assertEquals(1, ces.size());
assertEquals(ce, ces.iterator().next());
}
@@ -231,7 +231,7 @@ private static void addFact(OWLOntology o, OWLNamedIndividual source, OWLNamedIn
}
static class TestJsonOwlObjectParser {
- static OWLClassExpression parse(OWLGraphWrapper g, JsonOwlObject expression)
+ static OWLClassExpression parse(MinervaOWLGraphWrapper g, JsonOwlObject expression)
throws Exception {
if (expression == null) {
throw new Exception("Missing expression: null is not a valid expression.");
@@ -285,7 +285,7 @@ else if (JsonOwlObjectType.UnionOf == expression.type) {
}
}
- static OWLClassExpression parse(OWLGraphWrapper g, JsonOwlObject[] expressions, JsonOwlObjectType type)
+ static OWLClassExpression parse(MinervaOWLGraphWrapper g, JsonOwlObject[] expressions, JsonOwlObjectType type)
throws Exception {
if (expressions.length == 0) {
throw new Exception("Missing expressions: empty expression list is not allowed.");
@@ -309,7 +309,7 @@ else if (type == JsonOwlObjectType.IntersectionOf) {
}
}
- static Set parse(OWLGraphWrapper g, JsonOwlObject[] expressions)
+ static Set parse(MinervaOWLGraphWrapper g, JsonOwlObject[] expressions)
throws Exception {
if (expressions.length == 0) {
throw new Exception("Missing expressions: empty expression list is not allowed.");
diff --git a/minerva-lookup/pom.xml b/minerva-lookup/pom.xml
index 047d92b1..2bb805c6 100644
--- a/minerva-lookup/pom.xml
+++ b/minerva-lookup/pom.xml
@@ -30,10 +30,6 @@
minerva-core
${project.parent.version}
-
- org.bbop
- golr-client
-
diff --git a/minerva-lookup/src/main/java/org/bbop/golr/java/AbstractRetrieveGolr.java b/minerva-lookup/src/main/java/org/bbop/golr/java/AbstractRetrieveGolr.java
new file mode 100644
index 00000000..9a2ab243
--- /dev/null
+++ b/minerva-lookup/src/main/java/org/bbop/golr/java/AbstractRetrieveGolr.java
@@ -0,0 +1,250 @@
+package org.bbop.golr.java;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.utils.URIBuilder;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonSyntaxException;
+
+public abstract class AbstractRetrieveGolr {
+
+ protected static final Gson GSON = new GsonBuilder().create();
+
+ private final String server;
+ private int retryCount;
+
+ public AbstractRetrieveGolr(String server) {
+ this(server, 3);
+ }
+
+ public AbstractRetrieveGolr(String server, int retryCount) {
+ this.server = server;
+ this.retryCount = retryCount;
+ }
+
+ protected abstract boolean isIndentJson();
+
+ protected abstract List getRelevantFields();
+
+ URI createGolrRequest(List tagvalues, String category, int start, int pagination) throws IOException {
+ try {
+ URIBuilder builder = new URIBuilder(server);
+ String currentPath = StringUtils.trimToEmpty(builder.getPath());
+ builder.setPath(currentPath+"/select");
+ builder.addParameter("defType", "edismax");
+ builder.addParameter("qt", "standard");
+ builder.addParameter("wt", "json");
+ if (isIndentJson()) {
+ builder.addParameter("indent","on");
+ }
+ builder.addParameter("fl",StringUtils.join(getRelevantFields(), ','));
+ builder.addParameter("facet","false");
+ builder.addParameter("json.nl","arrarr");
+ builder.addParameter("q","*:*");
+ builder.addParameter("rows", Integer.toString(pagination));
+ builder.addParameter("start", Integer.toString(start));
+ builder.addParameter("fq", "document_category:\""+category+"\"");
+ for (String [] tagvalue : tagvalues) {
+ if (tagvalue.length == 2) {
+ builder.addParameter("fq", tagvalue[0]+":\""+tagvalue[1]+"\"");
+ }
+ else if (tagvalue.length > 2) {
+ // if there is more than one value, assume that this is an OR query
+ StringBuilder value = new StringBuilder();
+ value.append(tagvalue[0]).append(":(");
+ for (int i = 1; i < tagvalue.length; i++) {
+ if (i > 1) {
+ value.append(" OR ");
+ }
+ value.append('"').append(tagvalue[i]).append('"');
+ }
+ value.append(')');
+ builder.addParameter("fq", value.toString());
+ }
+ }
+ return builder.build();
+ } catch (URISyntaxException e) {
+ throw new IOException("Could not build URI for Golr request", e);
+ }
+ }
+
+ protected String getJsonStringFromUri(URI uri) throws IOException {
+ logRequest(uri);
+ return getJsonStringFromUri(uri, retryCount);
+ }
+
+ protected String getJsonStringFromUri(URI uri, int retryCount) throws IOException {
+ final URL url = uri.toURL();
+ final HttpURLConnection connection;
+ InputStream response = null;
+ // setup and open (actual connection)
+ try {
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(true); // warning does not follow redirects from http to https
+ response = connection.getInputStream(); // opens the connection to the server
+ }
+ catch (IOException e) {
+ IOUtils.closeQuietly(response);
+ return retryRequest(uri, e, retryCount);
+ }
+ // check status code
+ final int status;
+ try {
+ status = connection.getResponseCode();
+ } catch (IOException e) {
+ IOUtils.closeQuietly(response);
+ return retryRequest(uri, e, retryCount);
+ }
+ // handle unexpected status code
+ if (status != 200) {
+ // try to check error stream
+ String errorMsg = getErrorMsg(connection);
+
+ // construct message for exception
+ StringBuilder sb = new StringBuilder("Unexpected HTTP status code: "+status);
+
+ if (errorMsg != null) {
+ sb.append(" Details: ");
+ sb.append(errorMsg);
+ }
+ IOException e = new IOException(sb.toString());
+ return retryRequest(uri, e, retryCount);
+ }
+
+ // try to detect charset
+ String contentType = connection.getHeaderField("Content-Type");
+ String charset = null;
+
+ if (contentType != null) {
+ for (String param : contentType.replace(" ", "").split(";")) {
+ if (param.startsWith("charset=")) {
+ charset = param.split("=", 2)[1];
+ break;
+ }
+ }
+ }
+
+ // get string response from stream
+ String json;
+ try {
+ if (charset != null) {
+ json = IOUtils.toString(response, charset);
+ }
+ else {
+ json = IOUtils.toString(response);
+ }
+ } catch (IOException e) {
+ return retryRequest(uri, e, retryCount);
+ }
+ finally {
+ IOUtils.closeQuietly(response);
+ }
+ return json;
+ }
+
+ protected String retryRequest(URI uri, IOException e, int retryCount) throws IOException {
+ if (retryCount > 0) {
+ int remaining = retryCount - 1;
+ defaultRandomWait();
+ logRetry(uri, e, remaining);
+ return getJsonStringFromUri(uri, remaining);
+ }
+ logRequestError(uri, e);
+ throw e;
+ }
+
+ private static String getErrorMsg(HttpURLConnection connection) {
+ String errorMsg = null;
+ InputStream errorStream = null;
+ try {
+ errorStream = connection.getErrorStream();
+ if (errorStream != null) {
+ errorMsg =IOUtils.toString(errorStream);
+ }
+ errorMsg = StringUtils.trimToNull(errorMsg);
+ }
+ catch (IOException e) {
+ // ignore errors, while trying to retrieve the error message
+ }
+ finally {
+ IOUtils.closeQuietly(errorStream);
+ }
+ return errorMsg;
+ }
+
+ protected void defaultRandomWait() {
+ // wait a random interval between 400 and 1500 ms
+ randomWait(400, 1500);
+ }
+
+ protected void randomWait(int min, int max) {
+ Random random = new Random(System.currentTimeMillis());
+ long wait = min + random.nextInt((max - min));
+ try {
+ Thread.sleep(wait);
+ } catch (InterruptedException exception) {
+ // ignore
+ }
+ }
+
+
+ protected void logRequest(URI uri) {
+ // do nothing
+ // hook to implement logging of requests
+ }
+
+ protected void logRequestError(URI uri, IOException exception) {
+ // do nothing
+ // hook to implement logging of request errors
+ }
+
+ protected void logRetry(URI uri, IOException exception, int remaining) {
+ // do nothing
+ // hook to implement logging of a retry
+ }
+
+
+ protected > T parseGolrResponse(String response, Class clazz) throws IOException {
+ try {
+ T envelope = GSON.fromJson(response, clazz);
+ if (envelope == null || envelope.response == null || envelope.responseHeader == null) {
+ throw new IOException("Unexpected response content in GOLR response.");
+ }
+ if ("0".equals(envelope.responseHeader.status) == false) {
+ throw new IOException("Unexpected response status in GOLR response header: "+envelope.responseHeader.status);
+ }
+ return envelope;
+ } catch (JsonSyntaxException e) {
+ throw new IOException("Could not parse JSON response.", e);
+ }
+ }
+
+ static class GolrEnvelope {
+ GolrResponseHeader responseHeader;
+ GolrResponse response;
+ }
+
+ static class GolrResponseHeader {
+ String status;
+ String QTime;
+ Object params;
+ }
+
+ static class GolrResponse {
+ int numFound;
+ int start;
+ T[] docs;
+ }
+
+}
diff --git a/minerva-lookup/src/main/java/org/bbop/golr/java/RetrieveGolrAnnotations.java b/minerva-lookup/src/main/java/org/bbop/golr/java/RetrieveGolrAnnotations.java
new file mode 100644
index 00000000..d30bc505
--- /dev/null
+++ b/minerva-lookup/src/main/java/org/bbop/golr/java/RetrieveGolrAnnotations.java
@@ -0,0 +1,319 @@
+package org.bbop.golr.java;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.bbop.golr.java.RetrieveGolrAnnotations.GolrAnnotationExtension.GolrAnnotationExtensionEntry.GolrAnnotationExtensionRelation;
+
+//import owltools.gaf.Bioentity;
+//import owltools.gaf.ExtensionExpression;
+//import owltools.gaf.GafDocument;
+//import owltools.gaf.GeneAnnotation;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonSyntaxException;
+
+public class RetrieveGolrAnnotations extends AbstractRetrieveGolr{
+
+ static boolean JSON_INDENT_FLAG = false;
+ static int PAGINATION_CHUNK_SIZE = 100;
+
+ private static final Gson GSON = new GsonBuilder().create();
+
+ /*
+ * This flag indicates that missing c16 data, due to malformed JSON is acceptable.
+ */
+ private final boolean ignoreC16ParseErrors;
+
+ public RetrieveGolrAnnotations(String server) {
+ this(server, 3, false);
+ }
+
+ public RetrieveGolrAnnotations(String server, int retryCount, boolean ignoreC16ParseErrors) {
+ super(server, retryCount);
+ this.ignoreC16ParseErrors = ignoreC16ParseErrors;
+ }
+
+ @Override
+ protected boolean isIndentJson() {
+ return JSON_INDENT_FLAG;
+ }
+
+ @Override
+ protected List getRelevantFields() {
+ return GolrAnnotationDocument.getRelevantFields();
+ }
+
+// public GafDocument convert(List golrAnnotationDocuments) throws IOException {
+// Map entities = new HashMap