TimeScalesFactory.java
/* Copyright 2002-2016 CS Systèmes d'Information
* Licensed to CS Systèmes d'Information (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.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import org.orekit.data.DataProvidersManager;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;
import org.orekit.frames.EOPHistory;
import org.orekit.frames.FramesFactory;
import org.orekit.utils.IERSConventions;
/** Factory for predefined time scales.
* <p>
* This is a utility class, so its constructor is private.
* </p>
* @author Luc Maisonobe
*/
public class TimeScalesFactory implements Serializable {
/** Serializable UID. */
private static final long serialVersionUID = 20130807L;
/** International Atomic Time scale. */
private static TAIScale tai = null;
/** Universal Time Coordinate scale. */
private static UTCScale utc = null;
/** Universal Time 1 scale (tidal effects ignored). */
private static Map<IERSConventions, UT1Scale> ut1MapSimpleEOP = new HashMap<IERSConventions, UT1Scale>();
/** Universal Time 1 scale (tidal effects considered). */
private static Map<IERSConventions, UT1Scale> ut1MapCompleteEOP = new HashMap<IERSConventions, UT1Scale>();
/** Terrestrial Time scale. */
private static TTScale tt = null;
/** Galileo System Time scale. */
private static GalileoScale gst = null;
/** Global Positioning System scale. */
private static GPSScale gps = null;
/** Geocentric Coordinate Time scale. */
private static TCGScale tcg = null;
/** Barycentric Dynamic Time scale. */
private static TDBScale tdb = null;
/** Barycentric Coordinate Time scale. */
private static TCBScale tcb = null;
/** Greenwich Mean Sidereal Time scale. */
private static GMSTScale gmst = null;
/** UTCTAI offsets loaders. */
private static List<UTCTAIOffsetsLoader> loaders = new ArrayList<UTCTAIOffsetsLoader>();
/** Private constructor.
* <p>This class is a utility class, it should neither have a public
* nor a default constructor. This private constructor prevents
* the compiler from generating one automatically.</p>
*/
private TimeScalesFactory() {
}
/** 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 static void addUTCTAIOffsetsLoader(final UTCTAIOffsetsLoader loader) {
loaders.add(loader);
}
/** Add a loader for UTC-TAI offsets history files.
* @param loader custom loader to add
* @see #getUTC()
* @see #clearUTCTAILoaders()
* @deprecated as of 7.1, replaced with {@link #addUTCTAIOffsetsLoader(UTCTAIOffsetsLoader)}
*/
@Deprecated
public static void addUTCTAILoader(final UTCTAILoader loader) {
addUTCTAIOffsetsLoader(new UTCTAIOffsetsLoader() {
/** {@inheritDoc} */
@Override
public List<OffsetModel> loadOffsets() throws OrekitException {
// get the post-1972 constant offsets
DataProvidersManager.getInstance().feed(loader.getSupportedNames(), loader);
final SortedMap<DateComponents, Integer> constant = loader.loadTimeSteps();
if (constant.isEmpty()) {
// return an empty list, maybe another loader will find something ...
return Collections.emptyList();
}
// add the constant offsets
final List<OffsetModel> offsets = new ArrayList<OffsetModel>();
for (Map.Entry<DateComponents, Integer> entry : constant.entrySet()) {
offsets.add(new OffsetModel(entry.getKey(), entry.getValue()));
}
return offsets;
}
});
}
/** Add the default loader for UTC-TAI offsets history files.
* <p>
* The default loader looks for a file named {@code UTC-TAI.history}
* that must be in the IERS format.
* </p>
* @see <a href="http://hpiers.obspm.fr/eoppc/bul/bulc/UTC-TAI.history">IERS UTC-TAI.history file</a>
* @see #getUTC()
* @see #clearUTCTAILoaders()
* @deprecated as of 7.1, replaced with {@link #addDefaultUTCTAIOffsetsLoaders()}
*/
@Deprecated
public static void addDefaultUTCTAILoader() {
addUTCTAIOffsetsLoader(new UTCTAIHistoryFilesLoader());
}
/** 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 and
* {@link UTCTAIHistoryFilesLoader} that looks fir a file named
* {@code UTC-TAI.history} that must be in the IERS 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 #getUTC()
* @see #clearUTCTAIOffsetsLoaders()
* @since 7.1
*/
public static void addDefaultUTCTAIOffsetsLoaders() {
addUTCTAIOffsetsLoader(new TAIUTCDatFilesLoader(TAIUTCDatFilesLoader.DEFAULT_SUPPORTED_NAMES));
addUTCTAIOffsetsLoader(new UTCTAIHistoryFilesLoader());
}
/** Clear loaders for UTC-TAI offsets history files.
* @see #getUTC()
* @see #addUTCTAILoader(UTCTAILoader)
* @see #addDefaultUTCTAILoader
* @deprecated as of 7.1, replaced with {@link #clearUTCTAIOffsetsLoaders()}
*/
@Deprecated
public static void clearUTCTAILoaders() {
loaders.clear();
}
/** Clear loaders for UTC-TAI offsets history files.
* @see #getUTC()
* @see #addUTCTAIOffsetsLoader(UTCTAIOffsetsLoader)
* @see #addDefaultUTCTAIOffsetsLoaders()
* @since 7.1
*/
public static void clearUTCTAIOffsetsLoaders() {
loaders.clear();
}
/** Get the International Atomic Time scale.
* @return International Atomic Time scale
*/
public static TAIScale getTAI() {
synchronized (TimeScalesFactory.class) {
if (tai == null) {
tai = new TAIScale();
}
return tai;
}
}
/** Get the Universal Time Coordinate scale.
* <p>
* If no {@link UTCTAILoader} has been added by calling {@link
* #addUTCTAILoader(UTCTAILoader) addUTCTAILoader} or if {@link
* #clearUTCTAILoaders() clearUTCTAILoaders} has been called afterwards,
* the {@link #addDefaultUTCTAIOffsetsLoaders() addDefaultUTCTAILoaders} method
* will be called automatically.
* </p>
* @return Universal Time Coordinate scale
* @exception OrekitException if some data can't be read or some
* file content is corrupted
* @see #addUTCTAILoader(UTCTAILoader)
* @see #clearUTCTAILoaders()
* @see #addDefaultUTCTAIOffsetsLoaders()
*/
public static UTCScale getUTC() throws OrekitException {
synchronized (TimeScalesFactory.class) {
if (utc == null) {
List<OffsetModel> entries = null;
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 = new UTCScale(entries);
}
return utc;
}
}
/** Get the Universal Time 1 scale.
* <p>
* UT1 scale depends on both UTC scale and Earth Orientation Parameters,
* so this method loads these data sets. See the {@link #getUTC()
* TimeScalesFactory.getUTC()} and {@link
* FramesFactory#getEOPHistory(IERSConventions, boolean)} methods
* for an explanation of how the corresponding data loaders can be configured.
* </p>
* @param conventions IERS conventions for which EOP parameters will provide dUT1
* @param simpleEOP if true, tidal effects are ignored when interpolating EOP
* @return Universal Time 1 scale
* @exception OrekitException if some data can't be read or some
* file content is corrupted
* @see #getUTC()
* @see FramesFactory#getEOPHistory(IERSConventions, boolean)
*/
public static UT1Scale getUT1(final IERSConventions conventions, final boolean simpleEOP)
throws OrekitException {
synchronized (TimeScalesFactory.class) {
final Map<IERSConventions, UT1Scale> map =
simpleEOP ? ut1MapSimpleEOP : ut1MapCompleteEOP;
UT1Scale ut1 = map.get(conventions);
if (ut1 == null) {
ut1 = getUT1(FramesFactory.getEOPHistory(conventions, simpleEOP));
map.put(conventions, ut1);
}
return ut1;
}
}
/** Get the Universal Time 1 scale.
* <p>
* As this method allow associating any history with the time scale,
* it may involve large data sets. So this method does <em>not</em>
* cache the resulting {@link UT1Scale UT1Scale} instance, a new
* instance will be returned each time. In order to avoid wasting
* memory, calling {@link #getUT1(IERSConventions, boolean)}
* with the single enumerate corresponding to the conventions may be
* a better solution. This method is made available only for expert use.
* </p>
* @param history EOP parameters providing dUT1
* (may be null if no correction is desired)
* @return Universal Time 1 scale
* @exception OrekitException if some data can't be read or some
* file content is corrupted
* @see #getUT1(IERSConventions, boolean)
*/
public static UT1Scale getUT1(final EOPHistory history) throws OrekitException {
return new UT1Scale(history, getUTC());
}
/** Get the Terrestrial Time scale.
* @return Terrestrial Time scale
*/
public static TTScale getTT() {
synchronized (TimeScalesFactory.class) {
if (tt == null) {
tt = new TTScale();
}
return tt;
}
}
/** Get the Galileo System Time scale.
* @return Galileo System Time scale
*/
public static GalileoScale getGST() {
synchronized (TimeScalesFactory.class) {
if (gst == null) {
gst = new GalileoScale();
}
return gst;
}
}
/** Get the Global Positioning System scale.
* @return Global Positioning System scale
*/
public static GPSScale getGPS() {
synchronized (TimeScalesFactory.class) {
if (gps == null) {
gps = new GPSScale();
}
return gps;
}
}
/** Get the Geocentric Coordinate Time scale.
* @return Geocentric Coordinate Time scale
*/
public static TCGScale getTCG() {
synchronized (TimeScalesFactory.class) {
if (tcg == null) {
tcg = new TCGScale();
}
return tcg;
}
}
/** Get the Barycentric Dynamic Time scale.
* @return Barycentric Dynamic Time scale
*/
public static TDBScale getTDB() {
synchronized (TimeScalesFactory.class) {
if (tdb == null) {
tdb = new TDBScale();
}
return tdb;
}
}
/** Get the Barycentric Coordinate Time scale.
* @return Barycentric Coordinate Time scale
*/
public static TCBScale getTCB() {
synchronized (TimeScalesFactory.class) {
if (tcb == null) {
tcb = new TCBScale(getTDB());
}
return tcb;
}
}
/** Get the Greenwich Mean Sidereal Time scale.
* @param conventions IERS conventions for which EOP parameters will provide dUT1
* @param simpleEOP if true, tidal effects are ignored when interpolating EOP
* @return Greenwich Mean Sidereal Time scale
* @exception OrekitException if some data can't be read or some
* file content is corrupted
* @since 7.0
*/
public static GMSTScale getGMST(final IERSConventions conventions, final boolean simpleEOP) throws OrekitException {
synchronized (TimeScalesFactory.class) {
if (gmst == null) {
gmst = new GMSTScale(getUT1(conventions, simpleEOP));
}
return gmst;
}
}
}