+ /*
+ * lookup from lower-case form of a name to its canonical (standardised) form
+ */
+ private static Map<String, String> canonicalSourceNameLookup = new HashMap<>();
+
+ public final static int DB_SOURCE = 1;
+
+ public final static int DB_VERSION = 2;
+
+ public final static int DB_ID = 4;
+
+ public final static int DB_MAP = 8;
+
+ public final static int SEARCH_MODE_NO_MAP_NO_VERSION = DB_SOURCE | DB_ID;
+
+ public final static int SEARCH_MODE_FULL = DB_SOURCE | DB_VERSION | DB_ID
+ | DB_MAP;
+
+ static
+ {
+ // TODO load these from a resource file?
+ canonicalSourceNameLookup.put("uniprotkb/swiss-prot",
+ DBRefSource.UNIPROT);
+ canonicalSourceNameLookup.put("uniprotkb/trembl", DBRefSource.UNIPROT);
+
+ // Ensembl values for dbname in xref REST service:
+ canonicalSourceNameLookup.put("uniprot/sptrembl", DBRefSource.UNIPROT);
+ canonicalSourceNameLookup.put("uniprot/swissprot", DBRefSource.UNIPROT);
+
+ canonicalSourceNameLookup.put("pdb", DBRefSource.PDB);
+ canonicalSourceNameLookup.put("ensembl", DBRefSource.ENSEMBL);
+ // Ensembl Gn and Tr are for Ensembl genomic and transcript IDs as served
+ // from ENA.
+ canonicalSourceNameLookup.put("ensembl-tr", DBRefSource.ENSEMBL);
+ canonicalSourceNameLookup.put("ensembl-gn", DBRefSource.ENSEMBL);
+
+ // guarantee we always have lowercase entries for canonical string lookups
+ for (String k : canonicalSourceNameLookup.keySet())
+ {
+ canonicalSourceNameLookup.put(k.toLowerCase(Locale.ROOT),
+ canonicalSourceNameLookup.get(k));
+ }
+ }
+
+ /**
+ * Returns those DBRefEntry objects whose source identifier (once converted to
+ * Jalview's canonical form) is in the list of sources to search for. Returns
+ * null if no matches found.
+ *
+ * @param dbrefs
+ * DBRefEntry objects to search
+ * @param sources
+ * array of sources to select
+ * @return
+ */
+ public static List<DBRefEntry> selectRefs(List<DBRefEntry> dbrefs,
+ String[] sources)
+ {
+ if (dbrefs == null || sources == null)
+ {
+ return dbrefs;
+ }
+
+ // BH TODO (what?)
+ HashSet<String> srcs = new HashSet<String>();
+ for (String src : sources)
+ {
+ srcs.add(src.toUpperCase(Locale.ROOT));
+ }
+
+ int nrefs = dbrefs.size();
+ List<DBRefEntry> res = new ArrayList<DBRefEntry>();
+ for (int ib = 0; ib < nrefs; ib++)
+ {
+ DBRefEntry dbr = dbrefs.get(ib);
+ String source = getCanonicalName(dbr.getSource());
+ if (srcs.contains(source.toUpperCase(Locale.ROOT)))
+ {
+ res.add(dbr);
+ }
+ }
+ if (res.size() > 0)
+ {
+ // List<DBRefEntry> reply = new DBRefEntry[res.size()];
+ return res;// .toArray(reply);
+ }
+ return null;
+ }
+
+ private static boolean selectRefsBS(List<DBRefEntry> dbrefs,
+ int sourceKeys, BitSet bsSelect)
+ {
+ if (dbrefs == null || sourceKeys == 0)
+ {
+ return false;
+ }
+ for (int i = 0, n = dbrefs.size(); i < n; i++)
+ {
+ DBRefEntry dbr = dbrefs.get(i);
+ if ((dbr.getSourceKey() & sourceKeys) != 0)
+ {
+ bsSelect.clear(i);
+ }
+ }
+ return !bsSelect.isEmpty();
+ }
+
+ /**
+ * Returns a (possibly empty) list of those references that match the given
+ * entry, according to the given comparator.
+ *
+ * @param refs
+ * an array of database references to search
+ * @param entry
+ * an entry to compare against
+ * @param comparator
+ * @return
+ */
+ static List<DBRefEntry> searchRefs(DBRefEntry[] refs, DBRefEntry entry,
+ DbRefComp comparator)
+ {
+ List<DBRefEntry> rfs = new ArrayList<>();
+ if (refs == null || entry == null)
+ {
+ return rfs;
+ }
+ for (int i = 0; i < refs.length; i++)
+ {
+ if (comparator.matches(entry, refs[i]))
+ {
+ rfs.add(refs[i]);
+ }
+ }
+ return rfs;
+ }
+
+ /**
+ * look up source in an internal list of database reference sources and return
+ * the canonical jalview name for the source, or the original string if it has
+ * no canonical form.
+ *
+ * @param source
+ * @return canonical jalview source (one of jalview.datamodel.DBRefSource.*)
+ * or original source
+ */
+ public static String getCanonicalName(String source)
+ {
+ if (source == null)
+ {
+ return null;
+ }
+ String canonical = canonicalSourceNameLookup
+ .get(source.toLowerCase(Locale.ROOT));
+ return canonical == null ? source : canonical;
+ }
+
+ /**
+ * Returns a (possibly empty) list of those references that match the given
+ * entry. Currently uses a comparator which matches if
+ * <ul>
+ * <li>database sources are the same</li>
+ * <li>accession ids are the same</li>
+ * <li>both have no mapping, or the mappings are the same</li>
+ * </ul>
+ *
+ * @param ref
+ * Set of references to search
+ * @param entry
+ * pattern to match
+ * @param mode
+ * SEARCH_MODE_FULL for all; SEARCH_MODE_NO_MAP_NO_VERSION optional
+ * @return
+ */
+ public static List<DBRefEntry> searchRefs(List<DBRefEntry> ref,
+ DBRefEntry entry, int mode)
+ {
+ return searchRefs(ref, entry,
+ matchDbAndIdAndEitherMapOrEquivalentMapList, mode);
+ }
+
+ /**
+ * Returns a list of those references that match the given accession id
+ * <ul>
+ * <li>database sources are the same</li>
+ * <li>accession ids are the same</li>
+ * <li>both have no mapping, or the mappings are the same</li>
+ * </ul>
+ *
+ * @param refs
+ * Set of references to search
+ * @param accId
+ * accession id to match
+ * @return
+ */
+ public static List<DBRefEntry> searchRefs(List<DBRefEntry> refs,
+ String accId)
+ {
+ List<DBRefEntry> rfs = new ArrayList<DBRefEntry>();
+ if (refs == null || accId == null)
+ {
+ return rfs;
+ }
+ for (int i = 0, n = refs.size(); i < n; i++)
+ {
+ DBRefEntry e = refs.get(i);
+ if (accId.equals(e.getAccessionId()))
+ {
+ rfs.add(e);
+ }
+ }
+ return rfs;
+ // return searchRefs(refs, new DBRefEntry("", "", accId), matchId,
+ // SEARCH_MODE_FULL);
+ }
+
+ /**
+ * Returns a (possibly empty) list of those references that match the given
+ * entry, according to the given comparator.
+ *
+ * @param refs
+ * an array of database references to search
+ * @param entry
+ * an entry to compare against
+ * @param comparator
+ * @param mode
+ * SEARCH_MODE_FULL for all; SEARCH_MODE_NO_MAP_NO_VERSION optional
+ * @return
+ */
+ static List<DBRefEntry> searchRefs(List<DBRefEntry> refs,
+ DBRefEntry entry, DbRefComp comparator, int mode)
+ {
+ List<DBRefEntry> rfs = new ArrayList<DBRefEntry>();
+ if (refs == null || entry == null)
+ {
+ return rfs;
+ }
+ for (int i = 0, n = refs.size(); i < n; i++)
+ {
+ DBRefEntry e = refs.get(i);
+ if (comparator.matches(entry, e, SEARCH_MODE_FULL))
+ {
+ rfs.add(e);
+ }
+ }
+ return rfs;
+ }
+
+ interface DbRefComp
+ {
+ default public boolean matches(DBRefEntry refa, DBRefEntry refb)
+ {
+ return matches(refa, refb, SEARCH_MODE_FULL);
+ };
+
+ public boolean matches(DBRefEntry refa, DBRefEntry refb, int mode);
+ }
+
+ /**
+ * match on all non-null fields in refa
+ */
+ // TODO unused - remove? would be broken by equating "" with null
+ public static DbRefComp matchNonNullonA = new DbRefComp()
+ {
+ @Override
+ public boolean matches(DBRefEntry refa, DBRefEntry refb, int mode)
+ {
+ if ((mode & DB_SOURCE) != 0 && (refa.getSource() == null
+ || DBRefUtils.getCanonicalName(refb.getSource()).equals(
+ DBRefUtils.getCanonicalName(refa.getSource()))))
+ {
+ if ((mode & DB_VERSION) != 0 && (refa.getVersion() == null
+ || refb.getVersion().equals(refa.getVersion())))