LazyLoadedTimeScales.java
/* Contributed in the public domain.
* 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.time;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.orekit.data.DataProvidersManager;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.frames.EOPHistory;
import org.orekit.frames.LazyLoadedEop;
import org.orekit.utils.IERSConventions;
/**
* An implementation of {@link TimeScales} that loads auxiliary data, leap seconds and
* UT1-UTC, when it is first accessed. The list of loaders may be modified before the
* first data access.
*
* @author Luc Maisonobe
* @author Evan Ward
* @see TimeScalesFactory
* @since 10.1
*/
public class LazyLoadedTimeScales extends AbstractTimeScales {
/** Source of EOP data. */
private final LazyLoadedEop lazyLoadedEop;
/** UTCTAI offsets loaders. */
private final List<UTCTAIOffsetsLoader> loaders = new ArrayList<>();
/** Universal Time Coordinate scale. */
private AtomicReference<UTCScale> utc = new AtomicReference<>();
/** International Atomic Time scale. */
private AtomicReference<TAIScale> tai = new AtomicReference<>();
/** Terrestrial Time scale. */
private AtomicReference<TTScale> tt = new AtomicReference<>();
/** Galileo System Time scale. */
private AtomicReference<GalileoScale> gst = new AtomicReference<>();
/** GLObal NAvigation Satellite System scale. */
private AtomicReference<GLONASSScale> glonass = new AtomicReference<>();
/** Quasi-Zenith Satellite System scale. */
private AtomicReference<QZSSScale> qzss = new AtomicReference<>();
/** Global Positioning System scale. */
private AtomicReference<GPSScale> gps = new AtomicReference<>();
/** Geocentric Coordinate Time scale. */
private AtomicReference<TCGScale> tcg = new AtomicReference<>();
/** Barycentric Dynamic Time scale. */
private AtomicReference<TDBScale> tdb = new AtomicReference<>();
/** Barycentric Coordinate Time scale. */
private AtomicReference<TCBScale> tcb = new AtomicReference<>();
/** IRNSS System Time scale. */
private AtomicReference<IRNSSScale> irnss = new AtomicReference<>();
/** BDS System Time scale. */
private AtomicReference<BDTScale> bds = new AtomicReference<>();
/**
* Create a new set of time scales with the given sources of auxiliary data. This
* constructor uses the same {@link DataProvidersManager} for the default EOP loaders
* and the default leap second loaders.
*
* @param lazyLoadedEop loads Earth Orientation Parameters for {@link
* #getUT1(IERSConventions, boolean)}.
*/
public LazyLoadedTimeScales(final LazyLoadedEop lazyLoadedEop) {
this.lazyLoadedEop = lazyLoadedEop;
}
/**
* Add a loader for UTC-TAI offsets history files.
*
* @param loader custom loader to add
* @see TAIUTCDatFilesLoader
* @see UTCTAIHistoryFilesLoader
* @see UTCTAIBulletinAFilesLoader
* @see #getUTC()
* @see #clearUTCTAIOffsetsLoaders()
* @since 7.1
*/
public void addUTCTAIOffsetsLoader(final UTCTAIOffsetsLoader loader) {
synchronized (this) {
loaders.add(loader);
}
}
/**
* Add the default loaders for UTC-TAI offsets history files (both IERS and USNO).
* <p>
* The default loaders are {@link TAIUTCDatFilesLoader} that looks for a file named
* {@code tai-utc.dat} that must be in USNO format, {@link
* UTCTAIHistoryFilesLoader} that looks for a file named {@code UTC-TAI.history} that
* must be in the IERS format and {@link AGILeapSecondFilesLoader} that looks for a
* files named {@code LeapSecond.dat} that must be in AGI format. The {@link
* UTCTAIBulletinAFilesLoader} is<em>not</em> added by default as it is not recommended.
* USNO warned us that the TAI-UTC data present in bulletin A was for convenience only
* and was not reliable, there have been errors in several bulletins regarding these data.
* </p>
*
* @see <a href="http://maia.usno.navy.mil/ser7/tai-utc.dat">USNO tai-utc.dat
* file</a>
* @see <a href="http://hpiers.obspm.fr/eoppc/bul/bulc/UTC-TAI.history">IERS
* UTC-TAI.history file</a>
* @see TAIUTCDatFilesLoader
* @see UTCTAIHistoryFilesLoader
* @see AGILeapSecondFilesLoader
* @see #getUTC()
* @see #clearUTCTAIOffsetsLoaders()
* @since 7.1
*/
public void addDefaultUTCTAIOffsetsLoaders() {
synchronized (this) {
final DataProvidersManager dataProvidersManager =
lazyLoadedEop.getDataProvidersManager();
addUTCTAIOffsetsLoader(new TAIUTCDatFilesLoader(TAIUTCDatFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
addUTCTAIOffsetsLoader(new UTCTAIHistoryFilesLoader(dataProvidersManager));
addUTCTAIOffsetsLoader(new AGILeapSecondFilesLoader(AGILeapSecondFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
}
}
/**
* Clear loaders for UTC-TAI offsets history files.
*
* @see #getUTC()
* @see #addUTCTAIOffsetsLoader(UTCTAIOffsetsLoader)
* @see #addDefaultUTCTAIOffsetsLoaders()
* @since 7.1
*/
public void clearUTCTAIOffsetsLoaders() {
synchronized (this) {
loaders.clear();
}
}
@Override
public TAIScale getTAI() {
TAIScale refTai = tai.get();
if (refTai == null) {
tai.compareAndSet(null, new TAIScale());
refTai = tai.get();
}
return refTai;
}
@Override
public UTCScale getUTC() {
UTCScale refUtc = utc.get();
if (refUtc == null) {
synchronized (this) {
if (utc.get() == null) { // Check if utc was not loaded in the meantime
List<OffsetModel> entries = Collections.emptyList();
if (loaders.isEmpty()) {
addDefaultUTCTAIOffsetsLoaders();
}
for (UTCTAIOffsetsLoader loader : loaders) {
entries = loader.loadOffsets();
if (!entries.isEmpty()) {
break;
}
}
if (entries.isEmpty()) {
throw new OrekitException(OrekitMessages.NO_IERS_UTC_TAI_HISTORY_DATA_LOADED);
}
utc.compareAndSet(null, new UTCScale(getTAI(), entries));
}
refUtc = utc.get();
}
}
return refUtc;
}
@Override
public UT1Scale getUT1(final IERSConventions conventions, final boolean simpleEOP) {
// synchronized to maintain the same semantics as Orekit 10.0
synchronized (this) {
return super.getUT1(conventions, simpleEOP);
}
}
@Override
protected EOPHistory getEopHistory(final IERSConventions conventions,
final boolean simpleEOP) {
return lazyLoadedEop.getEOPHistory(conventions, simpleEOP, this);
}
// need to make this public for compatibility. Provides access to UT1 constructor.
/** {@inheritDoc} */
@Override
public UT1Scale getUT1(final EOPHistory history) {
return super.getUT1(history);
}
@Override
public TTScale getTT() {
TTScale refTt = tt.get();
if (refTt == null) {
tt.compareAndSet(null, new TTScale());
refTt = tt.get();
}
return refTt;
}
@Override
public GalileoScale getGST() {
GalileoScale refGst = gst.get();
if (refGst == null) {
gst.compareAndSet(null, new GalileoScale());
refGst = gst.get();
}
return refGst;
}
@Override
public GLONASSScale getGLONASS() {
GLONASSScale refGlonass = glonass.get();
if (refGlonass == null) {
glonass.compareAndSet(null, new GLONASSScale(getUTC()));
refGlonass = glonass.get();
}
return refGlonass;
}
@Override
public QZSSScale getQZSS() {
QZSSScale refQzss = qzss.get();
if (refQzss == null) {
qzss.compareAndSet(null, new QZSSScale());
refQzss = qzss.get();
}
return refQzss;
}
@Override
public GPSScale getGPS() {
GPSScale refGps = gps.get();
if (refGps == null) {
gps.compareAndSet(null, new GPSScale());
refGps = gps.get();
}
return refGps;
}
@Override
public TCGScale getTCG() {
TCGScale refTcg = tcg.get();
if (refTcg == null) {
tcg.compareAndSet(null, new TCGScale(getTT(), getTAI()));
refTcg = tcg.get();
}
return refTcg;
}
@Override
public TDBScale getTDB() {
TDBScale refTdb = tdb.get();
if (refTdb == null) {
tdb.compareAndSet(null, new TDBScale(getTT(), getJ2000Epoch()));
refTdb = tdb.get();
}
return refTdb;
}
@Override
public TCBScale getTCB() {
TCBScale refTcb = tcb.get();
if (refTcb == null) {
tcb.compareAndSet(null, new TCBScale(getTDB(), getTAI()));
refTcb = tcb.get();
}
return refTcb;
}
@Override
public GMSTScale getGMST(final IERSConventions conventions, final boolean simpleEOP) {
// synchronized to maintain the same semantics as Orekit 10.0
synchronized (this) {
return super.getGMST(conventions, simpleEOP);
}
}
@Override
public IRNSSScale getIRNSS() {
IRNSSScale refIrnss = irnss.get();
if (refIrnss == null) {
irnss.compareAndSet(null, new IRNSSScale());
refIrnss = irnss.get();
}
return refIrnss;
}
@Override
public BDTScale getBDT() {
BDTScale refBds = bds.get();
if (refBds == null) {
bds.compareAndSet(null, new BDTScale());
refBds = bds.get();
}
return refBds;
}
}