2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import java.text.ParseException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
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.
35 * Currently we do not parse "order()" specifiers, or indeterminate ranges of
36 * the format "<start..end" or "start..>end" or "start.end" or
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
47 public static List<int[]> parseLocation(String location)
50 location = location.trim(); // failsafe for untidy input data
51 if (location.startsWith("join("))
53 return parseJoin(location);
55 else if (location.startsWith("complement("))
57 return parseComplement(location);
59 if (location.startsWith("order("))
61 throw new ParseException(location, 0);
65 * try to parse m..n (or simply m)
67 String[] range = location.split("\\.\\.");
68 if (range.length == 1 || range.length == 2)
72 int start = Integer.valueOf(range[0]);
73 int end = range.length == 1 ? start : Integer.valueOf(range[1]);
74 return Collections.singletonList(new int[] { start, end });
75 } catch (NumberFormatException e)
78 * could be a location like <1..888 or 1..>888
80 throw new ParseException(location, 0);
86 * could be a location like 102.110 or 123^124
88 throw new ParseException(location, 0);
93 * Parses a complement(locationSpec) into a list of start-end ranges
97 * @throws ParseException
99 static List<int[]> parseComplement(String location) throws ParseException
102 * take what is inside complement()
104 if (!location.endsWith(")"))
106 throw new ParseException(location, 0);
108 String toComplement = location.substring("complement(".length(),
109 location.length() - 1);
110 List<int[]> ranges = parseLocation(toComplement);
113 * reverse the order and direction of ranges
115 Collections.reverse(ranges);
116 for (int[] range : ranges)
126 * Parses a join(loc1,loc2,...,locn) into a list of start-end ranges
130 * @throws ParseException
132 static List<int[]> parseJoin(String location) throws ParseException
134 List<int[]> ranges = new ArrayList<int[]>();
137 * take what is inside join()
139 if (!location.endsWith(")"))
141 throw new ParseException(location, 0);
143 String joinedLocs = location.substring("join(".length(),
144 location.length() - 1);
145 String[] locations = joinedLocs.split(",");
146 for (String loc : locations)
148 List<int[]> range = parseLocation(loc);
149 ranges.addAll(range);