1 package au.gov.amsa.util.nmea;
2
3 import java.util.Arrays;
4 import java.util.LinkedHashMap;
5
6 import org.apache.commons.lang3.StringUtils;
7
8 import com.google.common.collect.Maps;
9
10
11
12
13
14 public class NmeaMessageParser {
15
16 private static final String CHECKSUM_DELIMITER = "*";
17 private static final String PARAMETER_DELIMITER = ",";
18 private static final String CODE_DELIMITER = ":";
19
20
21
22
23
24
25
26 public NmeaMessage parse(String line) {
27 LinkedHashMap<String, String> tags = Maps.newLinkedHashMap();
28
29 String remaining;
30 if (line.startsWith("\\")) {
31 int tagFinish = line.lastIndexOf('\\', line.length() - 1);
32 if (tagFinish == -1)
33 throw new NmeaMessageParseException(
34 "no matching \\ symbol to finish tag block: " + line);
35 if (tagFinish == 0)
36 throw new NmeaMessageParseException("tag block is empty or not terminated");
37 tags = extractTags(line.substring(1, tagFinish));
38 remaining = line.substring(tagFinish + 1);
39 } else
40 remaining = line;
41
42 String[] items;
43 String checksum;
44 if (remaining.length() > 0) {
45 if (!remaining.contains("*"))
46 throw new NmeaMessageParseException("checksum delimiter * not found");
47 items = getNmeaItems(remaining);
48
49 checksum = line.substring(line.indexOf('*') + 1);
50 } else {
51 items = new String[] {};
52
53 checksum = "";
54 }
55
56 return new NmeaMessage(tags, Arrays.asList(items), checksum);
57 }
58
59
60
61
62
63
64
65
66
67 private static String[] getNmeaItems(String line) {
68 String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(line,
69 PARAMETER_DELIMITER);
70
71 String last = items[items.length - 1];
72 if (last.contains("*"))
73 items[items.length - 1] = last.substring(0, last.lastIndexOf('*'));
74 return items;
75 }
76
77
78
79
80
81
82
83
84 public static LinkedHashMap<String, String> extractTags(String s) {
85 LinkedHashMap<String, String> map = Maps.newLinkedHashMap();
86 int c = s.lastIndexOf(CHECKSUM_DELIMITER);
87 if (c == -1) {
88 return map;
89 }
90 s = s.substring(0, c);
91 String[] items = s.split(PARAMETER_DELIMITER);
92 for (String item : items) {
93 int i = item.indexOf(CODE_DELIMITER);
94 if (i == -1)
95 throw new NmeaMessageParseException(
96 "TAG BLOCK parameter is not is format 'a:b' :" + s);
97 map.put(item.substring(0, i), item.substring(i + 1));
98 }
99 return map;
100 }
101 }