X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2Fseqfetcher%2FASequenceFetcher.java;h=97babfd0769a321695ad08fd1db2d72cbf1cb79f;hb=fcb944cdd9de849c89f0a8744ae6e56e22de9c1e;hp=a8a390465c4b6466ca20ac1052f44ba890541f40;hpb=10e637daad8983c41db8679baabea5563d7371f4;p=jalview.git diff --git a/src/jalview/ws/seqfetcher/ASequenceFetcher.java b/src/jalview/ws/seqfetcher/ASequenceFetcher.java index a8a3904..97babfd 100644 --- a/src/jalview/ws/seqfetcher/ASequenceFetcher.java +++ b/src/jalview/ws/seqfetcher/ASequenceFetcher.java @@ -20,89 +20,124 @@ */ package jalview.ws.seqfetcher; +import jalview.api.FeatureSettingsModelI; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.SequenceI; +import jalview.util.DBRefUtils; +import jalview.util.MessageManager; + import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; -import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Stack; import java.util.Vector; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.DBRefEntry; -import jalview.datamodel.SequenceI; -import jalview.util.DBRefUtils; -import jalview.util.MessageManager; - public class ASequenceFetcher { - /** + /* * set of databases we can retrieve entries from */ - protected Hashtable> FETCHABLEDBS; + protected Hashtable> fetchableDbs; + + /* + * comparator to sort by tier (0/1/2) and name + */ + private Comparator proxyComparator; - public ASequenceFetcher() + /** + * Constructor + */ + protected ASequenceFetcher() { - super(); + /* + * comparator to sort proxies by tier and name + */ + proxyComparator = new Comparator() + { + @Override + public int compare(DbSourceProxy o1, DbSourceProxy o2) + { + /* + * Tier 0 precedes 1 precedes 2 + */ + int compared = Integer.compare(o1.getTier(), o2.getTier()); + if (compared == 0) + { + // defend against NullPointer - should never happen + String o1Name = o1.getDbName(); + String o2Name = o2.getDbName(); + if (o1Name != null && o2Name != null) + { + compared = o1Name.compareToIgnoreCase(o2Name); + } + } + return compared; + } + }; } /** - * get list of supported Databases + * get array of supported Databases * * @return database source string for each database - only the latest version * of a source db is bound to each source. */ public String[] getSupportedDb() { - if (FETCHABLEDBS == null) + if (fetchableDbs == null) { return null; } - String[] sf = new String[FETCHABLEDBS.size()]; - Enumeration e = FETCHABLEDBS.keys(); - int i = 0; - while (e.hasMoreElements()) - { - sf[i++] = (String) e.nextElement(); - } - ; + String[] sf = fetchableDbs.keySet() + .toArray(new String[fetchableDbs.size()]); return sf; } public boolean isFetchable(String source) { - Enumeration e = FETCHABLEDBS.keys(); - while (e.hasMoreElements()) + for (String db : fetchableDbs.keySet()) { - String db = (String) e.nextElement(); - if (source.compareToIgnoreCase(db) == 0) + if (source.equalsIgnoreCase(db)) { return true; } } - jalview.bin.Cache.log.warn("isFetchable doesn't know about '" + source - + "'"); + Cache.log.warn("isFetchable doesn't know about '" + source + "'"); return false; } - public SequenceI[] getSequences(jalview.datamodel.DBRefEntry[] refs) + /** + * Fetch sequences for the given cross-references + * + * @param refs + * @param dna + * if true, only fetch from nucleotide data sources, else peptide + * @return + */ + public SequenceI[] getSequences(List refs, boolean dna) { - SequenceI[] ret = null; - Vector rseqs = new Vector(); - Hashtable> queries = new Hashtable(); - for (int r = 0; r < refs.length; r++) + Vector rseqs = new Vector<>(); + Hashtable> queries = new Hashtable<>(); + for (DBRefEntry ref : refs) { - if (!queries.containsKey(refs[r].getSource())) + String canonical = DBRefUtils.getCanonicalName(ref.getSource()); + if (!queries.containsKey(canonical)) { - queries.put(refs[r].getSource(), new ArrayList()); + queries.put(canonical, new ArrayList()); } - List qset = queries.get(refs[r].getSource()); - if (!qset.contains(refs[r].getAccessionId())) + List qset = queries.get(canonical); + if (!qset.contains(ref.getAccessionId())) { - qset.add(refs[r].getAccessionId()); + qset.add(ref.getAccessionId()); } } Enumeration e = queries.keys(); @@ -118,22 +153,22 @@ public class ASequenceFetcher "Don't know how to fetch from this database :" + db)); continue; } - Iterator fetchers = getSourceProxy(db).iterator(); - Stack queriesLeft = new Stack(); - // List queriesFailed = new ArrayList(); + + Stack queriesLeft = new Stack<>(); queriesLeft.addAll(query); - while (fetchers.hasNext()) + + List proxies = getSourceProxy(db); + for (DbSourceProxy fetcher : proxies) { - List queriesMade = new ArrayList(); - HashSet queriesFound = new HashSet(); + List queriesMade = new ArrayList<>(); + HashSet queriesFound = new HashSet<>(); try { - DbSourceProxy fetcher = fetchers.next(); - boolean doMultiple = fetcher.getAccessionSeparator() != null; // No - // separator - // - no - // Multiple - // Queries + if (fetcher.isDnaCoding() != dna) + { + continue; // wrong sort of data + } + boolean doMultiple = fetcher.getMaximumQueryCount() > 1; while (!queriesLeft.isEmpty()) { StringBuffer qsb = new StringBuffer(); @@ -152,12 +187,11 @@ public class ASequenceFetcher try { // create a fetcher and go to it - seqset = fetcher.getSequenceRecords(qsb.toString()); // , - // queriesFailed); + seqset = fetcher.getSequenceRecords(qsb.toString()); } catch (Exception ex) { - System.err.println("Failed to retrieve the following from " - + db); + System.err.println( + "Failed to retrieve the following from " + db); System.err.println(qsb); ex.printStackTrace(System.err); } @@ -170,15 +204,14 @@ public class ASequenceFetcher for (int is = 0; is < seqs.length; is++) { rseqs.addElement(seqs[is]); - DBRefEntry[] frefs = DBRefUtils.searchRefs(seqs[is] - .getDBRef(), new DBRefEntry(db, null, null)); - if (frefs != null) + // BH 2015.01.25 check about version/accessid being null here + List frefs = DBRefUtils.searchRefs( + seqs[is].getDBRefs(), + new DBRefEntry(db, null, null), DBRefUtils.SEARCH_MODE_FULL); + for (DBRefEntry dbr : frefs) { - for (DBRefEntry dbr : frefs) - { - queriesFound.add(dbr.getAccessionId()); - queriesMade.remove(dbr.getAccessionId()); - } + queriesFound.add(dbr.getAccessionId()); + queriesMade.remove(dbr.getAccessionId()); } seqs[is] = null; } @@ -187,8 +220,8 @@ public class ASequenceFetcher { if (fetcher.getRawRecords() != null) { - System.out.println("# Retrieved from " + db + ":" - + qsb.toString()); + System.out.println( + "# Retrieved from " + db + ":" + qsb.toString()); StringBuffer rrb = fetcher.getRawRecords(); /* * for (int rr = 0; rr 0) { - ret = new SequenceI[rseqs.size()]; - Enumeration sqs = rseqs.elements(); + result = new SequenceI[rseqs.size()]; int si = 0; - while (sqs.hasMoreElements()) + for (SequenceI s : rseqs) { - SequenceI s = (SequenceI) sqs.nextElement(); - ret[si++] = s; + result[si++] = s; s.updatePDBIds(); } } - return ret; + return result; } public void reportStdError(String db, List queriesMade, Exception ex) { - System.err.println("Failed to retrieve the following references from " - + db); + System.err.println( + "Failed to retrieve the following references from " + db); int n = 0; for (String qv : queriesMade) { @@ -261,158 +294,180 @@ public class ASequenceFetcher } /** - * Retrieve an instance of the proxy for the given source + * Returns a list of proxies for the given source * * @param db * database source string TODO: add version string/wildcard for * retrieval of specific DB source/version combinations. - * @return an instance of DbSourceProxy for that db. + * @return a list of DbSourceProxy for the db */ public List getSourceProxy(String db) { - List dbs; - Map dblist = FETCHABLEDBS.get(db); + db = DBRefUtils.getCanonicalName(db); + Map dblist = fetchableDbs.get(db); if (dblist == null) { - return new ArrayList(); + return new ArrayList<>(); } - ; - if (dblist.size() > 1) + + /* + * sort so that primary sources precede secondary + */ + List dbs = new ArrayList<>(); + for (Entry entry : dblist.entrySet()) { - DbSourceProxy[] l = dblist.values().toArray(new DbSourceProxy[0]); - int i = 0; - String[] nm = new String[l.length]; - // make sure standard dbs appear first, followed by reference das sources, - // followed by anything else. - for (DbSourceProxy s : l) - { - nm[i++] = "" + s.getTier() + s.getDbName().toLowerCase(); - } - jalview.util.QuickSort.sort(nm, l); - dbs = new ArrayList(); - for (i = l.length - 1; i >= 0; i--) + DbSourceProxyRoot proxy = entry.getValue(); + if (proxy instanceof DbRoot) { - dbs.add(l[i]); + proxy = setProxy((DbRoot) proxy, dblist); } + dbs.add((DbSourceProxy) proxy); } - else + Collections.sort(dbs, proxyComparator); + return dbs; + } + + class DbRoot implements DbSourceProxyRoot + { + + private String sourceName; + + private String className; + + DbRoot(String sourceName, String className) { - dbs = new ArrayList(dblist.values()); + this.sourceName = sourceName; + this.className = className; } - return dbs; + + @Override + public String getDbSource() + { + return sourceName; + } + + /** + * lazy class creation + * + * @return the actual proxy object + */ + public DbSourceProxy getProxy() + { + try + { + return (DbSourceProxy) Class.forName(className).newInstance(); + } catch (Exception e) + { + // Serious problems if this happens. + throw new Error(MessageManager.getString( + "error.dbrefsource_implementation_exception"), e); + } + } + } /** - * constructs and instance of the proxy and registers it as a valid - * dbrefsource + * constructs an instance of the proxy and registers it as a valid dbrefsource * - * @param dbSourceProxy + * @param dbSourceProxyClass * reference for class implementing * jalview.ws.seqfetcher.DbSourceProxy */ protected void addDBRefSourceImpl( - Class dbSourceProxy) - throws java.lang.IllegalArgumentException + Class dbSourceProxyClass) + throws IllegalArgumentException { DbSourceProxy proxy = null; try { - DbSourceProxy proxyObj = dbSourceProxy.getConstructor().newInstance(); - proxy = proxyObj; + proxy = dbSourceProxyClass.getConstructor().newInstance(); } catch (IllegalArgumentException e) { throw e; } catch (Exception e) { // Serious problems if this happens. - throw new Error(MessageManager.getString("error.dbrefsource_implementation_exception"), e); + throw new Error(MessageManager + .getString("error.dbrefsource_implementation_exception"), e); } addDbRefSourceImpl(proxy); } + public void addDBRefSourceImpl(String sourceName, String className) + { + addDbRefSourceImpl(new DbRoot(sourceName, className)); + } + /** * add the properly initialised DbSourceProxy object 'proxy' to the list of * sequence fetchers * * @param proxy */ - protected void addDbRefSourceImpl(DbSourceProxy proxy) + void addDbRefSourceImpl(DbSourceProxyRoot proxy) { if (proxy != null) { - if (FETCHABLEDBS == null) + if (fetchableDbs == null) { - FETCHABLEDBS = new Hashtable>(); + fetchableDbs = new Hashtable<>(); } - Map slist = FETCHABLEDBS.get(proxy - .getDbSource()); + String key = proxy.getDbSource(); + Map slist = fetchableDbs.get(key); if (slist == null) { - FETCHABLEDBS.put(proxy.getDbSource(), - slist = new Hashtable()); + fetchableDbs.put(key, slist = new Hashtable<>()); } - slist.put(proxy.getDbName(), proxy); - } - } - - /** - * test if the database handler for dbName contains the given dbProperty when - * a dbName resolves to a set of proxies - this method will return the result - * of the test for the first instance. TODO implement additional method to - * query all sources for a db to find one with a particular property - * - * @param dbName - * @param dbProperty - * @return true if proxy has the given property - */ - public boolean hasDbSourceProperty(String dbName, String dbProperty) - { - // TODO: decide if invalidDbName exception is thrown here. - - List proxies = getSourceProxy(dbName); - if (proxies != null) - { - for (DbSourceProxy proxy : proxies) + if (proxy instanceof DbRoot) { - if (proxy.getDbSourceProperties() != null) - { - return proxy.getDbSourceProperties().containsKey(dbProperty); - } + slist.put("", proxy); + } + else + { + slist.put(((DbSourceProxy) proxy).getDbName(), proxy); } } - return false; } /** * select sources which are implemented by instances of the given class * - * @param class that implements DbSourceProxy + * @param class1 + * that implements DbSourceProxy * @return null or vector of source names for fetchers */ - public String[] getDbInstances(Class class1) + public String[] getDbInstances(Class class1) { - if (!jalview.ws.seqfetcher.DbSourceProxy.class.isAssignableFrom(class1)) + if (!DbSourceProxy.class.isAssignableFrom(class1)) { - throw new Error(MessageManager.formatMessage("error.implementation_error_dbinstance_must_implement_interface", new String[]{class1.toString()})); + throw new Error(MessageManager.formatMessage( + "error.implementation_error_dbinstance_must_implement_interface", + new String[] + { class1.toString() })); } - if (FETCHABLEDBS == null) + if (fetchableDbs == null) { return null; } - String[] sources = null; - Vector src = new Vector(); - Enumeration dbs = FETCHABLEDBS.keys(); - while (dbs.hasMoreElements()) + Vector src = new Vector<>(); + for (String dbSource : fetchableDbs.keySet()) { - String dbn = (String) dbs.nextElement(); - for (DbSourceProxy dbp : FETCHABLEDBS.get(dbn).values()) + Map dblist = fetchableDbs.get(dbSource); + for (Entry entry : dblist.entrySet()) { - if (class1.isAssignableFrom(dbp.getClass())) + DbSourceProxyRoot proxy = entry.getValue(); + if (proxy instanceof DbRoot) + { + proxy = setProxy((DbRoot) proxy, dblist); + } + Class c = proxy.getClass(); + if (class1 == c || class1.isAssignableFrom(c)) { - src.addElement(dbn); + src.addElement(dbSource); } } } + String[] sources = null; if (src.size() > 0) { src.copyInto(sources = new String[src.size()]); @@ -420,10 +475,24 @@ public class ASequenceFetcher return sources; } - public DbSourceProxy[] getDbSourceProxyInstances(Class class1) + private DbSourceProxyRoot setProxy(DbRoot root, + Map dblist) + { + DbSourceProxy proxy = root.getProxy(); + // Time to create the actual proxy + dblist.remove(""); + dblist.put(proxy.getDbName(), proxy); + return proxy; + } + + public DbSourceProxy[] getDbSourceProxyInstances(Class class1) { - ArrayList prlist = new ArrayList(); - for (String fetchable : getSupportedDb()) + if (fetchableDbs == null) + { + return null; + } + List prlist = new ArrayList<>(); + for (String fetchable : fetchableDbs.keySet()) { for (DbSourceProxy pr : getSourceProxy(fetchable)) { @@ -440,4 +509,28 @@ public class ASequenceFetcher return prlist.toArray(new DbSourceProxy[0]); } + /** + * Returns a preferred feature colouring scheme for the given source, or null + * if none is defined. + * + * @param source + * @return + */ + public FeatureSettingsModelI getFeatureColourScheme(String source) + { + /* + * return the first non-null colour scheme for any proxy for + * this database source + */ + for (DbSourceProxy proxy : getSourceProxy(source)) + { + FeatureSettingsModelI preferredColours = proxy + .getFeatureColourScheme(); + if (preferredColours != null) + { + return preferredColours; + } + } + return null; + } }