IIRVMessage.java

  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. import org.orekit.errors.OrekitIllegalStateException;
  19. import org.orekit.errors.OrekitInternalError;
  20. import org.orekit.errors.OrekitMessages;
  21. import org.orekit.files.iirv.terms.CheckSumTerm;
  22. import org.orekit.files.iirv.terms.CoordinateSystemTerm;
  23. import org.orekit.files.iirv.terms.CrossSectionalAreaTerm;
  24. import org.orekit.files.iirv.terms.DataSourceTerm;
  25. import org.orekit.files.iirv.terms.DayOfYearTerm;
  26. import org.orekit.files.iirv.terms.DragCoefficientTerm;
  27. import org.orekit.files.iirv.terms.MassTerm;
  28. import org.orekit.files.iirv.terms.MessageClassTerm;
  29. import org.orekit.files.iirv.terms.MessageEndConstantTerm;
  30. import org.orekit.files.iirv.terms.MessageIDTerm;
  31. import org.orekit.files.iirv.terms.MessageSourceTerm;
  32. import org.orekit.files.iirv.terms.MessageStartConstantTerm;
  33. import org.orekit.files.iirv.terms.MessageTypeTerm;
  34. import org.orekit.files.iirv.terms.OriginIdentificationTerm;
  35. import org.orekit.files.iirv.terms.OriginatorRoutingIndicatorTerm;
  36. import org.orekit.files.iirv.terms.PositionVectorComponentTerm;
  37. import org.orekit.files.iirv.terms.RoutingIndicatorTerm;
  38. import org.orekit.files.iirv.terms.SequenceNumberTerm;
  39. import org.orekit.files.iirv.terms.SolarReflectivityCoefficientTerm;
  40. import org.orekit.files.iirv.terms.SpareConstantTerm;
  41. import org.orekit.files.iirv.terms.SupportIdCodeTerm;
  42. import org.orekit.files.iirv.terms.VectorEpochTerm;
  43. import org.orekit.files.iirv.terms.VectorTypeTerm;
  44. import org.orekit.files.iirv.terms.VehicleIdCodeTerm;
  45. import org.orekit.files.iirv.terms.VelocityVectorComponentTerm;

  46. import java.util.ArrayList;
  47. import java.util.Arrays;
  48. import java.util.List;
  49. import java.util.Objects;

  50. /**
  51.  * Container for Improved Interrange Vector (IIRV) messages, implemented as a list of sequential {@link IIRVVector}
  52.  * instances.
  53.  * <p>
  54.  * The IIRV message consists of a series of sequential {@link IIRVVector}s that each contains ephemeris state data
  55.  * at a particular epoch. The message body is defined as:<p>
  56.  * {@code ttuuuuuuuqjjGIIRVarrrr<<≡≡}<br>
  57.  * {@code vs1ciiiibbnnndoyhhmmsssssccc<<≡≡}<br>
  58.  * {@code sxxxxxxxxxxxxsyyyyyyyyyyyyszzzzzzzzzzzzccc<<==}<br>
  59.  * {@code sxxxxxxxxxxxxsyyyyyyyyyyyyszzzzzzzzzzzzccc<<==}<br>
  60.  * {@code mmmmmmmmaaaaakkkksrrrrrrrccc<<==}<br>
  61.  * {@code ITERM oooo<<==}
  62.  * <table border="1">
  63.  *    <caption>Line No. / Characters / Value / Type / Description / Class</caption>
  64.  *    <tbody>
  65.  *        <tr>
  66.  *            <th rowspan="9">1</th>
  67.  *            <td>{@code tt}</td>
  68.  *            <td>2 characters</td>
  69.  *            <td>Constant</td>
  70.  *            <td>Message Type (Operations Data Message)</td>
  71.  *            <td>{@link MessageTypeTerm}</td>
  72.  *        <tr>
  73.  *            <td>{@code uuuuuuu}</td>
  74.  *            <td>0000000 to 9999999</td>
  75.  *            <td>Integer</td>
  76.  *            <td>Message ID</td>
  77.  *            <td>{@link MessageIDTerm}</td>
  78.  *        <tr>
  79.  *            <td>{@code q}</td>
  80.  *            <td>1 character</td>
  81.  *            <td>String</td>
  82.  *            <td>Message Source</td>
  83.  *            <td>{@link MessageSourceTerm}</td>
  84.  *        <tr>
  85.  *            <td>{@code jj}</td>
  86.  *            <td>
  87.  *                <ul>
  88.  *                <li> 10 = Nominal
  89.  *                <li> 15 = In-flight Update
  90.  *                </ul></td>
  91.  *            <td>String</td>
  92.  *            <td>Message class (10=nominal)</td>
  93.  *            <td>{@link MessageClassTerm}</td>
  94.  *        <tr>
  95.  *            <td>{@code GIIRV}</td>
  96.  *            <td>"GIIRV"</td>
  97.  *            <td>Constant</td>
  98.  *            <td>Message ID</td>
  99.  *            <td>{@link MessageStartConstantTerm}</td>
  100.  *        <tr>
  101.  *            <td>{@code a}</td>
  102.  *            <td>
  103.  *                <ul>
  104.  *                <li> ASCII space  = GSFC
  105.  *                <li> Z            = WLP
  106.  *                <li> E            = ETR
  107.  *                <li> L            = JPL
  108.  *                <li> W            = WTR
  109.  *                <li> J            = JSC
  110.  *                <li> P            = PMR
  111.  *                <li> A            = CSTC
  112.  *                <li> K            = KMR
  113.  *                <li> C            = CNES
  114.  *                </ul></td>
  115.  *            <td>String</td>
  116.  *            <td>Origin identification</td>
  117.  *            <td>{@link OriginIdentificationTerm}</td>
  118.  *        <tr>
  119.  *            <td>{@code rrrr}</td>
  120.  *            <td>
  121.  *                <ul>
  122.  *                <li>GSFC    = NASA Goddard Space Flight Center
  123.  *                <li>WLP     = Wallops Island tracking radars
  124.  *                <li>ETR     = NASA/USFC Eastern Test Range
  125.  *                <li>JPL     = NASA Jet Propulsion Laboratory
  126.  *                <li>WTR     = NASA/USFC Western Test Range
  127.  *                <li>JSC     = NASA Johnson Space Center
  128.  *                <li>PMR     = Navy Pacific Missile Range
  129.  *                <li>CSTC    = Air Force Satellite Control Facility
  130.  *                <li>KMR     = Army Kwajalein Missile Range
  131.  *                <li>CNES    = French Space Agency National <br>Centre for Space Studies (CNES)
  132.  *                <li>MANY    = Message originated from more <br>than one of the above stations
  133.  *                </ul></td>
  134.  *            <td>String</td>
  135.  *            <td>Destination routing indicator</td>
  136.  *            <td>{@link RoutingIndicatorTerm}</td>
  137.  *        <tr>
  138.  *            <td>{@code <<}</td>
  139.  *            <td>"\r\r"</td>
  140.  *            <td>Constant</td>
  141.  *            <td>Carriage returns</td>
  142.  *            <td>n/a</td>
  143.  *        <tr>
  144.  *            <td>==</td>
  145.  *            <td>"\n\n"</td>
  146.  *            <td>Constant</td>
  147.  *            <td>Line feeds</td>
  148.  *            <td>n/a</td>
  149.  *        <tr>
  150.  *            <th rowspan="12">2</th>
  151.  *            <td>{@code v}</td>
  152.  *            <td>
  153.  *                <ul>
  154.  *                <li> 1 = Free flight (routine on-orbit)
  155.  *                <li> 2 = Forced (special orbit update)
  156.  *                <li> 3 = Spare
  157.  *                <li> 4 = Maneuver ignition
  158.  *                <li> 5 = Maneuver cutoff
  159.  *                <li> 6 = Reentry
  160.  *                <li> 7 = Powered flight
  161.  *                <li> 8 = Stationary
  162.  *                <li> 9 = Spare
  163.  *                </ul></td>
  164.  *            <td>Integer</td>
  165.  *            <td>Vector type</td>
  166.  *            <td>{@link VectorTypeTerm}</td>
  167.  *        <tr>
  168.  *            <td>{@code s}</td>
  169.  *            <td>
  170.  *                <ul>
  171.  *                <li> 1 = Nominal/planning
  172.  *                <li> 2 = Real-time
  173.  *                <li> 3 = Off-line
  174.  *                <li> 4 = Off-line/mean
  175.  *                </ul></td>
  176.  *            <td>Integer</td>
  177.  *            <td>Source of data</td>
  178.  *            <td>{@link DataSourceTerm}</td>
  179.  *        <tr>
  180.  *            <td>{@code 1}</td>
  181.  *            <td>"1" = interrange message</td>
  182.  *            <td>Constant</td>
  183.  *            <td>Transfer type</td>
  184.  *            <td>{@link org.orekit.files.iirv.terms.TransferTypeConstantTerm}</td>
  185.  *        <tr>
  186.  *            <td>{@code c}</td>
  187.  *            <td>
  188.  *                <ul>
  189.  *                <li> 1 = Geocentric True-of-Date Rotating
  190.  *                <li> 2 = Geocentric mean of 1950.0 (B1950.0)
  191.  *                <li> 3 = Heliocentric B1950.0
  192.  *                <li> 4 = Reserved for JPL use (non-GSFC)
  193.  *                <li> 5 = Reserved for JPL use (non-GSFC)
  194.  *                <li> 6 = Geocentric mean of 2000.0 (J2000.0)
  195.  *                <li> 7 = Heliocentric J2000.0
  196.  *                </ul></td>
  197.  *            <td>Integer</td>
  198.  *            <td>Coordinate system</td>
  199.  *            <td>{@link CoordinateSystemTerm}</td>
  200.  *        <tr>
  201.  *            <td>{@code iiii}</td>
  202.  *            <td>0000-9999</td>
  203.  *            <td>Integer</td>
  204.  *            <td>Support Identification Code (SIC)</td>
  205.  *            <td>{@link SupportIdCodeTerm}</td>
  206.  *        <tr>
  207.  *            <td>{@code bb}</td>
  208.  *            <td>00-99</td>
  209.  *            <td>Integer</td>
  210.  *            <td>Vehicle Identification Code (VIC)</td>
  211.  *            <td>{@link VehicleIdCodeTerm}</td>
  212.  *        <tr>
  213.  *            <td>{@code nnn}</td>
  214.  *            <td>000-999</td>
  215.  *            <td>Integer</td>
  216.  *            <td>Sequence number</td>
  217.  *            <td>{@link SequenceNumberTerm}</td>
  218.  *        <tr>
  219.  *            <td>{@code doy}</td>
  220.  *            <td>001-366</td>
  221.  *            <td>Integer</td>
  222.  *            <td>Day of year</td>
  223.  *            <td>{@link DayOfYearTerm}</td>
  224.  *        <tr>
  225.  *            <td>{@code hhmmsssss}</td>
  226.  *            <td>000000000 - 235959999</td>
  227.  *            <td>Integer</td>
  228.  *            <td>Vector epoch (in UTC)<br>HH:mm:ss.SSS</td>
  229.  *            <td>{@link VectorEpochTerm}</td>
  230.  *        <tr>
  231.  *            <td>{@code ccc}</td>
  232.  *            <td>000-999</td>
  233.  *            <td>Integer</td>
  234.  *            <td>Checksum for line 2</td>
  235.  *            <td>{@link CheckSumTerm}</td>
  236.  *        <tr>
  237.  *            <td>{@code <<}</td>
  238.  *            <td>"\r\r"</td>
  239.  *            <td>Constant</td>
  240.  *            <td>Carriage returns</td>
  241.  *            <td>n/a</td>
  242.  *        <tr>
  243.  *            <td>==</td>
  244.  *            <td>"\n\n"</td>
  245.  *            <td>Constant</td>
  246.  *            <td>Line feeds</td>
  247.  *            <td>n/a</td>
  248.  *        <tr>
  249.  *            <th rowspan="7">3</th>
  250.  *            <td>{@code s}</td>
  251.  *            <td>
  252.  *                <ul>
  253.  *                <li> " " (ASCII Space) = positive
  254.  *                <li> "-" = Negative
  255.  *                </ul></td>
  256.  *            <td>Integer</td>
  257.  *            <td>Positive/negative sign</td>
  258.  *            <td>n/a</td>
  259.  *        <tr>
  260.  *            <td>{@code xxxxxxxxxxxx}</td>
  261.  *            <td>0 - 9999999999999</td>
  262.  *            <td>Integer</td>
  263.  *            <td>X component of position (m)</td>
  264.  *            <td>{@link PositionVectorComponentTerm}</td>
  265.  *        <tr>
  266.  *            <td>{@code yyyyyyyyyyyy}</td>
  267.  *            <td>0 - 9999999999999</td>
  268.  *            <td>Integer</td>
  269.  *            <td>Y component of position (m)</td>
  270.  *            <td>{@link PositionVectorComponentTerm}</td>
  271.  *        <tr>
  272.  *            <td>{@code zzzzzzzzzzzz}</td>
  273.  *            <td>0 - 9999999999999</td>
  274.  *            <td>Integer</td>
  275.  *            <td>Z component of position (m)</td>
  276.  *            <td>{@link PositionVectorComponentTerm}</td>
  277.  *        <tr>
  278.  *            <td>{@code ccc}</td>
  279.  *            <td>000-999</td>
  280.  *            <td>Integer</td>
  281.  *            <td>Checksum for line 3</td>
  282.  *            <td>{@link CheckSumTerm}</td>
  283.  *        <tr>
  284.  *            <td>{@code <<}</td>
  285.  *            <td>"\r\r"</td>
  286.  *            <td>Constant</td>
  287.  *            <td>Carriage returns</td>
  288.  *            <td>n/a</td>
  289.  *        <tr>
  290.  *            <td>==</td>
  291.  *            <td>"\n\n"</td>
  292.  *            <td>Constant</td>
  293.  *            <td>Line feeds</td>
  294.  *            <td>n/a</td>
  295.  *        <tr>
  296.  *            <th rowspan="7">4</th>
  297.  *            <td>{@code s}</td>
  298.  *            <td>
  299.  *                <ul>
  300.  *                <li> " " (ASCII Space) = positive
  301.  *                <li> "-" = Negative
  302.  *                </ul></td>
  303.  *            <td>Integer</td>
  304.  *            <td>Positive/negative sign</td>
  305.  *            <td>n/a</td>
  306.  *        <tr>
  307.  *            <td>{@code xxxxxxxxxxxx}</td>
  308.  *            <td>0 - 9999999999.999</td>
  309.  *            <td>Double</td>
  310.  *            <td>X component of velocity (m/s)</td>
  311.  *            <td>{@link VelocityVectorComponentTerm}</td>
  312.  *        <tr>
  313.  *            <td>{@code yyyyyyyyyyyy}</td>
  314.  *            <td>0 - 9999999999.999</td>
  315.  *            <td>Double</td>
  316.  *            <td>Y component of velocity (m/s)</td>
  317.  *            <td>{@link VelocityVectorComponentTerm}</td>
  318.  *        <tr>
  319.  *            <td>{@code zzzzzzzzzzzz}</td>
  320.  *            <td>0 - 9999999999.999</td>
  321.  *            <td>Double</td>
  322.  *            <td>Z component of velocity (m/s)</td>
  323.  *            <td>{@link VelocityVectorComponentTerm}</td>
  324.  *        <tr>
  325.  *            <td>{@code ccc}</td>
  326.  *            <td>000-999</td>
  327.  *            <td>Integer</td>
  328.  *            <td>Checksum for line 4</td>
  329.  *            <td>{@link CheckSumTerm}</td>
  330.  *        <tr>
  331.  *            <td>{@code <<}</td>
  332.  *            <td>"\r\r"</td>
  333.  *            <td>Constant</td>
  334.  *            <td>Carriage returns</td>
  335.  *            <td>n/a</td>
  336.  *        <tr>
  337.  *            <td>==</td>
  338.  *            <td>"\n\n"</td>
  339.  *            <td>Constant</td>
  340.  *            <td>Line feeds</td>
  341.  *            <td>n/a</td>
  342.  *        <tr>
  343.  *            <th rowspan="7">5</th>
  344.  *            <td>{@code mmmmmmmm}</td>
  345.  *            <td>0 - 99999999.9</td>
  346.  *            <td>Double</td>
  347.  *            <td>Spacecraft mass (kg)</td>
  348.  *            <td>{@link MassTerm}</td>
  349.  *        <tr>
  350.  *            <td>{@code aaaaa}</td>
  351.  *            <td>0 - 999.99</td>
  352.  *            <td>Double</td>
  353.  *            <td>Average cross-sectional area (m^2)</td>
  354.  *            <td>{@link CrossSectionalAreaTerm}</td>
  355.  *        <tr>
  356.  *            <td>{@code kkkk}</td>
  357.  *            <td>0 - 99.99</td>
  358.  *            <td>Double</td>
  359.  *            <td>Drag coefficient (dimensionless)</td>
  360.  *            <td>{@link DragCoefficientTerm}</td>
  361.  *        <tr>
  362.  *            <td>{@code srrrrrrr}</td>
  363.  *            <td>-99.99999 to 99.99999</td>
  364.  *            <td>Double</td>
  365.  *            <td>Solar reflectivity coefficient (dimensionless)</td>
  366.  *            <td>{@link SolarReflectivityCoefficientTerm}</td>
  367.  *        <tr>
  368.  *            <td>{@code ccc}</td>
  369.  *            <td>000-999</td>
  370.  *            <td>Integer</td>
  371.  *            <td>Checksum for line 5</td>
  372.  *            <td>{@link CheckSumTerm}</td>
  373.  *        <tr>
  374.  *            <td>{@code <<}</td>
  375.  *            <td>"\r\r"</td>
  376.  *            <td>Constant</td>
  377.  *            <td>Carriage returns</td>
  378.  *            <td>n/a</td>
  379.  *        <tr>
  380.  *            <td>==</td>
  381.  *            <td>"\n\n"</td>
  382.  *            <td>Constant</td>
  383.  *            <td>Line feeds</td>
  384.  *            <td>n/a</td>
  385.  *        <tr>
  386.  *            <th rowspan="5">6</th>
  387.  *            <td>{@code ITERM}</td>
  388.  *            <td>"ITERM"</td>
  389.  *            <td>Constant</td>
  390.  *            <td>End of message</td>
  391.  *            <td>{@link MessageEndConstantTerm}</td>
  392.  *        <tr>
  393.  *            <td>{@code ITERM}</td>
  394.  *            <td>ASCII Space</td>
  395.  *            <td>Constant</td>
  396.  *            <td>Spare (blank) character</td>
  397.  *            <td>{@link SpareConstantTerm}</td>
  398.  *        <tr>
  399.  *            <td>{@code oooo}</td>
  400.  *            <td>"GCQU" or "GAQD"</td>
  401.  *            <td>String</td>
  402.  *            <td>Originator routing indicator</td>
  403.  *            <td>{@link OriginatorRoutingIndicatorTerm}</td>
  404.  *        <tr>
  405.  *            <td>{@code <<}</td>
  406.  *            <td>"\r\r"</td>
  407.  *            <td>Constant</td>
  408.  *            <td>Carriage returns</td>
  409.  *            <td>n/a</td>
  410.  *        <tr>
  411.  *            <td>==</td>
  412.  *            <td>"\n\n"</td>
  413.  *            <td>Constant</td>
  414.  *            <td>Line feeds</td>
  415.  *            <td>n/a</td>
  416.  *        <tr>
  417.  *            <th>7-12</th>
  418.  *            <td colspan="5">Second {@link IIRVVector} in message</td>
  419.  *        <tr>
  420.  *            <th>13-18</th>
  421.  *            <td colspan="5">Third {@link IIRVVector} in message</td>
  422.  *        <tr>
  423.  *            <th>...</th>
  424.  *            <td colspan="5">nth {@link IIRVVector} in message</td>
  425.  *    </tbody>
  426.  * </table>
  427.  *
  428.  * @author Nick LaFarge
  429.  * @since 13.0
  430.  */
  431. public class IIRVMessage {

  432.     /** List of vectors that comprise the IIRV message. */
  433.     private final List<IIRVVector> vectors;

  434.     /** Constructor that initializes to an empty list of vectors. */
  435.     public IIRVMessage() {
  436.         this.vectors = new ArrayList<>();
  437.     }

  438.     /**
  439.      * Constructor from a list of IIRV {@link IIRVVector}s that monotonically increase in both
  440.      * {@link org.orekit.files.iirv.terms.SequenceNumberTerm} and time ({@link org.orekit.files.iirv.terms.DayOfYearTerm}
  441.      * and {@link org.orekit.files.iirv.terms.VectorEpochTerm}).
  442.      *
  443.      * @param vectors list of sequential {@link IIRVVector}s.
  444.      */
  445.     public IIRVMessage(final List<IIRVVector> vectors) {
  446.         // Perform validation checks
  447.         validateSequenceNumberIncreasing(vectors);
  448.         validateStaticValues(vectors);

  449.         this.vectors = vectors;
  450.     }

  451.     /**
  452.      * Constructor from a list of IIRV {@link IIRVVector}s that monotonically increase in both
  453.      * {@link org.orekit.files.iirv.terms.SequenceNumberTerm} and time ({@link org.orekit.files.iirv.terms.DayOfYearTerm}
  454.      * and {@link org.orekit.files.iirv.terms.VectorEpochTerm}).
  455.      *
  456.      * @param vectors list of sequential IIRV vectors.
  457.      */
  458.     public IIRVMessage(final IIRVVector... vectors) {
  459.         this(Arrays.asList(vectors));
  460.     }

  461.     /**
  462.      * Copy constructor.
  463.      *
  464.      * @param other other {@link IIRVMessage} instance.
  465.      */
  466.     public IIRVMessage(final IIRVMessage other) {
  467.         final List<IIRVVector> copied_vectors = new ArrayList<>();
  468.         for (IIRVVector v : other.getVectors()) {
  469.             copied_vectors.add(new IIRVVector(v));
  470.         }
  471.         validateSequenceNumberIncreasing(copied_vectors);
  472.         validateStaticValues(copied_vectors);
  473.         this.vectors = copied_vectors;
  474.     }

  475.     @Override
  476.     public boolean equals(final Object o) {
  477.         if (this == o) {
  478.             return true;
  479.         }
  480.         if (o == null || getClass() != o.getClass()) {
  481.             return false;
  482.         }
  483.         final IIRVMessage that = (IIRVMessage) o;
  484.         return Objects.equals(toMessageString(IncludeMessageMetadata.ALL_VECTORS), that.toMessageString(IncludeMessageMetadata.ALL_VECTORS));
  485.     }

  486.     @Override
  487.     public int hashCode() {
  488.         return Objects.hashCode(vectors);
  489.     }

  490.     /**
  491.      * Adds an {@link IIRVVector} to the message (see {@link ArrayList#add(Object)}).
  492.      *
  493.      * @param v IIRV vector to add to the message
  494.      */
  495.     public void add(final IIRVVector v) {
  496.         if (vectors.isEmpty()) {
  497.             vectors.add(v);
  498.             return;
  499.         }

  500.         // Check that the time and sequence number are increasing
  501.         final int prevLineNumber = vectors.size() - 1;
  502.         final IIRVVector prev = vectors.get(prevLineNumber);

  503.         // Verify sequence number is increasing by one
  504.         if (prev.getSequenceNumber().value() + 1 != v.getSequenceNumber().value()) {
  505.             throw new OrekitIllegalStateException(OrekitMessages.IIRV_SEQUENCE_NUMBER_MUST_BE_INCREASING_BY_ONE, prevLineNumber, prev.getSequenceNumber().value(), prevLineNumber, v.getSequenceNumber().value());
  506.         }

  507.         // Ensure the static values are consistent across all the vectors
  508.         validateStaticValues(vectors);

  509.         this.vectors.add(v);
  510.     }

  511.     /**
  512.      * Gets the {@link IIRVVector} located at a given index in the message.
  513.      *
  514.      * @param i index of the element to return
  515.      * @return element at the given index
  516.      * @see ArrayList#get(int)
  517.      */
  518.     public IIRVVector get(final int i) {
  519.         return vectors.get(i);
  520.     }

  521.     /**
  522.      * Returns the number of IIRV vectors contained in the message.
  523.      *
  524.      * @return number of IIRV vectors contained in the message
  525.      * @see ArrayList#size()
  526.      */
  527.     public int size() {
  528.         return vectors.size();
  529.     }

  530.     /**
  531.      * Returns true if no vectors exist in the message.
  532.      *
  533.      * @return true if no vectors exist in the message
  534.      * @see ArrayList#isEmpty()
  535.      */
  536.     public boolean isEmpty() {
  537.         return vectors.isEmpty();
  538.     }

  539.     /**
  540.      * Converts the {@link IIRVVector}s contained in the message file into a list of their String representations.
  541.      *
  542.      * @param includeMessageMetadataSetting Setting for when message metadata terms appear in the created IIRV message
  543.      * @return list of {@link IIRVVector} strings for each vector the message
  544.      * @see IIRVVector#toIIRVString
  545.      */
  546.     public ArrayList<String> getVectorStrings(final IncludeMessageMetadata includeMessageMetadataSetting) {
  547.         final ArrayList<String> messageStrings = new ArrayList<>();
  548.         for (int i = 0; i < vectors.size(); i++) {
  549.             final boolean includeMessageMetadata;
  550.             switch (includeMessageMetadataSetting) {
  551.                 case ALL_VECTORS: {
  552.                     includeMessageMetadata = true;
  553.                     break;
  554.                 }
  555.                 case FIRST_VECTOR_ONLY: {
  556.                     includeMessageMetadata = i == 0;
  557.                     break;
  558.                 }
  559.                 default:
  560.                     throw new OrekitInternalError(null);
  561.             }
  562.             messageStrings.add(vectors.get(i).toIIRVString(includeMessageMetadata));
  563.         }

  564.         return messageStrings;
  565.     }

  566.     /**
  567.      * Converts the {@link IIRVVector}s contained in the message file into a single String, where no deliminator
  568.      * included between each vector (the vectors already have trailing line carriage and line returns).
  569.      *
  570.      * @param includeMessageMetadataSetting Setting for when message metadata terms appear in the created IIRV message
  571.      * @return String containing all {@link IIRVVector}s for the IIRV message
  572.      * @see IIRVVector#toIIRVString
  573.      */
  574.     public String toMessageString(final IncludeMessageMetadata includeMessageMetadataSetting) {
  575.         return String.join("", getVectorStrings(includeMessageMetadataSetting));
  576.     }

  577.     /**
  578.      * Gets the list of sequential {@link IIRVVector} instances contained within the overall IIRV message.
  579.      *
  580.      * @return list of sequential {@link IIRVVector} instances contained within the overall IIRV message.
  581.      */
  582.     public List<IIRVVector> getVectors() {
  583.         return vectors;
  584.     }

  585.     /**
  586.      * Validates that values that are expected to remain constant do not change across a series of inputted
  587.      * IIRV vectors.
  588.      *
  589.      * @param iirvVectors List of {@link IIRVVector} instances to validate.
  590.      */
  591.     private void validateStaticValues(final List<IIRVVector> iirvVectors) {

  592.         // Check thatM select values are consistent across entire vector
  593.         final IIRVVector firstIIRV = iirvVectors.get(0);
  594.         for (int i = 1; i < iirvVectors.size(); i++) {
  595.             final IIRVVector iirv = iirvVectors.get(i);

  596.             // Check that terms you expect to remain constant, do remain constant
  597.             if (!firstIIRV.getMessageID().equals(iirv.getMessageID())) {
  598.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Message ID");
  599.             } else if (!firstIIRV.getMessageClass().equals(iirv.getMessageClass())) {
  600.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Message class");
  601.             } else if (!firstIIRV.getOriginIdentification().equals(iirv.getOriginIdentification())) {
  602.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Origin ID");
  603.             } else if (!firstIIRV.getRoutingIndicator().equals(iirv.getRoutingIndicator())) {
  604.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Routing indicator");
  605.             } else if (!firstIIRV.getVectorType().equals(iirv.getVectorType())) {
  606.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Vector type");
  607.             } else if (!firstIIRV.getDataSource().equals(iirv.getDataSource())) {
  608.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Data source");
  609.             } else if (!firstIIRV.getCoordinateSystem().equals(iirv.getCoordinateSystem())) {
  610.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Coordinate system");
  611.             } else if (!firstIIRV.getSupportIdCode().equals(iirv.getSupportIdCode())) {
  612.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Support ID code (SIC)");
  613.             } else if (!firstIIRV.getVehicleIdCode().equals(iirv.getVehicleIdCode())) {
  614.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_TERM_CHANGES_WITHIN_FILE, "Vehicle ID code (VID)");
  615.             }
  616.         }
  617.     }

  618.     /**
  619.      * Returns the satellite ID (set to the value of the {@link org.orekit.files.iirv.terms.VehicleIdCodeTerm}).
  620.      *
  621.      * @return the satellite ID
  622.      * @see org.orekit.files.iirv.terms.VehicleIdCodeTerm
  623.      */
  624.     public String getSatelliteID() {
  625.         return vectors.get(0).getVehicleIdCode().toEncodedString();
  626.     }

  627.     /**
  628.      * Validates that the sequence number increases by one for each element in a series of {@link IIRVVector}s.
  629.      *
  630.      * @param iirvVectors List of {@link IIRVVector} instances to validate.
  631.      */
  632.     private void validateSequenceNumberIncreasing(final List<IIRVVector> iirvVectors) {
  633.         if (iirvVectors.size() < 2) {
  634.             return;
  635.         }

  636.         // Check that sequence number increases by 1 each time
  637.         for (int i = 1; i < iirvVectors.size(); i++) {
  638.             final IIRVVector current = iirvVectors.get(i);
  639.             final IIRVVector prev = iirvVectors.get(i - 1);
  640.             if (current.getSequenceNumber().value() - prev.getSequenceNumber().value() != 1) {
  641.                 throw new OrekitIllegalStateException(OrekitMessages.IIRV_SEQUENCE_NUMBER_MUST_BE_INCREASING_BY_ONE, i - 1, prev.getSequenceNumber().value(), current.getSequenceNumber().value());
  642.             }
  643.         }
  644.     }

  645.     /**
  646.      * Options for how message metadata appears in the IIRV message file.
  647.      * <p>
  648.      * Message metadata fields refer to the first four terms defined for an IIRV vector:
  649.      * <ul>
  650.      *     <li>{@link MessageTypeTerm}</li>
  651.      *     <li>{@link org.orekit.files.iirv.terms.MessageIDTerm}</li>
  652.      *     <li>{@link MessageSourceTerm}</li>
  653.      *     <li>{@link org.orekit.files.iirv.terms.MessageClassTerm}</li>
  654.      * </ul>
  655.      *
  656.      * @author Nick LaFarge
  657.      * @since 13.0
  658.      */
  659.     public enum IncludeMessageMetadata {
  660.         /**
  661.          * Include message metadata fields in the first line of the first vector
  662.          * (when {@link org.orekit.files.iirv.terms.SequenceNumberTerm} is 0), and omit for all other vectors
  663.          * in a given IIRV message file.
  664.          */
  665.         FIRST_VECTOR_ONLY,

  666.         /** Include message metadata fields from all vectors in a given IIRV message file. */
  667.         ALL_VECTORS
  668.     }

  669. }