LazyLoadedTimeScales.java

  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. import java.util.ArrayList;
  19. import java.util.Collections;
  20. import java.util.List;
  21. import java.util.concurrent.atomic.AtomicReference;

  22. import org.orekit.data.DataProvidersManager;
  23. import org.orekit.errors.OrekitException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.frames.EOPHistory;
  26. import org.orekit.frames.LazyLoadedEop;
  27. import org.orekit.utils.IERSConventions;

  28. /**
  29.  * An implementation of {@link TimeScales} that loads auxiliary data, leap seconds and
  30.  * UT1-UTC, when it is first accessed. The list of loaders may be modified before the
  31.  * first data access.
  32.  *
  33.  * @author Luc Maisonobe
  34.  * @author Evan Ward
  35.  * @see TimeScalesFactory
  36.  * @since 10.1
  37.  */
  38. public class LazyLoadedTimeScales extends AbstractTimeScales {

  39.     /** Source of EOP data. */
  40.     private final LazyLoadedEop lazyLoadedEop;

  41.     /** UTCTAI offsets loaders. */
  42.     private final List<UTCTAIOffsetsLoader> loaders = new ArrayList<>();

  43.     /** Universal Time Coordinate scale. */
  44.     private final AtomicReference<UTCScale> utc = new AtomicReference<>();

  45.     /** International Atomic Time scale. */
  46.     private final AtomicReference<TAIScale> tai = new AtomicReference<>();

  47.     /** Terrestrial Time scale. */
  48.     private final AtomicReference<TTScale> tt = new AtomicReference<>();

  49.     /** Galileo System Time scale. */
  50.     private final AtomicReference<GalileoScale> gst = new AtomicReference<>();

  51.     /** GLObal NAvigation Satellite System scale. */
  52.     private final AtomicReference<GLONASSScale> glonass = new AtomicReference<>();

  53.     /** Quasi-Zenith Satellite System scale. */
  54.     private final AtomicReference<QZSSScale> qzss = new AtomicReference<>();

  55.     /** Global Positioning System scale. */
  56.     private final AtomicReference<GPSScale> gps = new AtomicReference<>();

  57.     /** Geocentric Coordinate Time scale. */
  58.     private final AtomicReference<TCGScale> tcg = new AtomicReference<>();

  59.     /** Barycentric Dynamic Time scale. */
  60.     private final AtomicReference<TDBScale> tdb = new AtomicReference<>();

  61.     /** Barycentric Coordinate Time scale. */
  62.     private final AtomicReference<TCBScale> tcb = new AtomicReference<>();

  63.     /** NavIC System Time scale. */
  64.     private final AtomicReference<NavicScale> navic = new AtomicReference<>();

  65.     /** BDS System Time scale. */
  66.     private final AtomicReference<BDTScale> bds = new AtomicReference<>();

  67.     /**
  68.      * Create a new set of time scales with the given sources of auxiliary data. This
  69.      * constructor uses the same {@link DataProvidersManager} for the default EOP loaders
  70.      * and the default leap second loaders.
  71.      *
  72.      * @param lazyLoadedEop loads Earth Orientation Parameters for {@link
  73.      *                      #getUT1(IERSConventions, boolean)}.
  74.      */
  75.     public LazyLoadedTimeScales(final LazyLoadedEop lazyLoadedEop) {
  76.         this.lazyLoadedEop = lazyLoadedEop;
  77.     }

  78.     /**
  79.      * Add a loader for UTC-TAI offsets history files.
  80.      *
  81.      * @param loader custom loader to add
  82.      * @see TAIUTCDatFilesLoader
  83.      * @see UTCTAIHistoryFilesLoader
  84.      * @see UTCTAIBulletinAFilesLoader
  85.      * @see #getUTC()
  86.      * @see #clearUTCTAIOffsetsLoaders()
  87.      * @since 7.1
  88.      */
  89.     public void addUTCTAIOffsetsLoader(final UTCTAIOffsetsLoader loader) {
  90.         synchronized (this) {
  91.             loaders.add(loader);
  92.         }
  93.     }

  94.     /**
  95.      * Add the default loaders for UTC-TAI offsets history files (both IERS and USNO).
  96.      * <p>
  97.      * The default loaders are {@link TAIUTCDatFilesLoader} that looks for a file named
  98.      * {@code tai-utc.dat} that must be in USNO format, {@link
  99.      * UTCTAIHistoryFilesLoader} that looks for a file named {@code UTC-TAI.history} that
  100.      * must be in the IERS format and {@link AGILeapSecondFilesLoader} that looks for a
  101.      * files named {@code LeapSecond.dat} that must be in AGI format. The {@link
  102.      * UTCTAIBulletinAFilesLoader} is<em>not</em> added by default as it is not recommended.
  103.      * USNO warned us that the TAI-UTC data present in bulletin A was for convenience only
  104.      * and was not reliable, there have been errors in several bulletins regarding these data.
  105.      * </p>
  106.      *
  107.      * @see <a href="http://maia.usno.navy.mil/ser7/tai-utc.dat">USNO tai-utc.dat
  108.      * file</a>
  109.      * @see <a href="http://hpiers.obspm.fr/eoppc/bul/bulc/UTC-TAI.history">IERS
  110.      * UTC-TAI.history file</a>
  111.      * @see TAIUTCDatFilesLoader
  112.      * @see UTCTAIHistoryFilesLoader
  113.      * @see AGILeapSecondFilesLoader
  114.      * @see #getUTC()
  115.      * @see #clearUTCTAIOffsetsLoaders()
  116.      * @since 7.1
  117.      */
  118.     public void addDefaultUTCTAIOffsetsLoaders() {
  119.         synchronized (this) {
  120.             final DataProvidersManager dataProvidersManager =
  121.                     lazyLoadedEop.getDataProvidersManager();
  122.             addUTCTAIOffsetsLoader(new TAIUTCDatFilesLoader(TAIUTCDatFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
  123.             addUTCTAIOffsetsLoader(new UTCTAIHistoryFilesLoader(dataProvidersManager));
  124.             addUTCTAIOffsetsLoader(new AGILeapSecondFilesLoader(AGILeapSecondFilesLoader.DEFAULT_SUPPORTED_NAMES, dataProvidersManager));
  125.         }
  126.     }

  127.     /**
  128.      * Clear loaders for UTC-TAI offsets history files.
  129.      *
  130.      * @see #getUTC()
  131.      * @see #addUTCTAIOffsetsLoader(UTCTAIOffsetsLoader)
  132.      * @see #addDefaultUTCTAIOffsetsLoaders()
  133.      * @since 7.1
  134.      */
  135.     public void clearUTCTAIOffsetsLoaders() {
  136.         synchronized (this) {
  137.             loaders.clear();
  138.         }
  139.     }

  140.     @Override
  141.     public TAIScale getTAI() {

  142.         TAIScale refTai = tai.get();
  143.         if (refTai == null) {
  144.             tai.compareAndSet(null, new TAIScale());
  145.             refTai = tai.get();
  146.         }

  147.         return refTai;

  148.     }

  149.     @Override
  150.     public UTCScale getUTC() {

  151.         UTCScale refUtc = utc.get();
  152.         if (refUtc == null) {
  153.             synchronized (this) {
  154.                 if (utc.get() == null) { // Check if utc was not loaded in the meantime
  155.                     List<OffsetModel> entries = Collections.emptyList();
  156.                     if (loaders.isEmpty()) {
  157.                         addDefaultUTCTAIOffsetsLoaders();
  158.                     }
  159.                     for (UTCTAIOffsetsLoader loader : loaders) {
  160.                         entries = loader.loadOffsets();
  161.                         if (!entries.isEmpty()) {
  162.                             break;
  163.                         }
  164.                     }
  165.                     if (entries.isEmpty()) {
  166.                         throw new OrekitException(OrekitMessages.NO_IERS_UTC_TAI_HISTORY_DATA_LOADED);
  167.                     }
  168.                     utc.compareAndSet(null, new UTCScale(getTAI(), entries));
  169.                 }
  170.                 refUtc = utc.get();
  171.             }
  172.         }

  173.         return refUtc;

  174.     }

  175.     @Override
  176.     public UT1Scale getUT1(final IERSConventions conventions, final boolean simpleEOP) {
  177.         // synchronized to maintain the same semantics as Orekit 10.0
  178.         synchronized (this) {
  179.             return super.getUT1(conventions, simpleEOP);
  180.         }
  181.     }

  182.     @Override
  183.     protected EOPHistory getEopHistory(final IERSConventions conventions,
  184.                                        final boolean simpleEOP) {
  185.         return lazyLoadedEop.getEOPHistory(conventions, simpleEOP, this);
  186.     }

  187.     // need to make this public for compatibility. Provides access to UT1 constructor.
  188.     /** {@inheritDoc} */
  189.     @Override
  190.     public UT1Scale getUT1(final EOPHistory history) {
  191.         return super.getUT1(history);
  192.     }

  193.     @Override
  194.     public TTScale getTT() {

  195.         TTScale refTt = tt.get();
  196.         if (refTt == null) {
  197.             tt.compareAndSet(null, new TTScale());
  198.             refTt = tt.get();
  199.         }

  200.         return refTt;

  201.     }

  202.     @Override
  203.     public GalileoScale getGST() {

  204.         GalileoScale refGst = gst.get();
  205.         if (refGst == null) {
  206.             gst.compareAndSet(null, new GalileoScale());
  207.             refGst = gst.get();
  208.         }

  209.         return refGst;

  210.     }

  211.     @Override
  212.     public GLONASSScale getGLONASS() {

  213.         GLONASSScale refGlonass = glonass.get();
  214.         if (refGlonass == null) {
  215.             glonass.compareAndSet(null, new GLONASSScale(getUTC()));
  216.             refGlonass = glonass.get();
  217.         }

  218.         return refGlonass;

  219.     }

  220.     @Override
  221.     public QZSSScale getQZSS() {

  222.         QZSSScale refQzss = qzss.get();
  223.         if (refQzss == null) {
  224.             qzss.compareAndSet(null, new QZSSScale());
  225.             refQzss = qzss.get();
  226.         }

  227.         return refQzss;

  228.     }

  229.     @Override
  230.     public GPSScale getGPS() {

  231.         GPSScale refGps = gps.get();
  232.         if (refGps == null) {
  233.             gps.compareAndSet(null, new GPSScale());
  234.             refGps = gps.get();
  235.         }

  236.         return refGps;

  237.     }

  238.     @Override
  239.     public TCGScale getTCG() {

  240.         TCGScale refTcg = tcg.get();
  241.         if (refTcg == null) {
  242.             tcg.compareAndSet(null, new TCGScale(getTT(), getTAI()));
  243.             refTcg = tcg.get();
  244.         }

  245.         return refTcg;

  246.     }

  247.     @Override
  248.     public TDBScale getTDB() {

  249.         TDBScale refTdb = tdb.get();
  250.         if (refTdb == null) {
  251.             tdb.compareAndSet(null, new TDBScale(getTT(), getJ2000Epoch()));
  252.             refTdb = tdb.get();
  253.         }

  254.         return refTdb;

  255.     }

  256.     @Override
  257.     public TCBScale getTCB() {

  258.         TCBScale refTcb = tcb.get();
  259.         if (refTcb == null) {
  260.             tcb.compareAndSet(null, new TCBScale(getTDB(), getTAI()));
  261.             refTcb = tcb.get();
  262.         }

  263.         return refTcb;

  264.     }

  265.     @Override
  266.     public GMSTScale getGMST(final IERSConventions conventions, final boolean simpleEOP) {
  267.         // synchronized to maintain the same semantics as Orekit 10.0
  268.         synchronized (this) {
  269.             return super.getGMST(conventions, simpleEOP);
  270.         }
  271.     }

  272.     @Override
  273.     public NavicScale getNavIC() {

  274.         NavicScale refNavIC = navic.get();
  275.         if (refNavIC == null) {
  276.             navic.compareAndSet(null, new NavicScale());
  277.             refNavIC = navic.get();
  278.         }

  279.         return refNavIC;

  280.     }

  281.     @Override
  282.     public BDTScale getBDT() {

  283.         BDTScale refBds = bds.get();
  284.         if (refBds == null) {
  285.             bds.compareAndSet(null, new BDTScale());
  286.             refBds = bds.get();
  287.         }

  288.         return refBds;

  289.     }

  290. }