JAL-1705 JAL-1191 SequenceOntologyLite added as hard-coded alternative
[jalview.git] / src / jalview / io / gff / SequenceOntology.java
index 685b83e..b069eef 100644 (file)
@@ -7,6 +7,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -25,32 +26,8 @@ import org.biojava.nbio.ontology.utils.Annotation;
  * A wrapper class that parses the Sequence Ontology and exposes useful access
  * methods. This version uses the BioJava parser.
  */
-public class SequenceOntology
+class SequenceOntology implements SequenceOntologyI
 {
-
-  /*
-   * selected commonly used values for quick reference
-   */
-  // SO:0000316
-  public static final String CDS = "CDS";
-
-  // SO:0001060
-  public static final String SEQUENCE_VARIANT = "sequence_variant";
-
-  // SO:0000147
-  public static final String EXON = "exon";
-
-  // SO:0000673
-  public static final String TRANSCRIPT = "transcript";
-
-  // SO:0000704
-  public static final String GENE = "gene";
-
-  /*
-   * singleton instance of this class
-   */
-  private static SequenceOntology instance;
-
   /*
    * the parsed Ontology data as modelled by BioJava
    */
@@ -73,26 +50,18 @@ public class SequenceOntology
    */
   private Map<Term, List<Term>> termIsA;
 
-  /**
-   * Returns singleton instance
-   * 
-   * @return
-   */
-  public synchronized static SequenceOntology getInstance()
-  {
-    if (instance == null)
-    {
-      instance = new SequenceOntology();
-    }
-    return instance;
-  }
+  private List<String> termsFound;
+
+  private List<String> termsNotFound;
 
   /**
-   * Private constructor to enforce use of singleton. Parses and caches the SO
-   * OBO data file.
+   * Package private constructor to enforce use of singleton. Parses and caches
+   * the SO OBO data file.
    */
-  private SequenceOntology()
+  SequenceOntology()
   {
+    termsFound = new ArrayList<String>();
+    termsNotFound = new ArrayList<String>();
     termsByDescription = new HashMap<String, Term>();
     termIsA = new HashMap<Term, List<Term>>();
 
@@ -248,7 +217,7 @@ public class SequenceOntology
    */
   public boolean isNucleotideMatch(String soTerm)
   {
-    return isA(soTerm, "nucleotide_match");
+    return isA(soTerm, NUCLEOTIDE_MATCH);
   }
 
   /**
@@ -261,7 +230,7 @@ public class SequenceOntology
    */
   public boolean isProteinMatch(String soTerm)
   {
-    return isA(soTerm, "protein_match");
+    return isA(soTerm, PROTEIN_MATCH);
   }
 
   /**
@@ -274,7 +243,7 @@ public class SequenceOntology
    */
   public boolean isPolypeptide(String soTerm)
   {
-    return isA(soTerm, "polypeptide");
+    return isA(soTerm, POLYPEPTIDE);
   }
 
   /**
@@ -285,23 +254,70 @@ public class SequenceOntology
    * @param parent
    * @return
    */
+  @Override
   public boolean isA(String child, String parent)
   {
+    if (child == null || parent == null)
+    {
+      return false;
+    }
     /*
      * optimise trivial checks like isA("CDS", "CDS")
      */
     if (child.equals(parent))
     {
+      termFound(child);
       return true;
     }
 
     Term childTerm = getTerm(child);
+    if (childTerm != null)
+    {
+      termFound(child);
+    }
+    else
+    {
+      termNotFound(child);
+    }
     Term parentTerm = getTerm(parent);
 
     return termIsA(childTerm, parentTerm);
   }
 
   /**
+   * Records a valid term queried for, for reporting purposes
+   * 
+   * @param term
+   */
+  private void termFound(String term)
+  {
+    synchronized (termsFound)
+    {
+      if (!termsFound.contains(term))
+      {
+        termsFound.add(term);
+      }
+    }
+  }
+
+  /**
+   * Records an invalid term queried for, for reporting purposes
+   * 
+   * @param term
+   */
+  private void termNotFound(String term)
+  {
+    synchronized (termsNotFound)
+    {
+      if (!termsNotFound.contains(term))
+      {
+        System.err.println("SO term " + term + " invalid");
+        termsNotFound.add(term);
+      }
+    }
+  }
+
+  /**
    * Returns true if the childTerm 'isA' parentTerm (directly or indirectly).
    * 
    * @param childTerm
@@ -402,6 +418,32 @@ public class SequenceOntology
 
   public boolean isSequenceVariant(String soTerm)
   {
-    return isA(soTerm, "sequence_variant");
+    return isA(soTerm, SEQUENCE_VARIANT);
+  }
+
+  /**
+   * Sorts (case-insensitive) and returns the list of valid terms queried for
+   */
+  @Override
+  public List<String> termsFound()
+  {
+    synchronized (termsFound)
+    {
+      Collections.sort(termsFound, String.CASE_INSENSITIVE_ORDER);
+      return termsFound;
+    }
+  }
+
+  /**
+   * Sorts (case-insensitive) and returns the list of invalid terms queried for
+   */
+  @Override
+  public List<String> termsNotFound()
+  {
+    synchronized (termsNotFound)
+    {
+      Collections.sort(termsNotFound, String.CASE_INSENSITIVE_ORDER);
+      return termsNotFound;
+    }
   }
 }