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() != null && metadata.getAltCovType() == AltCovarianceType.XYZ) {
267 data = new CdmData(commentsBlock, odParameters, addParameters,
268 stateVector, covMatrix, xyzCovMatrix, additionalCovMetadata);
269 } else if (metadata.getAltCovType() != null && metadata.getAltCovType() == 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 final Cdm file = new Cdm(header, segments, getConventions(), getDataContext());
308 return file;
309 }
310
311
312
313
314
315 boolean addGeneralComment(final String comment) {
316 return commentsBlock.addComment(comment);
317
318 }
319
320
321
322
323
324
325 boolean manageRelativeMetadataSection(final boolean starting) {
326 anticipateNext(starting ? this::processMetadataToken : structureProcessor);
327 return true;
328 }
329
330
331
332
333
334
335 boolean manageRelativeStateVectorSection(final boolean starting) {
336 anticipateNext(this::processMetadataToken);
337 return true;
338 }
339
340
341
342
343
344
345 boolean manageODParametersSection(final boolean starting) {
346 commentsBlock.refuseFurtherComments();
347 anticipateNext(starting ? this::processODParamToken : structureProcessor);
348 return true;
349 }
350
351
352
353
354
355
356 boolean manageAdditionalParametersSection(final boolean starting) {
357 commentsBlock.refuseFurtherComments();
358 anticipateNext(starting ? this::processAdditionalParametersToken : structureProcessor);
359 return true;
360 }
361
362
363
364
365
366
367 boolean manageStateVectorSection(final boolean starting) {
368 commentsBlock.refuseFurtherComments();
369 anticipateNext(starting ? this::processStateVectorToken : structureProcessor);
370 return true;
371 }
372
373
374
375
376
377
378 boolean manageXmlGeneralCovarianceSection(final boolean starting) {
379 commentsBlock.refuseFurtherComments();
380
381 if (starting) {
382 if (metadata.getAltCovType() == null) {
383 anticipateNext(this::processCovMatrixToken);
384 } else {
385 if (Double.isNaN(covMatrix.getCrr())) {
386
387 anticipateNext(this::processCovMatrixToken);
388 } else if ( metadata.getAltCovType() == AltCovarianceType.XYZ && xyzCovMatrix == null ||
389 metadata.getAltCovType() == AltCovarianceType.CSIG3EIGVEC3 && sig3eigvec3 == null ) {
390
391 anticipateNext(this::processAltCovarianceToken);
392 } else if (additionalCovMetadata == null) {
393
394 anticipateNext(this::processAdditionalCovMetadataToken);
395 }
396 }
397 } else {
398 anticipateNext(structureProcessor);
399 }
400
401 return true;
402 }
403
404
405
406
407
408
409 boolean manageUserDefinedParametersSection(final boolean starting) {
410 commentsBlock.refuseFurtherComments();
411 if (starting) {
412 if (userDefinedBlock == null) {
413
414 userDefinedBlock = new UserDefined();
415 }
416 anticipateNext(this::processUserDefinedToken);
417 } else {
418 anticipateNext(structureProcessor);
419 }
420 return true;
421 }
422
423
424
425
426
427 private boolean processMetadataToken(final ParseToken token) {
428 if (isDatafinished && getFileFormat() != FileFormat.XML) {
429 finalizeData();
430 isDatafinished = false;
431 }
432 if (metadata == null) {
433
434
435 prepareMetadata();
436 }
437 inMetadata();
438
439
440
441
442
443
444
445
446
447
448
449 final String tokenName = token.getName();
450 if (COMMENT.equals(tokenName) && doRelativeMetadata ) {
451 if (token.getType() == TokenType.ENTRY) {
452 relativeMetadata.addComment(token.getContentAsNormalizedString());
453 return true;
454 }
455 }
456 doRelativeMetadata = false;
457
458
459 if (tokenName == null) {
460 return false;
461 }
462
463
464 final CdmRelativeMetadataKey cdmRelativeMetadataKey;
465 try {
466 cdmRelativeMetadataKey = CdmRelativeMetadataKey.valueOf(tokenName);
467 } catch (IllegalArgumentException iaeM) {
468 final MetadataKey metadataKey;
469 try {
470 metadataKey = MetadataKey.valueOf(tokenName);
471 } catch (IllegalArgumentException iaeD) {
472 final CdmMetadataKey cdmMetadataKey;
473 try {
474 cdmMetadataKey = CdmMetadataKey.valueOf(tokenName);
475 } catch (IllegalArgumentException iaeC) {
476
477 return false;
478 }
479 return cdmMetadataKey.process(token, context, metadata);
480 }
481 return metadataKey.process(token, context, metadata);
482 }
483 return cdmRelativeMetadataKey.process(token, context, relativeMetadata);
484 }
485
486
487
488
489
490 private boolean processXmlSubStructureToken(final ParseToken token) {
491
492
493
494
495
496
497
498
499
500
501 if (METADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
502 RELATIVEMETADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
503 anticipateNext(this::processMetadataToken);
504 return true;
505
506 } else if (RELATIVEMETADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
507 METADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
508 final ParseToken replaceToken = new ParseToken(token.getType(), METADATA,
509 null, token.getUnits(), token.getLineNumber(), token.getFileName());
510
511 return structureProcessor.processToken(replaceToken);
512
513 } else {
514
515
516
517
518 if (commentsBlock == null && COMMENT.equals(token.getName())) {
519
520
521 if (doRelativeMetadata) {
522 if (token.getType() == TokenType.ENTRY) {
523 relativeMetadata.addComment(token.getContentAsNormalizedString());
524 doRelativeMetadata = false;
525 return true;
526
527 } else {
528
529
530
531 return true;
532 }
533 }
534
535
536 if (!doRelativeMetadata) {
537 if (token.getType() == TokenType.ENTRY) {
538 metadata.addComment(token.getContentAsNormalizedString());
539 return true;
540
541 } else {
542
543 return true;
544 }
545 }
546 }
547
548
549 try {
550 return token.getName() != null && !doRelativeMetadata &&
551 XmlSubStructureKey.valueOf(token.getName()).process(token, this);
552 } catch (IllegalArgumentException iae) {
553
554 return false;
555 }
556 }
557 }
558
559
560
561
562
563 private boolean processGeneralCommentToken(final ParseToken token) {
564 if (commentsBlock == null) {
565
566
567 finalizeMetadata();
568
569
570 prepareData();
571 }
572 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processODParamToken);
573 if (COMMENT.equals(token.getName()) && commentsBlock.acceptComments()) {
574 if (token.getType() == TokenType.ENTRY) {
575 commentsBlock.addComment(token.getContentAsNormalizedString());
576 }
577
578
579 commentsBlock.refuseFurtherComments();
580 return true;
581 } else {
582 return false;
583 }
584 }
585
586
587
588
589
590 private boolean processODParamToken(final ParseToken token) {
591 if (odParameters == null) {
592 odParameters = new ODParameters();
593 }
594 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAdditionalParametersToken);
595 try {
596 return token.getName() != null &&
597 ODParametersKey.valueOf(token.getName()).process(token, context, odParameters);
598 } catch (IllegalArgumentException iae) {
599
600 return false;
601 }
602 }
603
604
605
606
607
608 private boolean processAdditionalParametersToken(final ParseToken token) {
609 if (addParameters == null) {
610 addParameters = new AdditionalParameters(getFrameMapper());
611 }
612 if (moveCommentsIfEmpty(odParameters, addParameters)) {
613
614 odParameters = null;
615 }
616 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processStateVectorToken);
617 try {
618 return token.getName() != null &&
619 AdditionalParametersKey.valueOf(token.getName()).process(token, context, addParameters);
620 } catch (IllegalArgumentException iae) {
621
622 return false;
623 }
624 }
625
626
627
628
629
630 private boolean processStateVectorToken(final ParseToken token) {
631 if (moveCommentsIfEmpty(addParameters, stateVector)) {
632
633 addParameters = null;
634 }
635 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processCovMatrixToken);
636 try {
637 return token.getName() != null &&
638 StateVectorKey.valueOf(token.getName()).process(token, context, stateVector);
639 } catch (IllegalArgumentException iae) {
640
641 return false;
642 }
643 }
644
645
646
647
648
649 private boolean processCovMatrixToken(final ParseToken token) {
650
651 if (moveCommentsIfEmpty(stateVector, covMatrix)) {
652
653 stateVector = null;
654 }
655
656 if (metadata.getAltCovType() == null) {
657 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processMetadataToken);
658 } else {
659 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAltCovarianceToken);
660 }
661
662 isDatafinished = true;
663 try {
664 return token.getName() != null &&
665 RTNCovarianceKey.valueOf(token.getName()).process(token, context, covMatrix);
666 } catch (IllegalArgumentException iae) {
667
668 return false;
669 }
670 }
671
672
673
674
675
676 private boolean processAltCovarianceToken(final ParseToken token) {
677
678
679 if (metadata.getAltCovType() == 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() == 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() != null && metadata.getAltCovType() == AltCovarianceType.XYZ) {
702
703 return token.getName() != null &&
704 XYZCovarianceKey.valueOf(token.getName()).process(token, context, xyzCovMatrix);
705
706 } else if (metadata.getAltCovType() != null && metadata.getAltCovType() == 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