TdmParser.java

  1. /* Copyright 2002-2024 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.tdm;

  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.function.Function;

  21. import org.orekit.data.DataContext;
  22. import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
  23. import org.orekit.files.ccsds.section.HeaderProcessingState;
  24. import org.orekit.files.ccsds.section.KvnStructureProcessingState;
  25. import org.orekit.files.ccsds.section.MetadataKey;
  26. import org.orekit.files.ccsds.section.Segment;
  27. import org.orekit.files.ccsds.section.XmlStructureProcessingState;
  28. import org.orekit.files.ccsds.utils.ContextBinding;
  29. import org.orekit.files.ccsds.utils.FileFormat;
  30. import org.orekit.files.ccsds.utils.lexical.ParseToken;
  31. import org.orekit.files.ccsds.utils.parsing.AbstractConstituentParser;
  32. import org.orekit.files.ccsds.utils.parsing.ProcessingState;
  33. import org.orekit.utils.IERSConventions;


  34. /**
  35.  * Class for CCSDS Tracking 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.  *
  46.  * <p>References:</p>
  47.  * <ul>
  48.  *   <li><a href="https://public.ccsds.org/Pubs/503x0b1c1.pdf">CCSDS 503.0-B-1 recommended standard</a> ("Tracking Data Message", Blue Book, Issue 1, November 2007)</li>
  49.  *   <li><a href="https://public.ccsds.org/Pubs/505x0b1.pdf">CCSDS 505.0-B-1 recommended standard</a> ("XML Specification for Navigation Data Message", Blue Book, Issue 1, December 2010)</li>
  50.  * </ul>
  51.  *
  52.  * @author Maxime Journot
  53.  * @since 9.0
  54.  */
  55. public class TdmParser extends AbstractConstituentParser<TdmHeader, Tdm, TdmParser> {

  56.     /** Converter for {@link RangeUnits#RU Range Units} (may be null). */
  57.     private final RangeUnitsConverter converter;

  58.     /** Metadata for current observation block. */
  59.     private TdmMetadata metadata;

  60.     /** Context binding valid for current metadata. */
  61.     private ContextBinding context;

  62.     /** Current Observation Block being parsed. */
  63.     private ObservationsBlock observationsBlock;

  64.     /** File header. */
  65.     private TdmHeader header;

  66.     /** File segments. */
  67.     private List<Segment<TdmMetadata, ObservationsBlock>> segments;

  68.     /** Processor for global message structure. */
  69.     private ProcessingState structureProcessor;

  70.     /** Complete constructor.
  71.      * <p>
  72.      * Calling this constructor directly is not recommended. Users should rather use
  73.      * {@link org.orekit.files.ccsds.ndm.ParserBuilder#buildTdmParser()
  74.      * parserBuilder.buildTdmParser()}.
  75.      * </p>
  76.      * @param conventions IERS Conventions
  77.      * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
  78.      * @param dataContext used to retrieve frames, time scales, etc.
  79.      * @param parsedUnitsBehavior behavior to adopt for handling parsed units
  80.      * @param converter converter for {@link RangeUnits#RU Range Units} (may be null if there
  81.      * are no range observations in {@link RangeUnits#RU Range Units})
  82.      * @param filters filters to apply to parse tokens
  83.      * @since 12.0
  84.      */
  85.     public TdmParser(final IERSConventions conventions, final boolean simpleEOP, final DataContext dataContext,
  86.                      final ParsedUnitsBehavior parsedUnitsBehavior, final RangeUnitsConverter converter,
  87.                      final Function<ParseToken, List<ParseToken>>[] filters) {
  88.         super(Tdm.ROOT, Tdm.FORMAT_VERSION_KEY, conventions, simpleEOP, dataContext, parsedUnitsBehavior, filters);
  89.         this.converter = converter;
  90.     }

  91.     /** {@inheritDoc} */
  92.     @Override
  93.     public TdmHeader getHeader() {
  94.         return header;
  95.     }

  96.     /** {@inheritDoc} */
  97.     @Override
  98.     public void reset(final FileFormat fileFormat) {
  99.         header             = new TdmHeader();
  100.         segments           = new ArrayList<>();
  101.         metadata           = null;
  102.         context            = null;
  103.         observationsBlock  = null;
  104.         if (fileFormat == FileFormat.XML) {
  105.             structureProcessor = new XmlStructureProcessingState(Tdm.ROOT, this);
  106.             reset(fileFormat, structureProcessor);
  107.         } else {
  108.             structureProcessor = new KvnStructureProcessingState(this);
  109.             reset(fileFormat, new HeaderProcessingState(this));
  110.         }
  111.     }

  112.     /** {@inheritDoc} */
  113.     @Override
  114.     public Tdm build() {
  115.         return new Tdm(header, segments, getConventions(), getDataContext());
  116.     }

  117.     /** {@inheritDoc} */
  118.     @Override
  119.     public boolean prepareHeader() {
  120.         anticipateNext(new HeaderProcessingState(this));
  121.         return true;
  122.     }

  123.     /** {@inheritDoc} */
  124.     @Override
  125.     public boolean inHeader() {
  126.         anticipateNext(structureProcessor);
  127.         return true;
  128.     }

  129.     /** {@inheritDoc} */
  130.     @Override
  131.     public boolean finalizeHeader() {
  132.         header.validate(header.getFormatVersion());
  133.         return true;
  134.     }

  135.     /** {@inheritDoc} */
  136.     @Override
  137.     public boolean prepareMetadata() {
  138.         if (metadata != null) {
  139.             return false;
  140.         }
  141.         metadata  = new TdmMetadata();
  142.         context   = new ContextBinding(
  143.             this::getConventions, this::isSimpleEOP,
  144.             this::getDataContext, this::getParsedUnitsBehavior,
  145.             () -> null, metadata::getTimeSystem, () -> 0.0, () -> 1.0);
  146.         anticipateNext(this::processMetadataToken);
  147.         return true;
  148.     }

  149.     /** {@inheritDoc} */
  150.     @Override
  151.     public boolean inMetadata() {
  152.         anticipateNext(structureProcessor);
  153.         return true;
  154.     }

  155.     /** {@inheritDoc} */
  156.     @Override
  157.     public boolean finalizeMetadata() {
  158.         metadata.validate(header.getFormatVersion());
  159.         return true;
  160.     }

  161.     /** {@inheritDoc} */
  162.     @Override
  163.     public boolean prepareData() {
  164.         observationsBlock = new ObservationsBlock();
  165.         anticipateNext(this::processDataToken);
  166.         return true;
  167.     }

  168.     /** {@inheritDoc} */
  169.     @Override
  170.     public boolean inData() {
  171.         anticipateNext(structureProcessor);
  172.         return true;
  173.     }

  174.     /** {@inheritDoc} */
  175.     @Override
  176.     public boolean finalizeData() {
  177.         segments.add(new Segment<>(metadata, observationsBlock));
  178.         metadata          = null;
  179.         context           = null;
  180.         observationsBlock = null;
  181.         return true;
  182.     }

  183.     /** Process one metadata token.
  184.      * @param token token to process
  185.      * @return true if token was processed, false otherwise
  186.      */
  187.     private boolean processMetadataToken(final ParseToken token) {
  188.         inMetadata();
  189.         try {
  190.             return token.getName() != null &&
  191.                    MetadataKey.valueOf(token.getName()).process(token, context, metadata);
  192.         } catch (IllegalArgumentException iaeM) {
  193.             try {
  194.                 return TdmMetadataKey.valueOf(token.getName()).process(token, context, metadata);
  195.             } catch (IllegalArgumentException iaeT) {
  196.                 // token has not been recognized
  197.                 return false;
  198.             }
  199.         }
  200.     }

  201.     /** Process one data token.
  202.      * @param token token to process
  203.      * @return true if token was processed, false otherwise
  204.      */
  205.     private boolean processDataToken(final ParseToken token) {
  206.         try {
  207.             inData();
  208.             try {
  209.                 // global tokens (observation wrapper, comments, epoch in XML)
  210.                 return token.getName() != null &&
  211.                        TdmDataKey.valueOf(token.getName()).process(token, context, observationsBlock);
  212.             } catch (IllegalArgumentException iae) {
  213.                 // observation
  214.                 return ObservationType.valueOf(token.getName()).process(token, context, converter, metadata, observationsBlock);
  215.             }
  216.         } catch (IllegalArgumentException iae) {
  217.             // token has not been recognized
  218.             return false;
  219.         }
  220.     }

  221. }