1   /* Copyright 2002-2025 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.utils.ContextBinding;
21  import org.orekit.files.ccsds.utils.lexical.ParseToken;
22  import org.orekit.files.ccsds.utils.lexical.TokenType;
23  import org.orekit.utils.units.Unit;
24  
25  /** Keys for {@link SpinStabilized APM spin-stabilized} entries.
26   * @author Bryan Cazabonne
27   * @since 10.2
28   */
29  public enum SpinStabilizedKey {
30  
31      /** Comment entry. */
32      COMMENT((token, context, container) ->
33              token.getType() == TokenType.ENTRY ? container.addComment(token.getContentAsNormalizedString()) : true),
34  
35      /** First reference frame entry (only for ADM V1). */
36      SPIN_FRAME_A((token, context, container) -> token.processAsFrame(container.getEndpoints()::setFrameA, context, true, true, true)),
37  
38      /** First reference frame entry.
39       * @since 12.0
40       */
41      REF_FRAME_A((token, context, container) -> token.processAsFrame(container.getEndpoints()::setFrameA, context, true, true, true)),
42  
43      /** Second reference frame entry (only for ADM V1). */
44      SPIN_FRAME_B((token, context, container) -> {
45          if (token.getType() == TokenType.ENTRY) {
46              container.checkNotNull(container.getEndpoints().getFrameA(), SPIN_FRAME_A.name());
47              final boolean aIsSpaceraftBody = container.getEndpoints().getFrameA().asSpacecraftBodyFrame() != null;
48              return token.processAsFrame(container.getEndpoints()::setFrameB, context,
49                                          aIsSpaceraftBody, aIsSpaceraftBody, !aIsSpaceraftBody);
50          }
51          return true;
52      }),
53  
54      /** Second reference frame entry.
55       * @since 12.0
56       */
57      REF_FRAME_B((token, context, container) -> {
58          if (token.getType() == TokenType.ENTRY) {
59              container.checkNotNull(container.getEndpoints().getFrameA(), REF_FRAME_A.name());
60              final boolean aIsSpaceraftBody = container.getEndpoints().getFrameA().asSpacecraftBodyFrame() != null;
61              return token.processAsFrame(container.getEndpoints()::setFrameB, context,
62                                          aIsSpaceraftBody, aIsSpaceraftBody, !aIsSpaceraftBody);
63          }
64          return true;
65      }),
66  
67      /** Rotation direction entry (only for ADM V1). */
68      SPIN_DIR((token, context, container) -> {
69          if (token.getType() == TokenType.ENTRY) {
70              container.getEndpoints().setA2b(token.getContentAsUppercaseCharacter() == 'A');
71          }
72          return true;
73      }),
74  
75      /** Spin right ascension entry. */
76      SPIN_ALPHA((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
77                                                                      container::setSpinAlpha)),
78  
79      /** Spin declination entry. */
80      SPIN_DELTA((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
81                                                                      container::setSpinDelta)),
82  
83      /** Spin phase entry. */
84      SPIN_ANGLE((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
85                                                                      container::setSpinAngle)),
86  
87      /** Spin angular velocity entry. */
88      SPIN_ANGLE_VEL((token, context, container) -> token.processAsDouble(Units.DEG_PER_S, context.getParsedUnitsBehavior(),
89                                                                          container::setSpinAngleVel)),
90  
91      /** Nutation angle entry. */
92      NUTATION((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
93                                                                    container::setNutation)),
94  
95      /** Nutation period entry. */
96      NUTATION_PER((token, context, container) -> token.processAsDouble(Unit.SECOND, context.getParsedUnitsBehavior(),
97                                                                        container::setNutationPeriod)),
98  
99      /** Nutation phase entry. */
100     NUTATION_PHASE((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
101                                                                         container::setNutationPhase)),
102 
103     /** Momentum right ascension entry.
104      * @since 12.0
105      */
106     MOMENTUM_ALPHA((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
107                                                                         container::setMomentumAlpha)),
108 
109     /** Momentum declination entry.
110      * @since 12.0
111      */
112     MOMENTUM_DELTA((token, context, container) -> token.processAsDouble(Unit.DEGREE, context.getParsedUnitsBehavior(),
113                                                                         container::setMomentumDelta)),
114 
115     /** Nutation velocity entry.
116      * @since 12.0
117      */
118     NUTATION_VEL((token, context, container) -> token.processAsDouble(Units.DEG_PER_S, context.getParsedUnitsBehavior(),
119                                                                       container::setNutationVel));
120 
121     /** Processing method. */
122     private final transient TokenProcessor processor;
123 
124     /** Simple constructor.
125      * @param processor processing method
126      */
127     SpinStabilizedKey(final TokenProcessor processor) {
128         this.processor = processor;
129     }
130 
131     /** Process one token.
132      * @param token token to process
133      * @param context context binding
134      * @param container container to fill
135      * @return true of token was accepted
136      */
137     public boolean process(final ParseToken token, final ContextBinding context, final SpinStabilized container) {
138         return processor.process(token, context, container);
139     }
140 
141     /** Interface for processing one token. */
142     interface TokenProcessor {
143         /** Process one token.
144          * @param token token to process
145          * @param context context binding
146          * @param container container to fill
147          * @return true of token was accepted
148          */
149         boolean process(ParseToken token, ContextBinding context, SpinStabilized container);
150     }
151 
152 }