1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.ndm.adm.apm;
18
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import org.orekit.data.DataContext;
23 import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
24 import org.orekit.files.ccsds.ndm.adm.AdmMetadata;
25 import org.orekit.files.ccsds.ndm.adm.AdmMetadataKey;
26 import org.orekit.files.ccsds.ndm.adm.AdmParser;
27 import org.orekit.files.ccsds.section.CommentsContainer;
28 import org.orekit.files.ccsds.section.Header;
29 import org.orekit.files.ccsds.section.HeaderProcessingState;
30 import org.orekit.files.ccsds.section.MetadataKey;
31 import org.orekit.files.ccsds.section.Segment;
32 import org.orekit.files.ccsds.section.XmlStructureProcessingState;
33 import org.orekit.files.ccsds.utils.ContextBinding;
34 import org.orekit.files.ccsds.utils.FileFormat;
35 import org.orekit.files.ccsds.utils.lexical.ParseToken;
36 import org.orekit.files.ccsds.utils.lexical.TokenType;
37 import org.orekit.files.ccsds.utils.parsing.ErrorState;
38 import org.orekit.files.ccsds.utils.parsing.ProcessingState;
39 import org.orekit.time.AbsoluteDate;
40 import org.orekit.utils.IERSConventions;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class ApmParser extends AdmParser<Apm, ApmParser> {
57
58
59 private Header header;
60
61
62 private List<Segment<AdmMetadata, ApmData>> segments;
63
64
65 private AdmMetadata metadata;
66
67
68 private ContextBinding context;
69
70
71 private CommentsContainer commentsBlock;
72
73
74 private ApmQuaternion quaternionBlock;
75
76
77 private Euler eulerBlock;
78
79
80 private SpinStabilized spinStabilizedBlock;
81
82
83 private SpacecraftParameters spacecraftParametersBlock;
84
85
86 private Maneuver currentManeuver;
87
88
89 private List<Maneuver> maneuvers;
90
91
92 private ProcessingState structureProcessor;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public ApmParser(final IERSConventions conventions, final boolean simpleEOP, final DataContext dataContext,
108 final AbsoluteDate missionReferenceDate, final ParsedUnitsBehavior parsedUnitsBehavior) {
109 super(Apm.ROOT, Apm.FORMAT_VERSION_KEY, conventions, simpleEOP, dataContext,
110 missionReferenceDate, parsedUnitsBehavior);
111 }
112
113
114 @Override
115 public Header getHeader() {
116 return header;
117 }
118
119
120 @Override
121 public void reset(final FileFormat fileFormat) {
122 header = new Header(2.0);
123 segments = new ArrayList<>();
124 metadata = null;
125 context = null;
126 quaternionBlock = null;
127 eulerBlock = null;
128 spinStabilizedBlock = null;
129 spacecraftParametersBlock = null;
130 currentManeuver = null;
131 maneuvers = new ArrayList<>();
132 if (fileFormat == FileFormat.XML) {
133 structureProcessor = new XmlStructureProcessingState(Apm.ROOT, this);
134 reset(fileFormat, structureProcessor);
135 } else {
136 structureProcessor = new ErrorState();
137 reset(fileFormat, new HeaderProcessingState(this));
138 }
139 }
140
141
142 @Override
143 public boolean prepareHeader() {
144 anticipateNext(new HeaderProcessingState(this));
145 return true;
146 }
147
148
149 @Override
150 public boolean inHeader() {
151 anticipateNext(getFileFormat() == FileFormat.XML ? structureProcessor : this::processMetadataToken);
152 return true;
153 }
154
155
156 @Override
157 public boolean finalizeHeader() {
158 header.validate(header.getFormatVersion());
159 return true;
160 }
161
162
163 @Override
164 public boolean prepareMetadata() {
165 if (metadata != null) {
166 return false;
167 }
168 metadata = new AdmMetadata();
169 context = new ContextBinding(this::getConventions, this::isSimpleEOP,
170 this::getDataContext, this::getParsedUnitsBehavior,
171 this::getMissionReferenceDate,
172 metadata::getTimeSystem, () -> 0.0, () -> 1.0);
173 anticipateNext(this::processMetadataToken);
174 return true;
175 }
176
177
178 @Override
179 public boolean inMetadata() {
180 anticipateNext(getFileFormat() == FileFormat.XML ? structureProcessor : this::processGeneralCommentToken);
181 return true;
182 }
183
184
185 @Override
186 public boolean finalizeMetadata() {
187 metadata.validate(header.getFormatVersion());
188 return true;
189 }
190
191
192 @Override
193 public boolean prepareData() {
194 commentsBlock = new CommentsContainer();
195 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processGeneralCommentToken);
196 return true;
197 }
198
199
200 @Override
201 public boolean inData() {
202 return true;
203 }
204
205
206 @Override
207 public boolean finalizeData() {
208 if (metadata != null) {
209 final ApmData data = new ApmData(commentsBlock, quaternionBlock, eulerBlock,
210 spinStabilizedBlock, spacecraftParametersBlock);
211 for (final Maneuver maneuver : maneuvers) {
212 data.addManeuver(maneuver);
213 }
214 data.validate(header.getFormatVersion());
215 segments.add(new Segment<>(metadata, data));
216 }
217 metadata = null;
218 context = null;
219 quaternionBlock = null;
220 eulerBlock = null;
221 spinStabilizedBlock = null;
222 spacecraftParametersBlock = null;
223 currentManeuver = null;
224 return true;
225 }
226
227
228 @Override
229 public Apm build() {
230
231
232 finalizeData();
233 final Apm file = new Apm(header, segments, getConventions(), getDataContext());
234 return file;
235 }
236
237
238
239
240
241 boolean addGeneralComment(final String comment) {
242 return commentsBlock.addComment(comment);
243 }
244
245
246
247
248
249
250 boolean manageQuaternionSection(final boolean starting) {
251 anticipateNext(starting ? this::processQuaternionToken : structureProcessor);
252 return true;
253 }
254
255
256
257
258
259
260 boolean manageEulerElementsThreeSection(final boolean starting) {
261 anticipateNext(starting ? this::processEulerToken : structureProcessor);
262 return true;
263 }
264
265
266
267
268
269
270 boolean manageEulerElementsSpinSection(final boolean starting) {
271 anticipateNext(starting ? this::processSpinStabilizedToken : structureProcessor);
272 return true;
273 }
274
275
276
277
278
279
280 boolean manageSpacecraftParametersSection(final boolean starting) {
281 anticipateNext(starting ? this::processSpacecraftParametersToken : structureProcessor);
282 return true;
283 }
284
285
286
287
288
289
290 boolean manageManeuverParametersSection(final boolean starting) {
291 anticipateNext(starting ? this::processManeuverToken : structureProcessor);
292 return true;
293 }
294
295
296
297
298
299 private boolean processMetadataToken(final ParseToken token) {
300 if (metadata == null) {
301
302
303 prepareMetadata();
304 }
305 inMetadata();
306 try {
307 return token.getName() != null &&
308 MetadataKey.valueOf(token.getName()).process(token, context, metadata);
309 } catch (IllegalArgumentException iaeM) {
310 try {
311 return AdmMetadataKey.valueOf(token.getName()).process(token, context, metadata);
312 } catch (IllegalArgumentException iaeD) {
313
314 return false;
315 }
316 }
317 }
318
319
320
321
322
323 private boolean processXmlSubStructureToken(final ParseToken token) {
324 try {
325 return token.getName() != null &&
326 XmlSubStructureKey.valueOf(token.getName()).process(token, this);
327 } catch (IllegalArgumentException iae) {
328
329 return false;
330 }
331 }
332
333
334
335
336
337 private boolean processGeneralCommentToken(final ParseToken token) {
338 if (commentsBlock == null) {
339
340
341 finalizeMetadata();
342
343
344 prepareData();
345 }
346 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processQuaternionToken);
347 if ("COMMENT".equals(token.getName())) {
348 if (token.getType() == TokenType.ENTRY) {
349 commentsBlock.addComment(token.getContentAsNormalizedString());
350 }
351 return true;
352 } else {
353 return false;
354 }
355 }
356
357
358
359
360
361 private boolean processQuaternionToken(final ParseToken token) {
362 commentsBlock.refuseFurtherComments();
363 if (quaternionBlock == null) {
364 quaternionBlock = new ApmQuaternion();
365 }
366 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processEulerToken);
367 try {
368 return token.getName() != null &&
369 ApmQuaternionKey.valueOf(token.getName()).process(token, context, quaternionBlock);
370 } catch (IllegalArgumentException iae) {
371
372 return false;
373 }
374 }
375
376
377
378
379
380 private boolean processEulerToken(final ParseToken token) {
381 if (eulerBlock == null) {
382 eulerBlock = new Euler();
383 }
384 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processSpinStabilizedToken);
385 try {
386 return token.getName() != null &&
387 EulerKey.valueOf(token.getName()).process(token, context, eulerBlock);
388 } catch (IllegalArgumentException iae) {
389
390 return false;
391 }
392 }
393
394
395
396
397
398 private boolean processSpinStabilizedToken(final ParseToken token) {
399 if (spinStabilizedBlock == null) {
400 spinStabilizedBlock = new SpinStabilized();
401 if (moveCommentsIfEmpty(eulerBlock, spinStabilizedBlock)) {
402
403 eulerBlock = null;
404 }
405 }
406 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processSpacecraftParametersToken);
407 try {
408 return token.getName() != null &&
409 SpinStabilizedKey.valueOf(token.getName()).process(token, context, spinStabilizedBlock);
410 } catch (IllegalArgumentException iae) {
411
412 return false;
413 }
414 }
415
416
417
418
419
420 private boolean processSpacecraftParametersToken(final ParseToken token) {
421 if (spacecraftParametersBlock == null) {
422 spacecraftParametersBlock = new SpacecraftParameters();
423 if (moveCommentsIfEmpty(spinStabilizedBlock, spacecraftParametersBlock)) {
424
425 spinStabilizedBlock = null;
426 }
427 }
428 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processManeuverToken);
429 try {
430 return token.getName() != null &&
431 SpacecraftParametersKey.valueOf(token.getName()).process(token, context, spacecraftParametersBlock);
432 } catch (IllegalArgumentException iae) {
433
434 return false;
435 }
436 }
437
438
439
440
441
442 private boolean processManeuverToken(final ParseToken token) {
443 if (currentManeuver == null) {
444 currentManeuver = new Maneuver();
445 if (moveCommentsIfEmpty(spacecraftParametersBlock, currentManeuver)) {
446
447 spacecraftParametersBlock = null;
448 }
449 }
450 anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : new ErrorState());
451 try {
452 if (token.getName() != null &&
453 ManeuverKey.valueOf(token.getName()).process(token, context, currentManeuver)) {
454
455 if (currentManeuver.completed()) {
456
457 maneuvers.add(currentManeuver);
458 currentManeuver = null;
459 }
460 return true;
461 }
462 } catch (IllegalArgumentException iae) {
463
464 }
465
466 return false;
467 }
468
469
470
471
472
473
474 private boolean moveCommentsIfEmpty(final CommentsContainer origin, final CommentsContainer destination) {
475 if (origin != null && origin.acceptComments()) {
476
477 for (final String comment : origin.getComments()) {
478 destination.addComment(comment);
479 }
480 return true;
481 } else {
482 return false;
483 }
484 }
485
486 }