f68a00562baad15995bb16e255f71137a3c3310b
[jalview.git] / src / jalview / ws / dbsources / das / datamodel / JalviewSource.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.ws.dbsources.das.datamodel;
19
20 import java.text.ParseException;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.Hashtable;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.biodas.jdas.client.threads.MultipleConnectionPropertyProviderI;
28 import org.biodas.jdas.dassources.Capabilities;
29 import org.biodas.jdas.dassources.utils.DasTimeFormat;
30 import org.biodas.jdas.schema.sources.CAPABILITY;
31 import org.biodas.jdas.schema.sources.COORDINATES;
32 import org.biodas.jdas.schema.sources.MAINTAINER;
33 import org.biodas.jdas.schema.sources.PROP;
34 import org.biodas.jdas.schema.sources.SOURCE;
35 import org.biodas.jdas.schema.sources.VERSION;
36
37 import jalview.ws.dbsources.das.api.jalviewSourceI;
38 import jalview.ws.seqfetcher.DbSourceProxy;
39
40 public class JalviewSource implements jalviewSourceI
41 {
42   SOURCE source;
43
44   MultipleConnectionPropertyProviderI connprov;
45
46   public JalviewSource(SOURCE local2,
47           MultipleConnectionPropertyProviderI connprov, boolean local)
48   {
49     this.connprov = connprov;
50     this.local = local;
51     source = local2;
52   }
53
54   @Override
55   public String getTitle()
56   {
57     return source.getTitle();
58   }
59
60   @Override
61   public VERSION getVersion()
62   {
63
64     return getVersionFor(source);
65   }
66
67   @Override
68   public String getDocHref()
69   {
70     return source.getDocHref();
71   }
72
73   @Override
74   public String getDescription()
75   {
76     return source.getDescription();
77   }
78
79   @Override
80   public String getUri()
81   {
82     return source.getUri();
83   }
84
85   @Override
86   public MAINTAINER getMAINTAINER()
87   {
88     return source.getMAINTAINER();
89   }
90
91   @Override
92   public String getEmail()
93   {
94     return (local) ? null : source.getMAINTAINER().getEmail();
95   }
96
97   boolean local = false;
98
99   @Override
100   public boolean isLocal()
101   {
102     return local;
103   }
104
105   @Override
106   public boolean isSequenceSource()
107   {
108     String seqcap = "das1:" + Capabilities.SEQUENCE.getName();
109     for (String cp : getCapabilityList(getVersionFor(source)))
110     {
111       if (cp.equals(seqcap))
112       {
113         return true;
114
115       }
116     }
117     return false;
118   }
119
120   @Override
121   public boolean isFeatureSource()
122   {
123     String seqcap = "das1:" + Capabilities.FEATURES.getName();
124     for (String cp : getCapabilityList(getVersionFor(source)))
125     {
126       if (cp.equals(seqcap))
127       {
128         return true;
129
130       }
131     }
132     return false;
133   }
134
135   private VERSION getVersionFor(SOURCE ds)
136   {
137     VERSION latest = null;
138     for (VERSION v : ds.getVERSION())
139     {
140       if (latest == null
141               || isLaterThan(latest.getCreated(), v.getCreated()))
142       {
143         // TODO: das 1.6 - should just get the first version - ignore other
144         // versions since not specified how to construct URL from version's URI
145         // + source URI
146         latest = v;
147       }
148     }
149     return latest;
150   }
151
152   /**
153    * compare date strings. null or unparseable dates are assumed to be oldest
154    * 
155    * @param ref
156    * @param newer
157    * @return true iff ref comes before newer
158    */
159   private boolean isLaterThan(String ref, String newer)
160   {
161     Date refdate = null, newdate = null;
162     if (ref != null && ref.trim().length() > 0)
163     {
164       try
165       {
166         refdate = DasTimeFormat.fromDASString(ref.trim());
167
168       } catch (ParseException x)
169       {
170       }
171     }
172     if (newer != null && newer.trim().length() > 0)
173     {
174       try
175       {
176         newdate = DasTimeFormat.fromDASString(newer);
177       } catch (ParseException e)
178       {
179       }
180     }
181     if (refdate != null)
182     {
183       if (newdate != null)
184       {
185         return refdate.before(newdate);
186       }
187       return false;
188     }
189     if (newdate != null)
190     {
191       return true;
192     }
193     // assume first instance of source is newest in list. - TODO: check if
194     // natural ordering of source versions is newest first or oldest first
195     return false;
196   }
197
198   public String[] getLabelsFor(VERSION v)
199   {
200     ArrayList<String> labels = new ArrayList<String>();
201     for (PROP p : v.getPROP())
202     {
203       if (p.getName().equalsIgnoreCase("LABEL"))
204       {
205         labels.add(p.getValue());
206       }
207     }
208     return labels.toArray(new String[0]);
209   }
210
211   private CAPABILITY getCapability(Capabilities capability)
212   {
213     for (CAPABILITY p : getVersion().getCAPABILITY())
214     {
215       if (p.getType().equalsIgnoreCase(capability.getName())
216               || p.getType().equalsIgnoreCase(
217                       "das1:" + capability.getName()))
218       {
219         return p;
220       }
221     }
222     return null;
223   }
224
225   public String[] getCapabilityList(VERSION v)
226   {
227
228     ArrayList<String> labels = new ArrayList<String>();
229     for (CAPABILITY p : v.getCAPABILITY())
230     {
231       // TODO: work out what to do with namespace prefix
232       // does SEQUENCE == das1:SEQUENCE and das2:SEQUENCE ?
233       // for moment, just show all capabilities...
234       if (p.getType().startsWith("das1:"))
235       {
236         labels.add(p.getType());
237       }
238     }
239     return labels.toArray(new String[0]);
240   }
241
242   @Override
243   public List<DbSourceProxy> getSequenceSourceProxies()
244   {
245     if (!isSequenceSource())
246     {
247       return null;
248     }
249     ArrayList<DbSourceProxy> seqsources = new ArrayList<DbSourceProxy>();
250     if (!local)
251     {
252       VERSION v = getVersion();
253       Map<String, COORDINATES> latestc = new Hashtable<String, COORDINATES>();
254       for (COORDINATES cs : v.getCOORDINATES())
255       {
256         COORDINATES ltst = latestc.get(cs.getUri());
257         if (ltst == null
258                 || ltst.getVersion() == null
259                 || (ltst.getVersion() != null && cs.getVersion() != null && isLaterThan(
260                         ltst.getVersion(), cs.getVersion())))
261         {
262           latestc.put(cs.getUri(), cs);
263         }
264       }
265       for (COORDINATES cs : latestc.values())
266       {
267         DasSequenceSource ds;
268         /*
269          * if (css == null || css.length == 0) { // TODO: query das source
270          * directly to identify coordinate system... or // have to make up a
271          * coordinate system css = new DasCoordinateSystem[] { new
272          * DasCoordinateSystem() }; css[0].setName(d1s.getNickname());
273          * css[0].setUniqueId(d1s.getNickname()); } for (int c = 0; c <
274          * css.length; c++) {
275          */
276         try
277         {
278           seqsources.add(ds = new DasSequenceSource(getTitle() + " ("
279                   + cs.getAuthority() + " " + cs.getSource()
280                   + (cs.getVersion() != null ? " " + cs.getVersion() : "")
281                   + ")", cs.getAuthority(), source, v, cs, connprov));
282           if (seqsources.size() > 1)
283           {
284             System.err.println("Added another sequence DB source for "
285                     + getTitle() + " (" + ds.getDbName() + ")");
286           }
287         } catch (Exception e)
288         {
289           System.err.println("Ignoring sequence coord system " + cs + " ("
290                   + cs.getContent() + ") for source " + getTitle()
291                   + "- threw exception when constructing fetcher.\n");
292           e.printStackTrace();
293         }
294       }
295     }
296     else
297     {
298       try
299       {
300         seqsources.add(new DasSequenceSource(getTitle(), getTitle(),
301                 source, getVersion(), null, connprov));
302       } catch (Exception e)
303       {
304         // TODO Auto-generated catch block
305         e.printStackTrace();
306       }
307
308     }
309     if (seqsources.size() > 1)
310     {
311       // sort by name
312       DbSourceProxy[] tsort = seqsources.toArray(new DasSequenceSource[0]);
313       String[] nm = new String[tsort.length];
314       for (int i = 0; i < nm.length; i++)
315       {
316         nm[i] = tsort[i].getDbName().toLowerCase();
317       }
318       jalview.util.QuickSort.sort(nm, tsort);
319       seqsources.clear();
320       for (DbSourceProxy ssrc : tsort)
321       {
322         seqsources.add(ssrc);
323       }
324     }
325     return seqsources;
326   }
327
328   @Override
329   public String getSourceURL()
330   {
331     try
332     {
333       // kind of dumb, since
334       // org.biodas.jdas.dassources.utils.VersionAdapter.getSourceUriFromQueryUri()
335       // does this,
336       // but this way, we can access non DAS 1.6 compliant sources (which have
337       // to have a URL like <sourcename>/das/ and cause a validation exception)
338
339       for (CAPABILITY cap : getVersion().getCAPABILITY())
340       {
341         String capname = cap.getType().substring(
342                 cap.getType().indexOf(":") + 1);
343         int p = cap.getQueryUri().lastIndexOf(capname);
344         if (p < -1)
345         {
346           throw new Exception("Invalid das source: " + source.getUri());
347         }
348         if (cap.getQueryUri().charAt(p) == '/')
349         {
350           p--;
351         }
352         return cap.getQueryUri().substring(0, p);
353       }
354     } catch (Exception x)
355     {
356       System.err.println("Serious: Couldn't get the URL for source "
357               + source.getTitle());
358       x.printStackTrace();
359     }
360     return null;
361   }
362
363   @Override
364   public boolean isNewerThan(jalviewSourceI other)
365   {
366     return isLaterThan(getVersion().getCreated(), other.getVersion()
367             .getCreated());
368   }
369
370   @Override
371   public boolean isReferenceSource()
372   {
373     // TODO check source object for indication that we are the primary for a DAS coordinate system
374     return false;
375   }
376 }