IIRVVector.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.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.orekit.annotation.DefaultDataContext;
  20. import org.orekit.data.DataContext;
  21. import org.orekit.errors.OrekitIllegalArgumentException;
  22. import org.orekit.errors.OrekitInternalError;
  23. import org.orekit.errors.OrekitMessages;
  24. import org.orekit.files.iirv.terms.CheckSumTerm;
  25. import org.orekit.files.iirv.terms.CoordinateSystemTerm;
  26. import org.orekit.files.iirv.terms.CrossSectionalAreaTerm;
  27. import org.orekit.files.iirv.terms.DataSourceTerm;
  28. import org.orekit.files.iirv.terms.DayOfYearTerm;
  29. import org.orekit.files.iirv.terms.DragCoefficientTerm;
  30. import org.orekit.files.iirv.terms.IIRVTermUtils;
  31. import org.orekit.files.iirv.terms.MassTerm;
  32. import org.orekit.files.iirv.terms.MessageClassTerm;
  33. import org.orekit.files.iirv.terms.MessageEndConstantTerm;
  34. import org.orekit.files.iirv.terms.MessageIDTerm;
  35. import org.orekit.files.iirv.terms.MessageSourceTerm;
  36. import org.orekit.files.iirv.terms.MessageStartConstantTerm;
  37. import org.orekit.files.iirv.terms.MessageTypeTerm;
  38. import org.orekit.files.iirv.terms.OriginIdentificationTerm;
  39. import org.orekit.files.iirv.terms.OriginatorRoutingIndicatorTerm;
  40. import org.orekit.files.iirv.terms.PositionVectorComponentTerm;
  41. import org.orekit.files.iirv.terms.RoutingIndicatorTerm;
  42. import org.orekit.files.iirv.terms.SequenceNumberTerm;
  43. import org.orekit.files.iirv.terms.SolarReflectivityCoefficientTerm;
  44. import org.orekit.files.iirv.terms.SpareConstantTerm;
  45. import org.orekit.files.iirv.terms.SupportIdCodeTerm;
  46. import org.orekit.files.iirv.terms.TransferTypeConstantTerm;
  47. import org.orekit.files.iirv.terms.VectorEpochTerm;
  48. import org.orekit.files.iirv.terms.VectorTypeTerm;
  49. import org.orekit.files.iirv.terms.VehicleIdCodeTerm;
  50. import org.orekit.files.iirv.terms.VelocityVectorComponentTerm;
  51. import org.orekit.frames.Frame;
  52. import org.orekit.time.AbsoluteDate;
  53. import org.orekit.time.UTCScale;
  54. import org.orekit.utils.PVCoordinates;
  55. import org.orekit.utils.TimeStampedPVCoordinates;

  56. import java.util.ArrayList;
  57. import java.util.Arrays;
  58. import java.util.List;
  59. import java.util.Objects;
  60. import java.util.regex.Pattern;

  61. /**
  62.  * A vector containing ephemeris state, epoch, and metadata information that, when taken as a series,
  63.  * comprises an {@link IIRVMessage object}.
  64.  * <p>
  65.  * See {@link IIRVMessage} for documentation on the structure of a single IIRV vector within an IIRV message body.
  66.  *
  67.  * @author Nick LaFarge
  68.  * @see IIRVMessage
  69.  * @see IIRVEphemerisFile.IIRVEphemeris
  70.  * @since 13.0
  71.  */
  72. public class IIRVVector implements Comparable<IIRVVector> {

  73.     /** Line separator: two ASCII carriage returns and two ASCII line feeds. */
  74.     public static final String LINE_SEPARATOR = "\r\r\n\n";


  75.     /** For creating from a list of Strings, OK to omit the line separators. */
  76.     private static final String LINE_SEPARATOR_PATTERN = "(" + LINE_SEPARATOR + ")?";

  77.     /**
  78.      * Regular expression for validating for line 1 when message metadata is included.
  79.      * <p>
  80.      * Message metadata fields refer to the first four terms defined for an IIRV vector:
  81.      * <ul>
  82.      *     <li>{@link MessageTypeTerm}</li>
  83.      *     <li>{@link MessageIDTerm}</li>
  84.      *     <li>{@link MessageSourceTerm}</li>
  85.      *     <li>{@link MessageClassTerm}</li>
  86.      * </ul>
  87.      */
  88.     public static final Pattern LINE_1_PATTERN_METADATA_INCLUDED = Pattern.compile("^" + MessageTypeTerm.MESSAGE_TYPE_TERM_PATTERN + MessageIDTerm.MESSAGE_ID_TERM_PATTERN +
  89.         MessageSourceTerm.MESSAGE_SOURCE_TERM_PATTERN + MessageClassTerm.MESSAGE_CLASS_TERM_PATTERN + MessageStartConstantTerm.MESSAGE_START_TERM_STRING +
  90.         OriginIdentificationTerm.ORIGIN_IDENTIFICATION_TERM_PATTERN + RoutingIndicatorTerm.ROUTING_INDICATOR_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  91.     /**
  92.      * Regular expression for validating for line 1 when message metadata is omitted.
  93.      * <p>
  94.      * Message metadata fields refer to the first four terms defined for an IIRV vector:
  95.      * <ul>
  96.      *     <li>{@link MessageTypeTerm}</li>
  97.      *     <li>{@link MessageIDTerm}</li>
  98.      *     <li>{@link MessageSourceTerm}</li>
  99.      *     <li>{@link MessageClassTerm}</li>
  100.      * </ul>
  101.      */
  102.     public static final Pattern LINE_1_PATTERN_METADATA_OMITTED = Pattern.compile("^" + MessageStartConstantTerm.MESSAGE_START_TERM_STRING + OriginIdentificationTerm.ORIGIN_IDENTIFICATION_TERM_PATTERN + RoutingIndicatorTerm.ROUTING_INDICATOR_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  103.     /** Regular expression for validating for line 2. */
  104.     public static final Pattern LINE_2_PATTERN = Pattern.compile("^" + VectorTypeTerm.VECTOR_TYPE_TERM_PATTERN + DataSourceTerm.DATA_SOURCE_TERM_PATTERN + TransferTypeConstantTerm.TRANSFER_TYPE_TERM_STRING + CoordinateSystemTerm.COORDINATE_SYSTEM_TERM_PATTERN + SupportIdCodeTerm.SUPPORT_ID_TERM_PATTERN + VehicleIdCodeTerm.VEHICLE_ID_TERM_PATTERN + SequenceNumberTerm.SEQUENCE_NUMBER_TERM_PATTERN + DayOfYearTerm.DAY_OF_YEAR_PATTERN + VectorEpochTerm.VECTOR_EPOCH_TERM_PATTERN + CheckSumTerm.CHECK_SUM_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  105.     /** Regular expression for validating for line 3. */
  106.     public static final Pattern LINE_3_PATTERN = Pattern.compile("^" + PositionVectorComponentTerm.POSITION_VECTOR_COMPONENT_TERM_PATTERN + PositionVectorComponentTerm.POSITION_VECTOR_COMPONENT_TERM_PATTERN + PositionVectorComponentTerm.POSITION_VECTOR_COMPONENT_TERM_PATTERN + CheckSumTerm.CHECK_SUM_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  107.     /** Regular expression for validating for line 4. */
  108.     public static final Pattern LINE_4_PATTERN = Pattern.compile("^" + VelocityVectorComponentTerm.VELOCITY_VECTOR_COMPONENT_TERM_PATTERN + VelocityVectorComponentTerm.VELOCITY_VECTOR_COMPONENT_TERM_PATTERN + VelocityVectorComponentTerm.VELOCITY_VECTOR_COMPONENT_TERM_PATTERN + CheckSumTerm.CHECK_SUM_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  109.     /** Regular expression for validating for line 5. */
  110.     public static final Pattern LINE_5_PATTERN = Pattern.compile("^" + MassTerm.MASS_TERM_PATTERN + CrossSectionalAreaTerm.CROSS_SECTIONAL_AREA_TERM_PATTERN + DragCoefficientTerm.DRAG_COEFFICIENT_TERM_PATTERN + SolarReflectivityCoefficientTerm.SOLAR_REFLECTIVITY_COEFFICIENT_TERM_PATTERN + CheckSumTerm.CHECK_SUM_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  111.     /** Regular expression for validating for line 6. */
  112.     public static final Pattern LINE_6_PATTERN = Pattern.compile("^" + MessageEndConstantTerm.MESSAGE_END_TERM_STRING + SpareConstantTerm.SPARE_TERM_STRING + OriginatorRoutingIndicatorTerm.ORIGINATOR_ROUTING_INDICATOR_TERM_PATTERN + LINE_SEPARATOR_PATTERN);

  113.     /** Line 1: Message Type. */
  114.     private final MessageTypeTerm messageType;

  115.     /** Line 1: Message Identification. */
  116.     private final MessageIDTerm messageID;

  117.     /** Line 1: Message Source. */
  118.     private final MessageSourceTerm messageSource;

  119.     /** Line 1: Message class. */
  120.     private final MessageClassTerm messageClass;

  121.     /** Line 1: Message Start. */
  122.     private final MessageStartConstantTerm messageStart;

  123.     /** Line 1: Origin identification. */
  124.     private final OriginIdentificationTerm originIdentification;

  125.     /** Line 1: Destination routing indicator. */
  126.     private final RoutingIndicatorTerm routingIndicator;

  127.     /** Line 2: Vector type. */
  128.     private final VectorTypeTerm vectorType;

  129.     /** Line 2: Source of data. */
  130.     private final DataSourceTerm dataSource;

  131.     /** Line 2: Transfer Type. */
  132.     private final TransferTypeConstantTerm transferType;

  133.     /** Line 2: Transfer Type. */
  134.     private final CoordinateSystemTerm coordinateSystem;

  135.     /** Line 2: Support ID Code. */
  136.     private final SupportIdCodeTerm supportIdCode;

  137.     /** Line 2: Vehicle ID Code. */
  138.     private final VehicleIdCodeTerm vehicleIdCode;

  139.     /** Line 2: Sequence number. */
  140.     private final SequenceNumberTerm sequenceNumber;

  141.     /** Line 2: Day of year (1-366). */
  142.     private final DayOfYearTerm dayOfYear;

  143.     /** Line 2: Transfer Type. */
  144.     private final VectorEpochTerm vectorEpoch;

  145.     /** Line 2: Check Sum. */
  146.     private final CheckSumTerm line2CheckSum;

  147.     /** Line 3: x component of the position vector [m]. */
  148.     private final PositionVectorComponentTerm xPosition;

  149.     /** Line 3: y component of the position vector [m]. */
  150.     private final PositionVectorComponentTerm yPosition;

  151.     /** Line 3: z component of the position vector [m]. */
  152.     private final PositionVectorComponentTerm zPosition;

  153.     /** Line 3: Check Sum. */
  154.     private final CheckSumTerm line3CheckSum;

  155.     /** Line 3: x component of the velocity vector [m/s]. */
  156.     private final VelocityVectorComponentTerm xVelocity;

  157.     /** Line 3: y component of the position vector [m/s]. */
  158.     private final VelocityVectorComponentTerm yVelocity;

  159.     /** Line 3: z component of the position vector [m/s]. */
  160.     private final VelocityVectorComponentTerm zVelocity;

  161.     /** Line 4: Check Sum. */
  162.     private final CheckSumTerm line4CheckSum;

  163.     /** Line 5: Satellite mass [kg]. */
  164.     private final MassTerm mass;

  165.     /** Line 5: Average satellite cross-sectional area [m^2]. */
  166.     private final CrossSectionalAreaTerm crossSectionalArea;

  167.     /** Line 5: Drag coefficient [dimensionless]. */
  168.     private final DragCoefficientTerm dragCoefficient;

  169.     /** Line 5: Solar reflectivity coefficient [dimensionless]. */
  170.     private final SolarReflectivityCoefficientTerm solarReflectivityCoefficient;

  171.     /** Line 5: Check Sum. */
  172.     private final CheckSumTerm line5CheckSum;

  173.     /** Line 6: End of message (always ITERM). */
  174.     private final MessageEndConstantTerm endOfMessage;

  175.     /** Line 6: Spare term (always ASCII space). */
  176.     private final SpareConstantTerm spareTerm;

  177.     /** Line 6: originator of message (GCQU or GAQD). */
  178.     private final OriginatorRoutingIndicatorTerm originatorRoutingIndicatorTerm;

  179.     /** UTC time scale. */
  180.     private final UTCScale utc;

  181.     /**
  182.      * Constructs an IIRV message from its composite terms.
  183.      *
  184.      * @param messageType                    Message type
  185.      * @param messageID                      Message identification
  186.      * @param messageSource                  Message source
  187.      * @param messageClass                   Message class
  188.      * @param originIdentification           Origin identification
  189.      * @param routingIndicator               Destination routing indicator
  190.      * @param vectorType                     Vector type
  191.      * @param dataSource                     Data source
  192.      * @param coordinateSystem               Coordinate system
  193.      * @param supportIdCode                  Support identification code
  194.      * @param vehicleIdCode                  Vehicle identification code
  195.      * @param sequenceNumber                 Sequence number
  196.      * @param dayOfYear                      Day of year
  197.      * @param vectorEpoch                    Vector epoch
  198.      * @param xPosition                      X component of the position vector [m]
  199.      * @param yPosition                      Y component of the position vector [m]
  200.      * @param zPosition                      Z component of the position vector [m]
  201.      * @param xVelocity                      X component of the velocity vector [m/s]
  202.      * @param yVelocity                      Y component of the velocity vector [m/s]
  203.      * @param zVelocity                      Z component of the velocity vector [m/s]
  204.      * @param mass                           Satellite mass (kg)
  205.      * @param crossSectionalArea             Average satellite cross-sectional area [m^2]
  206.      * @param dragCoefficient                Drag coefficient [dimensionless]
  207.      * @param solarReflectivityCoefficient   Solar reflectivity coefficient [dimensionless]
  208.      * @param originatorRoutingIndicatorTerm Originator of message (GCQU or GAQD)
  209.      * @param utc                            UTC time scale
  210.      */
  211.     public IIRVVector(final MessageTypeTerm messageType, final MessageIDTerm messageID, final MessageSourceTerm messageSource, final MessageClassTerm messageClass, final OriginIdentificationTerm originIdentification, final RoutingIndicatorTerm routingIndicator, final VectorTypeTerm vectorType, final DataSourceTerm dataSource, final CoordinateSystemTerm coordinateSystem, final SupportIdCodeTerm supportIdCode, final VehicleIdCodeTerm vehicleIdCode, final SequenceNumberTerm sequenceNumber, final DayOfYearTerm dayOfYear, final VectorEpochTerm vectorEpoch, final PositionVectorComponentTerm xPosition, final PositionVectorComponentTerm yPosition, final PositionVectorComponentTerm zPosition, final VelocityVectorComponentTerm xVelocity, final VelocityVectorComponentTerm yVelocity, final VelocityVectorComponentTerm zVelocity, final MassTerm mass, final CrossSectionalAreaTerm crossSectionalArea, final DragCoefficientTerm dragCoefficient, final SolarReflectivityCoefficientTerm solarReflectivityCoefficient, final OriginatorRoutingIndicatorTerm originatorRoutingIndicatorTerm, final UTCScale utc) {

  212.         // Line 1
  213.         this.messageType = messageType;
  214.         this.messageID = messageID;
  215.         this.messageSource = messageSource;
  216.         this.messageClass = messageClass;
  217.         this.messageStart = new MessageStartConstantTerm();
  218.         this.originIdentification = originIdentification;
  219.         this.routingIndicator = routingIndicator;

  220.         // Line 2
  221.         this.vectorType = vectorType;
  222.         this.dataSource = dataSource;
  223.         this.transferType = new TransferTypeConstantTerm();
  224.         this.coordinateSystem = coordinateSystem;
  225.         this.supportIdCode = supportIdCode;
  226.         this.vehicleIdCode = vehicleIdCode;
  227.         this.sequenceNumber = sequenceNumber;
  228.         this.dayOfYear = dayOfYear;
  229.         this.vectorEpoch = vectorEpoch;
  230.         this.line2CheckSum = CheckSumTerm.fromIIRVTerms(this.vectorType, this.dataSource, this.transferType, this.coordinateSystem, this.supportIdCode, this.vehicleIdCode, this.sequenceNumber, this.dayOfYear, this.vectorEpoch);

  231.         // Line 3
  232.         this.xPosition = xPosition;
  233.         this.yPosition = yPosition;
  234.         this.zPosition = zPosition;
  235.         this.line3CheckSum = CheckSumTerm.fromIIRVTerms(this.xPosition, this.yPosition, this.zPosition);

  236.         // Line 4
  237.         this.xVelocity = xVelocity;
  238.         this.yVelocity = yVelocity;
  239.         this.zVelocity = zVelocity;
  240.         this.line4CheckSum = CheckSumTerm.fromIIRVTerms(this.xVelocity, this.yVelocity, this.zVelocity);

  241.         // Line 5
  242.         this.mass = mass;
  243.         this.crossSectionalArea = crossSectionalArea;
  244.         this.dragCoefficient = dragCoefficient;
  245.         this.solarReflectivityCoefficient = solarReflectivityCoefficient;
  246.         this.line5CheckSum = CheckSumTerm.fromIIRVTerms(this.mass, this.crossSectionalArea, this.dragCoefficient, this.solarReflectivityCoefficient);

  247.         // Line 6
  248.         this.endOfMessage = new MessageEndConstantTerm();
  249.         this.spareTerm = new SpareConstantTerm();
  250.         this.originatorRoutingIndicatorTerm = originatorRoutingIndicatorTerm;


  251.         // UTC time scale
  252.         this.utc = utc;
  253.     }

  254.     /**
  255.      * Constructs an IIRV message object given a list of 6 lines of message body (omitting blank line feeds).
  256.      *
  257.      * @param lines Six-element list of lines in an IIRV message
  258.      * @param utc   UTC time scale
  259.      */
  260.     public IIRVVector(final List<String> lines, final UTCScale utc) {
  261.         this(lines.get(0), lines.get(1), lines.get(2), lines.get(3), lines.get(4), lines.get(5), utc);
  262.     }

  263.     /**
  264.      * Constructs an IIRV message object given 6 lines of message body (omitting blank line feeds).
  265.      *
  266.      * @param line1 Line 1 of IIRV message body
  267.      * @param line2 Line 2 of IIRV message body
  268.      * @param line3 Line 3 of IIRV message body
  269.      * @param line4 Line 4 of IIRV message body
  270.      * @param line5 Line 5 of IIRV message body
  271.      * @param line6 Line 6 of IIRV message body
  272.      * @param utc   UTC time scale
  273.      */
  274.     public IIRVVector(final String line1, final String line2, final String line3, final String line4, final String line5, final String line6, final UTCScale utc) {
  275.         this.utc = utc;
  276.         final ArrayList<String> iirvLines = new ArrayList<>(Arrays.asList(line1, line2, line3, line4, line5, line6));

  277.         if (!IIRVVector.isFormatOK(iirvLines)) {
  278.             // trigger line-specific error
  279.             validateLines(iirvLines, true);
  280.             validateLines(iirvLines, false);

  281.             // this should never happen; error should have been triggered by one of the calls above
  282.             throw new OrekitInternalError(null);
  283.         }

  284.         // Parse Line 1
  285.         messageType = new MessageTypeTerm(line1.substring(0, 2));
  286.         messageStart = new MessageStartConstantTerm();
  287.         if (LINE_1_PATTERN_METADATA_INCLUDED.matcher(line1).matches()) {
  288.             messageID = new MessageIDTerm(line1.substring(2, 9));
  289.             messageSource = new MessageSourceTerm(line1.substring(9, 10));
  290.             messageClass = new MessageClassTerm(line1.substring(10, 12));
  291.             originIdentification = new OriginIdentificationTerm(line1.substring(17, 18));
  292.             routingIndicator = new RoutingIndicatorTerm(line1.substring(18, 22));
  293.         } else {
  294.             messageID = new MessageIDTerm(0);     // Default to 0
  295.             messageSource = MessageSourceTerm.DEFAULT;  // Default to "0"
  296.             messageClass = MessageClassTerm.NOMINAL;    // Default to "10" (nominal)
  297.             originIdentification = new OriginIdentificationTerm(line1.substring(5, 6));
  298.             routingIndicator = new RoutingIndicatorTerm(line1.substring(6, 10));
  299.         }

  300.         // Parse Line 2
  301.         vectorType = new VectorTypeTerm(line2.substring(0, 1));
  302.         dataSource = new DataSourceTerm(line2.substring(1, 2));
  303.         transferType = new TransferTypeConstantTerm();
  304.         coordinateSystem = new CoordinateSystemTerm(line2.substring(3, 4));
  305.         supportIdCode = new SupportIdCodeTerm(line2.substring(4, 8));
  306.         vehicleIdCode = new VehicleIdCodeTerm(line2.substring(8, 10));
  307.         sequenceNumber = new SequenceNumberTerm(line2.substring(10, 13));
  308.         dayOfYear = new DayOfYearTerm(line2.substring(13, 16));
  309.         vectorEpoch = new VectorEpochTerm(line2.substring(16, 25));
  310.         line2CheckSum = new CheckSumTerm(line2.substring(25, 28));

  311.         // Parse Line 3 (position coordinates in meters)
  312.         xPosition = new PositionVectorComponentTerm(line3.substring(0, 13));
  313.         yPosition = new PositionVectorComponentTerm(line3.substring(13, 26));
  314.         zPosition = new PositionVectorComponentTerm(line3.substring(26, 39));
  315.         line3CheckSum = new CheckSumTerm(line3.substring(39));

  316.         // Parse Line 4 (velocity coordinates in m/s)
  317.         xVelocity = new VelocityVectorComponentTerm(line4.substring(0, 13));
  318.         yVelocity = new VelocityVectorComponentTerm(line4.substring(13, 26));
  319.         zVelocity = new VelocityVectorComponentTerm(line4.substring(26, 39));
  320.         line4CheckSum = new CheckSumTerm(line4.substring(39));

  321.         // Parse Line 5
  322.         mass = new MassTerm(line5.substring(0, 8));
  323.         crossSectionalArea = new CrossSectionalAreaTerm(line5.substring(8, 13));
  324.         dragCoefficient = new DragCoefficientTerm(line5.substring(13, 17));
  325.         solarReflectivityCoefficient = new SolarReflectivityCoefficientTerm(line5.substring(17, 25));
  326.         line5CheckSum = new CheckSumTerm(line5.substring(25));

  327.         // Parse Line 6
  328.         endOfMessage = new MessageEndConstantTerm();
  329.         spareTerm = new SpareConstantTerm();
  330.         originatorRoutingIndicatorTerm = new OriginatorRoutingIndicatorTerm(line6.substring(6, 10));
  331.     }

  332.     /**
  333.      * Copy constructor.
  334.      *
  335.      * @param other Other IIRVVector to create from.
  336.      */
  337.     public IIRVVector(final IIRVVector other) {
  338.         this(other.toIIRVStrings(true), other.utc);
  339.     }

  340.     /**
  341.      * Checks the format validity for each line using regular expressions.
  342.      *
  343.      * @param lines the six-element list of lines
  344.      * @return true if format is valid, false otherwise
  345.      */
  346.     public static boolean isFormatOK(final List<String> lines) {
  347.         if (lines == null) {
  348.             return false;
  349.         }
  350.         if (lines.size() != 6) {
  351.             return false;
  352.         }
  353.         return isFormatOK(lines.get(0), lines.get(1), lines.get(2), lines.get(3), lines.get(4), lines.get(5));
  354.     }

  355.     /**
  356.      * Checks the format validity for each line using regular expressions.
  357.      *
  358.      * @param line1 Line 1 of IIRV message body
  359.      * @param line2 Line 2 of IIRV message body
  360.      * @param line3 Line 3 of IIRV message body
  361.      * @param line4 Line 4 of IIRV message body
  362.      * @param line5 Line 5 of IIRV message body
  363.      * @param line6 Line 6 of IIRV message body
  364.      * @return true if format is valid, false otherwise
  365.      */
  366.     public static boolean isFormatOK(final String line1, final String line2, final String line3, final String line4, final String line5, final String line6) {
  367.         // Attempt to validate the input lines: with metadata
  368.         try {
  369.             validateLines(line1, line2, line3, line4, line5, line6, true);
  370.             return true;
  371.         } catch (OrekitIllegalArgumentException oe) {
  372.             // Continue to other check
  373.         }

  374.         // Attempt to validate the input lines: without metadata
  375.         try {
  376.             validateLines(line1, line2, line3, line4, line5, line6, false);
  377.             return true;
  378.         } catch (OrekitIllegalArgumentException oe) {
  379.             return false;  // both validation checks failed
  380.         }
  381.     }

  382.     /**
  383.      * Check the format validity for each line using regular expressions.
  384.      *
  385.      * @param lines                            the six-element list of lines
  386.      * @param firstLineIncludesMessageMetadata true if message metadata terms are included in the first line
  387.      *                                         of the vector
  388.      */
  389.     public static void validateLines(final List<String> lines, final boolean firstLineIncludesMessageMetadata) {
  390.         if (lines == null) {
  391.             throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "lines");
  392.         }
  393.         if (lines.size() != 6) {
  394.             throw new OrekitIllegalArgumentException(OrekitMessages.INCONSISTENT_NUMBER_OF_ELEMENTS, 6, lines.size());
  395.         }

  396.         validateLines(lines.get(0), lines.get(1), lines.get(2), lines.get(3), lines.get(4), lines.get(5), firstLineIncludesMessageMetadata);
  397.     }


  398.     /**
  399.      * Check the format validity for each line using regular expressions.
  400.      *
  401.      * @param line1                            Line 1 of IIRV message body
  402.      * @param line2                            Line 2 of IIRV message body
  403.      * @param line3                            Line 3 of IIRV message body
  404.      * @param line4                            Line 4 of IIRV message body
  405.      * @param line5                            Line 5 of IIRV message body
  406.      * @param line6                            Line 6 of IIRV message body
  407.      * @param firstLineIncludesMessageMetadata true if message metadata terms are included in the first line
  408.      *                                         of the vector
  409.      */
  410.     public static void validateLines(final String line1, final String line2, final String line3, final String line4, final String line5, final String line6, final boolean firstLineIncludesMessageMetadata) {
  411.         // Validate line1 separately based on if metadata is included
  412.         if (line1 == null) {
  413.             throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "line1");
  414.         }
  415.         final Pattern line1Pattern = firstLineIncludesMessageMetadata ? LINE_1_PATTERN_METADATA_INCLUDED : LINE_1_PATTERN_METADATA_OMITTED;
  416.         final boolean lineOneOkay = line1Pattern.matcher(line1).matches();

  417.         // Validate remaining lines
  418.         final boolean lineTwoOkay = validateLine(1, line2);
  419.         final boolean lineThreeOkay = validateLine(2, line3);
  420.         final boolean lineFourOkay = validateLine(3, line4);
  421.         final boolean lineFiveOkay = validateLine(4, line5);
  422.         final boolean lineSixOkay = validateLine(5, line6);

  423.         if (!lineTwoOkay) {
  424.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 2, line2);
  425.         } else if (!lineThreeOkay) {
  426.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 3, line3);
  427.         } else if (!lineFourOkay) {
  428.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 4, line4);
  429.         } else if (!lineFiveOkay) {
  430.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 5, line5);
  431.         } else if (!lineSixOkay) {
  432.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 6, line6);
  433.         } else if (!lineOneOkay) {
  434.             // Do line 1 last since this is the one that can change format
  435.             throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_LINE_IN_VECTOR, 1, line1);
  436.         }
  437.     }

  438.     /**
  439.      * Check an input string against the specified line's regular expression, and validate the checksum for lines 2-5.
  440.      *
  441.      * @param lineIndex Line index to validate against (0-5)
  442.      * @param line      String to validate
  443.      * @return true if the inputted line string is valid, false otherwise.
  444.      */
  445.     public static boolean validateLine(final int lineIndex, final String line) {
  446.         if (line == null) {
  447.             throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "line");
  448.         } else if (line.length() < 3) {
  449.             throw new OrekitIllegalArgumentException(OrekitMessages.NOT_ENOUGH_DATA, line.length());
  450.         }

  451.         // Validate against regular expressions
  452.         final boolean regexMatches;
  453.         switch (lineIndex) {
  454.             case 0:
  455.                 final boolean line1Metadata = LINE_1_PATTERN_METADATA_INCLUDED.matcher(line).matches();
  456.                 final boolean line1NoMetadata = LINE_1_PATTERN_METADATA_OMITTED.matcher(line).matches();
  457.                 regexMatches = line1Metadata || line1NoMetadata;
  458.                 break;
  459.             case 1:
  460.                 regexMatches = LINE_2_PATTERN.matcher(line).matches();
  461.                 break;
  462.             case 2:
  463.                 regexMatches = LINE_3_PATTERN.matcher(line).matches();
  464.                 break;
  465.             case 3:
  466.                 regexMatches = LINE_4_PATTERN.matcher(line).matches();
  467.                 break;
  468.             case 4:
  469.                 regexMatches = LINE_5_PATTERN.matcher(line).matches();
  470.                 break;
  471.             case 5:
  472.                 regexMatches = LINE_6_PATTERN.matcher(line).matches();
  473.                 break;
  474.             default:
  475.                 throw new OrekitIllegalArgumentException(OrekitMessages.INVALID_PARAMETER_RANGE, "lineIndex", lineIndex, 0, 5);
  476.         }

  477.         // Validate checksum. Value is always "true" for lines that omit checksum (1, 6))
  478.         final boolean checksumValid;
  479.         if (lineIndex == 0 || lineIndex == 5) {
  480.             checksumValid = true;
  481.         } else {
  482.             try {
  483.                 checksumValid = CheckSumTerm.validateLineCheckSum(line);
  484.             } catch (OrekitIllegalArgumentException e) {
  485.                 return false;
  486.             }
  487.         }

  488.         return regexMatches && checksumValid;
  489.     }

  490.     /**
  491.      * Compares two IIRV vectors for equality based on their string representations, include message
  492.      * metadata information.
  493.      */
  494.     @Override
  495.     public int compareTo(final IIRVVector o) {
  496.         final String thisIIRV = toIIRVString(true);
  497.         final String otherIIRV = o.toIIRVString(true);
  498.         return thisIIRV.compareTo(otherIIRV);
  499.     }

  500.     /**
  501.      * Compares two IIRV vectors for equality based on their string representations, include message
  502.      * metadata information.
  503.      */
  504.     @Override
  505.     public boolean equals(final Object o) {
  506.         if (this == o) {
  507.             return true;
  508.         }
  509.         if (o == null || getClass() != o.getClass()) {
  510.             return false;
  511.         }
  512.         final IIRVVector vector = (IIRVVector) o;
  513.         return vector.toIIRVString(true).equals(toIIRVString(true));
  514.     }

  515.     @Override
  516.     public String toString() {
  517.         return toIIRVString(true);
  518.     }

  519.     @Override
  520.     public int hashCode() {
  521.         return Objects.hash(toString());
  522.     }

  523.     /**
  524.      * Combine each line to build a String containing the entire IIRV message (including carriage returns and line
  525.      * feeds).
  526.      *
  527.      * @param includeMessageMetadata If true, include message metadata terms
  528.      *                               ({@link MessageTypeTerm},
  529.      *                               {@link MessageIDTerm},
  530.      *                               {@link MessageSourceTerm},
  531.      *                               {@link MessageClassTerm})
  532.      *                               at the beginning of the first line.
  533.      * @return Full IIRV vector in String format
  534.      */
  535.     public String toIIRVString(final boolean includeMessageMetadata) {
  536.         final List<String> lines = toIIRVStrings(includeMessageMetadata);
  537.         final StringBuilder iirvVectorString = new StringBuilder();
  538.         for (String x : lines) {
  539.             iirvVectorString.append(x);
  540.             iirvVectorString.append(LINE_SEPARATOR);
  541.         }

  542.         return iirvVectorString.toString();
  543.     }

  544.     /**
  545.      * Computes each IIRV lines as Strings, validate it, and return it in a list.
  546.      *
  547.      * @param includeMessageMetadata If true, include message metadata terms
  548.      *                               ({@link MessageTypeTerm},
  549.      *                               {@link MessageIDTerm},
  550.      *                               {@link MessageSourceTerm},
  551.      *                               {@link MessageClassTerm})
  552.      *                               at the beginning of the first line.
  553.      * @return List of IIRV lines as Strings
  554.      */
  555.     public List<String> toIIRVStrings(final boolean includeMessageMetadata) {
  556.         final String line1 = buildLine1(includeMessageMetadata);
  557.         final String line2 = buildLine2();
  558.         final String line3 = buildLine3();
  559.         final String line4 = buildLine4();
  560.         final String line5 = buildLine5();
  561.         final String line6 = buildLine6();

  562.         // Validate each line and return
  563.         validateLines(line1, line2, line3, line4, line5, line6, includeMessageMetadata);
  564.         return new ArrayList<>(Arrays.asList(line1, line2, line3, line4, line5, line6));
  565.     }

  566.     /**
  567.      * Computes each IIRV lines as Strings, with each IIRV vector term separated by a forward slash '/'.
  568.      * <p>
  569.      * This method is intended to display more human-readable IIRV vectors, and should never be used
  570.      * for writing an actual IIRV message (see {@link #toIIRVStrings(boolean)}).
  571.      *
  572.      * @return List of six human-readable IIRV lines, with each IIRV vector term separated by a forward slash '/'
  573.      */
  574.     public List<String> toHumanReadableLines() {
  575.         final String deliminator = "/";
  576.         return new ArrayList<>(Arrays.asList(buildLine1SplitByTerm(deliminator, true), buildLine2SplitByTerm(deliminator), buildLine3SplitByTerm(deliminator), buildLine4SplitByTerm(deliminator), buildLine5SplitByTerm(deliminator), buildLine6SplitByTerm(deliminator)));
  577.     }

  578.     /**
  579.      * Builds the first line of the IIRV vector, not including ASCII carriage returns and line feeds.
  580.      * <br>
  581.      * Only includes message type, id, source, and class if this is the first IIRV in the sequence, i.e.,
  582.      * sequenceNumber=0
  583.      *
  584.      * @param includeMessageMetadata If true, include message metadata terms
  585.      *                               ({@link MessageTypeTerm},
  586.      *                               {@link MessageIDTerm},
  587.      *                               {@link MessageSourceTerm},
  588.      *                               {@link MessageClassTerm}) at the beginning of the line.
  589.      * @return Line 1 of IIRV vector
  590.      */
  591.     public String buildLine1(final boolean includeMessageMetadata) {
  592.         return buildLine1SplitByTerm("", includeMessageMetadata);
  593.     }

  594.     /**
  595.      * Builds the second line of the IIRV vector, not including ASCII carriage returns and line feeds.
  596.      *
  597.      * @return Line 2 of IIRV vector
  598.      */
  599.     public String buildLine2() {
  600.         return buildLine2SplitByTerm("");
  601.     }

  602.     /**
  603.      * Builds the third line of the IIRV vector, not including ASCII carriage returns and line feeds.
  604.      *
  605.      * @return Line 3 of IIRV vector
  606.      */
  607.     public String buildLine3() {
  608.         return buildLine3SplitByTerm("");
  609.     }

  610.     /**
  611.      * Builds the fourth line of the IIRV vector, not including ASCII carriage returns and line feeds.
  612.      *
  613.      * @return Line 4 of IIRV vector
  614.      */
  615.     public String buildLine4() {
  616.         return buildLine4SplitByTerm("");
  617.     }

  618.     /**
  619.      * Builds the fifth line of the IIRV vector, not including ASCII carriage returns and line feeds.
  620.      *
  621.      * @return Line 5 of IIRV vector
  622.      */
  623.     public String buildLine5() {
  624.         return buildLine5SplitByTerm("");
  625.     }

  626.     /**
  627.      * Builds the sixth line of the IIRV vector, not including ASCII carriage returns and line feeds.
  628.      *
  629.      * @return Line 6 of IIRV vector
  630.      */
  631.     public String buildLine6() {
  632.         return buildLine6SplitByTerm("");
  633.     }

  634.     /**
  635.      * Creates an {@link AbsoluteDate} instance (in UTC), with time components given by the {@link VectorEpochTerm},
  636.      * and date components from the {@link DayOfYearTerm} / inputted year.
  637.      *
  638.      * @param year Year associated with the created
  639.      * @return created {@link AbsoluteDate} instance
  640.      */
  641.     public AbsoluteDate getAbsoluteDate(final int year) {
  642.         return new AbsoluteDate(dayOfYear.getDateComponents(year), vectorEpoch.value(), utc);
  643.     }

  644.     /**
  645.      * Gets a position vector [x y z], represented as a {@link Vector3D} instance.
  646.      * <p>
  647.      * Data supplied by the {@link PositionVectorComponentTerm} values; See {@link #getXPosition()},
  648.      * {@link #getYPosition()}, {@link #getZPosition()}.
  649.      *
  650.      * @return Vector containing x,y,z position components
  651.      */
  652.     public Vector3D getPositionVector() {
  653.         return new Vector3D(xPosition.value(), yPosition.value(), zPosition.value());
  654.     }

  655.     /**
  656.      * Gets a velocity vector [vx vy vz], represented as a {@link Vector3D} instance.
  657.      * <p>
  658.      * Data supplied by the {@link VelocityVectorComponentTerm} values; See {@link #getXVelocity()},
  659.      * {@link #getYVelocity()}, {@link #getZVelocity()}.
  660.      *
  661.      * @return Vector containing x,y,z velocity components
  662.      */
  663.     public Vector3D getVelocityVector() {
  664.         return new Vector3D(xVelocity.value(), yVelocity.value(), zVelocity.value());
  665.     }

  666.     /**
  667.      * Gets the state vector and time data as a {@link TimeStampedPVCoordinates} instance.
  668.      * <p>
  669.      * Position and velocity data supplied by the x,y,z position components ({@link PositionVectorComponentTerm}) and
  670.      * vx, vy, vz velocity components ({@link VelocityVectorComponentTerm}). Epoch data given by {@link DayOfYearTerm}
  671.      * {@link VectorEpochTerm}.
  672.      *
  673.      * @param year The year of the corresponding coordinates (IIRV vector does not contain year information)
  674.      * @return Newly created {@link TimeStampedPVCoordinates} instance populated with data from the IIRV vector terms.
  675.      */
  676.     public TimeStampedPVCoordinates getTimeStampedPVCoordinates(final int year) {
  677.         return new TimeStampedPVCoordinates(getAbsoluteDate(year), getPositionVector(), getVelocityVector());
  678.     }

  679.     /**
  680.      * Gets the state vector as a {@link org.orekit.utils.PVCoordinates} instance.
  681.      * <p>
  682.      * Position and velocity data supplied by the x,y,z position components ({@link PositionVectorComponentTerm}) and
  683.      * vx, vy, vz velocity components ({@link VelocityVectorComponentTerm}).
  684.      *
  685.      * @return Newly created {@link PVCoordinates} instance populated with data from the IIRV vector terms.
  686.      */
  687.     public PVCoordinates getPVCoordinates() {
  688.         return new PVCoordinates(getPositionVector(), getVelocityVector());
  689.     }

  690.     /**
  691.      * Returns the {@link Frame} associated with the IIRV vector based on its {@link CoordinateSystemTerm}.
  692.      *
  693.      * @param context data context used to retrieve frames
  694.      * @return coordinate system
  695.      * @see CoordinateSystemTerm#getFrame
  696.      */
  697.     public Frame getFrame(final DataContext context) {
  698.         return coordinateSystem.getFrame(context);
  699.     }

  700.     /**
  701.      * Returns the {@link Frame} associated with the IIRV vector based on its {@link CoordinateSystemTerm}.
  702.      *
  703.      * @return coordinate system
  704.      * @see CoordinateSystemTerm#getFrame
  705.      */
  706.     @DefaultDataContext
  707.     public Frame getFrame() {
  708.         return coordinateSystem.getFrame();
  709.     }

  710.     /**
  711.      * Gets the message type term.
  712.      *
  713.      * @return the message type term
  714.      */
  715.     public MessageTypeTerm getMessageType() {
  716.         return messageType;
  717.     }

  718.     /**
  719.      * Gets the message ID term.
  720.      *
  721.      * @return the message ID term
  722.      */
  723.     public MessageIDTerm getMessageID() {
  724.         return messageID;
  725.     }

  726.     /**
  727.      * Gets the message source term.
  728.      *
  729.      * @return the message source term
  730.      */
  731.     public MessageSourceTerm getMessageSource() {
  732.         return messageSource;
  733.     }

  734.     /**
  735.      * Gets the message class term.
  736.      *
  737.      * @return the message class term
  738.      */
  739.     public MessageClassTerm getMessageClass() {
  740.         return messageClass;
  741.     }

  742.     /**
  743.      * Gets the message start term.
  744.      *
  745.      * @return the message start term
  746.      */
  747.     public MessageStartConstantTerm getMessageStart() {
  748.         return messageStart;
  749.     }

  750.     /**
  751.      * Gets the origin identification term.
  752.      *
  753.      * @return the origin identification term
  754.      */
  755.     public OriginIdentificationTerm getOriginIdentification() {
  756.         return originIdentification;
  757.     }

  758.     /**
  759.      * Gets the routing indicator term.
  760.      *
  761.      * @return the routing indicator term
  762.      */
  763.     public RoutingIndicatorTerm getRoutingIndicator() {
  764.         return routingIndicator;
  765.     }

  766.     /**
  767.      * Gets the vector type term.
  768.      *
  769.      * @return the vector type term
  770.      */
  771.     public VectorTypeTerm getVectorType() {
  772.         return vectorType;
  773.     }

  774.     /**
  775.      * Gets the data source term.
  776.      *
  777.      * @return the data source term
  778.      */
  779.     public DataSourceTerm getDataSource() {
  780.         return dataSource;
  781.     }

  782.     /**
  783.      * Gets the transfer type term.
  784.      *
  785.      * @return the transfer type term
  786.      */
  787.     public TransferTypeConstantTerm getTransferType() {
  788.         return transferType;
  789.     }

  790.     /**
  791.      * Gets the coordinate system term.
  792.      *
  793.      * @return the coordinate system term
  794.      */
  795.     public CoordinateSystemTerm getCoordinateSystem() {
  796.         return coordinateSystem;
  797.     }

  798.     /**
  799.      * Gets the support ID code term.
  800.      *
  801.      * @return the support ID code term
  802.      */
  803.     public SupportIdCodeTerm getSupportIdCode() {
  804.         return supportIdCode;
  805.     }

  806.     /**
  807.      * Gets the vehicle ID code term.
  808.      *
  809.      * @return the vehicle ID code term
  810.      */
  811.     public VehicleIdCodeTerm getVehicleIdCode() {
  812.         return vehicleIdCode;
  813.     }

  814.     /**
  815.      * Gets the sequence number term.
  816.      *
  817.      * @return the sequence number term
  818.      */
  819.     public SequenceNumberTerm getSequenceNumber() {
  820.         return sequenceNumber;
  821.     }

  822.     /**
  823.      * Gets the day of year term.
  824.      *
  825.      * @return the day of year term
  826.      */
  827.     public DayOfYearTerm getDayOfYear() {
  828.         return dayOfYear;
  829.     }

  830.     /**
  831.      * Gets the vector epoch term.
  832.      *
  833.      * @return the vector epoch term
  834.      */
  835.     public VectorEpochTerm getVectorEpoch() {
  836.         return vectorEpoch;
  837.     }

  838.     /**
  839.      * Gets the checksum value for line 2.
  840.      *
  841.      * @return the checksum value for line 2
  842.      */
  843.     public CheckSumTerm getLine2CheckSum() {
  844.         return line2CheckSum;
  845.     }

  846.     /**
  847.      * Gets the x component of position.
  848.      *
  849.      * @return the x component of position
  850.      */
  851.     public PositionVectorComponentTerm getXPosition() {
  852.         return xPosition;
  853.     }

  854.     /**
  855.      * Gets the y component of position.
  856.      *
  857.      * @return the y component of position
  858.      */
  859.     public PositionVectorComponentTerm getYPosition() {
  860.         return yPosition;
  861.     }

  862.     /**
  863.      * Gets the z component of position.
  864.      *
  865.      * @return the z component of position
  866.      */
  867.     public PositionVectorComponentTerm getZPosition() {
  868.         return zPosition;
  869.     }

  870.     /**
  871.      * Gets the checksum term for line 3.
  872.      *
  873.      * @return the checksum term for line 3
  874.      */
  875.     public CheckSumTerm getLine3CheckSum() {
  876.         return line3CheckSum;
  877.     }

  878.     /**
  879.      * Gets the x component of velocity.
  880.      *
  881.      * @return the x component of velocity
  882.      */
  883.     public VelocityVectorComponentTerm getXVelocity() {
  884.         return xVelocity;
  885.     }

  886.     /**
  887.      * Gets the y component of velocity.
  888.      *
  889.      * @return the y component of velocity
  890.      */
  891.     public VelocityVectorComponentTerm getYVelocity() {
  892.         return yVelocity;
  893.     }

  894.     /**
  895.      * Gets the z component of velocity.
  896.      *
  897.      * @return the z component of velocity
  898.      */
  899.     public VelocityVectorComponentTerm getZVelocity() {
  900.         return zVelocity;
  901.     }

  902.     /**
  903.      * Gets the checksum value for line 4 term.
  904.      *
  905.      * @return the checksum value for line 4 term
  906.      */
  907.     public CheckSumTerm getLine4CheckSum() {
  908.         return line4CheckSum;
  909.     }

  910.     /**
  911.      * Gets the mass term.
  912.      *
  913.      * @return the mass term
  914.      */
  915.     public MassTerm getMass() {
  916.         return mass;
  917.     }

  918.     /**
  919.      * Gets the cross-sectional area term.
  920.      *
  921.      * @return the cross-sectional area term
  922.      */
  923.     public CrossSectionalAreaTerm getCrossSectionalArea() {
  924.         return crossSectionalArea;
  925.     }

  926.     /**
  927.      * Gets the drag coefficient term.
  928.      *
  929.      * @return the drag coefficient term
  930.      */
  931.     public DragCoefficientTerm getDragCoefficient() {
  932.         return dragCoefficient;
  933.     }

  934.     /**
  935.      * Gets the solar reflectivity coefficient term.
  936.      *
  937.      * @return the solar reflectivity coefficient term
  938.      */
  939.     public SolarReflectivityCoefficientTerm getSolarReflectivityCoefficient() {
  940.         return solarReflectivityCoefficient;
  941.     }

  942.     /**
  943.      * Gets the checksum term for line 5.
  944.      *
  945.      * @return the checksum term for line 5
  946.      */
  947.     public CheckSumTerm getLine5CheckSum() {
  948.         return line5CheckSum;
  949.     }

  950.     /**
  951.      * Gets the "ITERM" message end term.
  952.      *
  953.      * @return the "ITERM" message end term
  954.      */
  955.     public MessageEndConstantTerm getMessageEnd() {
  956.         return endOfMessage;
  957.     }

  958.     /**
  959.      * Gets the spare character term (ASCII space).
  960.      *
  961.      * @return the spare character term (ASCII space)
  962.      */
  963.     public SpareConstantTerm getSpareTerm() {
  964.         return spareTerm;
  965.     }

  966.     /**
  967.      * Gets the originator routing indicator term.
  968.      *
  969.      * @return the originator routing indicator term
  970.      */
  971.     public OriginatorRoutingIndicatorTerm getOriginatorRoutingIndicator() {
  972.         return originatorRoutingIndicatorTerm;
  973.     }

  974.     /**
  975.      * Builds the first line of the IIRV, not including ASCII carriage returns and line feeds.
  976.      * <br>
  977.      * <p>
  978.      * Only includes message type, id, source, and class if this is the first IIRV in the sequence, i.e.,
  979.      * sequenceNumber=0.
  980.      *
  981.      * @param delimiter              Delimiter to split the terms in the message. Should always be "", except when printing
  982.      *                               for human readability.
  983.      * @param includeMessageMetadata If true, include message metadata terms
  984.      *                               ({@link MessageTypeTerm},
  985.      *                               {@link MessageIDTerm},
  986.      *                               {@link MessageSourceTerm},
  987.      *                               {@link MessageClassTerm}) at the beginning of the line.
  988.      * @return Line 1 of IIRV message
  989.      */
  990.     private String buildLine1SplitByTerm(final String delimiter, final boolean includeMessageMetadata) {
  991.         final String splitLine;
  992.         if (includeMessageMetadata) {
  993.             splitLine = IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, messageType, messageID, messageSource, messageClass, messageStart, originIdentification, routingIndicator);

  994.         } else {
  995.             splitLine = IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, messageStart, originIdentification, routingIndicator);
  996.         }
  997.         return splitLine;
  998.     }

  999.     /**
  1000.      * Builds the second line of the IIRV message, not including ASCII carriage returns and line feeds.
  1001.      *
  1002.      * @param delimiter Delimiter to split the terms in the message. Should always be "", except when printing
  1003.      *                  for human readability.
  1004.      * @return Line 2 of IIRV message
  1005.      */
  1006.     private String buildLine2SplitByTerm(final String delimiter) {
  1007.         return IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, vectorType, dataSource, transferType, coordinateSystem, supportIdCode, vehicleIdCode, sequenceNumber, dayOfYear, vectorEpoch, line2CheckSum);
  1008.     }

  1009.     /**
  1010.      * Builds the third line of the IIRV message, not including ASCII carriage returns and line feeds.
  1011.      *
  1012.      * @param delimiter Delimiter to split the terms in the message. Should always be "", except when printing
  1013.      *                  for human readability.
  1014.      * @return Line 3 of IIRV message
  1015.      */
  1016.     private String buildLine3SplitByTerm(final String delimiter) {
  1017.         return IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, xPosition, yPosition, zPosition, line3CheckSum);
  1018.     }

  1019.     /**
  1020.      * Builds the fourth line of the IIRV message, not including ASCII carriage returns and line feeds.
  1021.      *
  1022.      * @param delimiter Delimiter to split the terms in the message. Should always be "", except when printing
  1023.      *                  for human readability.
  1024.      * @return Line f of IIRV message
  1025.      */
  1026.     private String buildLine4SplitByTerm(final String delimiter) {
  1027.         return IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, xVelocity, yVelocity, zVelocity, line4CheckSum);
  1028.     }

  1029.     /**
  1030.      * Builds the fifth line of the IIRV message, not including ASCII carriage returns and line feeds.
  1031.      *
  1032.      * @param delimiter Delimiter to split the terms in the message. Should always be "", except when printing
  1033.      *                  for human readability.
  1034.      * @return Line 5 of IIRV message
  1035.      */
  1036.     private String buildLine5SplitByTerm(final String delimiter) {
  1037.         return IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, mass, crossSectionalArea, dragCoefficient, solarReflectivityCoefficient, line5CheckSum);
  1038.     }

  1039.     /**
  1040.      * Builds the sixth line of the IIRV message, not including ASCII carriage returns and line feeds.
  1041.      *
  1042.      * @param delimiter Delimiter to split the terms in the message. Should always be "", except when printing
  1043.      *                  for human readability.
  1044.      * @return Line 6 of IIRV message
  1045.      */
  1046.     private String buildLine6SplitByTerm(final String delimiter) {
  1047.         return IIRVTermUtils.iirvTermsToLineStringSplitByTerm(delimiter, endOfMessage, spareTerm, originatorRoutingIndicatorTerm);
  1048.     }

  1049. }