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