Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
DnaUtils | 28 | 34 | 12 |
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 java.text.ParseException; | |
24 | import java.util.ArrayList; | |
25 | import java.util.Collections; | |
26 | import java.util.List; | |
27 | ||
28 | public class DnaUtils | |
29 | { | |
30 | ||
31 | /** | |
32 | * Parses an ENA/GenBank format location specifier and returns a list of | |
33 | * [start, end] ranges. Throws an exception if not able to parse. | |
34 | * <p> | |
35 | * Currently we do not parse "order()" specifiers, or indeterminate ranges of | |
36 | * the format "<start..end" or "start..>end" or "start.end" or | |
37 | * "start^end" | |
38 | * | |
39 | * @param location | |
40 | * @return | |
41 | * @throws ParseException | |
42 | * if unable to parse the location (the exception message is the | |
43 | * location specifier being parsed); we use ParseException in | |
44 | * preference to the unchecked IllegalArgumentException | |
45 | * @see http://www.insdc.org/files/feature_table.html#3.4 | |
46 | */ | |
47 | 86 | public static List<int[]> parseLocation(String location) |
48 | throws ParseException | |
49 | { | |
50 | 86 | location = location.trim(); // failsafe for untidy input data |
51 | 85 | if (location.startsWith("join(")) |
52 | { | |
53 | 14 | return parseJoin(location); |
54 | } | |
55 | 71 | else if (location.startsWith("complement(")) |
56 | { | |
57 | 14 | return parseComplement(location); |
58 | } | |
59 | 57 | if (location.startsWith("order(")) |
60 | { | |
61 | 1 | throw new ParseException(location, 0); |
62 | } | |
63 | ||
64 | /* | |
65 | * try to parse m..n (or simply m) | |
66 | */ | |
67 | 56 | String[] range = location.split("\\.\\."); |
68 | 56 | if (range.length == 1 || range.length == 2) |
69 | { | |
70 | 56 | try |
71 | { | |
72 | 56 | int start = Integer.valueOf(range[0]); |
73 | 51 | int end = range.length == 1 ? start : Integer.valueOf(range[1]); |
74 | 50 | return Collections.singletonList(new int[] { start, end }); |
75 | } catch (NumberFormatException e) | |
76 | { | |
77 | /* | |
78 | * could be a location like <1..888 or 1..>888 | |
79 | */ | |
80 | 6 | throw new ParseException(location, 0); |
81 | } | |
82 | } | |
83 | else | |
84 | { | |
85 | /* | |
86 | * could be a location like 102.110 or 123^124 | |
87 | */ | |
88 | 0 | throw new ParseException(location, 0); |
89 | } | |
90 | } | |
91 | ||
92 | /** | |
93 | * Parses a complement(locationSpec) into a list of start-end ranges | |
94 | * | |
95 | * @param location | |
96 | * @return | |
97 | * @throws ParseException | |
98 | */ | |
99 | 14 | static List<int[]> parseComplement(String location) throws ParseException |
100 | { | |
101 | /* | |
102 | * take what is inside complement() | |
103 | */ | |
104 | 14 | if (!location.endsWith(")")) |
105 | { | |
106 | 3 | throw new ParseException(location, 0); |
107 | } | |
108 | 11 | String toComplement = location.substring("complement(".length(), |
109 | location.length() - 1); | |
110 | 11 | List<int[]> ranges = parseLocation(toComplement); |
111 | ||
112 | /* | |
113 | * reverse the order and direction of ranges | |
114 | */ | |
115 | 11 | Collections.reverse(ranges); |
116 | 11 | for (int[] range : ranges) |
117 | { | |
118 | 12 | int temp = range[0]; |
119 | 12 | range[0] = range[1]; |
120 | 12 | range[1] = temp; |
121 | } | |
122 | 11 | return ranges; |
123 | } | |
124 | ||
125 | /** | |
126 | * Parses a join(loc1,loc2,...,locn) into a list of start-end ranges | |
127 | * | |
128 | * @param location | |
129 | * @return | |
130 | * @throws ParseException | |
131 | */ | |
132 | 14 | static List<int[]> parseJoin(String location) throws ParseException |
133 | { | |
134 | 14 | List<int[]> ranges = new ArrayList<int[]>(); |
135 | ||
136 | /* | |
137 | * take what is inside join() | |
138 | */ | |
139 | 14 | if (!location.endsWith(")")) |
140 | { | |
141 | 3 | throw new ParseException(location, 0); |
142 | } | |
143 | 11 | String joinedLocs = location.substring("join(".length(), |
144 | location.length() - 1); | |
145 | 11 | String[] locations = joinedLocs.split(","); |
146 | 11 | for (String loc : locations) |
147 | { | |
148 | 25 | List<int[]> range = parseLocation(loc); |
149 | 23 | ranges.addAll(range); |
150 | } | |
151 | 9 | return ranges; |
152 | } | |
153 | ||
154 | } |