JAL-1965 refactored SeqIdName to public class, and more tests for word generation
[jalview.git] / src / jalview / analysis / SeqIdName.java
diff --git a/src/jalview/analysis/SeqIdName.java b/src/jalview/analysis/SeqIdName.java
new file mode 100644 (file)
index 0000000..ddf63ba
--- /dev/null
@@ -0,0 +1,151 @@
+package jalview.analysis;
+
+/**
+ * implements a weak hash map based on the first four characters of the given
+ * string, normalised to lower case
+ * 
+ * @author jprocter
+ *
+ */
+class SeqIdName
+{
+  String id, origid;
+
+  SeqIdName(String s)
+  {
+    if (s != null)
+    {
+      id = new String(s).toLowerCase();
+      origid = new String(s);
+    }
+    else
+    {
+      id = "";
+    }
+  }
+
+  @Override
+  public int hashCode()
+  {
+    return ((id.length() >= 4) ? id.substring(0, 4).hashCode() : id
+            .hashCode());
+  }
+
+  @Override
+  public boolean equals(Object s)
+  {
+    if (s == null)
+    {
+      return false;
+    }
+    if (s instanceof SeqIdName)
+    {
+      return this.equals((SeqIdName) s);
+    }
+    else
+    {
+      if (s instanceof String)
+      {
+        return this.equals((String) s);
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * matches if one ID properly contains another at a whitespace boundary.
+   * TODO: (JBPNote) These are not efficient. should use char[] for speed
+   * todo: (JBPNote) Set separator characters appropriately
+   * 
+   * @param s
+   *          SeqIdName
+   * @return boolean
+   */
+  public boolean equals(SeqIdName s)
+  {
+    // TODO: JAL-732 patch for cases when name includes a list of IDs, and the
+    // match contains one ID flanked
+    if (id.length() > s.id.length())
+    {
+      return check_wordmatch(id, s.id);
+    }
+    else
+    {
+      return check_wordmatch(s.id, id);
+    }
+  }
+
+  private boolean check_wordmatch(String longer, String shorter)
+  {
+    boolean elen = longer.length() == shorter.length();
+    int sp = longer.indexOf(shorter);
+    if (sp == -1)
+    {
+      return false;
+    }
+
+    if (sp == 0)
+    {
+      // end of match is word boundary
+      return elen ? true : (SequenceIdMatcher.WORD_SEP.indexOf(longer.charAt(shorter
+              .length() + sp)) > -1);
+    }
+    if (SequenceIdMatcher.WORD_SEP.indexOf(longer.charAt(sp - 1)) > -1)
+    {
+      if (sp + shorter.length() == longer.length())
+      {
+        return true;
+      }
+      else
+      {
+        // end of match is word boundary
+        return elen ? false
+                : sp + shorter.length() == longer.length() ? true
+                        : (SequenceIdMatcher.WORD_SEP.indexOf(longer.charAt(shorter
+                                .length() + sp)) > -1);
+      }
+    }
+    else
+    {
+      // prefix of match is not a word boundary
+      return false;
+    }
+  }
+
+  public boolean equals(String s)
+  {
+    s = s.toLowerCase(); // TODO: employ faster to lower case operation
+    if (id.length() > s.length())
+    {
+      return check_wordmatch(id, s);
+    }
+    else
+    {
+      return check_wordmatch(s, id);
+    }
+  }
+
+  @Override
+  public String toString()
+  {
+    return id;
+  }
+
+  public boolean equalsCase(String s)
+  {
+    if (origid.length() > s.length())
+    {
+      return check_wordmatch(origid, s);
+    }
+    else
+    {
+      return check_wordmatch(s, origid);
+    }
+  }
+
+  public boolean equalsCase(SeqIdName sid)
+  {
+    return equalsCase(sid.origid);
+  }
+}
\ No newline at end of file