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