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.apm;
18  
19  import org.orekit.files.ccsds.definitions.Units;
20  import org.orekit.files.ccsds.ndm.adm.AdmParser;
21  import org.orekit.files.ccsds.utils.ContextBinding;
22  import org.orekit.files.ccsds.utils.lexical.ParseToken;
23  import org.orekit.files.ccsds.utils.lexical.TokenType;
24  import org.orekit.utils.units.Unit;
25  
26  /** Keys for {@link ApmData APM Euler angles} entries.
27   * @author Bryan Cazabonne
28   * @since 10.2
29   */
30  public enum EulerKey {
31  
32      /** Rotation angles wrapping element in XML files. */
33      rotationAngles((token, context, container) -> true),
34  
35      /** Rotation rates wrapping element in XML files. */
36      rotationRates((token, context, container) -> true),
37  
38      /** Comment entry. */
39      COMMENT((token, context, container) ->
40              token.getType() == TokenType.ENTRY ? container.addComment(token.getContentAsNormalizedString()) : true),
41  
42      /** First reference frame entry. */
43      EULER_FRAME_A((token, context, container) -> token.processAsFrame(container.getEndpoints()::setFrameA, context, true, true, true)),
44  
45      /** Second reference frame entry. */
46      EULER_FRAME_B((token, context, container) -> {
47          if (token.getType() == TokenType.ENTRY) {
48              container.checkNotNull(container.getEndpoints().getFrameA(), EULER_FRAME_A);
49              final boolean aIsSpaceraftBody = container.getEndpoints().getFrameA().asSpacecraftBodyFrame() != null;
50              return token.processAsFrame(container.getEndpoints()::setFrameB, context,
51                                          aIsSpaceraftBody, aIsSpaceraftBody, !aIsSpaceraftBody);
52          }
53          return true;
54      }),
55  
56      /** Rotation direction entry. */
57      EULER_DIR((token, context, container) -> {
58          if (token.getType() == TokenType.ENTRY) {
59              container.getEndpoints().setA2b(token.getContentAsUppercaseCharacter() == 'A');
60          }
61          return true;
62      }),
63  
64      /** Rotation sequence entry. */
65      EULER_ROT_SEQ((token, context, container) -> AdmParser.processRotationOrder(token, container::setEulerRotSeq)),
66  
67      /** Reference frame for rate entry. */
68      RATE_FRAME((token, context, container) -> {
69          if (token.getType() == TokenType.ENTRY) {
70              final String content = token.getContentAsUppercaseString();
71              final char   suffix  = content.charAt(content.length() - 1);
72              container.setRateFrameIsA(suffix == 'A');
73          }
74          return true;
75      }),
76  
77      /** X body rotation angle entry. */
78      X_ANGLE((token, context, container) -> token.processAsLabeledDouble('X', Unit.DEGREE, context.getParsedUnitsBehavior(),
79                                                                          container::setRotationAngle)),
80  
81      /** Y body rotation angle entry. */
82      Y_ANGLE((token, context, container) -> token.processAsLabeledDouble('Y', Unit.DEGREE, context.getParsedUnitsBehavior(),
83                                                                          container::setRotationAngle)),
84  
85      /** Z body rotation angle entry. */
86      Z_ANGLE((token, context, container) -> token.processAsLabeledDouble('Z', Unit.DEGREE, context.getParsedUnitsBehavior(),
87                                                                          container::setRotationAngle)),
88  
89      /** X body rotation rate entry. */
90      X_RATE((token, context, container) -> token.processAsLabeledDouble('X', Units.DEG_PER_S, context.getParsedUnitsBehavior(),
91                                                                         container::setRotationRate)),
92  
93      /** Y body rotation rate entry. */
94      Y_RATE((token, context, container) -> token.processAsLabeledDouble('Y', Units.DEG_PER_S, context.getParsedUnitsBehavior(),
95                                                                         container::setRotationRate)),
96  
97      /** Z body rotation rate entry. */
98      Z_RATE((token, context, container) -> token.processAsLabeledDouble('Z', Units.DEG_PER_S, context.getParsedUnitsBehavior(),
99                                                                         container::setRotationRate));
100 
101     /** Processing method. */
102     private final TokenProcessor processor;
103 
104     /** Simple constructor.
105      * @param processor processing method
106      */
107     EulerKey(final TokenProcessor processor) {
108         this.processor = processor;
109     }
110 
111     /** Process one token.
112      * @param token token to process
113      * @param context context binding
114      * @param container container to fill
115      * @return true of token was accepted
116      */
117     public boolean process(final ParseToken token, final ContextBinding context, final Euler container) {
118         return processor.process(token, context, container);
119     }
120 
121     /** Interface for processing one token. */
122     interface TokenProcessor {
123         /** Process one token.
124          * @param token token to process
125          * @param context context binding
126          * @param container container to fill
127          * @return true of token was accepted
128          */
129         boolean process(ParseToken token, ContextBinding context, Euler container);
130     }
131 
132 }