1   /* Copyright 2002-2021 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.files.ccsds.ndm.adm;
18  
19  import java.util.Map;
20  
21  import org.hipparchus.geometry.euclidean.threed.RotationOrder;
22  import org.orekit.data.DataContext;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.files.ccsds.ndm.NdmConstituent;
26  import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
27  import org.orekit.files.ccsds.utils.lexical.ParseToken;
28  import org.orekit.files.ccsds.utils.lexical.TokenType;
29  import org.orekit.files.ccsds.utils.lexical.XmlTokenBuilder;
30  import org.orekit.files.ccsds.utils.parsing.AbstractConstituentParser;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.utils.IERSConventions;
33  
34  /**
35   * Base class for Attitude Data Message parsers.
36   * <p>
37   * Note than starting with Orekit 11.0, CCSDS message parsers are
38   * mutable objects that gather the data being parsed, until the
39   * message is complete and the {@link #parseMessage(org.orekit.data.DataSource)
40   * parseMessage} method has returned. This implies that parsers
41   * should <em>not</em> be used in a multi-thread context. The recommended
42   * way to use parsers is to either dedicate one parser for each message
43   * and drop it afterwards, or to use a single-thread loop.
44   * </p>
45   * @param <T> type of the file
46   * @param <P> type of the parser
47   * @author Luc Maisonobe
48   * @since 11.0
49   */
50  public abstract class AdmParser<T extends NdmConstituent<?, ?>, P extends AbstractConstituentParser<T, ?>>
51      extends AbstractConstituentParser<T, P> {
52  
53      /** Index rotation element name. */
54      private static final String ROTATION_1 = "rotation1";
55  
56      /** Index rotation element name. */
57      private static final String ROTATION_2 = "rotation2";
58  
59      /** Index rotation element name. */
60      private static final String ROTATION_3 = "rotation3";
61  
62      /** Reference date for Mission Elapsed Time or Mission Relative Time time systems. */
63      private final AbsoluteDate missionReferenceDate;
64  
65      /** Complete constructor.
66       * @param root root element for XML files
67       * @param formatVersionKey key for format version
68       * @param conventions IERS Conventions
69       * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
70       * @param dataContext used to retrieve frames, time scales, etc.
71       * @param missionReferenceDate reference date for Mission Elapsed Time or Mission Relative Time time systems
72       * (may be null if time system is absolute)
73       * @param parsedUnitsBehavior behavior to adopt for handling parsed units
74       */
75      protected AdmParser(final String root, final String formatVersionKey, final IERSConventions conventions,
76                          final boolean simpleEOP, final DataContext dataContext,
77                          final AbsoluteDate missionReferenceDate, final ParsedUnitsBehavior parsedUnitsBehavior) {
78          super(root, formatVersionKey, conventions, simpleEOP, dataContext, parsedUnitsBehavior);
79          this.missionReferenceDate = missionReferenceDate;
80      }
81  
82      /** {@inheritDoc} */
83      @Override
84      public Map<String, XmlTokenBuilder> getSpecialXmlElementsBuilders() {
85  
86          final Map<String, XmlTokenBuilder> builders = super.getSpecialXmlElementsBuilders();
87  
88          // special handling of rotation elements
89          builders.put(ROTATION_1, new RotationXmlTokenBuilder());
90          builders.put(ROTATION_2, new RotationXmlTokenBuilder());
91          builders.put(ROTATION_3, new RotationXmlTokenBuilder());
92  
93          return builders;
94  
95      }
96  
97      /**
98       * Get reference date for Mission Elapsed Time and Mission Relative Time time systems.
99       * @return the reference date
100      */
101     public AbsoluteDate getMissionReferenceDate() {
102         return missionReferenceDate;
103     }
104 
105     /** Process a CCSDS Euler angles sequence as a {@link RotationOrder}.
106      * @param sequence Euler angles sequence token
107      * @param consumer consumer of the rotation order
108      * @return always return {@code true}
109      */
110     public static boolean processRotationOrder(final ParseToken sequence,
111                                                final RotationOrderConsumer consumer) {
112         if (sequence.getType() == TokenType.ENTRY) {
113             try {
114                 consumer.accept(RotationOrder.valueOf(sequence.getContentAsUppercaseString().
115                                                       replace('1', 'X').
116                                                       replace('2', 'Y').
117                                                       replace('3', 'Z')));
118             } catch (IllegalArgumentException iae) {
119                 throw new OrekitException(OrekitMessages.CCSDS_INVALID_ROTATION_SEQUENCE,
120                                           sequence.getContentAsUppercaseString(),
121                                           sequence.getLineNumber(), sequence.getFileName());
122             }
123         }
124         return true;
125     }
126 
127     /** Interface representing instance methods that consume otation order values. */
128     public interface RotationOrderConsumer {
129         /** Consume a data.
130          * @param value value to consume
131          */
132         void accept(RotationOrder value);
133     }
134 
135 }