1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.cdm;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.function.Function;
22
23 import org.orekit.data.DataContext;
24 import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
25 import org.orekit.files.ccsds.definitions.TimeSystem;
26 import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
27 import org.orekit.files.ccsds.ndm.odm.UserDefined;
28 import org.orekit.files.ccsds.section.CommentsContainer;
29 import org.orekit.files.ccsds.section.KvnStructureProcessingState;
30 import org.orekit.files.ccsds.section.MetadataKey;
31 import org.orekit.files.ccsds.section.XmlStructureProcessingState;
32 import org.orekit.files.ccsds.utils.ContextBinding;
33 import org.orekit.files.ccsds.utils.FileFormat;
34 import org.orekit.files.ccsds.utils.lexical.ParseToken;
35 import org.orekit.files.ccsds.utils.lexical.TokenType;
36 import org.orekit.files.ccsds.utils.parsing.AbstractConstituentParser;
37 import org.orekit.files.ccsds.utils.parsing.ProcessingState;
38 import org.orekit.frames.Frame;
39 import org.orekit.utils.IERSConventions;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class CdmParser extends AbstractConstituentParser<CdmHeader, Cdm, CdmParser> {
56
57
58 private static final String COMMENT = "COMMENT";
59
60
61 private static final String RELATIVEMETADATA = "relativeMetadataData";
62
63
64 private static final String METADATA = "metadata";
65
66
67 private CdmHeader header;
68
69
70 private List<CdmSegment> segments;
71
72
73 private CdmMetadata metadata;
74
75
76 private CdmRelativeMetadata relativeMetadata;
77
78
79 private ContextBinding context;
80
81
82 private CommentsContainer commentsBlock;
83
84
85 private ODParameters odParameters;
86
87
88 private AdditionalParameters addParameters;
89
90
91 private StateVector stateVector;
92
93
94 private RTNCovariance covMatrix;
95
96
97 private XYZCovariance xyzCovMatrix;
98
99
100 private SigmaEigenvectorsCovariance sig3eigvec3;
101
102
103 private AdditionalCovarianceMetadata additionalCovMetadata;
104
105
106 private ProcessingState structureProcessor;
107
108
109 private boolean doRelativeMetadata;
110
111
112 private boolean isDatafinished;
113
114
115 private UserDefined userDefinedBlock;
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 public CdmParser(final IERSConventions conventions, final boolean simpleEOP, final DataContext dataContext,
132 final ParsedUnitsBehavior parsedUnitsBehavior,
133 final Function<ParseToken, List<ParseToken>>[] filters,
134 final CcsdsFrameMapper frameMapper) {
135 super(Cdm.ROOT, Cdm.FORMAT_VERSION_KEY, conventions, simpleEOP,
136 dataContext, parsedUnitsBehavior, filters, frameMapper);
137 this.doRelativeMetadata = true;
138 this.isDatafinished = false;
139 }
140
141
142 @Override
143 public CdmHeader getHeader() {
144 return header;
145 }
146
147
148 @Override
149 public void reset(final FileFormat fileFormat) {
150 header = new CdmHeader();
151 segments = new ArrayList<>();
152 metadata = null;
153 relativeMetadata = null;
154 context = null;
155 odParameters = null;
156 addParameters = null;
157 stateVector = null;
158 covMatrix = null;
159 xyzCovMatrix = null;
160 sig3eigvec3 = null;
161 additionalCovMetadata = null;
162 userDefinedBlock = null;
163 commentsBlock = null;
164 if (fileFormat == FileFormat.XML) {
165 structureProcessor = new XmlStructureProcessingState(Cdm.ROOT, this);
166 reset(fileFormat, structureProcessor);
167 } else {
168 structureProcessor = new KvnStructureProcessingState(this);
169 reset(fileFormat, new CdmHeaderProcessingState(this));
170 }
171 }
172
173
174 @Override
175 public boolean prepareHeader() {
176 anticipateNext(new CdmHeaderProcessingState(this));
177 return true;
178 }
179
180
181 @Override
182 public boolean inHeader() {
183 anticipateNext(getFileFormat() == FileFormat.XML ? structureProcessor : this::processMetadataToken);
184 return true;
185 }
186
187
188 @Override
189 public boolean finalizeHeader() {
190 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : structureProcessor);
191 header.validate(header.getFormatVersion());
192 return true;
193 }
194
195
196 @Override
197 public boolean prepareMetadata() {
198 if (metadata != null) {
199 return false;
200 }
201 if (doRelativeMetadata) {
202
203
204 relativeMetadata = new CdmRelativeMetadata();
205 relativeMetadata.setTimeSystem(TimeSystem.UTC);
206 }
207 metadata = new CdmMetadata(getDataContext(), getFrameMapper());
208 metadata.setRelativeMetadata(relativeMetadata);
209
210
211
212
213
214 context = new ContextBinding(this::getConventions, this::isSimpleEOP,
215 this::getDataContext, this::getParsedUnitsBehavior,
216 () -> null, relativeMetadata::getTimeSystem,
217 () -> 0.0, () -> 1.0);
218 anticipateNext(this::processMetadataToken);
219 return true;
220 }
221
222
223 @Override
224 public boolean inMetadata() {
225 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processGeneralCommentToken);
226 return true;
227 }
228
229
230 @Override
231 public boolean finalizeMetadata() {
232 metadata.validate(header.getFormatVersion());
233 relativeMetadata.validate();
234 anticipateNext(structureProcessor);
235 return true;
236 }
237
238
239 @Override
240 public boolean prepareData() {
241
242 stateVector = new StateVector();
243 covMatrix = new RTNCovariance();
244
245
246 commentsBlock = new CommentsContainer();
247 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processGeneralCommentToken);
248 return true;
249 }
250
251
252 @Override
253 public boolean inData() {
254 return true;
255 }
256
257
258 @Override
259 public boolean finalizeData() {
260
261 if (metadata != null) {
262
263 CdmData data = new CdmData(commentsBlock, odParameters, addParameters,
264 stateVector, covMatrix, additionalCovMetadata);
265
266 if (metadata.getAltCovType().isPresent() && metadata.getAltCovType().get() == AltCovarianceType.XYZ) {
267 data = new CdmData(commentsBlock, odParameters, addParameters,
268 stateVector, covMatrix, xyzCovMatrix, additionalCovMetadata);
269 } else if (metadata.getAltCovType().isPresent() && metadata.getAltCovType().get() == AltCovarianceType.CSIG3EIGVEC3) {
270 data = new CdmData(commentsBlock, odParameters, addParameters,
271 stateVector, covMatrix, sig3eigvec3, additionalCovMetadata);
272 }
273
274 data.validate(header.getFormatVersion());
275 segments.add(new CdmSegment(metadata, data));
276
277
278 if (userDefinedBlock != null && !userDefinedBlock.getParameters().isEmpty()) {
279 for (CdmSegment segment : segments) {
280 segment.getData().setUserDefinedBlock(userDefinedBlock);
281 }
282 }
283 }
284 metadata = null;
285 context = null;
286 odParameters = null;
287 addParameters = null;
288 stateVector = null;
289 covMatrix = null;
290 xyzCovMatrix = null;
291 sig3eigvec3 = null;
292 additionalCovMetadata = null;
293 userDefinedBlock = null;
294 commentsBlock = null;
295 return true;
296 }
297
298
299 @Override
300 public Cdm build() {
301
302
303 finalizeData();
304 if (userDefinedBlock != null && userDefinedBlock.getParameters().isEmpty()) {
305 userDefinedBlock = null;
306 }
307 return new Cdm(header, segments, getConventions(), getDataContext());
308 }
309
310
311
312
313
314 boolean addGeneralComment(final String comment) {
315 return commentsBlock.addComment(comment);
316
317 }
318
319
320
321
322
323
324 boolean manageRelativeMetadataSection(final boolean starting) {
325 anticipateNext(starting ? this::processMetadataToken : structureProcessor);
326 return true;
327 }
328
329
330
331
332
333
334 boolean manageRelativeStateVectorSection(final boolean starting) {
335 anticipateNext(this::processMetadataToken);
336 return true;
337 }
338
339
340
341
342
343
344 boolean manageODParametersSection(final boolean starting) {
345 commentsBlock.refuseFurtherComments();
346 anticipateNext(starting ? this::processODParamToken : structureProcessor);
347 return true;
348 }
349
350
351
352
353
354
355 boolean manageAdditionalParametersSection(final boolean starting) {
356 commentsBlock.refuseFurtherComments();
357 anticipateNext(starting ? this::processAdditionalParametersToken : structureProcessor);
358 return true;
359 }
360
361
362
363
364
365
366 boolean manageStateVectorSection(final boolean starting) {
367 commentsBlock.refuseFurtherComments();
368 anticipateNext(starting ? this::processStateVectorToken : structureProcessor);
369 return true;
370 }
371
372
373
374
375
376
377 boolean manageXmlGeneralCovarianceSection(final boolean starting) {
378 commentsBlock.refuseFurtherComments();
379
380 if (starting) {
381 if (metadata.getAltCovType().isEmpty()) {
382 anticipateNext(this::processCovMatrixToken);
383 } else {
384 if (Double.isNaN(covMatrix.getCrr())) {
385
386 anticipateNext(this::processCovMatrixToken);
387 } else if ( metadata.getAltCovType().get() == AltCovarianceType.XYZ && xyzCovMatrix == null ||
388 metadata.getAltCovType().get() == AltCovarianceType.CSIG3EIGVEC3 && sig3eigvec3 == null ) {
389
390 anticipateNext(this::processAltCovarianceToken);
391 } else if (additionalCovMetadata == null) {
392
393 anticipateNext(this::processAdditionalCovMetadataToken);
394 }
395 }
396 } else {
397 anticipateNext(structureProcessor);
398 }
399
400 return true;
401 }
402
403
404
405
406
407
408 boolean manageUserDefinedParametersSection(final boolean starting) {
409 commentsBlock.refuseFurtherComments();
410 if (starting) {
411 if (userDefinedBlock == null) {
412
413 userDefinedBlock = new UserDefined();
414 }
415 anticipateNext(this::processUserDefinedToken);
416 } else {
417 anticipateNext(structureProcessor);
418 }
419 return true;
420 }
421
422
423
424
425
426 private boolean processMetadataToken(final ParseToken token) {
427 if (isDatafinished && getFileFormat() != FileFormat.XML) {
428 finalizeData();
429 isDatafinished = false;
430 }
431 if (metadata == null) {
432
433
434 prepareMetadata();
435 }
436 inMetadata();
437
438
439
440
441
442
443
444
445
446
447
448 final String tokenName = token.getName();
449 if (COMMENT.equals(tokenName) && doRelativeMetadata ) {
450 if (token.getType() == TokenType.ENTRY) {
451 relativeMetadata.addComment(token.getContentAsNormalizedString());
452 return true;
453 }
454 }
455 doRelativeMetadata = false;
456
457
458 if (tokenName == null) {
459 return false;
460 }
461
462
463 final CdmRelativeMetadataKey cdmRelativeMetadataKey;
464 try {
465 cdmRelativeMetadataKey = CdmRelativeMetadataKey.valueOf(tokenName);
466 } catch (IllegalArgumentException iaeM) {
467 final MetadataKey metadataKey;
468 try {
469 metadataKey = MetadataKey.valueOf(tokenName);
470 } catch (IllegalArgumentException iaeD) {
471 final CdmMetadataKey cdmMetadataKey;
472 try {
473 cdmMetadataKey = CdmMetadataKey.valueOf(tokenName);
474 } catch (IllegalArgumentException iaeC) {
475
476 return false;
477 }
478 return cdmMetadataKey.process(token, context, metadata);
479 }
480 return metadataKey.process(token, context, metadata);
481 }
482 return cdmRelativeMetadataKey.process(token, context, relativeMetadata);
483 }
484
485
486
487
488
489 private boolean processXmlSubStructureToken(final ParseToken token) {
490
491
492
493
494
495
496
497
498
499
500 if (METADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
501 RELATIVEMETADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
502 anticipateNext(this::processMetadataToken);
503 return true;
504
505 } else if (RELATIVEMETADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
506 METADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
507 final ParseToken replaceToken = new ParseToken(token.getType(), METADATA,
508 null, token.getUnits(), token.getLineNumber(), token.getFileName());
509
510 return structureProcessor.processToken(replaceToken);
511
512 } else {
513
514
515
516
517 if (commentsBlock == null && COMMENT.equals(token.getName())) {
518
519
520 if (doRelativeMetadata) {
521 if (token.getType() == TokenType.ENTRY) {
522 relativeMetadata.addComment(token.getContentAsNormalizedString());
523 doRelativeMetadata = false;
524 return true;
525
526 } else {
527
528
529
530 return true;
531 }
532 }
533
534
535 if (!doRelativeMetadata) {
536 if (token.getType() == TokenType.ENTRY) {
537 metadata.addComment(token.getContentAsNormalizedString());
538 return true;
539
540 } else {
541
542 return true;
543 }
544 }
545 }
546
547
548 try {
549 return token.getName() != null && !doRelativeMetadata &&
550 XmlSubStructureKey.valueOf(token.getName()).process(token, this);
551 } catch (IllegalArgumentException iae) {
552
553 return false;
554 }
555 }
556 }
557
558
559
560
561
562 private boolean processGeneralCommentToken(final ParseToken token) {
563 if (commentsBlock == null) {
564
565
566 finalizeMetadata();
567
568
569 prepareData();
570 }
571 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processODParamToken);
572 if (COMMENT.equals(token.getName()) && commentsBlock.acceptComments()) {
573 if (token.getType() == TokenType.ENTRY) {
574 commentsBlock.addComment(token.getContentAsNormalizedString());
575 }
576
577
578 commentsBlock.refuseFurtherComments();
579 return true;
580 } else {
581 return false;
582 }
583 }
584
585
586
587
588
589 private boolean processODParamToken(final ParseToken token) {
590 if (odParameters == null) {
591 odParameters = new ODParameters();
592 }
593 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAdditionalParametersToken);
594 try {
595 return token.getName() != null &&
596 ODParametersKey.valueOf(token.getName()).process(token, context, odParameters);
597 } catch (IllegalArgumentException iae) {
598
599 return false;
600 }
601 }
602
603
604
605
606
607 private boolean processAdditionalParametersToken(final ParseToken token) {
608 if (addParameters == null) {
609 addParameters = new AdditionalParameters(getFrameMapper());
610 }
611 if (moveCommentsIfEmpty(odParameters, addParameters)) {
612
613 odParameters = null;
614 }
615 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processStateVectorToken);
616 try {
617 return token.getName() != null &&
618 AdditionalParametersKey.valueOf(token.getName()).process(token, context, addParameters);
619 } catch (IllegalArgumentException iae) {
620
621 return false;
622 }
623 }
624
625
626
627
628
629 private boolean processStateVectorToken(final ParseToken token) {
630 if (moveCommentsIfEmpty(addParameters, stateVector)) {
631
632 addParameters = null;
633 }
634 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processCovMatrixToken);
635 try {
636 return token.getName() != null &&
637 StateVectorKey.valueOf(token.getName()).process(token, context, stateVector);
638 } catch (IllegalArgumentException iae) {
639
640 return false;
641 }
642 }
643
644
645
646
647
648 private boolean processCovMatrixToken(final ParseToken token) {
649
650 if (moveCommentsIfEmpty(stateVector, covMatrix)) {
651
652 stateVector = null;
653 }
654
655 if (metadata.getAltCovType().isEmpty()) {
656 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processMetadataToken);
657 } else {
658 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAltCovarianceToken);
659 }
660
661 isDatafinished = true;
662 try {
663 return token.getName() != null &&
664 RTNCovarianceKey.valueOf(token.getName()).process(token, context, covMatrix);
665 } catch (IllegalArgumentException iae) {
666
667 return false;
668 }
669 }
670
671
672
673
674
675 private boolean processAltCovarianceToken(final ParseToken token) {
676
677
678 if (metadata.getAltCovType().isPresent()) {
679 if (metadata.getAltCovType().get() == AltCovarianceType.XYZ && xyzCovMatrix == null) {
680 xyzCovMatrix = new XYZCovariance(true);
681
682 if (moveCommentsIfEmpty(covMatrix, xyzCovMatrix)) {
683
684 covMatrix = null;
685 }
686 }
687
688 if (metadata.getAltCovType().get() == AltCovarianceType.CSIG3EIGVEC3 && sig3eigvec3 == null) {
689 sig3eigvec3 = new SigmaEigenvectorsCovariance(true);
690
691 if (moveCommentsIfEmpty(covMatrix, sig3eigvec3)) {
692
693 covMatrix = null;
694 }
695 }
696 }
697
698 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAdditionalCovMetadataToken);
699 try {
700
701 if (metadata.getAltCovType().isPresent() && metadata.getAltCovType().get() == AltCovarianceType.XYZ) {
702
703 return token.getName() != null &&
704 XYZCovarianceKey.valueOf(token.getName()).process(token, context, xyzCovMatrix);
705
706 } else if (metadata.getAltCovType().isPresent() && metadata.getAltCovType().get() == AltCovarianceType.CSIG3EIGVEC3) {
707
708 return token.getName() != null &&
709 SigmaEigenvectorsCovarianceKey.valueOf(token.getName()).process(token, context, sig3eigvec3);
710
711 } else {
712
713
714 return false;
715
716 }
717
718 } catch (IllegalArgumentException iae) {
719
720 return false;
721 }
722 }
723
724
725
726
727
728 private boolean processAdditionalCovMetadataToken(final ParseToken token) {
729
730
731 if ( additionalCovMetadata == null) {
732 additionalCovMetadata = new AdditionalCovarianceMetadata();
733 }
734
735 if (moveCommentsIfEmpty(xyzCovMatrix, additionalCovMetadata)) {
736
737 xyzCovMatrix = null;
738 } else if (moveCommentsIfEmpty(sig3eigvec3, additionalCovMetadata)) {
739
740 sig3eigvec3 = null;
741 }
742
743 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processUserDefinedToken);
744 try {
745 return token.getName() != null &&
746 AdditionalCovarianceMetadataKey.valueOf(token.getName()).process(token, context, additionalCovMetadata);
747 } catch (IllegalArgumentException iae) {
748
749 return false;
750 }
751 }
752
753
754
755
756
757 private boolean processUserDefinedToken(final ParseToken token) {
758
759 if (userDefinedBlock == null) {
760 userDefinedBlock = new UserDefined();
761 }
762
763 if (moveCommentsIfEmpty(additionalCovMetadata, userDefinedBlock)) {
764
765 additionalCovMetadata = null;
766 }
767
768 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processMetadataToken);
769
770 if (COMMENT.equals(token.getName())) {
771 return token.getType() == TokenType.ENTRY ? userDefinedBlock.addComment(token.getContentAsNormalizedString()) : true;
772 } else if (token.getName().startsWith(UserDefined.USER_DEFINED_PREFIX)) {
773 if (token.getType() == TokenType.ENTRY) {
774 userDefinedBlock.addEntry(token.getName().substring(UserDefined.USER_DEFINED_PREFIX.length()),
775 token.getContentAsNormalizedString());
776 }
777 return true;
778 } else {
779
780 return false;
781 }
782 }
783
784
785
786
787
788
789
790 private boolean moveCommentsIfEmpty(final CommentsContainer origin, final CommentsContainer destination) {
791 if (origin != null && origin.acceptComments()) {
792
793 for (final String comment : origin.getComments()) {
794 destination.addComment(comment);
795 }
796 return true;
797 } else {
798 return false;
799 }
800 }
801
802 }
803