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