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.section;
18  
19  import org.orekit.errors.OrekitException;
20  import org.orekit.errors.OrekitMessages;
21  import org.orekit.files.ccsds.utils.FileFormat;
22  import org.orekit.files.ccsds.utils.lexical.ParseToken;
23  import org.orekit.files.ccsds.utils.lexical.TokenType;
24  import org.orekit.files.ccsds.utils.parsing.AbstractConstituentParser;
25  import org.orekit.files.ccsds.utils.parsing.ProcessingState;
26  
27  /** {@link ProcessingState} for structure of {@link FileFormat#XML} CCSDS Messages.
28   * @author Luc Maisonobe
29   * @since 11.0
30   */
31  public class XmlStructureProcessingState implements ProcessingState {
32  
33      /** Name of the root element. */
34      private final String root;
35  
36      /** Parser for the complete message. */
37      private final AbstractConstituentParser<?, ?, ?> parser;
38  
39      /** Simple constructor.
40       * @param root name of the root element
41       * @param parser parser for the complete message
42       */
43      public XmlStructureProcessingState(final String root, final AbstractConstituentParser<?, ?, ?> parser) {
44          this.root   = root;
45          this.parser = parser;
46      }
47  
48      /** {@inheritDoc} */
49      @Override
50      public boolean processToken(final ParseToken token) {
51  
52          if (root.equals(token.getName())) {
53              parser.setEndTagSeen(token.getType() == TokenType.STOP);
54              return true;
55          }
56  
57          if (Double.isNaN(parser.getHeader().getFormatVersion())) {
58              // the first thing we expect (after the ignored start tag for root element) is the format version
59              if (parser.getFormatVersionKey() != null &&
60                  parser.getFormatVersionKey().equals(token.getName()) && token.getType() == TokenType.ENTRY) {
61                  parser.getHeader().setFormatVersion(token.getContentAsDouble());
62                  return true;
63              } else {
64                  throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, token.getFileName());
65              }
66          }
67  
68          try {
69              return XmlStructureKey.valueOf(token.getName()).process(token, parser);
70          } catch (IllegalArgumentException iae) {
71              // ignored, we delegate handling this token to fallback state
72              return false;
73          }
74      }
75  
76  }