1   /* Copyright 2022-2025 Luc Maisonobe
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.files.sinex;
18  
19  import org.orekit.time.TimeScales;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.List;
25  
26  /** Parser for Solution INdependent EXchange (SINEX) files.
27   * <p>
28   * The parser can be used to load several data types contained in Sinex files.
29   * The current supported data are: station coordinates, site eccentricities, EOP.
30   * </p>
31   * <p>
32   * The parsing of EOP parameters for multiple data sources in different SinexParser objects might pose
33   * a problem in case validity dates are overlapping. As Sinex daily solution files provide a single EOP
34   * entry, the Sinex parser will add points at the limits of data dates (startDate, endDate) of the Sinex
35   * file, which in case of overlap will lead to inconsistencies in the final EOPHistory object. Multiple
36   * data sources can be parsed using a single SinexParser to overcome this issue.
37   * </p>
38   * @author Luc Maisonobe
39   * @since 13.0
40   */
41  public class SinexParser extends AbstractSinexParser<Sinex, SinexParseInfo> {
42  
43      /** Top level parsers. */
44      private final List<LineParser<SinexParseInfo>> topParsers;
45  
46      /** Simple constructor.
47       * @param timeScales time scales
48       */
49      public SinexParser(final TimeScales timeScales) {
50  
51          super(timeScales);
52  
53          // set up parsers for supported blocks
54          final List<BlockParser<SinexParseInfo>> blockParsers = new ArrayList<>();
55          blockParsers.add(new BlockParser<>("SITE/ID",
56                                             Collections.singletonList(SingleLineBlockPredicate.SITE_ID)));
57          blockParsers.add(new BlockParser<>("SITE/ANTENNA",
58                                             Collections.singletonList(SingleLineBlockPredicate.SITE_ANTENNA)));
59          blockParsers.add(new BlockParser<>("SITE/GPS_PHASE_CENTER",
60                                             Collections.singletonList(SingleLineBlockPredicate.SITE_GPS_PHASE_CENTER)));
61          blockParsers.add(new BlockParser<>("SITE/GAL_PHASE_CENTER",
62                                             Collections.singletonList(SingleLineBlockPredicate.SITE_GAL_PHASE_CENTER)));
63          blockParsers.add(new BlockParser<>("SITE/ECCENTRICITY",
64                                             Collections.singletonList(SingleLineBlockPredicate.SITE_ECCENTRICITY)));
65          blockParsers.add(new BlockParser<>("SATELLITE/PHASE_CENTER",
66                                             Collections.singletonList(SingleLineBlockPredicate.SATELLITE_PHASE_CENTER)));
67          blockParsers.add(new BlockParser<>("SOLUTION/EPOCHS",
68                                             Collections.singletonList(SingleLineBlockPredicate.SOLUTION_EPOCHS)));
69          blockParsers.add(new BlockParser<>("SOLUTION/ESTIMATE",
70                                             Arrays.asList(StationPredicate.STAX, StationPredicate.STAY, StationPredicate.STAZ,
71                                                           StationPredicate.VELX, StationPredicate.VELY, StationPredicate.VELZ,
72                                                           PsdPredicate.AEXP_E, PsdPredicate.TEXP_E,
73                                                           PsdPredicate.ALOG_E, PsdPredicate.TLOG_E,
74                                                           PsdPredicate.AEXP_N, PsdPredicate.TEXP_N,
75                                                           PsdPredicate.ALOG_N, PsdPredicate.TLOG_N,
76                                                           PsdPredicate.AEXP_U, PsdPredicate.TEXP_U,
77                                                           PsdPredicate.ALOG_U, PsdPredicate.TLOG_U,
78                                                           EopPredicate.XPO,    EopPredicate.YPO,
79                                                           EopPredicate.LOD,    EopPredicate.UT,
80                                                           EopPredicate.NUT_LN, EopPredicate.NUT_OB,
81                                                           EopPredicate.NUT_X,  EopPredicate.NUT_Y,
82                                                           new IgnoredBlockContentPredicate<>())));
83  
84          // append at the end of the list one catch-all parser ignoring all remaining not supported blocks
85          blockParsers.add(new IgnoredBlockParser<>());
86  
87          // add the parser for the footer
88          topParsers = new ArrayList<>(blockParsers);
89          topParsers.add(new FooterParser<>("%ENDSNX"));
90  
91          // set up siblings
92          blockParsers.forEach(parser -> parser.setSiblingParsers(topParsers));
93  
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      protected LineParser<SinexParseInfo> firstLineParser() {
99          return new VersionParser<SinexParseInfo>("SNX") {
100             /** {@inheritDoc} */
101             @Override
102             public Iterable<LineParser<SinexParseInfo>> allowedNextParsers(final SinexParseInfo parseInfo) {
103                 return topParsers;
104             }
105         };
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     protected SinexParseInfo buildParseInfo() {
111         final SinexParseInfo parseInfo = new SinexParseInfo(getTimeScales());
112         parseInfo.setTimeScale(getTimeScales().getUTC());
113         return parseInfo;
114     }
115 
116 }