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