LazyLoadedCelestialBodies.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.bodies;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.orekit.data.DataProvidersManager;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.frames.Frame;
- import org.orekit.time.TimeScales;
- /**
- * This class lazily loads auxiliary data when it is needed by a requested body. It is
- * designed to match the behavior of {@link CelestialBodyFactory} in Orekit 10.0.
- *
- * @author Luc Maisonobe
- * @author Evan Ward
- * @see CelestialBodyFactory
- * @since 10.1
- */
- public class LazyLoadedCelestialBodies implements CelestialBodies {
- /** Supplies the auxiliary data files. */
- private final DataProvidersManager dataProvidersManager;
- /** Provides access to time scales when parsing bodies. */
- private final TimeScales timeScales;
- /** Earth centered frame aligned with ICRF. */
- private final Frame gcrf;
- /** Celestial body loaders map. */
- private final Map<String, List<CelestialBodyLoader>> loadersMap = new HashMap<>();
- /** Celestial body map. */
- private final Map<String, CelestialBody> celestialBodyMap = new HashMap<>();
- /**
- * Create a celestial body factory with the given auxiliary data sources.
- *
- * @param dataProvidersManager supplies JPL ephemerides auxiliary data files.
- * @param timeScales set of time scales to use when loading bodies.
- * @param gcrf Earth centered frame aligned with ICRF.
- */
- public LazyLoadedCelestialBodies(final DataProvidersManager dataProvidersManager,
- final TimeScales timeScales,
- final Frame gcrf) {
- this.dataProvidersManager = dataProvidersManager;
- this.timeScales = timeScales;
- this.gcrf = gcrf;
- }
- /** Add a loader for celestial bodies.
- * @param name name of the body (may be one of the predefined names or a user-defined name)
- * @param loader custom loader to add for the body
- * @see #addDefaultCelestialBodyLoader(String)
- * @see #clearCelestialBodyLoaders(String)
- * @see #clearCelestialBodyLoaders()
- */
- public void addCelestialBodyLoader(final String name,
- final CelestialBodyLoader loader) {
- synchronized (loadersMap) {
- loadersMap.computeIfAbsent(name, k -> new ArrayList<>()).add(loader);
- }
- }
- /** Add the default loaders for all predefined celestial bodies.
- * @param supportedNames regular expression for supported files names
- * (may be null if the default JPL file names are used)
- * <p>
- * The default loaders look for DE405 or DE406 JPL ephemerides.
- * </p>
- * @see <a href="ftp://ssd.jpl.nasa.gov/pub/eph/planets/Linux/de405/">DE405 JPL ephemerides</a>
- * @see <a href="ftp://ssd.jpl.nasa.gov/pub/eph/planets/Linux/de406/">DE406 JPL ephemerides</a>
- * @see #addCelestialBodyLoader(String, CelestialBodyLoader)
- * @see #addDefaultCelestialBodyLoader(String)
- * @see #clearCelestialBodyLoaders(String)
- * @see #clearCelestialBodyLoaders()
- */
- public void addDefaultCelestialBodyLoader(final String supportedNames) {
- addDefaultCelestialBodyLoader(CelestialBodyFactory.SOLAR_SYSTEM_BARYCENTER, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.SUN, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.MERCURY, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.VENUS, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.EARTH_MOON, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.EARTH, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.MOON, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.MARS, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.JUPITER, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.SATURN, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.URANUS, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.NEPTUNE, supportedNames);
- addDefaultCelestialBodyLoader(CelestialBodyFactory.PLUTO, supportedNames);
- }
- /** Add the default loaders for celestial bodies.
- * @param name name of the body (if not one of the predefined names, the method does nothing)
- * @param supportedNames regular expression for supported files names
- * (may be null if the default JPL file names are used)
- * <p>
- * The default loaders look for DE405 or DE406 JPL ephemerides.
- * </p>
- * @see <a href="ftp://ssd.jpl.nasa.gov/pub/eph/planets/Linux/de405/">DE405 JPL ephemerides</a>
- * @see <a href="ftp://ssd.jpl.nasa.gov/pub/eph/planets/Linux/de406/">DE406 JPL ephemerides</a>
- * @see #addCelestialBodyLoader(String, CelestialBodyLoader)
- * @see #addDefaultCelestialBodyLoader(String)
- * @see #clearCelestialBodyLoaders(String)
- * @see #clearCelestialBodyLoaders()
- */
- public void addDefaultCelestialBodyLoader(final String name,
- final String supportedNames) {
- CelestialBodyLoader loader = null;
- if (name.equalsIgnoreCase(CelestialBodyFactory.SOLAR_SYSTEM_BARYCENTER)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.SOLAR_SYSTEM_BARYCENTER, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.SUN)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.SUN, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.MERCURY)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.MERCURY, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.VENUS)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.VENUS, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.EARTH_MOON)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.EARTH_MOON, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.EARTH)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.EARTH, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.MOON)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.MOON, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.MARS)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.MARS, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.JUPITER)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.JUPITER, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.SATURN)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.SATURN, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.URANUS)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.URANUS, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.NEPTUNE)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.NEPTUNE, dataProvidersManager, timeScales, gcrf);
- } else if (name.equalsIgnoreCase(CelestialBodyFactory.PLUTO)) {
- loader =
- new JPLEphemeridesLoader(supportedNames, JPLEphemeridesLoader.EphemerisType.PLUTO, dataProvidersManager, timeScales, gcrf);
- }
- if (loader != null) {
- addCelestialBodyLoader(name, loader);
- }
- }
- /** Clear loaders for one celestial body.
- * <p>
- * Calling this method also clears the celestial body that
- * has been loaded via this {@link CelestialBodyLoader}.
- * </p>
- * @param name name of the body
- * @see #addCelestialBodyLoader(String, CelestialBodyLoader)
- * @see #clearCelestialBodyLoaders()
- * @see #clearCelestialBodyCache(String)
- */
- public void clearCelestialBodyLoaders(final String name) {
- // use same synchronization order as in getBody to prevent deadlocks
- synchronized (celestialBodyMap) {
- // take advantage of reentrent synchronization as
- // clearCelestialBodyCache uses the same lock inside
- clearCelestialBodyCache(name);
- synchronized (loadersMap) {
- loadersMap.remove(name);
- }
- }
- }
- /** Clear loaders for all celestial bodies.
- * <p>
- * Calling this method also clears all loaded celestial bodies.
- * </p>
- * @see #addCelestialBodyLoader(String, CelestialBodyLoader)
- * @see #clearCelestialBodyLoaders(String)
- * @see #clearCelestialBodyCache()
- */
- public void clearCelestialBodyLoaders() {
- synchronized (celestialBodyMap) {
- clearCelestialBodyCache();
- synchronized (loadersMap) {
- loadersMap.clear();
- }
- }
- }
- /** Clear the specified celestial body from the internal cache.
- * @param name name of the body
- */
- public void clearCelestialBodyCache(final String name) {
- synchronized (celestialBodyMap) {
- celestialBodyMap.remove(name);
- }
- }
- /** Clear all loaded celestial bodies.
- * <p>
- * Calling this method will remove all loaded bodies from the internal
- * cache. Subsequent calls to {@link #getBody(String)} or similar methods
- * will result in a reload of the requested body from the configured loader(s).
- * </p>
- */
- public void clearCelestialBodyCache() {
- synchronized (celestialBodyMap) {
- celestialBodyMap.clear();
- }
- }
- @Override
- public CelestialBody getSolarSystemBarycenter() {
- return getBody(CelestialBodyFactory.SOLAR_SYSTEM_BARYCENTER);
- }
- @Override
- public CelestialBody getSun() {
- return getBody(CelestialBodyFactory.SUN);
- }
- @Override
- public CelestialBody getMercury() {
- return getBody(CelestialBodyFactory.MERCURY);
- }
- @Override
- public CelestialBody getVenus() {
- return getBody(CelestialBodyFactory.VENUS);
- }
- @Override
- public CelestialBody getEarthMoonBarycenter() {
- return getBody(CelestialBodyFactory.EARTH_MOON);
- }
- @Override
- public CelestialBody getEarth() {
- return getBody(CelestialBodyFactory.EARTH);
- }
- @Override
- public CelestialBody getMoon() {
- return getBody(CelestialBodyFactory.MOON);
- }
- @Override
- public CelestialBody getMars() {
- return getBody(CelestialBodyFactory.MARS);
- }
- @Override
- public CelestialBody getJupiter() {
- return getBody(CelestialBodyFactory.JUPITER);
- }
- @Override
- public CelestialBody getSaturn() {
- return getBody(CelestialBodyFactory.SATURN);
- }
- @Override
- public CelestialBody getUranus() {
- return getBody(CelestialBodyFactory.URANUS);
- }
- @Override
- public CelestialBody getNeptune() {
- return getBody(CelestialBodyFactory.NEPTUNE);
- }
- @Override
- public CelestialBody getPluto() {
- return getBody(CelestialBodyFactory.PLUTO);
- }
- /**
- * {@inheritDoc}
- *
- * <p>
- * If no {@link CelestialBodyLoader} has been added by calling {@link
- * #addCelestialBodyLoader(String, CelestialBodyLoader) addCelestialBodyLoader} or if
- * {@link #clearCelestialBodyLoaders(String) clearCelestialBodyLoaders} has been
- * called afterwards, the {@link #addDefaultCelestialBodyLoader(String, String)
- * addDefaultCelestialBodyLoader} method will be called automatically, once with the
- * default name for JPL DE ephemerides and once with the default name for IMCCE INPOP
- * files.
- * </p>
- */
- @Override
- public CelestialBody getBody(final String name) {
- synchronized (celestialBodyMap) {
- CelestialBody body = celestialBodyMap.get(name);
- if (body == null) {
- synchronized (loadersMap) {
- List<CelestialBodyLoader> loaders = loadersMap.get(name);
- if (loaders == null || loaders.isEmpty()) {
- addDefaultCelestialBodyLoader(name, JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES);
- addDefaultCelestialBodyLoader(name, JPLEphemeridesLoader.DEFAULT_INPOP_SUPPORTED_NAMES);
- loaders = loadersMap.get(name);
- }
- OrekitException delayedException = null;
- for (CelestialBodyLoader loader : loaders) {
- try {
- body = loader.loadCelestialBody(name);
- if (body != null) {
- break;
- }
- } catch (OrekitException oe) {
- delayedException = oe;
- }
- }
- if (body == null) {
- throw (delayedException != null) ?
- delayedException :
- new OrekitException(OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY, name);
- }
- }
- // save the body
- celestialBodyMap.put(name, body);
- }
- return body;
- }
- }
- }