fb0d6761a951cf0e7216dbd72482b999a8cc0c03
[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.UrlLink;
31
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.StringTokenizer;
39 import java.util.Vector;
40
41 /**
42  * 
43  * Implements the UrlProviderI interface for a UrlProvider object which serves
44  * custom URLs defined by the user
45  * 
46  * @author $author$
47  * @version $Revision$
48  */
49 public class CustomUrlProvider extends UrlProviderImpl
50 {
51
52   // minimum length of substitution in url link string
53   private static final int MIN_SUBST_LENGTH = 4;
54
55   // Default sequence URL link label for SRS
56   private static final String SRS_LABEL = "SRS";
57
58   // map of string ids to urlLinks
59   private HashMap<String, UrlLink> urls;
60
61   /**
62    * Construct UrlProvider for custom (user-entered) URLs
63    * 
64    * @param cachedUrlList
65    *          list of URLs in form stored in Cache. i.e. SEP delimited string
66    */
67   public CustomUrlProvider(String cachedUrlList)
68   {
69     try
70     {
71       urls = new HashMap<String, UrlLink>();
72
73       // cachedUrlList is in form <label>|<url>|<label>|<url>...
74       // parse cachedUrlList into labels (used as id) and url links
75       StringTokenizer st = new StringTokenizer(cachedUrlList, SEP);
76       while (st.hasMoreElements())
77       {
78         String name = st.nextToken();
79
80         if (!isMiriamId(name))
81         {
82           // this one of our custom urls
83           String url = st.nextToken();
84           // check for '|' within a regex
85           int rxstart = url.indexOf(DELIM + DB_ACCESSION + DELIM);
86           if (rxstart == -1)
87           {
88             rxstart = url.indexOf(DELIM + SEQUENCE_ID + DELIM);
89           }
90           while (rxstart == -1 && url.indexOf("/=" + DELIM) == -1
91                   && st.hasMoreTokens())
92           {
93             url = url + SEP + st.nextToken();
94           }
95           urls.put(name, new UrlLink(name + SEP + url));
96         }
97       }
98     } catch (Exception ex)
99     {
100       System.out.println(ex + "\nError parsing sequence links");
101     }
102     upgradeOldLinks();
103
104   }
105
106   /**
107    * Construct UrlProvider for custom (user-entered) URLs
108    * 
109    * @param urlList
110    *          list of URLs as (label,url) pairs
111    */
112   public CustomUrlProvider(Map<String, String> urlList)
113   {
114     try
115     {
116       urls = new HashMap<String, UrlLink>();
117       Iterator<Map.Entry<String, String>> it = urlList.entrySet()
118               .iterator();
119       while (it.hasNext())
120       {
121         Map.Entry<String, String> pair = it.next();
122         urls.put(pair.getKey(),
123                 new UrlLink(pair.getKey() + SEP + pair.getValue()));
124       }
125     } catch (Exception ex)
126     {
127       System.out.println(ex + "\nError parsing sequence links");
128     }
129     upgradeOldLinks();
130   }
131
132   /*
133    * Upgrade any legacy links which may have been left lying around
134    */
135   private void upgradeOldLinks()
136   {
137     // upgrade old SRS link
138     if (urls.containsKey(SRS_LABEL))
139     {
140       urls.remove(SRS_LABEL);
141       urls.put(DEFAULT_LABEL, new UrlLink(DEFAULT_STRING));
142     }
143   }
144
145   @Override
146   public Vector<String> getLinksForDisplay()
147   {
148     Vector<String> links = new Vector<String>();
149     Iterator<Map.Entry<String, UrlLink>> it = urls.entrySet().iterator();
150     while (it.hasNext())
151     {
152       Map.Entry<String, UrlLink> pair = it.next();
153       links.add(pair.getValue().toString());
154     }
155     return links;
156   }
157
158   @Override
159   public List<UrlLinkDisplay> getLinksForTable()
160   {
161     ArrayList<UrlLinkDisplay> displayLinks = new ArrayList<UrlLinkDisplay>();
162     for (Entry<String, UrlLink> entry : urls.entrySet())
163     {
164       String key = entry.getKey();
165       boolean isDefault = (key.equals(defaultUrl));
166       boolean isSelected = true; // custom urls always selected
167       String displayLink = entry.getValue().toString().split("\\|")[1]; // TODO
168                                                                         // sort
169                                                                         // this
170                                                                         // out
171                                                                         // properly!
172       displayLinks.add(new UrlLinkDisplay(key, key, displayLink,
173               isSelected,
174               isDefault));
175     }
176     return displayLinks;
177   }
178
179   @Override
180   public boolean setDefaultUrl(String id)
181   {
182     if (urls.containsKey(id))
183     {
184       defaultUrl = id;
185     }
186     else
187     {
188       defaultUrl = null;
189     }
190     return urls.containsKey(id);
191   }
192
193   @Override
194   public String writeUrlsAsString()
195   {
196     StringBuffer links = new StringBuffer();
197     if (urls.size() > 0)
198     {
199       for (UrlLink link : urls.values())
200       {
201         links.append(link.toString());
202         links.append(SEP);
203       }
204
205       // remove last SEP
206       links.setLength(links.length() - 1);
207     }
208     else
209     {
210       urls.clear();
211     }
212     return links.toString();
213   }
214
215   @Override
216   public String getDefaultUrl(String seqid)
217   {
218     if (defaultUrl == null)
219     {
220       return null;
221     }
222
223     String url = null;
224     UrlLink urlLink = urls.get(defaultUrl);
225     String[] defaultUrls = urlLink.makeUrls(seqid, true);
226     if (defaultUrls == null || defaultUrls[0] == null
227             || defaultUrls[0].length() < MIN_SUBST_LENGTH)
228     {
229       url = null;
230     }
231     else
232     {
233       // just take first URL made from regex
234       url = defaultUrls[1];
235     }
236     return url;
237   }
238
239   @Override
240   public String getDefaultTarget(String seqid)
241   {
242     return urls.get(defaultUrl).getTarget();
243   }
244
245   @Override
246   public void setUrlLinks(Vector<String> names, Vector<String> urlstrings)
247   {
248     HashMap<String, UrlLink> newurls = new HashMap<String, UrlLink>();
249
250     // should check that lists are same length but this function is likely
251     // to change once the Preferences dialog is rebuilt
252
253     for (int i = 0; i < names.size(); ++i)
254     {
255       // don't allow MIRIAM ids as custom url names (as the links will overwrite
256       // each other)
257       // unlikely user would try to do this, but...
258       if (isMiriamId(names.elementAt(i)))
259       {
260         throw new IllegalArgumentException(MessageManager.formatMessage(
261                 "exception.url_cannot_have_miriam_id", names.elementAt(i)));
262       }
263       // don't allow duplicate key names as entries will be overwritten
264       if (newurls.containsKey(names.elementAt(i)))
265       {
266         throw new IllegalArgumentException(MessageManager.formatMessage(
267                 "exception.url_cannot_have_duplicate_id",
268                 names.elementAt(i)));
269       }
270       newurls.put(names.elementAt(i), new UrlLink(names.elementAt(i) + SEP
271               + urlstrings.elementAt(i)));
272     }
273
274     // don't update until we're sure this set is ok
275     urls = newurls;
276
277   }
278
279   @Override
280   public void setUrlData(List<UrlLinkDisplay> links)
281   {
282     HashMap<String, UrlLink> newurls = new HashMap<String, UrlLink>();
283
284     Iterator<UrlLinkDisplay> it = links.iterator();
285     while (it.hasNext())
286     {
287       UrlLinkDisplay link = it.next();
288
289       // MIRIAM ids will be handled by a different UrlProvider class
290       if (!isMiriamId(link.getId()))
291       {
292
293         // don't allow duplicate key names as entries will be overwritten
294         if (newurls.containsKey(link.getId()))
295         {
296           throw new IllegalArgumentException(MessageManager.formatMessage(
297                   "exception.url_cannot_have_duplicate_id", link.getId()));
298         }
299         if (link.getIsSelected())
300         {
301           newurls.put(link.getId(),
302                   new UrlLink(link.getId() + SEP + link.getUrl()));
303
304           // sort out default and selected ids
305           if (link.getIsDefault())
306           {
307             setDefaultUrl(link.getId());
308           }
309         }
310           // TODO KM make it possible to set and save selected custom urls
311
312       }
313
314     }
315     urls = newurls;
316   }
317
318   @Override
319   public String chooseDefaultUrl()
320   {
321     // unilaterally set the default id to the EMBL_EBI link
322     
323     if (!urls.containsKey(DEFAULT_LABEL))
324     {
325       urls.put(DEFAULT_LABEL, new UrlLink(DEFAULT_STRING));
326     }
327     defaultUrl = DEFAULT_LABEL;
328     return DEFAULT_LABEL;
329   }
330
331 }