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.gnss;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  import java.util.function.Function;
22  
23  import org.orekit.errors.OrekitIllegalArgumentException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.time.TimeScale;
26  import org.orekit.time.TimeScales;
27  
28  /** Enumerate for the time systems used in navigation files.
29   *
30   * @author Thomas Neidhart
31   * @author Evan Ward
32   * @author Thomas Paulet
33   * @since 11.0
34   */
35  public enum TimeSystem {
36  
37      /** Global Positioning System. */
38      GPS("GPS", "GP", "G", TimeScales::getGPS),
39  
40      /** GLONASS. */
41      GLONASS("GLO", "GL", "R", TimeScales::getGLONASS),
42  
43      /** GALILEO. */
44      GALILEO("GAL", "GA", "E", TimeScales::getGST),
45  
46      /** International Atomic Time. */
47      TAI("TAI", null, null, TimeScales::getTAI),
48  
49      /** Coordinated Universal Time. */
50      UTC("UTC", "UT", null, TimeScales::getUTC),
51  
52      /** Quasi-Zenith System. */
53      QZSS("QZS", "QZ", "J", TimeScales::getQZSS),
54  
55      /** Beidou. */
56      BEIDOU("BDT", "BD", "C", TimeScales::getBDT),
57  
58      /** NavIC. */
59      NAVIC("IRN", "IR", "I", TimeScales::getNavIC),
60  
61      /** SBAS.
62       * @since 12.0
63       */
64      SBAS(null, "SB", "S", TimeScales::getUTC),
65  
66      /** GMT (should only be used in RUN BY / DATE entries).
67       * @since 12.0
68       */
69      GMT("GMT", null, null, TimeScales::getUTC),
70  
71      /** Unknown (should only be used in RUN BY / DATE entries). */
72      UNKNOWN("LCL", null, null, TimeScales::getGPS);
73  
74      /** Parsing key map. */
75      private static final Map<String, TimeSystem> KEYS_MAP = new HashMap<>();
76  
77      /** Parsing two letters code map.
78       * @since 12.0
79       */
80      private static final Map<String, TimeSystem> TLC_MAP = new HashMap<>();
81  
82      /** Parsing one letters code map.
83       * @since 12.0
84       */
85      private static final Map<String, TimeSystem> OLC_MAP = new HashMap<>();
86  
87      static {
88          for (final TimeSystem timeSystem : values()) {
89              if (timeSystem.key != null) {
90                  KEYS_MAP.put(timeSystem.key, timeSystem);
91              }
92              if (timeSystem.twoLettersCode != null) {
93                  TLC_MAP.put(timeSystem.twoLettersCode, timeSystem);
94              }
95              if (timeSystem.oneLetterCode != null) {
96                  OLC_MAP.put(timeSystem.oneLetterCode, timeSystem);
97              }
98          }
99      }
100 
101     /** Key for the system. */
102     private final String key;
103 
104     /** Two-letters code.
105      * @since 12.0
106      */
107     private final String twoLettersCode;
108 
109     /** One-letter code.
110      * @since 12.0
111      */
112     private final String oneLetterCode;
113 
114     /** Time scale provider.
115      * @since 12.0
116      */
117     private final Function<TimeScales, TimeScale> timeScaleProvider;
118 
119     /** Simple constructor.
120      * @param key key letter (may be null)
121      * @param twoLettersCode two letters code (may be null)
122      * @param oneLetterCode one letter code (may be null)
123      * @param timeScaleProvider time scale provider
124      */
125     TimeSystem(final String key, final String twoLettersCode, final String oneLetterCode,
126                final Function<TimeScales, TimeScale> timeScaleProvider) {
127         this.key               = key;
128         this.twoLettersCode    = twoLettersCode;
129         this.oneLetterCode     = oneLetterCode;
130         this.timeScaleProvider = timeScaleProvider;
131     }
132 
133     /** Get the 3 letters key of the time system.
134      * @return 3 letters key
135      * @since 12.0
136      */
137     public String getKey() {
138         return key;
139     }
140 
141     /** Get the two letters code.
142      * @return two letters code (may be null for non-GNSS time systems)
143      * @since 12.2
144      */
145     public String getTwoLettersCode() {
146         return twoLettersCode;
147     }
148 
149     /** Get the one letter code.
150      * @return one letter code (may be null for non-GNSS time systems)
151      * @since 12.2
152      */
153     public String getOneLetterCode() {
154         return oneLetterCode;
155     }
156 
157     /** Parse a string to get the time system.
158      * <p>
159      * The string must be the time system.
160      * </p>
161      * @param s string to parse
162      * @return the time system
163      * @exception OrekitIllegalArgumentException if the string does not correspond to a time system key
164      */
165     public static TimeSystem parseTimeSystem(final String s)
166         throws OrekitIllegalArgumentException {
167         final TimeSystem timeSystem = KEYS_MAP.get(s);
168         if (timeSystem == null) {
169             throw new OrekitIllegalArgumentException(OrekitMessages.UNKNOWN_TIME_SYSTEM, s);
170         }
171         return timeSystem;
172     }
173 
174     /** Parse a string to get the time system.
175      * <p>
176      * The string must be the two letters code of the time system.
177      * </p>
178      * @param code string to parse
179      * @return the time system
180      * @exception OrekitIllegalArgumentException if the string does not correspond to a time system key
181      */
182     public static TimeSystem parseTwoLettersCode(final String code)
183         throws OrekitIllegalArgumentException {
184         final TimeSystem timeSystem = TLC_MAP.get(code);
185         if (timeSystem == null) {
186             throw new OrekitIllegalArgumentException(OrekitMessages.UNKNOWN_TIME_SYSTEM, code);
187         }
188         return timeSystem;
189     }
190 
191     /** Parse a string to get the time system.
192      * <p>
193      * The string must be the one letters code of the time system.
194      * The one letter code is the RINEX GNSS system flag.
195      * </p>
196      * @param code string to parse
197      * @return the time system
198      * @exception OrekitIllegalArgumentException if the string does not correspond to a time system key
199      */
200     public static TimeSystem parseOneLetterCode(final String code)
201         throws OrekitIllegalArgumentException {
202         final TimeSystem timeSystem = OLC_MAP.get(code);
203         if (timeSystem == null) {
204             throw new OrekitIllegalArgumentException(OrekitMessages.UNKNOWN_TIME_SYSTEM, code);
205         }
206         return timeSystem;
207     }
208 
209     /** Get the time scale corresponding to time system.
210      * @param timeScales the set of time scales to use
211      * @return the time scale corresponding to time system in the set of time scales
212      */
213     public TimeScale getTimeScale(final TimeScales timeScales) {
214         return timeScaleProvider.apply(timeScales);
215     }
216 
217 }