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