1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.odm.opm;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.function.Function;
23
24 import org.orekit.data.DataContext;
25 import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
26 import org.orekit.files.ccsds.ndm.odm.CartesianCovariance;
27 import org.orekit.files.ccsds.ndm.odm.CartesianCovarianceKey;
28 import org.orekit.files.ccsds.ndm.odm.OdmCommonMetadata;
29 import org.orekit.files.ccsds.ndm.odm.CommonMetadataKey;
30 import org.orekit.files.ccsds.ndm.odm.KeplerianElements;
31 import org.orekit.files.ccsds.ndm.odm.KeplerianElementsKey;
32 import org.orekit.files.ccsds.ndm.odm.OdmHeader;
33 import org.orekit.files.ccsds.ndm.odm.OdmMetadataKey;
34 import org.orekit.files.ccsds.ndm.odm.OdmParser;
35 import org.orekit.files.ccsds.ndm.odm.SpacecraftParameters;
36 import org.orekit.files.ccsds.ndm.odm.SpacecraftParametersKey;
37 import org.orekit.files.ccsds.ndm.odm.StateVector;
38 import org.orekit.files.ccsds.ndm.odm.StateVectorKey;
39 import org.orekit.files.ccsds.ndm.odm.UserDefined;
40 import org.orekit.files.ccsds.section.CommentsContainer;
41 import org.orekit.files.ccsds.section.HeaderProcessingState;
42 import org.orekit.files.ccsds.section.MetadataKey;
43 import org.orekit.files.ccsds.section.Segment;
44 import org.orekit.files.ccsds.section.XmlStructureProcessingState;
45 import org.orekit.files.ccsds.utils.ContextBinding;
46 import org.orekit.files.ccsds.utils.FileFormat;
47 import org.orekit.files.ccsds.utils.lexical.ParseToken;
48 import org.orekit.files.ccsds.utils.lexical.TokenType;
49 import org.orekit.files.ccsds.utils.lexical.UserDefinedXmlTokenBuilder;
50 import org.orekit.files.ccsds.utils.lexical.XmlTokenBuilder;
51 import org.orekit.files.ccsds.utils.parsing.ErrorState;
52 import org.orekit.files.ccsds.utils.parsing.ProcessingState;
53 import org.orekit.time.AbsoluteDate;
54 import org.orekit.utils.IERSConventions;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class OpmParser extends OdmParser<Opm, OpmParser> {
71
72
73 private final double defaultMass;
74
75
76 private OdmHeader header;
77
78
79 private List<Segment<OdmCommonMetadata, OpmData>> segments;
80
81
82 private OdmCommonMetadata metadata;
83
84
85 private ContextBinding context;
86
87
88 private StateVector stateVectorBlock;
89
90
91 private KeplerianElements keplerianElementsBlock;
92
93
94 private SpacecraftParameters spacecraftParametersBlock;
95
96
97 private CartesianCovariance covarianceBlock;
98
99
100 private Maneuver currentManeuver;
101
102
103 private List<Maneuver> maneuverBlocks;
104
105
106 private UserDefined userDefinedBlock;
107
108
109 private ProcessingState structureProcessor;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 public OpmParser(final IERSConventions conventions, final boolean simpleEOP,
128 final DataContext dataContext,
129 final AbsoluteDate missionReferenceDate, final double mu,
130 final double defaultMass, final ParsedUnitsBehavior parsedUnitsBehavior,
131 final Function<ParseToken, List<ParseToken>>[] filters) {
132 super(Opm.ROOT, Opm.FORMAT_VERSION_KEY, conventions, simpleEOP, dataContext,
133 missionReferenceDate, mu, parsedUnitsBehavior, filters);
134 this.defaultMass = defaultMass;
135 }
136
137
138 @Override
139 public Map<String, XmlTokenBuilder> getSpecialXmlElementsBuilders() {
140
141 final Map<String, XmlTokenBuilder> builders = super.getSpecialXmlElementsBuilders();
142
143
144 builders.put(UserDefined.USER_DEFINED_XML_TAG, new UserDefinedXmlTokenBuilder());
145
146 return builders;
147
148 }
149
150
151 @Override
152 public OdmHeader getHeader() {
153 return header;
154 }
155
156
157 @Override
158 public void reset(final FileFormat fileFormat) {
159 header = new OdmHeader();
160 segments = new ArrayList<>();
161 metadata = null;
162 context = null;
163 stateVectorBlock = null;
164 keplerianElementsBlock = null;
165 spacecraftParametersBlock = null;
166 covarianceBlock = null;
167 currentManeuver = null;
168 maneuverBlocks = new ArrayList<>();
169 userDefinedBlock = null;
170 if (fileFormat == FileFormat.XML) {
171 structureProcessor = new XmlStructureProcessingState(Opm.ROOT, this);
172 reset(fileFormat, structureProcessor);
173 } else {
174 structureProcessor = new ErrorState();
175 reset(fileFormat, new HeaderProcessingState(this));
176 }
177 }
178
179
180 @Override
181 public boolean prepareHeader() {
182 anticipateNext(new HeaderProcessingState(this));
183 return true;
184 }
185
186
187 @Override
188 public boolean inHeader() {
189 anticipateNext(getFileFormat() == FileFormat.XML ? structureProcessor : this::processMetadataToken);
190 return true;
191 }
192
193
194 @Override
195 public boolean finalizeHeader() {
196 header.validate(header.getFormatVersion());
197 return true;
198 }
199
200
201 @Override
202 public boolean prepareMetadata() {
203 if (metadata != null) {
204 return false;
205 }
206 metadata = new OdmCommonMetadata();
207 context = new ContextBinding(this::getConventions, this::isSimpleEOP,
208 this::getDataContext, this::getParsedUnitsBehavior,
209 this::getMissionReferenceDate,
210 metadata::getTimeSystem, () -> 0.0, () -> 1.0);
211 anticipateNext(this::processMetadataToken);
212 return true;
213 }
214
215
216 @Override
217 public boolean inMetadata() {
218 anticipateNext(getFileFormat() == FileFormat.XML ? structureProcessor : this::processStateVectorToken);
219 return true;
220 }
221
222
223 @Override
224 public boolean finalizeMetadata() {
225 metadata.finalizeMetadata(context);
226 metadata.validate(header.getFormatVersion());
227 if (metadata.getCenter().getBody() != null) {
228 setMuCreated(metadata.getCenter().getBody().getGM());
229 }
230 return true;
231 }
232
233
234 @Override
235 public boolean prepareData() {
236 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processStateVectorToken);
237 return true;
238 }
239
240
241 @Override
242 public boolean inData() {
243 return true;
244 }
245
246
247 @Override
248 public boolean finalizeData() {
249 if (metadata != null) {
250 if (userDefinedBlock != null && userDefinedBlock.getParameters().isEmpty()) {
251 userDefinedBlock = null;
252 }
253 if (keplerianElementsBlock != null) {
254 keplerianElementsBlock.setEpoch(stateVectorBlock.getEpoch());
255 if (Double.isNaN(keplerianElementsBlock.getMu())) {
256 keplerianElementsBlock.setMu(getSelectedMu());
257 } else {
258 setMuParsed(keplerianElementsBlock.getMu());
259 }
260 }
261 final double mass = spacecraftParametersBlock == null ?
262 defaultMass : spacecraftParametersBlock.getMass();
263 final OpmData data = new OpmData(stateVectorBlock, keplerianElementsBlock,
264 spacecraftParametersBlock, covarianceBlock,
265 maneuverBlocks, userDefinedBlock,
266 mass);
267 data.validate(header.getFormatVersion());
268 segments.add(new Segment<>(metadata, data));
269 }
270 metadata = null;
271 context = null;
272 stateVectorBlock = null;
273 keplerianElementsBlock = null;
274 spacecraftParametersBlock = null;
275 covarianceBlock = null;
276 currentManeuver = null;
277 maneuverBlocks = null;
278 userDefinedBlock = null;
279 return true;
280 }
281
282
283 @Override
284 public Opm build() {
285
286
287 finalizeData();
288 return new Opm(header, segments, getConventions(), getDataContext(), getSelectedMu());
289 }
290
291
292
293
294
295
296 boolean manageStateVectorSection(final boolean starting) {
297 anticipateNext(starting ? this::processStateVectorToken : structureProcessor);
298 return true;
299 }
300
301
302
303
304
305
306 boolean manageKeplerianElementsSection(final boolean starting) {
307 anticipateNext(starting ? this::processKeplerianElementsToken : structureProcessor);
308 return true;
309 }
310
311
312
313
314
315
316 boolean manageSpacecraftParametersSection(final boolean starting) {
317 anticipateNext(starting ? this::processSpacecraftParametersToken : structureProcessor);
318 return true;
319 }
320
321
322
323
324
325
326 boolean manageCovarianceSection(final boolean starting) {
327 anticipateNext(starting ? this::processCovarianceToken : structureProcessor);
328 return true;
329 }
330
331
332
333
334
335
336 boolean manageManeuversSection(final boolean starting) {
337 anticipateNext(starting ? this::processManeuverToken : structureProcessor);
338 return true;
339 }
340
341
342
343
344
345
346 boolean manageUserDefinedParametersSection(final boolean starting) {
347 anticipateNext(starting ? this::processUserDefinedToken : structureProcessor);
348 return true;
349 }
350
351
352
353
354
355 private boolean processMetadataToken(final ParseToken token) {
356 if (metadata == null) {
357
358
359 prepareMetadata();
360 }
361 inMetadata();
362 try {
363 return token.getName() != null &&
364 MetadataKey.valueOf(token.getName()).process(token, context, metadata);
365 } catch (IllegalArgumentException iaeM) {
366 try {
367 return OdmMetadataKey.valueOf(token.getName()).process(token, context, metadata);
368 } catch (IllegalArgumentException iaeD) {
369 try {
370 return CommonMetadataKey.valueOf(token.getName()).process(token, context, metadata);
371 } catch (IllegalArgumentException iaeC) {
372
373 return false;
374 }
375 }
376 }
377 }
378
379
380
381
382
383 private boolean processXmlSubStructureToken(final ParseToken token) {
384 try {
385 return token.getName() != null &&
386 XmlSubStructureKey.valueOf(token.getName()).process(token, this);
387 } catch (IllegalArgumentException iae) {
388
389 return false;
390 }
391 }
392
393
394
395
396
397 private boolean processStateVectorToken(final ParseToken token) {
398 if (stateVectorBlock == null) {
399
400
401 finalizeMetadata();
402
403
404 prepareData();
405 stateVectorBlock = new StateVector();
406 }
407 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processKeplerianElementsToken);
408 try {
409 return token.getName() != null &&
410 StateVectorKey.valueOf(token.getName()).process(token, context, stateVectorBlock);
411 } catch (IllegalArgumentException iae) {
412
413 return false;
414 }
415 }
416
417
418
419
420
421 private boolean processKeplerianElementsToken(final ParseToken token) {
422 if (keplerianElementsBlock == null) {
423 keplerianElementsBlock = new KeplerianElements();
424 }
425 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processSpacecraftParametersToken);
426 try {
427 return token.getName() != null &&
428 KeplerianElementsKey.valueOf(token.getName()).process(token, context, keplerianElementsBlock);
429 } catch (IllegalArgumentException iae) {
430
431 return false;
432 }
433 }
434
435
436
437
438
439 private boolean processSpacecraftParametersToken(final ParseToken token) {
440 if (spacecraftParametersBlock == null) {
441 spacecraftParametersBlock = new SpacecraftParameters();
442 if (moveCommentsIfEmpty(keplerianElementsBlock, spacecraftParametersBlock)) {
443
444 keplerianElementsBlock = null;
445 }
446 }
447 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processCovarianceToken);
448 try {
449 return token.getName() != null &&
450 SpacecraftParametersKey.valueOf(token.getName()).process(token, context, spacecraftParametersBlock);
451 } catch (IllegalArgumentException iae) {
452
453 return false;
454 }
455 }
456
457
458
459
460
461 private boolean processCovarianceToken(final ParseToken token) {
462 if (covarianceBlock == null) {
463
464 final OdmCommonMetadata savedMetadata = metadata;
465 covarianceBlock = new CartesianCovariance(savedMetadata::getReferenceFrame);
466 if (moveCommentsIfEmpty(spacecraftParametersBlock, covarianceBlock)) {
467
468 spacecraftParametersBlock = null;
469 }
470 }
471 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processManeuverToken);
472 try {
473 return token.getName() != null &&
474 CartesianCovarianceKey.valueOf(token.getName()).process(token, context, covarianceBlock);
475 } catch (IllegalArgumentException iae) {
476
477 return false;
478 }
479 }
480
481
482
483
484
485 private boolean processManeuverToken(final ParseToken token) {
486 if (currentManeuver == null) {
487 currentManeuver = new Maneuver();
488 if (covarianceBlock != null && moveCommentsIfEmpty(covarianceBlock, currentManeuver)) {
489
490 covarianceBlock = null;
491 }
492 }
493 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processUserDefinedToken);
494 try {
495 if (token.getName() != null &&
496 ManeuverKey.valueOf(token.getName()).process(token, context, currentManeuver)) {
497
498 if (currentManeuver.completed()) {
499
500 maneuverBlocks.add(currentManeuver);
501 currentManeuver = null;
502 }
503 return true;
504 }
505 } catch (IllegalArgumentException iae) {
506
507 }
508
509 return false;
510 }
511
512
513
514
515
516 private boolean processUserDefinedToken(final ParseToken token) {
517 if (userDefinedBlock == null) {
518 userDefinedBlock = new UserDefined();
519 if (moveCommentsIfEmpty(currentManeuver, userDefinedBlock)) {
520
521 currentManeuver = null;
522 }
523 }
524 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : new ErrorState());
525 if (token.getName().startsWith(UserDefined.USER_DEFINED_PREFIX)) {
526 if (token.getType() == TokenType.ENTRY) {
527 userDefinedBlock.addEntry(token.getName().substring(UserDefined.USER_DEFINED_PREFIX.length()),
528 token.getContentAsNormalizedString());
529 }
530 return true;
531 } else {
532
533 return false;
534 }
535 }
536
537
538
539
540
541
542 private boolean moveCommentsIfEmpty(final CommentsContainer origin, final CommentsContainer destination) {
543 if (origin != null && origin.acceptComments()) {
544
545 for (final String comment : origin.getComments()) {
546 destination.addComment(comment);
547 }
548 return true;
549 } else {
550 return false;
551 }
552 }
553
554 }