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.terms;
18
19
20 import org.orekit.errors.OrekitIllegalArgumentException;
21 import org.orekit.errors.OrekitMessages;
22 import org.orekit.files.iirv.IIRVVector;
23 import org.orekit.files.iirv.terms.base.IIRVVectorTerm;
24 import org.orekit.files.iirv.terms.base.LongValuedIIRVTerm;
25
26 /**
27 * Three-character checksum to validate message.
28 * <p>
29 * Calculated by summing the decimal equivalent of the preceding characters in the line, counting spaces as 0 and
30 * negative signs as 1:
31 * <ul>
32 * <li> 0 through 9 = face value
33 * <li> Minus (-) = 1
34 * <li> ASCII Space = 0
35 * </ul>
36 * <p>
37 * Valid Values: 000-999
38 *
39 * @author Nick LaFarge
40 * @since 13.0
41 */
42 public class CheckSumTerm extends LongValuedIIRVTerm {
43
44 /** The length of the IIRV term within the message. */
45 public static final int CHECK_SUM_TERM_LENGTH = 3;
46
47 /** Regular expression that ensures the validity of string values for this term. */
48 public static final String CHECK_SUM_TERM_PATTERN = "\\d{3}";
49
50 /**
51 * Constructor.
52 * <p>
53 * See {@link LongValuedIIRVTerm#LongValuedIIRVTerm(String, String, int, boolean)}
54 *
55 * @param value value of the coordinate system term
56 */
57 public CheckSumTerm(final String value) {
58 super(CHECK_SUM_TERM_PATTERN, value.replace(IIRVVector.LINE_SEPARATOR, ""), CHECK_SUM_TERM_LENGTH, false);
59 }
60
61 /**
62 * Constructor.
63 * <p>
64 * See {@link LongValuedIIRVTerm#LongValuedIIRVTerm(String, long, int, boolean)}
65 *
66 * @param value value of the coordinate system term
67 */
68 public CheckSumTerm(final long value) {
69 super(CHECK_SUM_TERM_PATTERN, value, CHECK_SUM_TERM_LENGTH, false);
70 }
71
72 /**
73 * Constructs an IIRV checksum from a series of IIRVTerm instances.
74 *
75 * @param terms IIRVTerms to compute checksum
76 * @return newly created CheckSum instance
77 */
78 public static CheckSumTerm fromIIRVTerms(final IIRVVectorTerm<?>... terms) {
79 final String lineString = IIRVTermUtils.iirvTermsToLineString(terms);
80 return new CheckSumTerm(computeChecksum(lineString));
81 }
82
83 /**
84 * Computes the sum of the decimal equivalent of characters in the line, counting spaces as 0 and
85 * negative signs as 1.
86 *
87 * @param input input string to compute checksum from
88 * @return computed checksum integer value
89 */
90 public static int computeChecksum(final String input) {
91 // Compute the sum based on the characters
92 int sum = 0;
93 for (int i = 0; i < input.length(); i++) {
94 final char c = input.charAt(i);
95 final int valueToAdd;
96 if (Character.isDigit(c)) {
97 valueToAdd = Character.getNumericValue(c); // Convert the digit character to its numeric value
98 } else if (c == ' ') {
99 valueToAdd = 0; // Space counts as 0
100 } else if (c == '-') {
101 valueToAdd = 1; // Sign character counts as 1
102 } else {
103 throw new OrekitIllegalArgumentException(OrekitMessages.IIRV_INVALID_TERM_VALUE, c);
104 }
105 sum += valueToAdd; // Increment the sum
106 }
107 return sum;
108 }
109
110 /**
111 * Validate a line's embedded checksum value.
112 *
113 * @param line string line of an IIRV message (including checksum as the final three characters)
114 * @return true if the derived and embedded checksum values are equal
115 */
116 public static boolean validateLineCheckSum(final String line) {
117 // Don't include carriage/line returns in checksum
118 final String strippedLine = line.replace(IIRVVector.LINE_SEPARATOR, "");
119
120 // Separate message from checksum
121 final String message = strippedLine.substring(0, strippedLine.length() - 3);
122 final String checkSum = strippedLine.substring(strippedLine.length() - 3);
123
124 return CheckSumTerm.computeChecksum(message) == Integer.parseInt(checkSum);
125 }
126
127 /**
128 * Validate the checksum from a line based on the object's checksum integer value.
129 *
130 * @param line string line of an IIRV message (including checksum as the final three characters)
131 * @return true if the extracted checksum value matches this object's integer value
132 */
133 public boolean validateAgainstLineString(final String line) {
134 final String strippedLine = line.replace(IIRVVector.LINE_SEPARATOR, "");
135 final String message = strippedLine.substring(0, strippedLine.length() - 3);
136 final int computedChecksum = computeChecksum(message);
137 return value() == computedChecksum;
138 }
139
140 }