1 /* Contributed in the public domain.
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.time;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.orekit.data.DataProvidersManager;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.frames.EOPHistory;
27 import org.orekit.frames.LazyLoadedEop;
28 import org.orekit.utils.IERSConventions;
29
30 /**
31 * An implementation of {@link TimeScales} that loads auxiliary data, leap seconds and
32 * UT1-UTC, when it is first accessed. The list of loaders may be modified before the
33 * first data access.
34 *
35 * @author Luc Maisonobe
36 * @author Evan Ward
37 * @see TimeScalesFactory
38 * @since 10.1
39 */
40 public class LazyLoadedTimeScales extends AbstractTimeScales {
41
42 /** Source of EOP data. */
43 private final LazyLoadedEop lazyLoadedEop;
44
45 /** UTCTAI offsets loaders. */
46 private final List<UTCTAIOffsetsLoader> loaders = new ArrayList<>();
47 /** Universal Time Coordinate scale. */
48 private UTCScale utc = null;
49
50 /** International Atomic Time scale. */
51 private TAIScale tai = null;
52
53 /** Terrestrial Time scale. */
54 private TTScale tt = null;
55
56 /** Galileo System Time scale. */
57 private GalileoScale gst = null;
58
59 /** GLObal NAvigation Satellite System scale. */
60 private GLONASSScale glonass = null;
61
62 /** Quasi-Zenith Satellite System scale. */
63 private QZSSScale qzss = null;
64
65 /** Global Positioning System scale. */
66 private GPSScale gps = null;
67
68 /** Geocentric Coordinate Time scale. */
69 private TCGScale tcg = null;
70
71 /** Barycentric Dynamic Time scale. */
72 private TDBScale tdb = null;
73
74 /** Barycentric Coordinate Time scale. */
75 private TCBScale tcb = null;
76
77 /** IRNSS System Time scale. */
78 private IRNSSScale irnss = null;
79
80 /** BDS System Time scale. */
81 private BDTScale bds = null;
82
83 /**
84 * Create a new set of time scales with the given sources of auxiliary data. This
85 * constructor uses the same {@link DataProvidersManager} for the default EOP loaders
86 * and the default leap second loaders.
87 *
88 * @param lazyLoadedEop loads Earth Orientation Parameters for {@link
89 * #getUT1(IERSConventions, boolean)}.
90 */
91 public LazyLoadedTimeScales(final LazyLoadedEop lazyLoadedEop) {
92 this.lazyLoadedEop = lazyLoadedEop;
93 }
94
95 /**
96 * Add a loader for UTC-TAI offsets history files.
97 *
98 * @param loader custom loader to add
99 * @see TAIUTCDatFilesLoader
100 * @see UTCTAIHistoryFilesLoader
101 * @see UTCTAIBulletinAFilesLoader
102 * @see #getUTC()
103 * @see #clearUTCTAIOffsetsLoaders()
104 * @since 7.1
105 */
106 public void addUTCTAIOffsetsLoader(final UTCTAIOffsetsLoader loader) {
107 synchronized (this) {
108 loaders.add(loader);
109 }
110 }
111
112 /**
113 * Add the default loaders for UTC-TAI offsets history files (both IERS and USNO).
114 * <p>
115 * The default loaders are {@link TAIUTCDatFilesLoader} that looks for a file named
116 * {@code tai-utc.dat} that must be in USNO format, {@link
117 * UTCTAIHistoryFilesLoader} that looks for a file named {@code UTC-TAI.history} that
118 * must be in the IERS format and {@link AGILeapSecondFilesLoader} that looks for a
119 * files named {@code LeapSecond.dat} that must be in AGI format. The {@link
120 * UTCTAIBulletinAFilesLoader} is<em>not</em> added by default as it is not recommended.
121 * USNO warned us that the TAI-UTC data present in bulletin A was for convenience only
122 * and was not reliable, there have been errors in several bulletins regarding these data.
123 * </p>
124 *
125 * @see <a href="http://maia.usno.navy.mil/ser7/tai-utc.dat">USNO tai-utc.dat
126 * file</a>
127 * @see <a href="http://hpiers.obspm.fr/eoppc/bul/bulc/UTC-TAI.history">IERS
128 * UTC-TAI.history file</a>
129 * @see TAIUTCDatFilesLoader
130 * @see UTCTAIHistoryFilesLoader
131 * @see AGILeapSecondFilesLoader
132 * @see #getUTC()
133 * @see #clearUTCTAIOffsetsLoaders()
134 * @since 7.1
135 */
136 public void addDefaultUTCTAIOffsetsLoaders() {
137 synchronized (this) {
138 final DataProvidersManager dataProvidersManager =
139 lazyLoadedEop.getDataProvidersManager();
140 addUTCTAIOffsetsLoader(new TAIUTCDatFilesLoader(TAIUTCDatFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
141 addUTCTAIOffsetsLoader(new UTCTAIHistoryFilesLoader(dataProvidersManager));
142 addUTCTAIOffsetsLoader(new AGILeapSecondFilesLoader(AGILeapSecondFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
143 }
144 }
145
146 /**
147 * Clear loaders for UTC-TAI offsets history files.
148 *
149 * @see #getUTC()
150 * @see #addUTCTAIOffsetsLoader(UTCTAIOffsetsLoader)
151 * @see #addDefaultUTCTAIOffsetsLoaders()
152 * @since 7.1
153 */
154 public void clearUTCTAIOffsetsLoaders() {
155 synchronized (this) {
156 loaders.clear();
157 }
158 }
159
160 @Override
161 public TAIScale getTAI() {
162 synchronized (this) {
163
164 if (tai == null) {
165 tai = new TAIScale();
166 }
167
168 return tai;
169
170 }
171 }
172
173 @Override
174 public UTCScale getUTC() {
175 synchronized (this) {
176 if (utc == null) {
177 List<OffsetModel> entries = Collections.emptyList();
178 if (loaders.isEmpty()) {
179 addDefaultUTCTAIOffsetsLoaders();
180 }
181 for (UTCTAIOffsetsLoader loader : loaders) {
182 entries = loader.loadOffsets();
183 if (!entries.isEmpty()) {
184 break;
185 }
186 }
187 if (entries.isEmpty()) {
188 throw new OrekitException(OrekitMessages.NO_IERS_UTC_TAI_HISTORY_DATA_LOADED);
189 }
190 utc = new UTCScale(getTAI(), entries);
191 }
192
193 return utc;
194 }
195 }
196
197 @Override
198 public UT1Scale getUT1(final IERSConventions conventions, final boolean simpleEOP) {
199 // synchronized to maintain the same semantics as Orekit 10.0
200 synchronized (this) {
201 return super.getUT1(conventions, simpleEOP);
202 }
203 }
204
205 @Override
206 protected EOPHistory getEopHistory(final IERSConventions conventions,
207 final boolean simpleEOP) {
208 return lazyLoadedEop.getEOPHistory(conventions, simpleEOP, this);
209 }
210
211 // need to make this public for compatibility. Provides access to UT1 constructor.
212 /** {@inheritDoc} */
213 @Override
214 public UT1Scale getUT1(final EOPHistory history) {
215 return super.getUT1(history);
216 }
217
218 @Override
219 public TTScale getTT() {
220 synchronized (this) {
221
222 if (tt == null) {
223 tt = new TTScale();
224 }
225
226 return tt;
227
228 }
229 }
230
231 @Override
232 public GalileoScale getGST() {
233 synchronized (this) {
234
235 if (gst == null) {
236 gst = new GalileoScale();
237 }
238
239 return gst;
240
241 }
242 }
243
244 @Override
245 public GLONASSScale getGLONASS() {
246 synchronized (this) {
247
248 if (glonass == null) {
249 glonass = new GLONASSScale(getUTC());
250 }
251
252 return glonass;
253
254 }
255 }
256
257 @Override
258 public QZSSScale getQZSS() {
259 synchronized (this) {
260
261 if (qzss == null) {
262 qzss = new QZSSScale();
263 }
264
265 return qzss;
266
267 }
268 }
269
270 @Override
271 public GPSScale getGPS() {
272 synchronized (this) {
273
274 if (gps == null) {
275 gps = new GPSScale();
276 }
277
278 return gps;
279
280 }
281 }
282
283 @Override
284 public TCGScale getTCG() {
285 synchronized (this) {
286
287 if (tcg == null) {
288 tcg = new TCGScale(getTT(), getTAI());
289 }
290
291 return tcg;
292
293 }
294 }
295
296 @Override
297 public TDBScale getTDB() {
298 synchronized (this) {
299
300 if (tdb == null) {
301 tdb = new TDBScale(getTT(), getJ2000Epoch());
302 }
303
304 return tdb;
305
306 }
307 }
308
309 @Override
310 public TCBScale getTCB() {
311 synchronized (this) {
312
313 if (tcb == null) {
314 tcb = new TCBScale(getTDB(), getTAI());
315 }
316
317 return tcb;
318
319 }
320 }
321
322 @Override
323 public GMSTScale getGMST(final IERSConventions conventions, final boolean simpleEOP) {
324 // synchronized to maintain the same semantics as Orekit 10.0
325 synchronized (this) {
326 return super.getGMST(conventions, simpleEOP);
327 }
328 }
329
330 @Override
331 public IRNSSScale getIRNSS() {
332 synchronized (this) {
333
334 if (irnss == null) {
335 irnss = new IRNSSScale();
336 }
337
338 return irnss;
339
340 }
341 }
342
343 @Override
344 public BDTScale getBDT() {
345 synchronized (this) {
346
347 if (bds == null) {
348 bds = new BDTScale();
349 }
350
351 return bds;
352
353 }
354 }
355
356 }