1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ilrs;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.util.Optional;
22 import java.util.regex.Pattern;
23 import java.util.stream.Stream;
24
25 import org.hipparchus.util.FastMath;
26 import org.orekit.annotation.DefaultDataContext;
27 import org.orekit.data.DataContext;
28 import org.orekit.data.DataSource;
29 import org.orekit.errors.OrekitException;
30 import org.orekit.errors.OrekitMessages;
31 import org.orekit.files.ilrs.CRD.AnglesMeasurement;
32 import org.orekit.files.ilrs.CRD.CRDDataBlock;
33 import org.orekit.files.ilrs.CRD.MeteorologicalMeasurement;
34 import org.orekit.files.ilrs.CRD.RangeMeasurement;
35 import org.orekit.files.ilrs.CRDConfiguration.DetectorConfiguration;
36 import org.orekit.files.ilrs.CRDConfiguration.LaserConfiguration;
37 import org.orekit.files.ilrs.CRDConfiguration.MeteorologicalConfiguration;
38 import org.orekit.files.ilrs.CRDConfiguration.SoftwareConfiguration;
39 import org.orekit.files.ilrs.CRDConfiguration.SystemConfiguration;
40 import org.orekit.files.ilrs.CRDConfiguration.TimingSystemConfiguration;
41 import org.orekit.files.ilrs.CRDConfiguration.TransponderConfiguration;
42 import org.orekit.time.AbsoluteDate;
43 import org.orekit.time.DateComponents;
44 import org.orekit.time.TimeComponents;
45 import org.orekit.time.TimeScale;
46 import org.orekit.utils.units.Unit;
47 import org.orekit.utils.units.UnitsConverter;
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class CRDParser {
62
63
64 public static final String DEFAULT_CRD_SUPPORTED_NAMES = "^(?!0+$)\\w{1,12}\\_\\d{6,8}.\\w{3}$";
65
66
67 private static final Unit NM = Unit.parse("nm");
68
69
70 private static final Unit KHZ = Unit.parse("kHz");
71
72
73 private static final Unit US = Unit.parse("µs");
74
75
76 private static final UnitsConverter MBAR_TO_BAR = new UnitsConverter(Unit.parse("mbar"), Unit.parse("bar"));
77
78
79 private static final String FILE_FORMAT = "CRD";
80
81
82 private static final Pattern SEPARATOR = Pattern.compile("\\s+");
83
84
85 private static final Pattern COMMA = Pattern.compile(",");
86
87
88 private final TimeScale timeScale;
89
90
91
92
93
94
95 @DefaultDataContext
96 public CRDParser() {
97 this(DataContext.getDefault().getTimeScales().getUTC());
98 }
99
100
101
102
103
104 public CRDParser(final TimeScale utc) {
105 this.timeScale = utc;
106 }
107
108
109
110
111
112 public TimeScale getTimeScale() {
113 return timeScale;
114 }
115
116
117
118
119
120
121
122 public CRD parse(final DataSource source) throws IOException {
123
124
125 final ParseInfo pi = new ParseInfo();
126
127 int lineNumber = 0;
128 Stream<LineParser> crdParsers = Stream.of(LineParser.H1);
129 try (BufferedReader reader = new BufferedReader(source.getOpener().openReaderOnce())) {
130 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
131 ++lineNumber;
132 final String l = line;
133 final Optional<LineParser> selected = crdParsers.filter(p -> p.canHandle(l)).findFirst();
134 if (selected.isPresent()) {
135 try {
136 selected.get().parse(line, pi);
137 } catch (StringIndexOutOfBoundsException | NumberFormatException e) {
138 throw new OrekitException(e,
139 OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
140 lineNumber, source.getName(), line);
141 }
142 crdParsers = selected.get().allowedNext();
143 }
144 if (pi.done) {
145
146 return pi.file;
147 }
148 }
149 }
150
151
152 throw new OrekitException(OrekitMessages.CRD_UNEXPECTED_END_OF_FILE, lineNumber);
153
154 }
155
156
157
158
159
160
161
162
163
164 private static int checkRollover(final double lastSecOfDay, final double secOfDay) {
165 return (secOfDay > lastSecOfDay) ? 0 : 1;
166 }
167
168
169
170
171
172
173 private class ParseInfo {
174
175
176 private CRD file;
177
178
179 private int version;
180
181
182 private CRDDataBlock dataBlock;
183
184
185 private CRDHeader header;
186
187
188 private CRDConfiguration configurationRecords;
189
190
191 private TimeScale timeScale;
192
193
194 private DateComponents startEpoch;
195
196
197 private boolean done;
198
199
200
201
202 protected ParseInfo() {
203
204
205 this.done = false;
206 this.version = 1;
207 this.startEpoch = DateComponents.J2000_EPOCH;
208
209
210 this.file = new CRD();
211 this.header = new CRDHeader();
212 this.configurationRecords = new CRDConfiguration();
213 this.dataBlock = new CRDDataBlock();
214
215
216 this.timeScale = CRDParser.this.timeScale;
217
218 }
219
220 }
221
222
223 private enum LineParser {
224
225
226 H1("H1", "h1") {
227
228
229 @Override
230 public void parse(final String line, final ParseInfo pi) {
231
232
233 final String[] values = SEPARATOR.split(line);
234
235
236 final String format = values[1];
237 pi.version = Integer.parseInt(values[2]);
238
239
240 if (!format.equalsIgnoreCase(FILE_FORMAT)) {
241 throw new OrekitException(OrekitMessages.UNEXPECTED_FORMAT_FOR_ILRS_FILE, FILE_FORMAT, format);
242 }
243
244
245 pi.header.setFormat(format);
246 pi.header.setVersion(pi.version);
247
248
249 final int year = Integer.parseInt(values[3]);
250 final int month = Integer.parseInt(values[4]);
251 final int day = Integer.parseInt(values[5]);
252 pi.header.setProductionEpoch(new DateComponents(year, month, day));
253
254
255 pi.header.setProductionHour(Integer.parseInt(values[6]));
256
257 }
258
259
260 @Override
261 public Stream<LineParser> allowedNext() {
262 return Stream.of(H2, COMMENTS);
263 }
264
265 },
266
267
268 H2("H2", "h2") {
269
270
271 @Override
272 public void parse(final String line, final ParseInfo pi) {
273
274
275 final String[] values = SEPARATOR.split(line);
276
277
278 pi.header.setStationName(values[1]);
279
280
281 pi.header.setSystemIdentifier(Integer.parseInt(values[2]));
282 pi.header.setSystemNumber(Integer.parseInt(values[3]));
283 pi.header.setSystemOccupancy(Integer.parseInt(values[4]));
284
285
286 pi.header.setEpochIdentifier(Integer.parseInt(values[5]));
287
288
289 if (pi.version == 2) {
290 pi.header.setStationNetword(values[6]);
291 }
292
293 }
294
295
296 @Override
297 public Stream<LineParser> allowedNext() {
298 return Stream.of(H3, COMMENTS);
299 }
300
301 },
302
303
304 H3("H3", "h3") {
305
306
307 @Override
308 public void parse(final String line, final ParseInfo pi) {
309
310
311 final String[] values = SEPARATOR.split(line);
312
313
314 pi.header.setName(values[1]);
315
316
317 pi.header.setIlrsSatelliteId(values[2]);
318 pi.header.setSic(values[3]);
319 pi.header.setNoradId(values[4]);
320
321
322 pi.header.setSpacecraftEpochTimeScale(Integer.parseInt(values[5]));
323
324
325 pi.header.setTargetClass(Integer.parseInt(values[6]));
326 if (pi.version == 2) {
327 pi.header.setTargetLocation(Integer.parseInt(values[7]));
328 }
329
330 }
331
332
333 @Override
334 public Stream<LineParser> allowedNext() {
335 return Stream.of(H4, COMMENTS);
336 }
337
338 },
339
340
341 H4("H4", "h4") {
342
343
344 @Override
345 public void parse(final String line, final ParseInfo pi) {
346
347
348 final String[] values = SEPARATOR.split(line);
349
350
351 pi.header.setDataType(Integer.parseInt(values[1]));
352
353
354 final int yearS = Integer.parseInt(values[2]);
355 final int monthS = Integer.parseInt(values[3]);
356 final int dayS = Integer.parseInt(values[4]);
357 final int hourS = Integer.parseInt(values[5]);
358 final int minuteS = Integer.parseInt(values[6]);
359 final double secondS = Integer.parseInt(values[7]);
360
361 pi.startEpoch = new DateComponents(yearS, monthS, dayS);
362
363 pi.header.setStartEpoch(new AbsoluteDate(yearS, monthS, dayS,
364 hourS, minuteS, secondS,
365 pi.timeScale));
366
367
368 final int yearE = Integer.parseInt(values[8]);
369 final int monthE = Integer.parseInt(values[9]);
370 final int dayE = Integer.parseInt(values[10]);
371 final int hourE = Integer.parseInt(values[11]);
372 final int minuteE = Integer.parseInt(values[12]);
373 final double secondE = Integer.parseInt(values[13]);
374
375 pi.header.setEndEpoch(new AbsoluteDate(yearE, monthE, dayE,
376 hourE, minuteE, secondE,
377 pi.timeScale));
378
379
380 pi.header.setDataReleaseFlag(Integer.parseInt(values[14]));
381
382
383 pi.header.setIsTroposphericRefractionApplied(readBoolean(values[15]));
384 pi.header.setIsCenterOfMassCorrectionApplied(readBoolean(values[16]));
385 pi.header.setIsReceiveAmplitudeCorrectionApplied(readBoolean(values[17]));
386 pi.header.setIsStationSystemDelayApplied(readBoolean(values[18]));
387 pi.header.setIsTransponderDelayApplied(readBoolean(values[19]));
388
389
390 pi.header.setRangeType(Integer.parseInt(values[20]));
391
392
393 pi.header.setQualityIndicator(Integer.parseInt(values[21]));
394
395 }
396
397
398 @Override
399 public Stream<LineParser> allowedNext() {
400 return Stream.of(H5, C0, COMMENTS);
401 }
402
403 },
404
405
406 H5("H5", "h5") {
407
408
409 @Override
410 public void parse(final String line, final ParseInfo pi) {
411
412
413 final String[] values = SEPARATOR.split(line);
414
415
416 pi.header.setPredictionType(Integer.parseInt(values[1]));
417 pi.header.setYearOfCentury(Integer.parseInt(values[2]));
418 pi.header.setDateAndTime(values[3]);
419 pi.header.setPredictionProvider(values[4]);
420 pi.header.setSequenceNumber(Integer.parseInt(values[5]));
421
422 }
423
424
425 @Override
426 public Stream<LineParser> allowedNext() {
427 return Stream.of(C0, COMMENTS);
428 }
429
430 },
431
432
433 C0("C0", "c0") {
434
435
436 @Override
437 public void parse(final String line, final ParseInfo pi) {
438
439
440 final SystemConfiguration systemRecord = new SystemConfiguration();
441
442
443 final String[] values = SEPARATOR.split(line);
444
445
446 systemRecord.setWavelength(NM.toSI(Double.parseDouble(values[2])));
447
448
449 systemRecord.setSystemId(values[3]);
450
451
452 pi.configurationRecords.setSystemRecord(systemRecord);
453
454 }
455
456
457 @Override
458 public Stream<LineParser> allowedNext() {
459 return Stream.of(C1, C2, C3, C4, C5, C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
460 }
461
462 },
463
464
465
466 C1("C1", "c1") {
467
468
469 @Override
470 public void parse(final String line, final ParseInfo pi) {
471
472
473 final LaserConfiguration laserRecord = new LaserConfiguration();
474
475
476 final String[] values = SEPARATOR.split(line);
477
478
479 laserRecord.setLaserId(values[2]);
480 laserRecord.setLaserType(values[3]);
481 laserRecord.setPrimaryWavelength(NM.toSI(Double.parseDouble(values[4])));
482 laserRecord.setNominalFireRate(Double.parseDouble(values[5]));
483 laserRecord.setPulseEnergy(Double.parseDouble(values[6]));
484 laserRecord.setPulseWidth(Double.parseDouble(values[7]));
485 laserRecord.setBeamDivergence(Double.parseDouble(values[8]));
486 laserRecord.setPulseInOutgoingSemiTrain(Integer.parseInt(values[9]));
487
488
489 pi.configurationRecords.setLaserRecord(laserRecord);
490
491 }
492
493
494 @Override
495 public Stream<LineParser> allowedNext() {
496 return Stream.of(C2, C3, C4, C5, C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
497 }
498
499 },
500
501
502 C2("C2", "c2") {
503
504
505 @Override
506 public void parse(final String line, final ParseInfo pi) {
507
508
509 final DetectorConfiguration detectorRecord = new DetectorConfiguration();
510
511
512 final String[] values = SEPARATOR.split(line);
513
514
515 detectorRecord.setDetectorId(values[2]);
516 detectorRecord.setDetectorType(values[3]);
517 detectorRecord.setApplicableWavelength(NM.toSI(Double.parseDouble(values[4])));
518 detectorRecord.setQuantumEfficiency(Double.parseDouble(values[5]));
519 detectorRecord.setAppliedVoltage(Double.parseDouble(values[6]));
520 detectorRecord.setDarkCount(KHZ.toSI(Double.parseDouble(values[7])));
521 detectorRecord.setOutputPulseType(values[8]);
522 detectorRecord.setOutputPulseWidth(Double.parseDouble(values[9]));
523 detectorRecord.setSpectralFilter(NM.toSI(Double.parseDouble(values[10])));
524 detectorRecord.setTransmissionOfSpectralFilter(Double.parseDouble(values[11]));
525 detectorRecord.setSpatialFilter(Double.parseDouble(values[12]));
526 detectorRecord.setExternalSignalProcessing(values[13]);
527
528
529 if (pi.version == 2) {
530 detectorRecord.setAmplifierGain(Double.parseDouble(values[14]));
531 detectorRecord.setAmplifierBandwidth(KHZ.toSI(Double.parseDouble(values[15])));
532 detectorRecord.setAmplifierInUse(values[16]);
533 }
534
535
536 pi.configurationRecords.setDetectorRecord(detectorRecord);
537
538 }
539
540
541 @Override
542 public Stream<LineParser> allowedNext() {
543 return Stream.of(C3, C4, C5, C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
544 }
545
546 },
547
548
549 C3("C3", "c3") {
550
551
552 @Override
553 public void parse(final String line, final ParseInfo pi) {
554
555
556 final TimingSystemConfiguration timingRecord = new TimingSystemConfiguration();
557
558
559 final String[] values = SEPARATOR.split(line);
560
561
562 timingRecord.setLocalTimingId(values[2]);
563 timingRecord.setTimeSource(values[3]);
564 timingRecord.setFrequencySource(values[4]);
565 timingRecord.setTimer(values[5]);
566 timingRecord.setTimerSerialNumber(values[6]);
567 timingRecord.setEpochDelayCorrection(US.toSI(Double.parseDouble(values[7])));
568
569
570 pi.configurationRecords.setTimingRecord(timingRecord);
571
572 }
573
574
575 @Override
576 public Stream<LineParser> allowedNext() {
577 return Stream.of(C4, C5, C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
578 }
579
580 },
581
582
583 C4("C4", "c4") {
584
585
586 @Override
587 public void parse(final String line, final ParseInfo pi) {
588
589
590 final TransponderConfiguration transponderRecord = new TransponderConfiguration();
591
592
593 final String[] values = SEPARATOR.split(line);
594
595
596 transponderRecord.setTransponderId(values[2]);
597 transponderRecord.setStationUTCOffset(NM.toSI(Double.parseDouble(values[3])));
598 transponderRecord.setStationOscDrift(Double.parseDouble(values[4]));
599 transponderRecord.setTranspUTCOffset(NM.toSI(Double.parseDouble(values[5])));
600 transponderRecord.setTranspOscDrift(Double.parseDouble(values[6]));
601
602
603 transponderRecord.setTranspClkRefTime(Double.parseDouble(values[7]));
604
605
606 transponderRecord.setStationClockAndDriftApplied(Integer.parseInt(values[8]));
607 transponderRecord.setSpacecraftClockAndDriftApplied(Integer.parseInt(values[9]));
608
609
610 transponderRecord.setIsSpacecraftTimeSimplified(readBoolean(values[10]));
611
612
613 pi.configurationRecords.setTransponderRecord(transponderRecord);
614
615 }
616
617
618 @Override
619 public Stream<LineParser> allowedNext() {
620 return Stream.of(C5, C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
621 }
622
623 },
624
625
626 C5("C5", "c5") {
627
628
629 @Override
630 public void parse(final String line, final ParseInfo pi) {
631
632
633 final SoftwareConfiguration softwareRecord = new SoftwareConfiguration();
634
635
636 final String[] values = SEPARATOR.split(line);
637
638
639 softwareRecord.setSoftwareId(values[2]);
640 softwareRecord.setTrackingSoftwares(COMMA.split(values[3]));
641 softwareRecord.setTrackingSoftwareVersions(COMMA.split(values[4]));
642 softwareRecord.setProcessingSoftwares(COMMA.split(values[5]));
643 softwareRecord.setProcessingSoftwareVersions(COMMA.split(values[6]));
644
645
646 pi.configurationRecords.setSoftwareRecord(softwareRecord);
647
648 }
649
650
651 @Override
652 public Stream<LineParser> allowedNext() {
653 return Stream.of(C6, C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
654 }
655
656 },
657
658
659 C6("C6", "c6") {
660
661
662 @Override
663 public void parse(final String line, final ParseInfo pi) {
664
665
666 final MeteorologicalConfiguration meteoRecord = new MeteorologicalConfiguration();
667
668
669 final String[] values = SEPARATOR.split(line);
670
671
672 meteoRecord.setMeteorologicalId(values[2]);
673 meteoRecord.setPressSensorManufacturer(values[3]);
674 meteoRecord.setPressSensorModel(values[4]);
675 meteoRecord.setPressSensorSerialNumber(values[5]);
676 meteoRecord.setTempSensorManufacturer(values[6]);
677 meteoRecord.setTempSensorModel(values[7]);
678 meteoRecord.setTempSensorSerialNumber(values[8]);
679 meteoRecord.setHumiSensorManufacturer(values[9]);
680 meteoRecord.setHumiSensorModel(values[10]);
681 meteoRecord.setHumiSensorSerialNumber(values[11]);
682
683
684 pi.configurationRecords.setMeteorologicalRecord(meteoRecord);
685
686 }
687
688
689 @Override
690 public Stream<LineParser> allowedNext() {
691 return Stream.of(C7, TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
692 }
693
694 },
695
696
697 C7("C7", "c7") {
698
699
700 @Override
701 public void parse(final String line, final ParseInfo pi) {
702
703 }
704
705
706 @Override
707 public Stream<LineParser> allowedNext() {
708 return Stream.of(TEN, ELEVEN, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
709 }
710
711 },
712
713
714 TEN("10") {
715
716
717 private double lastSecOfDay = 0;
718
719
720 private int dayShift = 0;
721
722
723 @Override
724 public void parse(final String line, final ParseInfo pi) {
725
726
727 final String[] values = SEPARATOR.split(line);
728
729
730 final double secOfDay = Double.parseDouble(values[1]);
731 final double timeOfFlight = Double.parseDouble(values[2]);
732 final int epochEvent = Integer.parseInt(values[4]);
733
734
735 dayShift = dayShift + checkRollover(lastSecOfDay, secOfDay);
736
737 final AbsoluteDate epoch = new AbsoluteDate(pi.startEpoch, new TimeComponents(secOfDay), pi.timeScale).shiftedBy(dayShift * 86400);
738 final RangeMeasurement range = new RangeMeasurement(epoch, timeOfFlight, epochEvent);
739 pi.dataBlock.addRangeData(range);
740
741 lastSecOfDay = secOfDay;
742 }
743
744
745 @Override
746 public Stream<LineParser> allowedNext() {
747 return Stream.of(H8, TEN, TWELVE, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
748 }
749
750 },
751
752
753 ELEVEN("11") {
754
755
756 private double lastSecOfDay = 0;
757
758
759 private int dayShift = 0;
760
761
762 @Override
763 public void parse(final String line, final ParseInfo pi) {
764
765
766 final String[] values = SEPARATOR.split(line);
767
768
769 final double secOfDay = Double.parseDouble(values[1]);
770 final double timeOfFlight = Double.parseDouble(values[2]);
771 final int epochEvent = Integer.parseInt(values[4]);
772 final double snr = (pi.version == 2) ? Double.parseDouble(values[13]) : Double.NaN;
773
774
775 dayShift = dayShift + checkRollover(lastSecOfDay, secOfDay);
776
777 final AbsoluteDate epoch = new AbsoluteDate(pi.startEpoch, new TimeComponents(secOfDay), pi.timeScale).shiftedBy(dayShift * 86400);
778 final RangeMeasurement range = new RangeMeasurement(epoch, timeOfFlight, epochEvent, snr);
779 pi.dataBlock.addRangeData(range);
780
781 }
782
783
784 @Override
785 public Stream<LineParser> allowedNext() {
786 return Stream.of(H8, ELEVEN, TWELVE, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
787 }
788
789 },
790
791
792 TWELVE("12") {
793
794
795 @Override
796 public void parse(final String line, final ParseInfo pi) {
797
798 }
799
800
801 @Override
802 public Stream<LineParser> allowedNext() {
803 return Stream.of(H8, TEN, ELEVEN, TWELVE, METEO, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
804 }
805
806 },
807
808
809 METEO("20") {
810
811
812 private double lastSecOfDay = 0;
813
814
815 private int dayShift = 0;
816
817
818 @Override
819 public void parse(final String line, final ParseInfo pi) {
820
821
822 final String[] values = SEPARATOR.split(line);
823
824
825 final double secOfDay = Double.parseDouble(values[1]);
826 final double pressure = MBAR_TO_BAR.convert(Double.parseDouble(values[2]));
827 final double temperature = Double.parseDouble(values[3]);
828 final double humidity = Double.parseDouble(values[4]);
829
830
831 dayShift = dayShift + checkRollover(lastSecOfDay, secOfDay);
832
833 final AbsoluteDate epoch = new AbsoluteDate(pi.startEpoch, new TimeComponents(secOfDay), pi.timeScale).shiftedBy(dayShift * 86400);
834 final MeteorologicalMeasurement meteo = new MeteorologicalMeasurement(epoch, pressure,
835 temperature, humidity);
836 pi.dataBlock.addMeteoData(meteo);
837
838 }
839
840
841 @Override
842 public Stream<LineParser> allowedNext() {
843 return Stream.of(H8, METEO, METEO_SUPP, TEN, ELEVEN, TWELVE, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
844 }
845
846 },
847
848
849 METEO_SUPP("21") {
850
851
852 @Override
853 public void parse(final String line, final ParseInfo pi) {
854
855 }
856
857
858 @Override
859 public Stream<LineParser> allowedNext() {
860 return Stream.of(H8, METEO, METEO_SUPP, TEN, ELEVEN, TWELVE, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
861 }
862
863 },
864
865
866 ANGLES("30") {
867
868
869 private double lastSecOfDay = 0;
870
871
872 private int dayShift = 0;
873
874
875 @Override
876 public void parse(final String line, final ParseInfo pi) {
877
878
879 final String[] values = SEPARATOR.split(line);
880
881
882 final double secOfDay = Double.parseDouble(values[1]);
883 final double azmiuth = FastMath.toRadians(Double.parseDouble(values[2]));
884 final double elevation = FastMath.toRadians(Double.parseDouble(values[3]));
885 final int directionFlag = Integer.parseInt(values[4]);
886 final int orginFlag = Integer.parseInt(values[5]);
887 final boolean isRefractionCorrected = readBoolean(values[6]);
888
889
890
891 double azimuthRate = Double.NaN;
892 double elevationRate = Double.NaN;
893 if (pi.version == 2) {
894 azimuthRate = readDoubleWithNaN(values[7]);
895 elevationRate = readDoubleWithNaN(values[8]);
896 }
897
898
899 dayShift = dayShift + checkRollover(lastSecOfDay, secOfDay);
900
901 final AbsoluteDate epoch = new AbsoluteDate(pi.startEpoch, new TimeComponents(secOfDay), pi.timeScale);
902 final AnglesMeasurement angles = new AnglesMeasurement(epoch, azmiuth, elevation,
903 directionFlag, orginFlag,
904 isRefractionCorrected,
905 azimuthRate, elevationRate);
906 pi.dataBlock.addAnglesData(angles);
907
908 }
909
910
911 @Override
912 public Stream<LineParser> allowedNext() {
913 return Stream.of(H8, METEO, TEN, ELEVEN, ANGLES, CALIB, STAT, COMPATIBILITY, COMMENTS);
914 }
915
916 },
917
918
919 CALIB("40") {
920
921
922 @Override
923 public void parse(final String line, final ParseInfo pi) {
924
925 }
926
927
928 @Override
929 public Stream<LineParser> allowedNext() {
930 return Stream.of(H8, METEO, CALIB, CALIB_DETAILS, CALIB_SHOT, TEN, ELEVEN, TWELVE, ANGLES, STAT, COMPATIBILITY, COMMENTS);
931 }
932
933 },
934
935
936 CALIB_DETAILS("41") {
937
938
939 @Override
940 public void parse(final String line, final ParseInfo pi) {
941
942 }
943
944
945 @Override
946 public Stream<LineParser> allowedNext() {
947 return Stream.of(H8, METEO, CALIB, CALIB_DETAILS, CALIB_SHOT, TEN, ELEVEN, TWELVE, ANGLES, STAT, COMPATIBILITY, COMMENTS);
948 }
949
950 },
951
952
953 CALIB_SHOT("42") {
954
955
956 @Override
957 public void parse(final String line, final ParseInfo pi) {
958
959 }
960
961
962 @Override
963 public Stream<LineParser> allowedNext() {
964 return Stream.of(H8, METEO, CALIB, CALIB_DETAILS, CALIB_SHOT, TEN, ELEVEN, TWELVE, ANGLES, STAT, COMPATIBILITY, COMMENTS);
965 }
966
967 },
968
969
970 STAT("50") {
971
972
973 @Override
974 public void parse(final String line, final ParseInfo pi) {
975
976 }
977
978
979 @Override
980 public Stream<LineParser> allowedNext() {
981 return Stream.of(H8, METEO, CALIB, CALIB_DETAILS, CALIB_SHOT, TEN, ELEVEN, TWELVE, ANGLES, STAT, COMPATIBILITY, H8, COMMENTS);
982 }
983
984 },
985
986
987 COMPATIBILITY("60") {
988
989
990 @Override
991 public void parse(final String line, final ParseInfo pi) {
992
993 }
994
995
996 @Override
997 public Stream<LineParser> allowedNext() {
998 return Stream.of(H8, METEO, CALIB, CALIB_DETAILS, CALIB_SHOT, TEN, ELEVEN, TWELVE, ANGLES, STAT, COMPATIBILITY, COMMENTS);
999 }
1000
1001 },
1002
1003
1004 COMMENTS("00") {
1005
1006
1007 @Override
1008 public void parse(final String line, final ParseInfo pi) {
1009
1010
1011 final String comment = line.split(getFirstIdentifier())[1].trim();
1012 pi.file.getComments().add(comment);
1013
1014 }
1015
1016
1017 @Override
1018 public Stream<LineParser> allowedNext() {
1019 return Stream.of(H1, H2, H3, H4, H5, H8, H9, C0, C1, C2, C3, C4, C5, C6, C7, TEN, ELEVEN, TWELVE, METEO,
1020 METEO_SUPP, ANGLES, CALIB, CALIB_DETAILS, CALIB_SHOT, STAT, COMPATIBILITY, COMMENTS);
1021
1022 }
1023
1024 },
1025
1026
1027 H8("H8", "h8") {
1028
1029
1030 @Override
1031 public void parse(final String line, final ParseInfo pi) {
1032
1033
1034 pi.dataBlock.setHeader(pi.header);
1035 pi.dataBlock.setConfigurationRecords(pi.configurationRecords);
1036
1037
1038 pi.file.addDataBlock(pi.dataBlock);
1039
1040
1041 pi.startEpoch = DateComponents.J2000_EPOCH;
1042 pi.header = new CRDHeader();
1043 pi.configurationRecords = new CRDConfiguration();
1044 pi.dataBlock = new CRDDataBlock();
1045
1046 }
1047
1048
1049 @Override
1050 public Stream<LineParser> allowedNext() {
1051 return Stream.of(H1, H9, COMMENTS);
1052 }
1053
1054 },
1055
1056
1057 H9("H9", "h9") {
1058
1059
1060 @Override
1061 public void parse(final String line, final ParseInfo pi) {
1062 pi.done = true;
1063 }
1064
1065
1066 @Override
1067 public Stream<LineParser> allowedNext() {
1068 return Stream.of(H9);
1069 }
1070
1071 };
1072
1073
1074 private final Pattern[] patterns;
1075
1076
1077 private final String[] identifiers;
1078
1079
1080
1081
1082 LineParser(final String... identifier) {
1083 this.identifiers = identifier;
1084
1085 this.patterns = new Pattern[identifiers.length];
1086 for (int index = 0; index < patterns.length; index++) {
1087 patterns[index] = Pattern.compile(identifiers[index]);
1088 }
1089 }
1090
1091
1092
1093
1094
1095 public String getFirstIdentifier() {
1096 return identifiers[0];
1097 }
1098
1099
1100
1101
1102
1103 public abstract void parse(String line, ParseInfo pi);
1104
1105
1106
1107
1108 public abstract Stream<LineParser> allowedNext();
1109
1110
1111
1112
1113
1114 public boolean canHandle(final String line) {
1115
1116 final String lineId = SEPARATOR.split(line)[0];
1117
1118 for (Pattern pattern : patterns) {
1119 if (pattern.matcher(lineId).matches()) {
1120 return true;
1121 }
1122 }
1123
1124 return false;
1125 }
1126
1127
1128
1129
1130
1131
1132 private static boolean readBoolean(final String value) {
1133 return Integer.parseInt(value) == 1;
1134 }
1135
1136
1137
1138
1139
1140
1141 private static double readDoubleWithNaN(final String value) {
1142 return "na".equals(value) ? Double.NaN : Double.parseDouble(value);
1143 }
1144
1145 }
1146
1147 }