/* * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1) * Copyright (C) 2014 The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.ws.dbsources.das.datamodel; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; import org.biodas.jdas.client.SequenceClient; import org.biodas.jdas.client.adapters.sequence.DasSequenceAdapter; import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI; import org.biodas.jdas.client.threads.SequenceClientMultipleSources; import org.biodas.jdas.schema.sequence.SEQUENCE; import org.biodas.jdas.schema.sources.COORDINATES; import org.biodas.jdas.schema.sources.SOURCE; import org.biodas.jdas.schema.sources.VERSION; import com.stevesoft.pat.Regex; import jalview.ws.dbsources.das.api.jalviewSourceI; import jalview.ws.seqfetcher.*; import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.DBRefEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; /** * an instance of this class is created for each unique DAS Sequence source (ie * one capable of handling the 'sequence' for a particular MapMaster) * * @author JimP * */ public class DasSequenceSource extends DbSourceProxyImpl implements DbSourceProxy { private jalviewSourceI jsrc; protected SOURCE source = null; protected VERSION version = null; protected COORDINATES coordsys = null; protected String dbname = "DASCS"; protected String dbrefname = "das:source"; protected MultipleConnectionPropertyProviderI connprops = null; /** * DAS sources are tier 1 - if we have a direct DB connection then we should prefer it */ private int tier=1; /** * create a new DbSource proxy for a DAS 1 source * * @param dbnbame * Human Readable Name to use when fetching from this source * @param dbrefname * DbRefName for DbRefs attached to sequences retrieved from this * source * @param source * Das1Source * @param coordsys * specific coordinate system to use for this source * @throws Exception * if source is not capable of the 'sequence' command */ public DasSequenceSource(String dbname, String dbrefname, SOURCE source, VERSION version, COORDINATES coordsys, MultipleConnectionPropertyProviderI connprops) throws Exception { if (!(jsrc = new JalviewSource(source, connprops, false)) .isSequenceSource()) { throw new Exception("Source " + source.getTitle() + " does not support the sequence command."); } this.tier = 1+((jsrc.isLocal() || jsrc.isReferenceSource()) ? 0 : 1); this.source = source; this.dbname = dbname; this.dbrefname = dbrefname.toUpperCase(); if (coordsys != null) { this.coordsys = coordsys; } this.connprops = connprops; } public String getAccessionSeparator() { return "\t"; } public Regex getAccessionValidator() { /** ? * */ return Regex.perlCode("m/([^:]+)(:\\d+,\\d+)?/"); } public String getDbName() { // TODO: map to return dbname + " (DAS)"; } public String getDbSource() { return dbrefname; } public String getDbVersion() { return coordsys != null ? coordsys.getVersion() : ""; } public AlignmentI getSequenceRecords(String queries) throws Exception { StringTokenizer st = new StringTokenizer(queries, "\t"); List toks = new ArrayList(), src = new ArrayList(), acIds = new ArrayList(); while (st.hasMoreTokens()) { String t; toks.add(t = st.nextToken()); acIds.add(t.replaceAll(":[0-9,]+", "")); } src.add(jsrc.getSourceURL()); Map, DasSequenceAdapter>> resultset = new HashMap, DasSequenceAdapter>>(); Map, Exception>> errors = new HashMap, Exception>>(); // First try multiple sources boolean multiple = true, retry = false; do { if (!multiple) { retry = false; // slow, fetch one at a time. for (String sr : src) { System.err .println("Retrieving IDs individually from das source: " + sr); org.biodas.jdas.client.SequenceClient sq = new SequenceClient( connprops.getConnectionPropertyProviderFor(sr)); for (String q : toks) { List qset = Arrays.asList(new String[] { q }); try { DasSequenceAdapter s = sq.fetchData(sr, qset); Map, DasSequenceAdapter> dss = resultset.get(sr); if (dss == null) { resultset .put(sr, dss = new HashMap, DasSequenceAdapter>()); } dss.put(qset, s); } catch (Exception x) { Map, Exception> ers = errors.get(sr); if (ers == null) { errors.put(sr, ers = new HashMap, Exception>()); } ers.put(qset, x); } } } } else { SequenceClientMultipleSources sclient; sclient = new SequenceClientMultipleSources(); sclient.fetchData(src, toks, resultset, errors); sclient.shutDown(); while (!sclient.isTerminated()) { try { Thread.sleep(200); } catch (InterruptedException x) { } } if (resultset.isEmpty() && !errors.isEmpty()) { retry = true; multiple = false; } } } while (retry); if (resultset.isEmpty()) { System.err.println("Sequence Query to " + jsrc.getTitle() + " with '" + queries + "' returned no sequences."); return null; } else { Vector seqs = null; for (Map.Entry, DasSequenceAdapter>> resset : resultset .entrySet()) { for (Map.Entry, DasSequenceAdapter> result : resset .getValue().entrySet()) { DasSequenceAdapter dasseqresp = result.getValue(); List accessions = result.getKey(); for (SEQUENCE e : dasseqresp.getSequence()) { String lbl = e.getId(); if (acIds.indexOf(lbl) == -1) { System.err .println("Warning - received sequence event for strange accession code (" + lbl + ")"); } else { if (seqs == null) { if (e.getContent().length() == 0) { System.err .println("Empty sequence returned for accession code (" + lbl + ") from " + resset.getKey() + " (source is " + getDbName()); continue; } } seqs = new java.util.Vector(); // JDAS returns a sequence complete with any newlines and spaces // in the XML Sequence sq = new Sequence(lbl, e.getContent().replaceAll( "\\s+", "")); sq.setStart(e.getStart().intValue()); sq.addDBRef(new DBRefEntry(getDbSource(), getDbVersion() + ":" + e.getVersion(), lbl)); seqs.addElement(sq); } } } } if (seqs == null || seqs.size() == 0) return null; SequenceI[] sqs = new SequenceI[seqs.size()]; for (int i = 0, iSize = seqs.size(); i < iSize; i++) { sqs[i] = (SequenceI) seqs.elementAt(i); } Alignment al = new Alignment(sqs); if (jsrc.isFeatureSource()) { java.util.Vector srcs = new java.util.Vector(); srcs.addElement(jsrc); try { jalview.ws.DasSequenceFeatureFetcher dssf = new jalview.ws.DasSequenceFeatureFetcher( sqs, null, srcs, false, false, multiple); while (dssf.isRunning()) { try { Thread.sleep(200); } catch (InterruptedException x) { } } } catch (Exception x) { Cache.log .error("Couldn't retrieve features for sequence from its source.", x); } } return al; } } public String getTestQuery() { return coordsys == null ? "" : coordsys.getTestRange(); } public boolean isValidReference(String accession) { // TODO try to validate an accession against source // We don't really know how to do this without querying source return true; } /** * @return the source */ public SOURCE getSource() { return source; } /** * @return the coordsys */ public COORDINATES getCoordsys() { return coordsys; } @Override public int getTier() { return tier; } }