1 /* Copyright 2024-2025 The Johns Hopkins University Applied Physics Laboratory
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.files.iirv;
18
19 import org.orekit.errors.OrekitIllegalStateException;
20 import org.orekit.errors.OrekitInternalError;
21 import org.orekit.errors.OrekitMessages;
22 import org.orekit.files.iirv.terms.CheckSumTerm;
23 import org.orekit.files.iirv.terms.CoordinateSystemTerm;
24 import org.orekit.files.iirv.terms.CrossSectionalAreaTerm;
25 import org.orekit.files.iirv.terms.DataSourceTerm;
26 import org.orekit.files.iirv.terms.DayOfYearTerm;
27 import org.orekit.files.iirv.terms.DragCoefficientTerm;
28 import org.orekit.files.iirv.terms.MassTerm;
29 import org.orekit.files.iirv.terms.MessageClassTerm;
30 import org.orekit.files.iirv.terms.MessageEndConstantTerm;
31 import org.orekit.files.iirv.terms.MessageIDTerm;
32 import org.orekit.files.iirv.terms.MessageSourceTerm;
33 import org.orekit.files.iirv.terms.MessageStartConstantTerm;
34 import org.orekit.files.iirv.terms.MessageTypeTerm;
35 import org.orekit.files.iirv.terms.OriginIdentificationTerm;
36 import org.orekit.files.iirv.terms.OriginatorRoutingIndicatorTerm;
37 import org.orekit.files.iirv.terms.PositionVectorComponentTerm;
38 import org.orekit.files.iirv.terms.RoutingIndicatorTerm;
39 import org.orekit.files.iirv.terms.SequenceNumberTerm;
40 import org.orekit.files.iirv.terms.SolarReflectivityCoefficientTerm;
41 import org.orekit.files.iirv.terms.SpareConstantTerm;
42 import org.orekit.files.iirv.terms.SupportIdCodeTerm;
43 import org.orekit.files.iirv.terms.VectorEpochTerm;
44 import org.orekit.files.iirv.terms.VectorTypeTerm;
45 import org.orekit.files.iirv.terms.VehicleIdCodeTerm;
46 import org.orekit.files.iirv.terms.VelocityVectorComponentTerm;
47
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.List;
51 import java.util.Objects;
52
53 /**
54 * Container for Improved Interrange Vector (IIRV) messages, implemented as a list of sequential {@link IIRVVector}
55 * instances.
56 * <p>
57 * The IIRV message consists of a series of sequential {@link IIRVVector}s that each contains ephemeris state data
58 * at a particular epoch. The message body is defined as:<p>
59 * {@code ttuuuuuuuqjjGIIRVarrrr<<≡≡}<br>
60 * {@code vs1ciiiibbnnndoyhhmmsssssccc<<≡≡}<br>
61 * {@code sxxxxxxxxxxxxsyyyyyyyyyyyyszzzzzzzzzzzzccc<<==}<br>
62 * {@code sxxxxxxxxxxxxsyyyyyyyyyyyyszzzzzzzzzzzzccc<<==}<br>
63 * {@code mmmmmmmmaaaaakkkksrrrrrrrccc<<==}<br>
64 * {@code ITERM oooo<<==}
65 * <table border="1">
66 * <caption>Line No. / Characters / Value / Type / Description / Class</caption>
67 * <tbody>
68 * <tr>
69 * <th rowspan="9">1</th>
70 * <td>{@code tt}</td>
71 * <td>2 characters</td>
72 * <td>Constant</td>
73 * <td>Message Type (Operations Data Message)</td>
74 * <td>{@link MessageTypeTerm}</td>
75 * <tr>
76 * <td>{@code uuuuuuu}</td>
77 * <td>0000000 to 9999999</td>
78 * <td>Integer</td>
79 * <td>Message ID</td>
80 * <td>{@link MessageIDTerm}</td>
81 * <tr>
82 * <td>{@code q}</td>
83 * <td>1 character</td>
84 * <td>String</td>
85 * <td>Message Source</td>
86 * <td>{@link MessageSourceTerm}</td>
87 * <tr>
88 * <td>{@code jj}</td>
89 * <td>
90 * <ul>
91 * <li> 10 = Nominal
92 * <li> 15 = In-flight Update
93 * </ul></td>
94 * <td>String</td>
95 * <td>Message class (10=nominal)</td>
96 * <td>{@link MessageClassTerm}</td>
97 * <tr>
98 * <td>{@code GIIRV}</td>
99 * <td>"GIIRV"</td>
100 * <td>Constant</td>
101 * <td>Message ID</td>
102 * <td>{@link MessageStartConstantTerm}</td>
103 * <tr>
104 * <td>{@code a}</td>
105 * <td>
106 * <ul>
107 * <li> ASCII space = GSFC
108 * <li> Z = WLP
109 * <li> E = ETR
110 * <li> L = JPL
111 * <li> W = WTR
112 * <li> J = JSC
113 * <li> P = PMR
114 * <li> A = CSTC
115 * <li> K = KMR
116 * <li> C = CNES
117 * </ul></td>
118 * <td>String</td>
119 * <td>Origin identification</td>
120 * <td>{@link OriginIdentificationTerm}</td>
121 * <tr>
122 * <td>{@code rrrr}</td>
123 * <td>
124 * <ul>
125 * <li>GSFC = NASA Goddard Space Flight Center
126 * <li>WLP = Wallops Island tracking radars
127 * <li>ETR = NASA/USFC Eastern Test Range
128 * <li>JPL = NASA Jet Propulsion Laboratory
129 * <li>WTR = NASA/USFC Western Test Range
130 * <li>JSC = NASA Johnson Space Center
131 * <li>PMR = Navy Pacific Missile Range
132 * <li>CSTC = Air Force Satellite Control Facility
133 * <li>KMR = Army Kwajalein Missile Range
134 * <li>CNES = French Space Agency National <br>Centre for Space Studies (CNES)
135 * <li>MANY = Message originated from more <br>than one of the above stations
136 * </ul></td>
137 * <td>String</td>
138 * <td>Destination routing indicator</td>
139 * <td>{@link RoutingIndicatorTerm}</td>
140 * <tr>
141 * <td>{@code <<}</td>
142 * <td>"\r\r"</td>
143 * <td>Constant</td>
144 * <td>Carriage returns</td>
145 * <td>n/a</td>
146 * <tr>
147 * <td>==</td>
148 * <td>"\n\n"</td>
149 * <td>Constant</td>
150 * <td>Line feeds</td>
151 * <td>n/a</td>
152 * <tr>
153 * <th rowspan="12">2</th>
154 * <td>{@code v}</td>
155 * <td>
156 * <ul>
157 * <li> 1 = Free flight (routine on-orbit)
158 * <li> 2 = Forced (special orbit update)
159 * <li> 3 = Spare
160 * <li> 4 = Maneuver ignition
161 * <li> 5 = Maneuver cutoff
162 * <li> 6 = Reentry
163 * <li> 7 = Powered flight
164 * <li> 8 = Stationary
165 * <li> 9 = Spare
166 * </ul></td>
167 * <td>Integer</td>
168 * <td>Vector type</td>
169 * <td>{@link VectorTypeTerm}</td>
170 * <tr>
171 * <td>{@code s}</td>
172 * <td>
173 * <ul>
174 * <li> 1 = Nominal/planning
175 * <li> 2 = Real-time
176 * <li> 3 = Off-line
177 * <li> 4 = Off-line/mean
178 * </ul></td>
179 * <td>Integer</td>
180 * <td>Source of data</td>
181 * <td>{@link DataSourceTerm}</td>
182 * <tr>
183 * <td>{@code 1}</td>
184 * <td>"1" = interrange message</td>
185 * <td>Constant</td>
186 * <td>Transfer type</td>
187 * <td>{@link org.orekit.files.iirv.terms.TransferTypeConstantTerm}</td>
188 * <tr>
189 * <td>{@code c}</td>
190 * <td>
191 * <ul>
192 * <li> 1 = Geocentric True-of-Date Rotating
193 * <li> 2 = Geocentric mean of 1950.0 (B1950.0)
194 * <li> 3 = Heliocentric B1950.0
195 * <li> 4 = Reserved for JPL use (non-GSFC)
196 * <li> 5 = Reserved for JPL use (non-GSFC)
197 * <li> 6 = Geocentric mean of 2000.0 (J2000.0)
198 * <li> 7 = Heliocentric J2000.0
199 * </ul></td>
200 * <td>Integer</td>
201 * <td>Coordinate system</td>
202 * <td>{@link CoordinateSystemTerm}</td>
203 * <tr>
204 * <td>{@code iiii}</td>
205 * <td>0000-9999</td>
206 * <td>Integer</td>
207 * <td>Support Identification Code (SIC)</td>
208 * <td>{@link SupportIdCodeTerm}</td>
209 * <tr>
210 * <td>{@code bb}</td>
211 * <td>00-99</td>
212 * <td>Integer</td>
213 * <td>Vehicle Identification Code (VIC)</td>
214 * <td>{@link VehicleIdCodeTerm}</td>
215 * <tr>
216 * <td>{@code nnn}</td>
217 * <td>000-999</td>
218 * <td>Integer</td>
219 * <td>Sequence number</td>
220 * <td>{@link SequenceNumberTerm}</td>
221 * <tr>
222 * <td>{@code doy}</td>
223 * <td>001-366</td>
224 * <td>Integer</td>
225 * <td>Day of year</td>
226 * <td>{@link DayOfYearTerm}</td>
227 * <tr>
228 * <td>{@code hhmmsssss}</td>
229 * <td>000000000 - 235959999</td>
230 * <td>Integer</td>
231 * <td>Vector epoch (in UTC)<br>HH:mm:ss.SSS</td>
232 * <td>{@link VectorEpochTerm}</td>
233 * <tr>
234 * <td>{@code ccc}</td>
235 * <td>000-999</td>
236 * <td>Integer</td>
237 * <td>Checksum for line 2</td>
238 * <td>{@link CheckSumTerm}</td>
239 * <tr>
240 * <td>{@code <<}</td>
241 * <td>"\r\r"</td>
242 * <td>Constant</td>
243 * <td>Carriage returns</td>
244 * <td>n/a</td>
245 * <tr>
246 * <td>==</td>
247 * <td>"\n\n"</td>
248 * <td>Constant</td>
249 * <td>Line feeds</td>
250 * <td>n/a</td>
251 * <tr>
252 * <th rowspan="7">3</th>
253 * <td>{@code s}</td>
254 * <td>
255 * <ul>
256 * <li> " " (ASCII Space) = positive
257 * <li> "-" = Negative
258 * </ul></td>
259 * <td>Integer</td>
260 * <td>Positive/negative sign</td>
261 * <td>n/a</td>
262 * <tr>
263 * <td>{@code xxxxxxxxxxxx}</td>
264 * <td>0 - 9999999999999</td>
265 * <td>Integer</td>
266 * <td>X component of position (m)</td>
267 * <td>{@link PositionVectorComponentTerm}</td>
268 * <tr>
269 * <td>{@code yyyyyyyyyyyy}</td>
270 * <td>0 - 9999999999999</td>
271 * <td>Integer</td>
272 * <td>Y component of position (m)</td>
273 * <td>{@link PositionVectorComponentTerm}</td>
274 * <tr>
275 * <td>{@code zzzzzzzzzzzz}</td>
276 * <td>0 - 9999999999999</td>
277 * <td>Integer</td>
278 * <td>Z component of position (m)</td>
279 * <td>{@link PositionVectorComponentTerm}</td>
280 * <tr>
281 * <td>{@code ccc}</td>
282 * <td>000-999</td>
283 * <td>Integer</td>
284 * <td>Checksum for line 3</td>
285 * <td>{@link CheckSumTerm}</td>
286 * <tr>
287 * <td>{@code <<}</td>
288 * <td>"\r\r"</td>
289 * <td>Constant</td>
290 * <td>Carriage returns</td>
291 * <td>n/a</td>
292 * <tr>
293 * <td>==</td>
294 * <td>"\n\n"</td>
295 * <td>Constant</td>
296 * <td>Line feeds</td>
297 * <td>n/a</td>
298 * <tr>
299 * <th rowspan="7">4</th>
300 * <td>{@code s}</td>
301 * <td>
302 * <ul>
303 * <li> " " (ASCII Space) = positive
304 * <li> "-" = Negative
305 * </ul></td>
306 * <td>Integer</td>
307 * <td>Positive/negative sign</td>
308 * <td>n/a</td>
309 * <tr>
310 * <td>{@code xxxxxxxxxxxx}</td>
311 * <td>0 - 9999999999.999</td>
312 * <td>Double</td>
313 * <td>X component of velocity (m/s)</td>
314 * <td>{@link VelocityVectorComponentTerm}</td>
315 * <tr>
316 * <td>{@code yyyyyyyyyyyy}</td>
317 * <td>0 - 9999999999.999</td>
318 * <td>Double</td>
319 * <td>Y component of velocity (m/s)</td>
320 * <td>{@link VelocityVectorComponentTerm}</td>
321 * <tr>
322 * <td>{@code zzzzzzzzzzzz}</td>
323 * <td>0 - 9999999999.999</td>
324 * <td>Double</td>
325 * <td>Z component of velocity (m/s)</td>
326 * <td>{@link VelocityVectorComponentTerm}</td>
327 * <tr>
328 * <td>{@code ccc}</td>
329 * <td>000-999</td>
330 * <td>Integer</td>
331 * <td>Checksum for line 4</td>
332 * <td>{@link CheckSumTerm}</td>
333 * <tr>
334 * <td>{@code <<}</td>
335 * <td>"\r\r"</td>
336 * <td>Constant</td>
337 * <td>Carriage returns</td>
338 * <td>n/a</td>
339 * <tr>
340 * <td>==</td>
341 * <td>"\n\n"</td>
342 * <td>Constant</td>
343 * <td>Line feeds</td>
344 * <td>n/a</td>
345 * <tr>
346 * <th rowspan="7">5</th>
347 * <td>{@code mmmmmmmm}</td>
348 * <td>0 - 99999999.9</td>
349 * <td>Double</td>
350 * <td>Spacecraft mass (kg)</td>
351 * <td>{@link MassTerm}</td>
352 * <tr>
353 * <td>{@code aaaaa}</td>
354 * <td>0 - 999.99</td>
355 * <td>Double</td>
356 * <td>Average cross-sectional area (m^2)</td>
357 * <td>{@link CrossSectionalAreaTerm}</td>
358 * <tr>
359 * <td>{@code kkkk}</td>
360 * <td>0 - 99.99</td>
361 * <td>Double</td>
362 * <td>Drag coefficient (dimensionless)</td>
363 * <td>{@link DragCoefficientTerm}</td>
364 * <tr>
365 * <td>{@code srrrrrrr}</td>
366 * <td>-99.99999 to 99.99999</td>
367 * <td>Double</td>
368 * <td>Solar reflectivity coefficient (dimensionless)</td>
369 * <td>{@link SolarReflectivityCoefficientTerm}</td>
370 * <tr>
371 * <td>{@code ccc}</td>
372 * <td>000-999</td>
373 * <td>Integer</td>
374 * <td>Checksum for line 5</td>
375 * <td>{@link CheckSumTerm}</td>
376 * <tr>
377 * <td>{@code <<}</td>
378 * <td>"\r\r"</td>
379 * <td>Constant</td>
380 * <td>Carriage returns</td>
381 * <td>n/a</td>
382 * <tr>
383 * <td>==</td>
384 * <td>"\n\n"</td>
385 * <td>Constant</td>
386 * <td>Line feeds</td>
387 * <td>n/a</td>
388 * <tr>
389 * <th rowspan="5">6</th>
390 * <td>{@code ITERM}</td>
391 * <td>"ITERM"</td>
392 * <td>Constant</td>
393 * <td>End of message</td>
394 * <td>{@link MessageEndConstantTerm}</td>
395 * <tr>
396 * <td>{@code ITERM}</td>
397 * <td>ASCII Space</td>
398 * <td>Constant</td>
399 * <td>Spare (blank) character</td>
400 * <td>{@link SpareConstantTerm}</td>
401 * <tr>
402 * <td>{@code oooo}</td>
403 * <td>"GCQU" or "GAQD"</td>
404 * <td>String</td>
405 * <td>Originator routing indicator</td>
406 * <td>{@link OriginatorRoutingIndicatorTerm}</td>
407 * <tr>
408 * <td>{@code <<}</td>
409 * <td>"\r\r"</td>
410 * <td>Constant</td>
411 * <td>Carriage returns</td>
412 * <td>n/a</td>
413 * <tr>
414 * <td>==</td>
415 * <td>"\n\n"</td>
416 * <td>Constant</td>
417 * <td>Line feeds</td>
418 * <td>n/a</td>
419 * <tr>
420 * <th>7-12</th>
421 * <td colspan="5">Second {@link IIRVVector} in message</td>
422 * <tr>
423 * <th>13-18</th>
424 * <td colspan="5">Third {@link IIRVVector} in message</td>
425 * <tr>
426 * <th>...</th>
427 * <td colspan="5">nth {@link IIRVVector} in message</td>
428 * </tbody>
429 * </table>
430 *
431 * @author Nick LaFarge
432 * @since 13.0
433 */
434 public class IIRVMessage {
435
436 /** List of vectors that comprise the IIRV message. */
437 private final List<IIRVVector> vectors;
438
439 /** Constructor that initializes to an empty list of vectors. */
440 public IIRVMessage() {
441 this.vectors = new ArrayList<>();
442 }
443
444 /**
445 * Constructor from a list of IIRV {@link IIRVVector}s that monotonically increase in both
446 * {@link org.orekit.files.iirv.terms.SequenceNumberTerm} and time ({@link org.orekit.files.iirv.terms.DayOfYearTerm}
447 * and {@link org.orekit.files.iirv.terms.VectorEpochTerm}).
448 *
449 * @param vectors list of sequential {@link IIRVVector}s.
450 */
451 public IIRVMessage(final List<IIRVVector> vectors) {
452 // Perform validation checks
453 validateSequenceNumberIncreasing(vectors);
454 validateStaticValues(vectors);
455
456 this.vectors = vectors;
457 }
458
459 /**
460 * Constructor from a list of IIRV {@link IIRVVector}s that monotonically increase in both
461 * {@link org.orekit.files.iirv.terms.SequenceNumberTerm} and time ({@link org.orekit.files.iirv.terms.DayOfYearTerm}
462 * and {@link org.orekit.files.iirv.terms.VectorEpochTerm}).
463 *
464 * @param vectors list of sequential IIRV vectors.
465 */
466 public IIRVMessage(final IIRVVector... vectors) {
467 this(Arrays.asList(vectors));
468 }
469
470 /**
471 * Copy constructor.
472 *
473 * @param other other {@link IIRVMessage} instance.
474 */
475 public IIRVMessage(final IIRVMessage other) {
476 final List<IIRVVector> copied_vectors = new ArrayList<>();
477 for (IIRVVector v : other.getVectors()) {
478 copied_vectors.add(new IIRVVector(v));
479 }
480 validateSequenceNumberIncreasing(copied_vectors);
481 validateStaticValues(copied_vectors);
482 this.vectors = copied_vectors;
483 }
484
485 @Override
486 public boolean equals(final Object o) {
487 if (this == o) {
488 return true;
489 }
490 if (o == null || getClass() != o.getClass()) {
491 return false;
492 }
493 final IIRVMessage that = (IIRVMessage) o;
494 return Objects.equals(toMessageString(IncludeMessageMetadata.ALL_VECTORS), that.toMessageString(IncludeMessageMetadata.ALL_VECTORS));
495 }
496
497 @Override
498 public int hashCode() {
499 return Objects.hashCode(vectors);
500 }
501
502 /**
503 * Adds an {@link IIRVVector} to the message (see {@link ArrayList#add(Object)}).
504 *
505 * @param v IIRV vector to add to the message
506 */
507 public void add(final IIRVVector v) {
508 if (vectors.isEmpty()) {
509 vectors.add(v);
510 return;
511 }
512
513 // Check that the time and sequence number are increasing
514 final int prevLineNumber = vectors.size() - 1;
515 final IIRVVector prev = vectors.get(prevLineNumber);
516
517 // Verify sequence number is increasing by one
518 if (prev.getSequenceNumber().value() + 1 != v.getSequenceNumber().value()) {
519 throw new OrekitIllegalStateException(OrekitMessages.IIRV_SEQUENCE_NUMBER_MUST_BE_INCREASING_BY_ONE, prevLineNumber, prev.getSequenceNumber().value(), prevLineNumber, v.getSequenceNumber().value());
520 }
521
522 // Ensure the static values are consistent across all the vectors
523 validateStaticValues(vectors);
524
525 this.vectors.add(v);
526 }
527
528 /**
529 * Gets the {@link IIRVVector} located at a given index in the message.
530 *
531 * @param i index of the element to return
532 * @return element at the given index
533 * @see ArrayList#get(int)
534 */
535 public IIRVVector get(final int i) {
536 return vectors.get(i);
537 }
538
539 /**
540 * Returns the number of IIRV vectors contained in the message.
541 *
542 * @return number of IIRV vectors contained in the message
543 * @see ArrayList#size()
544 */
545 public int size() {
546 return vectors.size();
547 }
548
549 /**
550 * Returns true if no vectors exist in the message.
551 *
552 * @return true if no vectors exist in the message
553 * @see ArrayList#isEmpty()
554 */
555 public boolean isEmpty() {
556 return vectors.isEmpty();
557 }
558
559 /**
560 * Converts the {@link IIRVVector}s contained in the message file into a list of their String representations.
561 *
562 * @param includeMessageMetadataSetting Setting for when message metadata terms appear in the created IIRV message
563 * @return list of {@link IIRVVector} strings for each vector the message
564 * @see IIRVVector#toIIRVString
565 */
566 public ArrayList<String> getVectorStrings(final IncludeMessageMetadata includeMessageMetadataSetting) {
567 final ArrayList<String> messageStrings = new ArrayList<>();
568 for (int i = 0; i < vectors.size(); i++) {
569 final boolean includeMessageMetadata;
570 switch (includeMessageMetadataSetting) {
571 case ALL_VECTORS: {
572 includeMessageMetadata = true;
573 break;
574 }
575 case FIRST_VECTOR_ONLY: {
576 includeMessageMetadata = i == 0;
577 break;
578 }
579 default:
580 throw new OrekitInternalError(null);
581 }
582 messageStrings.add(vectors.get(i).toIIRVString(includeMessageMetadata));
583 }
584
585 return messageStrings;
586 }
587
588 /**
589 * Converts the {@link IIRVVector}s contained in the message file into a single String, where no deliminator
590 * included between each vector (the vectors already have trailing line carriage and line returns).
591 *
592 * @param includeMessageMetadataSetting Setting for when message metadata terms appear in the created IIRV message
593 * @return String containing all {@link IIRVVector}s for the IIRV message
594 * @see IIRVVector#toIIRVString
595 */
596 public String toMessageString(final IncludeMessageMetadata includeMessageMetadataSetting) {
597 return String.join("", getVectorStrings(includeMessageMetadataSetting));
598 }
599
600 /**
601 * Gets the list of sequential {@link IIRVVector} instances contained within the overall IIRV message.
602 *
603 * @return list of sequential {@link IIRVVector} instances contained within the overall IIRV message.
604 */
605 public List<IIRVVector> getVectors() {
606 return vectors;
607 }
608
609 /**
610 * Validates that values that are expected to remain constant do not change across a series of inputted
611 * IIRV vectors.
612 *
613 * @param iirvVectors List of {@link IIRVVector} instances to validate.
614 */
615 private void validateStaticValues(final List<IIRVVector> iirvVectors) {
616
617 // Check thatM select values are consistent across entire vector
618 final IIRVVector firstIIRV = iirvVectors.get(0);
619 for (int i = 1; i < iirvVectors.size(); i++) {
620 final IIRVVector iirv = iirvVectors.get(i);
621
622 // Check that terms you expect to remain constant, do remain constant
623 if (!firstIIRV.getMessageID().equals(iirv.getMessageID())) {
624 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Message ID");
625 } else if (!firstIIRV.getMessageClass().equals(iirv.getMessageClass())) {
626 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Message class");
627 } else if (!firstIIRV.getOriginIdentification().equals(iirv.getOriginIdentification())) {
628 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Origin ID");
629 } else if (!firstIIRV.getRoutingIndicator().equals(iirv.getRoutingIndicator())) {
630 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Routing indicator");
631 } else if (!firstIIRV.getVectorType().equals(iirv.getVectorType())) {
632 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Vector type");
633 } else if (!firstIIRV.getDataSource().equals(iirv.getDataSource())) {
634 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Data source");
635 } else if (!firstIIRV.getCoordinateSystem().equals(iirv.getCoordinateSystem())) {
636 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Coordinate system");
637 } else if (!firstIIRV.getSupportIdCode().equals(iirv.getSupportIdCode())) {
638 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Support ID code (SIC)");
639 } else if (!firstIIRV.getVehicleIdCode().equals(iirv.getVehicleIdCode())) {
640 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Vehicle ID code (VID)");
641 }
642 }
643 }
644
645 /**
646 * Returns the satellite ID (set to the value of the {@link org.orekit.files.iirv.terms.VehicleIdCodeTerm}).
647 *
648 * @return the satellite ID
649 * @see org.orekit.files.iirv.terms.VehicleIdCodeTerm
650 */
651 public String getSatelliteID() {
652 return vectors.get(0).getVehicleIdCode().toEncodedString();
653 }
654
655 /**
656 * Validates that the sequence number increases by one for each element in a series of {@link IIRVVector}s.
657 *
658 * @param iirvVectors List of {@link IIRVVector} instances to validate.
659 */
660 private void validateSequenceNumberIncreasing(final List<IIRVVector> iirvVectors) {
661 if (iirvVectors.size() < 2) {
662 return;
663 }
664
665 // Check that sequence number increases by 1 each time
666 for (int i = 1; i < iirvVectors.size(); i++) {
667 final IIRVVector current = iirvVectors.get(i);
668 final IIRVVector prev = iirvVectors.get(i - 1);
669 if (current.getSequenceNumber().value() - prev.getSequenceNumber().value() != 1) {
670 throw new OrekitIllegalStateException(OrekitMessages.IIRV_SEQUENCE_NUMBER_MUST_BE_INCREASING_BY_ONE, i - 1, prev.getSequenceNumber().value(), current.getSequenceNumber().value());
671 }
672 }
673 }
674
675 /**
676 * Options for how message metadata appears in the IIRV message file.
677 * <p>
678 * Message metadata fields refer to the first four terms defined for an IIRV vector:
679 * <ul>
680 * <li>{@link MessageTypeTerm}</li>
681 * <li>{@link org.orekit.files.iirv.terms.MessageIDTerm}</li>
682 * <li>{@link MessageSourceTerm}</li>
683 * <li>{@link org.orekit.files.iirv.terms.MessageClassTerm}</li>
684 * </ul>
685 *
686 * @author Nick LaFarge
687 * @since 13.0
688 */
689 public enum IncludeMessageMetadata {
690 /**
691 * Include message metadata fields in the first line of the first vector
692 * (when {@link org.orekit.files.iirv.terms.SequenceNumberTerm} is 0), and omit for all other vectors
693 * in a given IIRV message file.
694 */
695 FIRST_VECTOR_ONLY,
696
697 /** Include message metadata fields from all vectors in a given IIRV message file. */
698 ALL_VECTORS
699 }
700
701 }