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 if (COMMENT.equals(token.getName()) && doRelativeMetadata ) {
446 if (token.getType() == TokenType.ENTRY) {
447 relativeMetadata.addComment(token.getContentAsNormalizedString());
448 return true;
449 }
450 }
451 doRelativeMetadata = false;
452
453 try {
454 return token.getName() != null &&
455 CdmRelativeMetadataKey.valueOf(token.getName()).process(token, context, relativeMetadata);
456 } catch (IllegalArgumentException iaeM) {
457 try {
458 return MetadataKey.valueOf(token.getName()).process(token, context, metadata);
459 } catch (IllegalArgumentException iaeD) {
460 try {
461 return CdmMetadataKey.valueOf(token.getName()).process(token, context, metadata);
462 } catch (IllegalArgumentException iaeC) {
463
464 return false;
465 }
466 }
467 }
468 }
469
470
471
472
473
474 private boolean processXmlSubStructureToken(final ParseToken token) {
475
476
477
478
479
480
481
482
483
484
485 if (METADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
486 RELATIVEMETADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
487 anticipateNext(this::processMetadataToken);
488 return true;
489
490 } else if (RELATIVEMETADATA.equals(token.getName()) && TokenType.START.equals(token.getType()) ||
491 METADATA.equals(token.getName()) && TokenType.STOP.equals(token.getType())) {
492 final ParseToken replaceToken = new ParseToken(token.getType(), METADATA,
493 null, token.getUnits(), token.getLineNumber(), token.getFileName());
494
495 return structureProcessor.processToken(replaceToken);
496
497 } else {
498
499
500
501
502 if (commentsBlock == null && COMMENT.equals(token.getName())) {
503
504
505 if (doRelativeMetadata) {
506 if (token.getType() == TokenType.ENTRY) {
507 relativeMetadata.addComment(token.getContentAsNormalizedString());
508 doRelativeMetadata = false;
509 return true;
510
511 } else {
512
513
514
515 return true;
516 }
517 }
518
519
520 if (!doRelativeMetadata) {
521 if (token.getType() == TokenType.ENTRY) {
522 metadata.addComment(token.getContentAsNormalizedString());
523 return true;
524
525 } else {
526
527 return true;
528 }
529 }
530 }
531
532
533 try {
534 return token.getName() != null && !doRelativeMetadata &&
535 XmlSubStructureKey.valueOf(token.getName()).process(token, this);
536 } catch (IllegalArgumentException iae) {
537
538 return false;
539 }
540 }
541 }
542
543
544
545
546
547 private boolean processGeneralCommentToken(final ParseToken token) {
548 if (commentsBlock == null) {
549
550
551 finalizeMetadata();
552
553
554 prepareData();
555 }
556 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processODParamToken);
557 if (COMMENT.equals(token.getName()) && commentsBlock.acceptComments()) {
558 if (token.getType() == TokenType.ENTRY) {
559 commentsBlock.addComment(token.getContentAsNormalizedString());
560 }
561
562
563 commentsBlock.refuseFurtherComments();
564 return true;
565 } else {
566 return false;
567 }
568 }
569
570
571
572
573
574 private boolean processODParamToken(final ParseToken token) {
575 if (odParameters == null) {
576 odParameters = new ODParameters();
577 }
578 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAdditionalParametersToken);
579 try {
580 return token.getName() != null &&
581 ODParametersKey.valueOf(token.getName()).process(token, context, odParameters);
582 } catch (IllegalArgumentException iae) {
583
584 return false;
585 }
586 }
587
588
589
590
591
592 private boolean processAdditionalParametersToken(final ParseToken token) {
593 if (addParameters == null) {
594 addParameters = new AdditionalParameters();
595 }
596 if (moveCommentsIfEmpty(odParameters, addParameters)) {
597
598 odParameters = null;
599 }
600 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processStateVectorToken);
601 try {
602 return token.getName() != null &&
603 AdditionalParametersKey.valueOf(token.getName()).process(token, context, addParameters);
604 } catch (IllegalArgumentException iae) {
605
606 return false;
607 }
608 }
609
610
611
612
613
614 private boolean processStateVectorToken(final ParseToken token) {
615 if (moveCommentsIfEmpty(addParameters, stateVector)) {
616
617 addParameters = null;
618 }
619 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processCovMatrixToken);
620 try {
621 return token.getName() != null &&
622 StateVectorKey.valueOf(token.getName()).process(token, context, stateVector);
623 } catch (IllegalArgumentException iae) {
624
625 return false;
626 }
627 }
628
629
630
631
632
633 private boolean processCovMatrixToken(final ParseToken token) {
634
635 if (moveCommentsIfEmpty(stateVector, covMatrix)) {
636
637 stateVector = null;
638 }
639
640 if (metadata.getAltCovType() == null) {
641 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processMetadataToken);
642 } else {
643 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAltCovarianceToken);
644 }
645
646 isDatafinished = true;
647 try {
648 return token.getName() != null &&
649 RTNCovarianceKey.valueOf(token.getName()).process(token, context, covMatrix);
650 } catch (IllegalArgumentException iae) {
651
652 return false;
653 }
654 }
655
656
657
658
659
660 private boolean processAltCovarianceToken(final ParseToken token) {
661
662
663 if (metadata.getAltCovType() == AltCovarianceType.XYZ && xyzCovMatrix == null) {
664 xyzCovMatrix = new XYZCovariance(true);
665
666 if (moveCommentsIfEmpty(covMatrix, xyzCovMatrix)) {
667
668 covMatrix = null;
669 }
670 }
671
672 if (metadata.getAltCovType() == AltCovarianceType.CSIG3EIGVEC3 && sig3eigvec3 == null) {
673 sig3eigvec3 = new SigmaEigenvectorsCovariance(true);
674
675 if (moveCommentsIfEmpty(covMatrix, sig3eigvec3)) {
676
677 covMatrix = null;
678 }
679 }
680
681
682 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processAdditionalCovMetadataToken);
683 try {
684
685 if (metadata.getAltCovType() != null && metadata.getAltCovType() == AltCovarianceType.XYZ) {
686
687 return token.getName() != null &&
688 XYZCovarianceKey.valueOf(token.getName()).process(token, context, xyzCovMatrix);
689
690 } else if (metadata.getAltCovType() != null && metadata.getAltCovType() == AltCovarianceType.CSIG3EIGVEC3) {
691
692 return token.getName() != null &&
693 SigmaEigenvectorsCovarianceKey.valueOf(token.getName()).process(token, context, sig3eigvec3);
694
695 } else {
696
697
698 return false;
699
700 }
701
702 } catch (IllegalArgumentException iae) {
703
704 return false;
705 }
706 }
707
708
709
710
711
712 private boolean processAdditionalCovMetadataToken(final ParseToken token) {
713
714
715 if ( additionalCovMetadata == null) {
716 additionalCovMetadata = new AdditionalCovarianceMetadata();
717 }
718
719 if (moveCommentsIfEmpty(xyzCovMatrix, additionalCovMetadata)) {
720
721 xyzCovMatrix = null;
722 } else if (moveCommentsIfEmpty(sig3eigvec3, additionalCovMetadata)) {
723
724 sig3eigvec3 = null;
725 }
726
727 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processUserDefinedToken);
728 try {
729 return token.getName() != null &&
730 AdditionalCovarianceMetadataKey.valueOf(token.getName()).process(token, context, additionalCovMetadata);
731 } catch (IllegalArgumentException iae) {
732
733 return false;
734 }
735 }
736
737
738
739
740
741 private boolean processUserDefinedToken(final ParseToken token) {
742
743 if (userDefinedBlock == null) {
744 userDefinedBlock = new UserDefined();
745 }
746
747 if (moveCommentsIfEmpty(additionalCovMetadata, userDefinedBlock)) {
748
749 additionalCovMetadata = null;
750 }
751
752 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processMetadataToken);
753
754 if (COMMENT.equals(token.getName())) {
755 return token.getType() == TokenType.ENTRY ? userDefinedBlock.addComment(token.getContentAsNormalizedString()) : true;
756 } else if (token.getName().startsWith(UserDefined.USER_DEFINED_PREFIX)) {
757 if (token.getType() == TokenType.ENTRY) {
758 userDefinedBlock.addEntry(token.getName().substring(UserDefined.USER_DEFINED_PREFIX.length()),
759 token.getContentAsNormalizedString());
760 }
761 return true;
762 } else {
763
764 return false;
765 }
766 }
767
768
769
770
771
772
773
774 private boolean moveCommentsIfEmpty(final CommentsContainer origin, final CommentsContainer destination) {
775 if (origin != null && origin.acceptComments()) {
776
777 for (final String comment : origin.getComments()) {
778 destination.addComment(comment);
779 }
780 return true;
781 } else {
782 return false;
783 }
784 }
785
786 }
787