JAL-2316 Added database name column to URL links table in preferences
[jalview.git] / src / jalview / urls / CustomUrlProvider.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ 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
22 package jalview.urls;
23
24 import static jalview.util.UrlConstants.DB_ACCESSION;
25 import static jalview.util.UrlConstants.DELIM;
26 import static jalview.util.UrlConstants.SEP;
27 import static jalview.util.UrlConstants.SEQUENCE_ID;
28
29 import jalview.util.MessageManager;
30 import jalview.util.UrlConstants;
31 import jalview.util.UrlLink;
32
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.StringTokenizer;
40 import java.util.Vector;
41
42 /**
43  * 
44  * Implements the UrlProviderI interface for a UrlProvider object which serves
45  * custom URLs defined by the user
46  * 
47  * @author $author$
48  * @version $Revision$
49  */
50 public class CustomUrlProvider extends UrlProviderImpl
51 {
52   // Default sequence URL link label for SRS
53   private static final String SRS_LABEL = "SRS";
54
55   // map of string ids to urlLinks (selected)
56   private HashMap<String, UrlLink> selectedUrls;
57
58   // map of string ids to urlLinks (not selected)
59   private HashMap<String, UrlLink> nonselectedUrls;
60
61   /**
62    * Construct UrlProvider for custom (user-entered) URLs
63    * 
64    * @param inMenuUrlList
65    *          list of URLs set to be displayed in menu, in form stored in Cache.
66    *          i.e. SEP delimited string
67    * @param storedUrlList
68    *          list of custom URLs entered by user but not currently displayed in
69    *          menu, in form stored in Cache
70    */
71   public CustomUrlProvider(String inMenuUrlList, String storedUrlList)
72   {
73     try
74     {
75       selectedUrls = parseUrlStrings(inMenuUrlList);
76       nonselectedUrls = parseUrlStrings(storedUrlList);
77     } catch (Exception ex)
78     {
79       System.out
80               .println(ex.getMessage() + "\nError parsing sequence links");
81     }
82   }
83
84   /**
85    * Construct UrlProvider for custom (user-entered) URLs
86    * 
87    * @param urlList
88    *          list of URLs to be displayed in menu, as (label,url) pairs
89    * @param storedUrlList
90    *          list of custom URLs entered by user but not currently displayed in
91    *          menu, as (label,url) pairs
92    */
93   public CustomUrlProvider(Map<String, String> inMenuUrlList,
94           Map<String, String> storedUrlList)
95   {
96     try
97     {
98       selectedUrls = parseUrlList(inMenuUrlList);
99       nonselectedUrls = parseUrlList(storedUrlList);
100     } catch (Exception ex)
101     {
102       System.out
103               .println(ex.getMessage() + "\nError parsing sequence links");
104     }
105   }
106
107   private HashMap<String, UrlLink> parseUrlStrings(String urlStrings)
108   {
109     // cachedUrlList is in form <label>|<url>|<label>|<url>...
110     // parse cachedUrlList into labels (used as id) and url links
111     HashMap<String, UrlLink> urls = new HashMap<String, UrlLink>();
112
113     StringTokenizer st = new StringTokenizer(urlStrings, SEP);
114     while (st.hasMoreElements())
115     {
116       String name = st.nextToken();
117
118       if (!isMiriamId(name))
119       {
120         // this one of our custom urls
121         String url = st.nextToken();
122         // check for '|' within a regex
123         int rxstart = url.indexOf(DELIM + DB_ACCESSION + DELIM);
124         if (rxstart == -1)
125         {
126           rxstart = url.indexOf(DELIM + SEQUENCE_ID + DELIM);
127         }
128         while (rxstart == -1 && url.indexOf("/=" + DELIM) == -1
129                 && st.hasMoreTokens())
130         {
131           url = url + SEP + st.nextToken();
132         }
133         urls.put(name, new UrlLink(name, url, name));
134       }
135     }
136     upgradeOldLinks(urls);
137     return urls;
138   }
139
140   private HashMap<String, UrlLink> parseUrlList(Map<String, String> urlList)
141   {
142     HashMap<String, UrlLink> urls = new HashMap<String, UrlLink>();
143     if (urlList == null)
144     {
145       return urls;
146     }
147
148     Iterator<Map.Entry<String, String>> it = urlList.entrySet().iterator();
149     while (it.hasNext())
150     {
151       Map.Entry<String, String> pair = it.next();
152       urls.put(pair.getKey(),
153  new UrlLink(pair.getKey(), pair.getValue(),
154               pair.getKey()));
155     }
156     upgradeOldLinks(urls);
157     return urls;
158   }
159
160   /*
161    * Upgrade any legacy links which may have been left lying around
162    */
163   private void upgradeOldLinks(HashMap<String, UrlLink> urls)
164   {
165     // upgrade old SRS link
166     if (urls.containsKey(SRS_LABEL))
167     {
168       urls.remove(SRS_LABEL);
169       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
170       link.setDescription(UrlConstants.DEFAULT_LABEL);
171       urls.put(UrlConstants.DEFAULT_LABEL, link);
172     }
173   }
174
175   @Override
176   public Vector<String> getLinksForMenu()
177   {
178     Vector<String> links = new Vector<String>();
179     Iterator<Map.Entry<String, UrlLink>> it = selectedUrls.entrySet()
180             .iterator();
181     while (it.hasNext())
182     {
183       Map.Entry<String, UrlLink> pair = it.next();
184       links.add(pair.getValue().toString());
185     }
186     return links;
187   }
188
189   @Override
190   public List<UrlLinkDisplay> getLinksForTable()
191   {
192     ArrayList<UrlLinkDisplay> displayLinks = new ArrayList<UrlLinkDisplay>();
193     displayLinks = getLinksForTable(selectedUrls, true);
194     displayLinks.addAll(getLinksForTable(nonselectedUrls, false));
195     return displayLinks;
196   }
197
198   private ArrayList<UrlLinkDisplay> getLinksForTable(
199           HashMap<String, UrlLink> urlList, boolean selected)
200   {
201     return super.getLinksForTable(urlList, null, selected);
202   }
203
204   @Override
205   public boolean setPrimaryUrl(String id)
206   {
207     if (selectedUrls.containsKey(id))
208     {
209       primaryUrl = id;
210     }
211     else if (nonselectedUrls.containsKey(id))
212     {
213       primaryUrl = id;
214     }
215     else
216     {
217       primaryUrl = null;
218     }
219
220     return (primaryUrl != null);
221   }
222
223   @Override
224   public String writeUrlsAsString(boolean selected)
225   {
226     StringBuffer links = new StringBuffer();
227     HashMap<String, UrlLink> urls;
228     if (selected)
229     {
230       urls = selectedUrls;
231     }
232     else
233     {
234       urls = nonselectedUrls;
235     }
236     if (urls.size() > 0)
237     {
238       for (Entry<String, UrlLink> entry : urls.entrySet())
239       {
240         links.append(entry.getValue().toString());
241         links.append(SEP);
242       }
243
244       // remove last SEP
245       links.setLength(links.length() - 1);
246     }
247     else
248     {
249       urls.clear();
250     }
251     return links.toString();
252   }
253
254   @Override
255   public String getPrimaryUrl(String seqid)
256   {
257     String result = super.getPrimaryUrl(seqid, selectedUrls);
258     if (result == null)
259     {
260       result = super.getPrimaryUrl(seqid, nonselectedUrls);
261     }
262     return result;
263   }
264
265   @Override
266   public String getPrimaryUrlId()
267   {
268     return primaryUrl;
269   }
270
271   @Override
272   public String getPrimaryTarget(String seqid)
273   {
274     return selectedUrls.get(primaryUrl).getTarget();
275   }
276
277   @Override
278   public void setUrlData(List<UrlLinkDisplay> links)
279   {
280     HashMap<String, UrlLink> unselurls = new HashMap<String, UrlLink>();
281     HashMap<String, UrlLink> selurls = new HashMap<String, UrlLink>();
282
283     Iterator<UrlLinkDisplay> it = links.iterator();
284     while (it.hasNext())
285     {
286       UrlLinkDisplay link = it.next();
287
288       // MIRIAM ids will be handled by a different UrlProvider class
289       if (!isMiriamId(link.getId()))
290       {
291         // don't allow duplicate key names as entries will be overwritten
292         if (unselurls.containsKey(link.getId())
293                 || selurls.containsKey(link.getId()))
294         {
295           throw new IllegalArgumentException(MessageManager.formatMessage(
296                   "exception.url_cannot_have_duplicate_id", link.getId()));
297         }
298         if (link.getIsSelected())
299         {
300           selurls.put(link.getId(),
301                   new UrlLink(link.getName(), link.getUrl(), link.getName()));
302         }
303         else
304         {
305           unselurls
306                   .put(link.getId(),
307                           new UrlLink(link.getName(), link.getUrl(), link
308                                   .getName()));
309         }
310         // sort out primary and selected ids
311         if (link.getIsPrimary())
312         {
313           setPrimaryUrl(link.getId());
314         }
315       }
316
317     }
318     nonselectedUrls = unselurls;
319     selectedUrls = selurls;
320   }
321
322   @Override
323   public String choosePrimaryUrl()
324   {
325     // unilaterally set the primary id to the EMBL_EBI link
326     if ((!nonselectedUrls.containsKey(UrlConstants.DEFAULT_LABEL))
327             && (!selectedUrls.containsKey(UrlConstants.DEFAULT_LABEL)))
328     {
329       UrlLink link = new UrlLink(UrlConstants.DEFAULT_STRING);
330       link.setDescription(UrlConstants.DEFAULT_LABEL);
331       selectedUrls.put(UrlConstants.DEFAULT_LABEL, link);
332     }
333     primaryUrl = UrlConstants.DEFAULT_LABEL;
334     return UrlConstants.DEFAULT_LABEL;
335   }
336
337   @Override
338   public boolean contains(String id)
339   {
340     return (selectedUrls.containsKey(id) || nonselectedUrls.containsKey(id));
341   }
342
343 }