Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
UrlLink | 47 | 150 | 85 |
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 | package jalview.util; | |
22 | ||
23 | import static jalview.util.UrlConstants.DB_ACCESSION; | |
24 | import static jalview.util.UrlConstants.DELIM; | |
25 | import static jalview.util.UrlConstants.SEP; | |
26 | import static jalview.util.UrlConstants.SEQUENCE_ID; | |
27 | ||
28 | import jalview.datamodel.DBRefEntry; | |
29 | import jalview.datamodel.SequenceI; | |
30 | ||
31 | import java.util.Arrays; | |
32 | import java.util.Collections; | |
33 | import java.util.Comparator; | |
34 | import java.util.List; | |
35 | import java.util.Map; | |
36 | import java.util.Vector; | |
37 | ||
38 | /** | |
39 | * A helper class to parse URL Link strings taken from applet parameters or | |
40 | * jalview properties file using the com.stevesoft.pat.Regex implementation. | |
41 | * Jalview 2.4 extension allows regular expressions to be used to parse ID | |
42 | * strings and replace the result in the URL. Regex's operate on the whole ID | |
43 | * string given to the matchURL method, if no regex is supplied, then only text | |
44 | * following the first pipe symbol will be substituted. Usage documentation | |
45 | * todo. | |
46 | */ | |
47 | public class UrlLink | |
48 | { | |
49 | private static final String SEQUENCEID_PLACEHOLDER = DELIM + SEQUENCE_ID | |
50 | + DELIM; | |
51 | ||
52 | private static final String ACCESSION_PLACEHOLDER = DELIM + DB_ACCESSION | |
53 | + DELIM; | |
54 | ||
55 | /** | |
56 | * A comparator that puts SEQUENCE_ID template links before DB_ACCESSION | |
57 | * links, and otherwise orders by link name + url (not case sensitive). It | |
58 | * expects to compare strings formatted as "Name|URLTemplate" where the | |
59 | * template may include $SEQUENCE_ID$ or $DB_ACCESSION$ or neither. | |
60 | */ | |
61 | public static final Comparator<String> LINK_COMPARATOR = new Comparator<String>() | |
62 | { | |
63 | 118 | @Override |
64 | public int compare(String link1, String link2) | |
65 | { | |
66 | 118 | if (link1 == null || link2 == null) |
67 | { | |
68 | 3 | return 0; // for failsafe only |
69 | } | |
70 | 115 | if (link1.contains(SEQUENCEID_PLACEHOLDER) |
71 | && link2.contains(ACCESSION_PLACEHOLDER)) | |
72 | { | |
73 | 24 | return -1; |
74 | } | |
75 | 91 | if (link2.contains(SEQUENCEID_PLACEHOLDER) |
76 | && link1.contains(ACCESSION_PLACEHOLDER)) | |
77 | { | |
78 | 45 | return 1; |
79 | } | |
80 | 46 | return String.CASE_INSENSITIVE_ORDER.compare(link1, link2); |
81 | } | |
82 | }; | |
83 | ||
84 | private static final String EQUALS = "="; | |
85 | ||
86 | private static final String SPACE = " "; | |
87 | ||
88 | private String urlSuffix; | |
89 | ||
90 | private String urlPrefix; | |
91 | ||
92 | private String target; | |
93 | ||
94 | private String label; | |
95 | ||
96 | private String dbname; | |
97 | ||
98 | private String regexReplace; | |
99 | ||
100 | private boolean dynamic = false; | |
101 | ||
102 | private boolean usesDBaccession = false; | |
103 | ||
104 | private String invalidMessage = null; | |
105 | ||
106 | /** | |
107 | * parse the given linkString of the form '<label>SEP<url>' into parts url may | |
108 | * contain a string $SEQUENCE_ID<=optional regex=>$ where <=optional regex=> | |
109 | * must be of the form =/<perl style regex>/=$ | |
110 | * | |
111 | * @param link | |
112 | */ | |
113 | 15399 | public UrlLink(String link) |
114 | { | |
115 | 15399 | int sep = link.indexOf(SEP); |
116 | 15399 | int psqid = link.indexOf(DELIM + DB_ACCESSION); |
117 | 15399 | int nsqid = link.indexOf(DELIM + SEQUENCE_ID); |
118 | 15399 | if (psqid > -1) |
119 | { | |
120 | 15216 | dynamic = true; |
121 | 15216 | usesDBaccession = true; |
122 | ||
123 | 15216 | sep = parseLabel(sep, psqid, link); |
124 | ||
125 | 15216 | int endOfRegex = parseUrl(link, DB_ACCESSION, psqid, sep); |
126 | 15216 | parseTarget(link, sep, endOfRegex); |
127 | } | |
128 | 183 | else if (nsqid > -1) |
129 | { | |
130 | 172 | dynamic = true; |
131 | 172 | sep = parseLabel(sep, nsqid, link); |
132 | ||
133 | 172 | int endOfRegex = parseUrl(link, SEQUENCE_ID, nsqid, sep); |
134 | ||
135 | 172 | parseTarget(link, sep, endOfRegex); |
136 | } | |
137 | else | |
138 | { | |
139 | 11 | label = link.substring(0, sep).trim(); |
140 | ||
141 | // if there's a third element in the url link string | |
142 | // it is the target name, otherwise target=label | |
143 | 11 | int lastsep = link.lastIndexOf(SEP); |
144 | 11 | if (lastsep != sep) |
145 | { | |
146 | 8 | urlPrefix = link.substring(sep + 1, lastsep).trim(); |
147 | 8 | target = link.substring(lastsep + 1).trim(); |
148 | } | |
149 | else | |
150 | { | |
151 | 3 | urlPrefix = link.substring(sep + 1).trim(); |
152 | 3 | target = label; |
153 | } | |
154 | ||
155 | 11 | regexReplace = null; // implies we trim any prefix if necessary // |
156 | 11 | urlSuffix = null; |
157 | } | |
158 | ||
159 | 15399 | label = label.trim(); |
160 | 15399 | target = target.trim(); |
161 | } | |
162 | ||
163 | /** | |
164 | * Alternative constructor for separate name, link and description | |
165 | * | |
166 | * @param name | |
167 | * The string used to match the link to a DB reference id | |
168 | * @param url | |
169 | * The url to link to | |
170 | * @param desc | |
171 | * The description of the associated target DB | |
172 | */ | |
173 | 15252 | public UrlLink(String name, String url, String desc) |
174 | { | |
175 | 15252 | this(name + SEP + url + SEP + desc); |
176 | } | |
177 | ||
178 | /** | |
179 | * @return the url_suffix | |
180 | */ | |
181 | 5 | public String getUrlSuffix() |
182 | { | |
183 | 5 | return urlSuffix; |
184 | } | |
185 | ||
186 | /** | |
187 | * @return the url_prefix | |
188 | */ | |
189 | 15 | public String getUrlPrefix() |
190 | { | |
191 | 15 | return urlPrefix; |
192 | } | |
193 | ||
194 | /** | |
195 | * @return the target | |
196 | */ | |
197 | 32 | public String getTarget() |
198 | { | |
199 | 32 | return target; |
200 | } | |
201 | ||
202 | /** | |
203 | * @return the label | |
204 | */ | |
205 | 135 | public String getLabel() |
206 | { | |
207 | 135 | return label; |
208 | } | |
209 | ||
210 | 377 | public String getUrlWithToken() |
211 | { | |
212 | 377 | String var = (usesDBaccession ? DB_ACCESSION : SEQUENCE_ID); |
213 | ||
214 | 377 | return urlPrefix |
215 | 377 | + (dynamic |
216 | ? (DELIM + var | |
217 | 366 | + ((regexReplace != null) |
218 | ? EQUALS + regexReplace + EQUALS + DELIM | |
219 | : DELIM)) | |
220 | : "") | |
221 | 377 | + ((urlSuffix == null) ? "" : urlSuffix); |
222 | } | |
223 | ||
224 | /** | |
225 | * @return the regexReplace | |
226 | */ | |
227 | 80 | public String getRegexReplace() |
228 | { | |
229 | 80 | return regexReplace; |
230 | } | |
231 | ||
232 | /** | |
233 | * @return the invalidMessage | |
234 | */ | |
235 | 13 | public String getInvalidMessage() |
236 | { | |
237 | 13 | return invalidMessage; |
238 | } | |
239 | ||
240 | /** | |
241 | * Check if URL string was parsed properly. | |
242 | * | |
243 | * @return boolean - if false then <code>getInvalidMessage</code> returns an | |
244 | * error message | |
245 | */ | |
246 | 104 | public boolean isValid() |
247 | { | |
248 | 104 | return invalidMessage == null; |
249 | } | |
250 | ||
251 | /** | |
252 | * | |
253 | * @return whether link is dynamic | |
254 | */ | |
255 | 6 | public boolean isDynamic() |
256 | { | |
257 | 6 | return dynamic; |
258 | } | |
259 | ||
260 | /** | |
261 | * | |
262 | * @return whether link uses DB Accession id | |
263 | */ | |
264 | 136 | public boolean usesDBAccession() |
265 | { | |
266 | 136 | return usesDBaccession; |
267 | } | |
268 | ||
269 | /** | |
270 | * Set the label | |
271 | * | |
272 | * @param newlabel | |
273 | */ | |
274 | 44 | public void setLabel(String newlabel) |
275 | { | |
276 | 44 | this.label = newlabel; |
277 | } | |
278 | ||
279 | /** | |
280 | * Set the target | |
281 | * | |
282 | * @param desc | |
283 | */ | |
284 | 6 | public void setTarget(String desc) |
285 | { | |
286 | 6 | target = desc; |
287 | } | |
288 | ||
289 | /** | |
290 | * return one or more URL strings by applying regex to the given idstring | |
291 | * | |
292 | * @param idstring | |
293 | * @param onlyIfMatches | |
294 | * - when true url strings are only made if regex is defined and | |
295 | * matches | |
296 | * @return String[] { part of idstring substituted, full substituted url , .. | |
297 | * next part, next url..} | |
298 | */ | |
299 | 55 | public String[] makeUrls(String idstring, boolean onlyIfMatches) |
300 | { | |
301 | 55 | if (dynamic) |
302 | { | |
303 | 55 | if (regexReplace != null) |
304 | { | |
305 | 8 | com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex |
306 | .perlCode("/" + regexReplace + "/"); | |
307 | 8 | if (rg.search(idstring)) |
308 | { | |
309 | 6 | int ns = rg.numSubs(); |
310 | 6 | if (ns == 0) |
311 | { | |
312 | // take whole regex | |
313 | 0 | return new String[] { rg.stringMatched(), |
314 | urlPrefix + rg.stringMatched() + urlSuffix }; | |
315 | } /* | |
316 | * else if (ns==1) { // take only subgroup match return new String[] | |
317 | * { rg.stringMatched(1), url_prefix+rg.stringMatched(1)+url_suffix | |
318 | * }; } | |
319 | */ | |
320 | else | |
321 | { | |
322 | // debug | |
323 | 24 | for (int s = 0; s <= rg.numSubs(); s++) |
324 | { | |
325 | 18 | jalview.bin.Console.errPrintln("Sub " + s + " : " |
326 | + rg.matchedFrom(s) + " : " + rg.matchedTo(s) + " : '" | |
327 | + rg.stringMatched(s) + "'"); | |
328 | } | |
329 | // try to collate subgroup matches | |
330 | 6 | Vector<String> subs = new Vector<>(); |
331 | // have to loop through submatches, collating them at top level | |
332 | // match | |
333 | 6 | int s = 0; // 1; |
334 | 24 | while (s <= ns) |
335 | { | |
336 | 18 | if (s + 1 <= ns && rg.matchedTo(s) > -1 |
337 | && rg.matchedTo(s + 1) > -1 | |
338 | && rg.matchedTo(s + 1) < rg.matchedTo(s)) | |
339 | { | |
340 | // s is top level submatch. search for submatches enclosed by | |
341 | // this one | |
342 | 0 | int r = s + 1; |
343 | 0 | String mtch = ""; |
344 | 0 | while (r <= ns && rg.matchedTo(r) <= rg.matchedTo(s)) |
345 | { | |
346 | 0 | if (rg.matchedFrom(r) > -1) |
347 | { | |
348 | 0 | mtch += rg.stringMatched(r); |
349 | } | |
350 | 0 | r++; |
351 | } | |
352 | 0 | if (mtch.length() > 0) |
353 | { | |
354 | 0 | subs.addElement(mtch); |
355 | 0 | subs.addElement(urlPrefix + mtch + urlSuffix); |
356 | } | |
357 | 0 | s = r; |
358 | } | |
359 | else | |
360 | { | |
361 | 18 | if (rg.matchedFrom(s) > -1) |
362 | { | |
363 | 6 | subs.addElement(rg.stringMatched(s)); |
364 | 6 | subs.addElement( |
365 | urlPrefix + rg.stringMatched(s) + urlSuffix); | |
366 | } | |
367 | 18 | s++; |
368 | } | |
369 | } | |
370 | ||
371 | 6 | String[] res = new String[subs.size()]; |
372 | 18 | for (int r = 0, rs = subs.size(); r < rs; r++) |
373 | { | |
374 | 12 | res[r] = subs.elementAt(r); |
375 | } | |
376 | 6 | subs.removeAllElements(); |
377 | 6 | return res; |
378 | } | |
379 | } | |
380 | 2 | if (onlyIfMatches) |
381 | { | |
382 | 1 | return null; |
383 | } | |
384 | } | |
385 | /* Otherwise - trim off any 'prefix' - pre 2.4 Jalview behaviour */ | |
386 | 48 | if (idstring.indexOf(SEP) > -1) |
387 | { | |
388 | 0 | idstring = idstring.substring(idstring.lastIndexOf(SEP) + 1); |
389 | } | |
390 | ||
391 | // just return simple url substitution. | |
392 | 48 | return new String[] { idstring, urlPrefix + idstring + urlSuffix }; |
393 | } | |
394 | else | |
395 | { | |
396 | 0 | return new String[] { "", urlPrefix }; |
397 | } | |
398 | } | |
399 | ||
400 | 291 | @Override |
401 | public String toString() | |
402 | { | |
403 | 291 | return label + SEP + getUrlWithToken(); |
404 | } | |
405 | ||
406 | /** | |
407 | * @return delimited string containing label, url and target | |
408 | */ | |
409 | 17 | public String toStringWithTarget() |
410 | { | |
411 | 17 | return label + SEP + getUrlWithToken() + SEP + target; |
412 | } | |
413 | ||
414 | /** | |
415 | * Parse the label from the link string | |
416 | * | |
417 | * @param firstSep | |
418 | * Location of first occurrence of separator in link string | |
419 | * @param psqid | |
420 | * Position of sequence id or name in link string | |
421 | * @param link | |
422 | * Link string containing database name and url | |
423 | * @return Position of last separator symbol prior to any regex symbols | |
424 | */ | |
425 | 15388 | protected int parseLabel(int firstSep, int psqid, String link) |
426 | { | |
427 | 15388 | int p = firstSep; |
428 | 15388 | int sep = firstSep; |
429 | 15388 | do |
430 | { | |
431 | 15388 | sep = p; |
432 | 15388 | p = link.indexOf(SEP, sep + 1); |
433 | 15388 | } while (p > sep && p < psqid); |
434 | // Assuming that the URL itself does not contain any SEP symbols | |
435 | // sep now contains last pipe symbol position prior to any regex symbols | |
436 | 15388 | label = link.substring(0, sep); |
437 | ||
438 | 15388 | return sep; |
439 | } | |
440 | ||
441 | /** | |
442 | * Parse the target from the link string | |
443 | * | |
444 | * @param link | |
445 | * Link string containing database name and url | |
446 | * @param sep | |
447 | * Location of first separator symbol | |
448 | * @param endOfRegex | |
449 | * Location of end of any regular expression in link string | |
450 | */ | |
451 | 15388 | protected void parseTarget(String link, int sep, int endOfRegex) |
452 | { | |
453 | 15388 | int lastsep = link.lastIndexOf(SEP); |
454 | ||
455 | 15388 | if ((lastsep != sep) && (lastsep > endOfRegex)) |
456 | { | |
457 | // final element in link string is the target | |
458 | 15245 | target = link.substring(lastsep + 1).trim(); |
459 | } | |
460 | else | |
461 | { | |
462 | 143 | target = label; |
463 | } | |
464 | ||
465 | 15388 | if (target.indexOf(SEP) > -1) |
466 | { | |
467 | // SEP terminated database name / www target at start of Label | |
468 | 0 | target = target.substring(0, target.indexOf(SEP)); |
469 | } | |
470 | 15388 | else if (target.indexOf(SPACE) > 2) |
471 | { | |
472 | // space separated label - first word matches database name | |
473 | 94 | target = target.substring(0, target.indexOf(SPACE)); |
474 | } | |
475 | } | |
476 | ||
477 | /** | |
478 | * Parse the URL part of the link string | |
479 | * | |
480 | * @param link | |
481 | * Link string containing database name and url | |
482 | * @param varName | |
483 | * Name of variable in url string (e.g. SEQUENCE_ID, SEQUENCE_NAME) | |
484 | * @param sqidPos | |
485 | * Position of id or name in link string | |
486 | * @param sep | |
487 | * Position of separator in link string | |
488 | * @return Location of end of any regex in link string | |
489 | */ | |
490 | 15388 | protected int parseUrl(String link, String varName, int sqidPos, int sep) |
491 | { | |
492 | 15388 | urlPrefix = link.substring(sep + 1, sqidPos).trim(); |
493 | ||
494 | // delimiter at start of regex: e.g. $SEQUENCE_ID=/ | |
495 | 15388 | String startDelimiter = DELIM + varName + "=/"; |
496 | ||
497 | // delimiter at end of regex: /=$ | |
498 | 15388 | String endDelimiter = "/=" + DELIM; |
499 | ||
500 | 15388 | int startLength = startDelimiter.length(); |
501 | ||
502 | // Parse URL : Whole URL string first | |
503 | 15388 | int p = link.indexOf(endDelimiter, sqidPos + startLength); |
504 | ||
505 | 15388 | if (link.indexOf(startDelimiter) == sqidPos |
506 | && (p > sqidPos + startLength)) | |
507 | { | |
508 | // Extract Regex and suffix | |
509 | 4 | urlSuffix = link.substring(p + endDelimiter.length()); |
510 | 4 | regexReplace = link.substring(sqidPos + startLength, p); |
511 | 4 | try |
512 | { | |
513 | 4 | com.stevesoft.pat.Regex rg = com.stevesoft.pat.Regex |
514 | .perlCode("/" + regexReplace + "/"); | |
515 | 4 | if (rg == null) |
516 | { | |
517 | 1 | invalidMessage = "Invalid Regular Expression : '" + regexReplace |
518 | + "'\n"; | |
519 | } | |
520 | } catch (Exception e) | |
521 | { | |
522 | 0 | invalidMessage = "Invalid Regular Expression : '" + regexReplace |
523 | + "'\n"; | |
524 | } | |
525 | } | |
526 | else | |
527 | { | |
528 | // no regex | |
529 | 15384 | regexReplace = null; |
530 | // verify format is really correct. | |
531 | 15384 | if (link.indexOf(DELIM + varName + DELIM) == sqidPos) |
532 | { | |
533 | 15381 | int lastsep = link.lastIndexOf(SEP); |
534 | 15381 | if (lastsep < sqidPos + startLength - 1) |
535 | { | |
536 | // the last SEP character was before the regex, ignore | |
537 | 139 | lastsep = link.length(); |
538 | } | |
539 | 15381 | urlSuffix = link.substring(sqidPos + startLength - 1, lastsep) |
540 | .trim(); | |
541 | 15381 | regexReplace = null; |
542 | } | |
543 | else | |
544 | { | |
545 | 3 | invalidMessage = "Warning: invalid regex structure for URL link : " |
546 | + link; | |
547 | } | |
548 | } | |
549 | ||
550 | 15388 | return p; |
551 | } | |
552 | ||
553 | /** | |
554 | * Create a set of URL links for a sequence | |
555 | * | |
556 | * @param seq | |
557 | * The sequence to create links for | |
558 | * @param linkset | |
559 | * Map of links: key = id + SEP + link, value = [target, label, id, | |
560 | * link] | |
561 | */ | |
562 | 97 | public void createLinksFromSeq(final SequenceI seq, |
563 | Map<String, List<String>> linkset) | |
564 | { | |
565 | 97 | if (seq != null && dynamic) |
566 | { | |
567 | 94 | createDynamicLinks(seq, linkset); |
568 | } | |
569 | else | |
570 | { | |
571 | 3 | createStaticLink(linkset); |
572 | } | |
573 | } | |
574 | ||
575 | /** | |
576 | * Create a static URL link | |
577 | * | |
578 | * @param linkset | |
579 | * Map of links: key = id + SEP + link, value = [target, label, id, | |
580 | * link] | |
581 | */ | |
582 | 3 | protected void createStaticLink(Map<String, List<String>> linkset) |
583 | { | |
584 | 3 | if (!linkset.containsKey(label + SEP + getUrlPrefix())) |
585 | { | |
586 | // Add a non-dynamic link | |
587 | 3 | linkset.put(label + SEP + getUrlPrefix(), |
588 | Arrays.asList(target, label, null, getUrlPrefix())); | |
589 | } | |
590 | } | |
591 | ||
592 | /** | |
593 | * Create dynamic URL links | |
594 | * | |
595 | * @param seq | |
596 | * The sequence to create links for | |
597 | * @param linkset | |
598 | * Map of links: key = id + SEP + link, value = [target, label, id, | |
599 | * link] | |
600 | */ | |
601 | 94 | protected void createDynamicLinks(final SequenceI seq, |
602 | Map<String, List<String>> linkset) | |
603 | { | |
604 | // collect id string too | |
605 | 94 | String id = seq.getName(); |
606 | 94 | String descr = seq.getDescription(); |
607 | 94 | if (descr != null && descr.length() < 1) |
608 | { | |
609 | 0 | descr = null; |
610 | } | |
611 | ||
612 | 94 | if (usesDBAccession()) // link is ID |
613 | { | |
614 | // collect matching db-refs | |
615 | 70 | List<DBRefEntry> dbr = DBRefUtils.selectRefs(seq.getDBRefs(), |
616 | new String[] | |
617 | { target }); | |
618 | ||
619 | // if there are any dbrefs which match up with the link | |
620 | 70 | if (dbr != null) |
621 | { | |
622 | 16 | for (int r = 0, nd = dbr.size(); r < nd; r++) |
623 | { | |
624 | // create Bare ID link for this URL | |
625 | 10 | createBareURLLink(dbr.get(r).getAccessionId(), true, linkset); |
626 | } | |
627 | } | |
628 | } | |
629 | 24 | else if (!usesDBAccession() && id != null) // link is name |
630 | { | |
631 | // create Bare ID link for this URL | |
632 | 24 | createBareURLLink(id, false, linkset); |
633 | } | |
634 | ||
635 | // Create urls from description but only for URL links which are regex | |
636 | // links | |
637 | 94 | if (descr != null && getRegexReplace() != null) |
638 | { | |
639 | // create link for this URL from description where regex matches | |
640 | 0 | createBareURLLink(descr, false, linkset); |
641 | } | |
642 | } | |
643 | ||
644 | /* | |
645 | * Create a bare URL Link | |
646 | * Returns map where key = id + SEP + link, and value = [target, label, id, link] | |
647 | */ | |
648 | 34 | protected void createBareURLLink(String id, Boolean combineLabel, |
649 | Map<String, List<String>> linkset) | |
650 | { | |
651 | 34 | String[] urls = makeUrls(id, true); |
652 | 34 | if (urls != null) |
653 | { | |
654 | 68 | for (int u = 0; u < urls.length; u += 2) |
655 | { | |
656 | 34 | if (!linkset.containsKey(urls[u] + SEP + urls[u + 1])) |
657 | { | |
658 | 34 | String thisLabel = label; |
659 | 34 | if (combineLabel) |
660 | { | |
661 | // incorporate label with idstring | |
662 | 10 | thisLabel = label + SEP + urls[u]; |
663 | } | |
664 | ||
665 | 34 | linkset.put(urls[u] + SEP + urls[u + 1], |
666 | Arrays.asList(target, thisLabel, urls[u], urls[u + 1])); | |
667 | } | |
668 | } | |
669 | } | |
670 | } | |
671 | ||
672 | /** | |
673 | * Sorts links (formatted as LinkName|LinkPattern) suitable for display in a | |
674 | * menu | |
675 | * <ul> | |
676 | * <li>SEQUENCE_ID links precede DB_ACCESSION links (i.e. canonical lookup | |
677 | * before cross-references)</li> | |
678 | * <li>otherwise by Link name (case insensitive)</li> | |
679 | * </ul> | |
680 | * | |
681 | * @param nlinks | |
682 | */ | |
683 | 23 | public static void sort(List<String> nlinks) |
684 | { | |
685 | 23 | Collections.sort(nlinks, LINK_COMPARATOR); |
686 | } | |
687 | } |