1   /* Copyright 2002-2025 CS GROUP
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.ccsds.ndm.odm;
18  
19  import java.util.List;
20  import java.util.function.Function;
21  
22  import org.orekit.data.DataContext;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.files.ccsds.ndm.NdmConstituent;
26  import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
27  import org.orekit.files.ccsds.utils.lexical.ParseToken;
28  import org.orekit.files.ccsds.utils.parsing.AbstractConstituentParser;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.utils.IERSConventions;
31  
32  /** Common parser for Orbit Parameter/Ephemeris/Mean/Comprehensive Messages.
33   * <p>
34   * Note than starting with Orekit 11.0, CCSDS message parsers are
35   * mutable objects that gather the data being parsed, until the
36   * message is complete and the {@link #parseMessage(org.orekit.data.DataSource)
37   * parseMessage} method has returned. This implies that parsers
38   * should <em>not</em> be used in a multi-thread context. The recommended
39   * way to use parsers is to either dedicate one parser for each message
40   * and drop it afterwards, or to use a single-thread loop.
41   * </p>
42   * @param <T> type of the ODM file
43   * @param <P> type of the parser
44   * @author Luc Maisonobe
45   * @since 11.0
46   */
47  public abstract class OdmParser<T extends NdmConstituent<OdmHeader, ?>, P extends OdmParser<T, ?>>
48      extends AbstractConstituentParser<OdmHeader, T, P> {
49  
50      /** Reference date for Mission Elapsed Time or Mission Relative Time time systems. */
51      private final AbsoluteDate missionReferenceDate;
52  
53      /** Gravitational coefficient set by the user in the parser. */
54      private final double muSet;
55  
56      /** Gravitational coefficient parsed in the ODM File. */
57      private double muParsed;
58  
59      /** Gravitational coefficient created from the knowledge of the central body. */
60      private double muCreated;
61  
62      /** Complete constructor.
63       * @param root root element for XML files
64       * @param formatVersionKey key for format version
65       * @param conventions IERS Conventions
66       * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
67       * @param dataContext used to retrieve frames and time scales
68       * @param missionReferenceDate reference date for Mission Elapsed Time or Mission Relative Time time systems
69       * @param mu gravitational coefficient
70       * @param parsedUnitsBehavior behavior to adopt for handling parsed units
71       * @param filters filters to apply to parse tokens
72       * @since 12.0
73       */
74      protected OdmParser(final String root, final String formatVersionKey,
75                          final IERSConventions conventions, final boolean simpleEOP,
76                          final DataContext dataContext, final AbsoluteDate missionReferenceDate,
77                          final double mu, final ParsedUnitsBehavior parsedUnitsBehavior,
78                          final Function<ParseToken, List<ParseToken>>[] filters) {
79          super(root, formatVersionKey, conventions, simpleEOP, dataContext, parsedUnitsBehavior, filters);
80          this.missionReferenceDate = missionReferenceDate;
81          this.muSet                = mu;
82          this.muParsed             = Double.NaN;
83          this.muCreated            = Double.NaN;
84      }
85  
86      /**
87       * Get reference date for Mission Elapsed Time and Mission Relative Time time systems.
88       * @return the reference date
89       */
90      public AbsoluteDate getMissionReferenceDate() {
91          return missionReferenceDate;
92      }
93  
94      /** Get the gravitational coefficient set at construction.
95       * @return gravitational coefficient set at construction
96       */
97      protected double getMuSet() {
98          return muSet;
99      }
100 
101     /**
102      * Set the gravitational coefficient parsed in the ODM File.
103      * @param muParsed the coefficient to be set
104      */
105     protected void setMuParsed(final double muParsed) {
106         this.muParsed = muParsed;
107     }
108 
109     /**
110      * Set the gravitational coefficient created from the knowledge of the central body.
111      * @param muCreated the coefficient to be set
112      */
113     protected void setMuCreated(final double muCreated) {
114         this.muCreated = muCreated;
115     }
116 
117     /**
118      * Select the gravitational coefficient to use.
119      * In order of decreasing priority, finalMU is set equal to:
120      * <ol>
121      *   <li>the coefficient parsed in the file,</li>
122      *   <li>the coefficient set by the user with the parser's method setMu,</li>
123      *   <li>the coefficient created from the knowledge of the central body.</li>
124      * </ol>
125      * @return selected gravitational coefficient
126      */
127     public double getSelectedMu() {
128         if (!Double.isNaN(muParsed)) {
129             return muParsed;
130         } else if (!Double.isNaN(muSet)) {
131             return muSet;
132         } else if (!Double.isNaN(muCreated)) {
133             return muCreated;
134         } else {
135             throw new OrekitException(OrekitMessages.CCSDS_UNKNOWN_GM);
136         }
137     }
138 
139 }