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