OceanLoadingCoefficientsBLQFactory.java

  1. /* Copyright 2002-2024 CS GROUP
  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.models.earth.displacement;

  18. import java.io.InputStream;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. import java.util.Optional;
  22. import java.util.stream.Collectors;

  23. import org.orekit.annotation.DefaultDataContext;
  24. import org.orekit.data.AbstractSelfFeedingLoader;
  25. import org.orekit.data.DataContext;
  26. import org.orekit.data.DataLoader;
  27. import org.orekit.data.DataProvidersManager;
  28. import org.orekit.data.DataSource;
  29. import org.orekit.errors.OrekitException;
  30. import org.orekit.errors.OrekitMessages;

  31. /**
  32.  * Factory for ocean loading coefficients, using Onsala Space Observatory files in BLQ format.
  33.  * <p>
  34.  * Files in BLQ format can be generated using the form at the
  35.  * <a href="http://holt.oso.chalmers.se/loading/">Bos-Scherneck web site</a>,
  36.  * selecting BLQ as the output format.
  37.  * </p>
  38.  * <p>
  39.  * The sites names are extracted from the file content, not the file name, because the
  40.  * file can contain more than one station. As we expect existing files may have been
  41.  * stripped from headers and footers, we do not attempt to parse them. We only parse
  42.  * the series of 7 lines blocks starting with the lines with the station names and their
  43.  * coordinates and the 6 data lines that follows. Several such blocks may appear in the
  44.  * file. Copy-pasting the entire mail received from OSO after completing the web site
  45.  * form works, as intermediate lines between the 7 lines blocks are simply ignored.
  46.  * </p>
  47.  * @see OceanLoadingCoefficients
  48.  * @see OceanLoading
  49.  * @since 9.1
  50.  * @author Luc Maisonobe
  51.  */
  52. public class OceanLoadingCoefficientsBLQFactory extends AbstractSelfFeedingLoader {

  53.     /** Default supported files name pattern for Onsala Space Observatory files in BLQ format. */
  54.     public static final String DEFAULT_BLQ_SUPPORTED_NAMES = "^.+\\.blq$";

  55.     /** Parsed coefficients. */
  56.     private final List<OceanLoadingCoefficients> coefficients;

  57.     /** Simple constructor. This constructor uses the {@link DataContext#getDefault()
  58.      * default data context}.
  59.      * <p>
  60.      * Files in BLQ format can be generated using the form at the
  61.      * <a href="http://holt.oso.chalmers.se/loading/">Bos-Scherneck web site</a>,
  62.      * selecting BLQ as the output format.
  63.      * </p>
  64.      * @param supportedNames regular expression for supported files names
  65.      * @see #DEFAULT_BLQ_SUPPORTED_NAMES
  66.      * @see #OceanLoadingCoefficientsBLQFactory(String, DataProvidersManager)
  67.      */
  68.     @DefaultDataContext
  69.     public OceanLoadingCoefficientsBLQFactory(final String supportedNames) {
  70.         this(supportedNames, DataContext.getDefault().getDataProvidersManager());
  71.     }

  72.     /**
  73.      * This constructor allows specification of the source of the BLQ auxiliary data
  74.      * files.
  75.      *
  76.      * <p>
  77.      * Files in BLQ format can be generated using the form at the
  78.      * <a href="http://holt.oso.chalmers.se/loading/">Bos-Scherneck web site</a>,
  79.      * selecting BLQ as the output format.
  80.      * </p>
  81.      * @param supportedNames regular expression for supported files names
  82.      * @param dataProvidersManager provides access to auxiliary data files.
  83.      * @see #DEFAULT_BLQ_SUPPORTED_NAMES
  84.      * @since 10.1
  85.      */
  86.     public OceanLoadingCoefficientsBLQFactory(final String supportedNames,
  87.                                               final DataProvidersManager dataProvidersManager) {
  88.         super(supportedNames, dataProvidersManager);

  89.         this.coefficients   = new ArrayList<>();

  90.     }

  91.     /** Lazy loading of coefficients.
  92.      */
  93.     private void loadsIfNeeded() {
  94.         if (coefficients.isEmpty()) {
  95.             feed(new DataLoader() {

  96.                 /** {@inheritDoc} */
  97.                 @Override
  98.                 public boolean stillAcceptsData() {
  99.                     return true;
  100.                 }

  101.                 /** {@inheritDoc} */
  102.                 @Override
  103.                 public void loadData(final InputStream input, final String name) {
  104.                     final OceanLoadingCoefficientsBlqParser parser = new OceanLoadingCoefficientsBlqParser();
  105.                     coefficients.addAll(parser.parse(new DataSource(name, () -> input)));
  106.                 }
  107.             });
  108.         }
  109.     }

  110.     /** Get the list of sites for which we have found coefficients, in lexicographic order ignoring case.
  111.      * @return list of sites for which we have found coefficients, in lexicographic order ignoring case
  112.      */
  113.     public List<String> getSites() {

  114.         loadsIfNeeded();

  115.         // extract sites names from the map
  116.         return coefficients.stream()
  117.                 .map(OceanLoadingCoefficients::getSiteName)
  118.                 // sort to ensure we have a reproducible order
  119.                 .sorted(String::compareToIgnoreCase)
  120.                 .collect(Collectors.toList());

  121.     }

  122.     /** Get the coefficients for a given site.
  123.      * @param site site name (as it appears in the Onsala Space Observatory files in BLQ format),
  124.      * ignoring case
  125.      * @return coefficients for the site
  126.      */
  127.     public OceanLoadingCoefficients getCoefficients(final String site) {

  128.         loadsIfNeeded();

  129.         final Optional<OceanLoadingCoefficients> optional =
  130.                         coefficients.stream().filter(c -> c.getSiteName().equalsIgnoreCase(site)).findFirst();
  131.         if (!optional.isPresent()) {
  132.             throw new OrekitException(OrekitMessages.STATION_NOT_FOUND,
  133.                                       site,
  134.                                       String.join(", ", getSites()));
  135.         }

  136.         return optional.get();

  137.     }

  138. }