1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.rinex.utils.parsing;
18
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
21
22 import org.hipparchus.util.FastMath;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitInternalError;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.files.rinex.RinexFile;
27 import org.orekit.files.rinex.section.RinexBaseHeader;
28 import org.orekit.files.rinex.section.RinexComment;
29 import org.orekit.files.rinex.utils.RinexFileType;
30 import org.orekit.gnss.SatelliteSystem;
31 import org.orekit.gnss.TimeSystem;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.time.DateComponents;
34 import org.orekit.time.DateTimeComponents;
35 import org.orekit.time.Month;
36 import org.orekit.time.TimeComponents;
37 import org.orekit.time.TimeScale;
38 import org.orekit.time.TimeScales;
39
40
41
42
43
44
45 public class RinexUtils {
46
47
48 public static final int LABEL_INDEX = 60;
49
50
51 private static final Pattern SPLITTING_PATTERN = Pattern.compile("([0-9A-Za-z/-]+) *([0-9:]+) *([A-Z][A-Z0-9_-]*)?");
52
53
54 private static final Pattern DATE_DD_MMM_YY_PATTERN = Pattern.compile("([0-9]{2})-([A-Za-z]{3})-([0-9]{2})");
55
56
57 private static final Pattern DATE_ISO_8601_PATTERN = Pattern.compile("([0-9]{4})-?([0-9]{2})-?([0-9]{2})");
58
59
60 private static final Pattern DATE_EUROPEAN_PATTERN = Pattern.compile("([0-9]{2})/([0-9]{2})/([0-9]{2})");
61
62
63 private static final Pattern TIME_PATTERN = Pattern.compile("([0-9]{2}):?([0-9]{2})(?::?([0-9]{2}))?");
64
65
66
67
68
69
70 private RinexUtils() {
71 }
72
73
74
75
76
77 public static String getLabel(final String line) {
78 return line.length() < LABEL_INDEX ? "" : line.substring(LABEL_INDEX).trim();
79 }
80
81
82
83
84
85
86 public static boolean matchesLabel(final String line, final String label) {
87 return getLabel(line).equals(label);
88 }
89
90
91
92
93
94
95
96 public static void parseVersionFileTypeSatelliteSystem(final String line, final String name,
97 final RinexBaseHeader header,
98 final double... supportedVersions) {
99
100
101 final double parsedVersion = parseDouble(line, 0, 9);
102
103 boolean found = false;
104 for (final double supported : supportedVersions) {
105 if (FastMath.abs(parsedVersion - supported) < 1.0e-4) {
106 found = true;
107 break;
108 }
109 }
110 if (!found) {
111 final StringBuilder builder = new StringBuilder();
112 for (final double supported : supportedVersions) {
113 if (builder.length() > 0) {
114 builder.append(", ");
115 }
116 builder.append(supported);
117 }
118 throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT_VERSION,
119 parsedVersion, name, builder.toString());
120 }
121 header.setFormatVersion(parsedVersion);
122
123
124 if (header.getFileType() != RinexFileType.parseRinexFileType(parseString(line, 20, 1))) {
125 throw new OrekitException(OrekitMessages.WRONG_PARSING_TYPE, name);
126 }
127
128
129 switch (header.getFileType()) {
130 case OBSERVATION:
131
132 header.setSatelliteSystem(SatelliteSystem.parseSatelliteSystemWithGPSDefault(parseString(line, 40, 1)));
133 break;
134 case NAVIGATION: {
135 if (header.getFormatVersion() < 3.0) {
136
137
138
139 header.setSatelliteSystem(SatelliteSystem.GPS);
140
141
142 final String entry = parseString(line, 0, LABEL_INDEX).toUpperCase();
143 for (final SatelliteSystem satelliteSystem : SatelliteSystem.values()) {
144 if (entry.contains(satelliteSystem.name())) {
145
146 header.setSatelliteSystem(satelliteSystem);
147 break;
148 }
149 }
150
151 } else {
152
153 header.setSatelliteSystem(SatelliteSystem.parseSatelliteSystemWithGPSDefault(parseString(line, 40, 1)));
154 }
155 break;
156 }
157 default:
158
159 throw new OrekitInternalError(null);
160 }
161
162 }
163
164
165
166
167
168
169
170
171 public static void parseProgramRunByDate(final String line, final int lineNumber,
172 final String name, final TimeScales timeScales,
173 final RinexBaseHeader header) {
174
175
176 header.setProgramName(parseString(line, 0, 20));
177
178
179 header.setRunByName(parseString(line, 20, 20));
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 final Matcher splittingMatcher = SPLITTING_PATTERN.matcher(parseString(line, 40, 20));
197 if (splittingMatcher.matches()) {
198
199
200 final DateComponents dc;
201 final Matcher abbrevMatcher = DATE_DD_MMM_YY_PATTERN.matcher(splittingMatcher.group(1));
202 if (abbrevMatcher.matches()) {
203
204 dc = new DateComponents(convert2DigitsYear(Integer.parseInt(abbrevMatcher.group(3))),
205 Month.parseMonth(abbrevMatcher.group(2)).getNumber(),
206 Integer.parseInt(abbrevMatcher.group(1)));
207 } else {
208 final Matcher isoMatcher = DATE_ISO_8601_PATTERN.matcher(splittingMatcher.group(1));
209 if (isoMatcher.matches()) {
210 dc = new DateComponents(Integer.parseInt(isoMatcher.group(1)),
211 Integer.parseInt(isoMatcher.group(2)),
212 Integer.parseInt(isoMatcher.group(3)));
213 } else {
214 final Matcher europeanMatcher = DATE_EUROPEAN_PATTERN.matcher(splittingMatcher.group(1));
215 if (europeanMatcher.matches()) {
216 dc = new DateComponents(convert2DigitsYear(Integer.parseInt(europeanMatcher.group(3))),
217 Integer.parseInt(europeanMatcher.group(2)),
218 Integer.parseInt(europeanMatcher.group(1)));
219 } else {
220 dc = null;
221 }
222 }
223 }
224
225
226 final TimeComponents tc;
227 final Matcher timeMatcher = TIME_PATTERN.matcher(splittingMatcher.group(2));
228 if (timeMatcher.matches()) {
229 tc = new TimeComponents(Integer.parseInt(timeMatcher.group(1)),
230 Integer.parseInt(timeMatcher.group(2)),
231 timeMatcher.group(3) != null ? Integer.parseInt(timeMatcher.group(3)) : 0);
232 } else {
233 tc = null;
234 }
235
236
237 final String zone = splittingMatcher.groupCount() > 2 ? splittingMatcher.group(3) : "";
238
239 if (dc != null && tc != null) {
240
241 final DateTimeComponents dtc = new DateTimeComponents(dc, tc);
242 header.setCreationDateComponents(dtc);
243 final TimeScale timeScale = zone == null ?
244 timeScales.getUTC() :
245 TimeSystem.parseTimeSystem(zone).getTimeScale(timeScales);
246 header.setCreationDate(new AbsoluteDate(dtc, timeScale));
247 header.setCreationTimeZone(zone);
248 return;
249 }
250
251 }
252
253
254 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
255 lineNumber, name, line);
256
257 }
258
259
260
261
262
263
264 public static void parseComment(final int lineNumber, final String line, final RinexFile<?> rinexFile) {
265 rinexFile.addComment(new RinexComment(lineNumber, parseString(line, 0, 60)));
266 }
267
268
269
270
271
272
273
274
275 public static double parseDouble(final String line, final int startIndex, final int size) {
276 final String subString = parseString(line, startIndex, size);
277 if (subString == null || subString.isEmpty()) {
278 return Double.NaN;
279 } else {
280 return Double.parseDouble(subString.replace('D', 'E').trim());
281 }
282 }
283
284
285
286
287
288
289
290
291 public static int parseInt(final String line, final int startIndex, final int size) {
292 final String subString = parseString(line, startIndex, size);
293 if (subString == null || subString.isEmpty()) {
294 return 0;
295 } else {
296 return Integer.parseInt(subString.trim());
297 }
298 }
299
300
301
302
303
304
305
306
307 public static String parseString(final String line, final int startIndex, final int size) {
308 if (line.length() > startIndex) {
309 return line.substring(startIndex, FastMath.min(line.length(), startIndex + size)).trim();
310 } else {
311 return null;
312 }
313 }
314
315
316
317
318
319
320 public static int convert2DigitsYear(final int yy) {
321 return yy >= 80 ? (yy + 1900) : (yy + 2000);
322 }
323
324 }