ParseInfo.java
- /* Copyright 2022-2025 Luc Maisonobe
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.files.sinex;
- import org.hipparchus.util.FastMath;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.time.DateComponents;
- import org.orekit.time.TimeScale;
- import org.orekit.time.TimeScales;
- import org.orekit.utils.Constants;
- import org.orekit.utils.units.Unit;
- import java.util.regex.Pattern;
- /** Transient data used for parsing a SINEX file.
- * @param <T> type of the SINEX files
- * @author Luc Maisonobe
- * @since 13.0
- */
- public abstract class ParseInfo<T extends AbstractSinex> {
- /** 00:000:00000 epoch. */
- private static final String DEFAULT_EPOCH_TWO_DIGITS = "00:000:00000";
- /** 0000:000:00000 epoch. */
- private static final String DEFAULT_EPOCH_FOUR_DIGITS = "0000:000:00000";
- /** Pattern for delimiting regular expressions. */
- private static final Pattern SEPARATOR = Pattern.compile(":");
- /** Time scales. */
- private final TimeScales timeScales;
- /** Name of the data source. */
- private String name;
- /** Current line. */
- private String line;
- /** Current line number of the navigation message. */
- private int lineNumber;
- /** SINEX file creation date as extracted for the first line. */
- private AbsoluteDate creationDate;
- /** SINEX file creation date as extracted for the first line. */
- private String creationDateString;
- /** Start time of the data used in the Sinex solution. */
- private AbsoluteDate startDate;
- /** Start time of the data used in the Sinex solution. */
- private String startDateString;
- /** End time of the data used in the Sinex solution. */
- private AbsoluteDate endDate;
- /** End time of the data used in the Sinex solution. */
- private String endDateString;
- /** Time scale. */
- private TimeScale timeScale;
- /** Simple constructor.
- * @param timeScales time scales
- */
- protected ParseInfo(final TimeScales timeScales) {
- this.timeScales = timeScales;
- }
- /** Start parsing of a new data source.
- * @param newName name of the new data source
- */
- void newSource(final String newName) {
- // initialize parsing
- this.name = newName;
- this.line = null;
- this.lineNumber = 0;
- }
- /** Get name of data source.
- * @return name of data source
- */
- protected String getName() {
- return name;
- }
- /** Set current line.
- * @param line current line
- */
- void setLine(final String line)
- {
- this.line = line;
- }
- /** Get current line.
- * @return current line
- */
- String getLine() {
- return line;
- }
- /** Increment line number.
- */
- void incrementLineNumber() {
- ++lineNumber;
- }
- /** Get current line number.
- * @return current line number
- */
- int getLineNumber() {
- return lineNumber;
- }
- /** Set creation date.
- * @param dateString creation date
- */
- protected void setCreationDate(final String dateString) {
- this.creationDateString = dateString;
- this.creationDate = stringEpochToAbsoluteDate(creationDateString, false);
- }
- /** Get creation date.
- * @return creation date
- */
- protected AbsoluteDate getCreationDate() {
- return creationDate;
- }
- /** Set start date if earlier than previous setting.
- * @param candidateStartDateString candidate start date
- */
- protected void setStartDateIfEarlier(final String candidateStartDateString) {
- final AbsoluteDate candidateStart = stringEpochToAbsoluteDate(candidateStartDateString, true);
- if (startDate == null || candidateStart.isBefore(startDate)) {
- // this is either the first setting
- // or we are parsing a new data source referring to an earlier date than previous ones
- this.startDateString = candidateStartDateString;
- this.startDate = candidateStart;
- }
- }
- /** Get start date.
- * @return start date
- */
- protected AbsoluteDate getStartDate() {
- return startDate;
- }
- /** Set end date if later than previous setting.
- * @param candidateEndDateString end date
- */
- protected void setEndDateIfLater(final String candidateEndDateString) {
- final AbsoluteDate candidateEnd = stringEpochToAbsoluteDate(candidateEndDateString, true);
- if (endDate == null || candidateEnd.isAfter(endDate)) {
- // this is either the first setting
- // or we are parsing a new data source referring to a later date than previous ones
- this.endDateString = candidateEndDateString;
- this.endDate = candidateEnd;
- }
- }
- /** Get end date.
- * @return end date
- */
- protected AbsoluteDate getEndDate() {
- return endDate;
- }
- /** Set time scale.
- * @param timeScale time scale
- */
- protected void setTimeScale(final TimeScale timeScale) {
- this.timeScale = timeScale;
- // A time scale has been parsed, update start, end, and creation dates
- // to take into account the time scale
- if (startDateString != null) {
- startDate = stringEpochToAbsoluteDate(startDateString, true);
- }
- if (endDateString != null) {
- endDate = stringEpochToAbsoluteDate(endDateString, false);
- }
- if (creationDateString != null) {
- creationDate = stringEpochToAbsoluteDate(creationDateString, false);
- }
- }
- /** Get time scales.
- * @return time scales
- */
- TimeScales getTimeScales() {
- return timeScales;
- }
- /** Build the parsed file.
- * @return built parsed file
- */
- protected abstract T build();
- /** Extract a string from current line.
- * @param start start index of the string
- * @param length length of the string
- * @return parsed string
- */
- protected String parseString(final int start, final int length) {
- return line.substring(start, FastMath.min(line.length(), start + length)).trim();
- }
- /** Extract a double from current line.
- * @param start start index of the real
- * @param length length of the real
- * @return parsed real
- */
- protected double parseDouble(final int start, final int length) {
- return Double.parseDouble(parseString(start, length));
- }
- /** Extract an integer from current line.
- * @param start start index of the real
- * @param length length of the real
- * @return parsed integer
- */
- protected int parseInt(final int start, final int length) {
- return Integer.parseInt(parseString(start, length));
- }
- /** Extract a double from current line and convert in SI unit.
- * @param startUnit start index of the unit
- * @param lengthUnit length of the unit
- * @param startDouble start index of the real
- * @param lengthDouble length of the real
- * @return parsed double in SI unit
- */
- protected double parseDoubleWithUnit(final int startUnit, final int lengthUnit,
- final int startDouble, final int lengthDouble) {
- final Unit unit = Unit.parse(parseString(startUnit, lengthUnit));
- return unit.toSI(parseDouble(startDouble, lengthDouble));
- }
- /** Transform a String epoch to an AbsoluteDate.
- * @param stringDate string epoch
- * @param isStart true if epoch is a start validity epoch
- * @return the corresponding AbsoluteDate
- */
- protected AbsoluteDate stringEpochToAbsoluteDate(final String stringDate, final boolean isStart) {
- // Deal with 00:000:00000 epochs
- if (DEFAULT_EPOCH_TWO_DIGITS.equals(stringDate) || DEFAULT_EPOCH_FOUR_DIGITS.equals(stringDate)) {
- // If it's a start validity epoch, the file start date shall be used.
- // For end validity epoch, future infinity is acceptable.
- return isStart ? startDate : AbsoluteDate.FUTURE_INFINITY;
- }
- // Date components
- final String[] fields = SEPARATOR.split(stringDate);
- // Read fields
- final int digitsYear = Integer.parseInt(fields[0]);
- final int day = Integer.parseInt(fields[1]);
- final int secInDay = Integer.parseInt(fields[2]);
- // Data year
- final int year;
- if (digitsYear > 50 && digitsYear < 100) {
- year = 1900 + digitsYear;
- } else if (digitsYear < 100) {
- year = 2000 + digitsYear;
- } else {
- year = digitsYear;
- }
- // Return an absolute date.
- // Initialize to 1st January of the given year because
- // sometimes day is equal to 0 in the file.
- return new AbsoluteDate(new DateComponents(year, 1, 1), timeScale).
- shiftedBy(Constants.JULIAN_DAY * (day - 1)).
- shiftedBy(secInDay);
- }
- }