XmlGenerator.java

  1. /* Copyright 2002-2022 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.utils.generation;

  18. import java.io.IOException;
  19. import java.util.List;

  20. import org.orekit.files.ccsds.utils.FileFormat;
  21. import org.orekit.utils.AccurateFormatter;
  22. import org.orekit.utils.units.Unit;

  23. /** Generator for eXtended Markup Language CCSDS messages.
  24.  * @author Luc Maisonobe
  25.  * @since 11.0
  26.  */
  27. public class XmlGenerator extends AbstractGenerator {

  28.     /** Default number of space for each indentation level. */
  29.     public static final int DEFAULT_INDENT = 2;

  30.     /** Name of the units attribute. */
  31.     public static final String UNITS = "units";

  32.     /** XML prolog. */
  33.     private static final String PROLOG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n";

  34.     /** Root element start tag. */
  35.     private static final String ROOT_START = "<%s id=\"%s\" version=\"%.1f\">%n";

  36.     /** Element end tag. */
  37.     private static final String START_TAG = "<%s>%n";

  38.     /** Element end tag. */
  39.     private static final String END_TAG = "</%s>%n";

  40.     /** Leaf element format without attributes. */
  41.     private static final String LEAF_0_ATTRIBUTES = "<%s>%s</%s>%n";

  42.     /** Leaf element format with one attribute. */
  43.     private static final String LEAF_1_ATTRIBUTE = "<%s %s=\"%s\">%s</%s>%n";

  44.     /** Leaf element format with two attributes. */
  45.     private static final String LEAF_2_ATTRIBUTES = "<%s %s=\"%s\" %s=\"%s\">%s</%s>%n";

  46.     /** Comment key. */
  47.     private static final String COMMENT = "COMMENT";

  48.     /** Indentation size. */
  49.     private final int indentation;

  50.     /** Nesting level. */
  51.     private int level;

  52.     /** Simple constructor.
  53.      * @param output destination of generated output
  54.      * @param indentation number of space for each indentation level
  55.      * @param outputName output name for error messages
  56.      * @param writeUnits if true, units must be written
  57.      * @see #DEFAULT_INDENT
  58.      * @throws IOException if an I/O error occurs.
  59.      */
  60.     public XmlGenerator(final Appendable output, final int indentation,
  61.                         final String outputName, final boolean writeUnits) throws IOException {
  62.         super(output, outputName, writeUnits);
  63.         this.indentation = indentation;
  64.         this.level       = 0;
  65.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, PROLOG));
  66.     }

  67.     /** {@inheritDoc} */
  68.     @Override
  69.     public FileFormat getFormat() {
  70.         return FileFormat.XML;
  71.     }

  72.     /** {@inheritDoc} */
  73.     @Override
  74.     public void startMessage(final String root, final String messageTypeKey, final double version) throws IOException {
  75.         indent();
  76.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, ROOT_START,
  77.                                    root, messageTypeKey, version));
  78.         ++level;
  79.     }

  80.     /** {@inheritDoc} */
  81.     @Override
  82.     public void endMessage(final String root) throws IOException {
  83.         --level;
  84.         indent();
  85.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, END_TAG,
  86.                                    root));
  87.     }

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     public void writeComments(final List<String> comments) throws IOException {
  91.         for (final String comment : comments) {
  92.             writeEntry(COMMENT, comment, null, false);
  93.         }
  94.     }

  95.     /** Write an element with one attribute.
  96.      * @param name tag name
  97.      * @param value element value
  98.      * @param attributeName attribute name
  99.      * @param attributeValue attribute value
  100.      * @throws IOException if an I/O error occurs.
  101.      */
  102.     public void writeOneAttributeElement(final String name, final String value,
  103.                                          final String attributeName, final String attributeValue)
  104.         throws IOException {
  105.         indent();
  106.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, LEAF_1_ATTRIBUTE,
  107.                                    name, attributeName, attributeValue, value, name));
  108.     }

  109.     /** Write an element with two attributes.
  110.      * @param name tag name
  111.      * @param value element value
  112.      * @param attribute1Name attribute 1 name
  113.      * @param attribute1Value attribute 1 value
  114.      * @param attribute2Name attribute 2 name
  115.      * @param attribute2Value attribute 2 value
  116.      * @throws IOException if an I/O error occurs.
  117.      */
  118.     public void writeTwoAttributesElement(final String name, final String value,
  119.                                           final String attribute1Name, final String attribute1Value,
  120.                                           final String attribute2Name, final String attribute2Value)
  121.         throws IOException {
  122.         indent();
  123.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, LEAF_2_ATTRIBUTES,
  124.                                    name,
  125.                                    attribute1Name, attribute1Value, attribute2Name, attribute2Value,
  126.                                    value, name));
  127.     }

  128.     /** {@inheritDoc} */
  129.     @Override
  130.     public void writeEntry(final String key, final String value, final Unit unit, final boolean mandatory) throws IOException {
  131.         if (value == null) {
  132.             complain(key, mandatory);
  133.         } else {
  134.             indent();
  135.             if (writeUnits(unit)) {
  136.                 writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, LEAF_1_ATTRIBUTE,
  137.                                            key, UNITS, siToCcsdsName(unit.getName()), value, key));
  138.             } else {
  139.                 writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, LEAF_0_ATTRIBUTES,
  140.                                            key, value, key));
  141.             }
  142.         }
  143.     }

  144.     /** {@inheritDoc} */
  145.     @Override
  146.     public void enterSection(final String name) throws IOException {
  147.         indent();
  148.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, START_TAG, name));
  149.         ++level;
  150.         super.enterSection(name);
  151.     }

  152.     /** {@inheritDoc} */
  153.     @Override
  154.     public String exitSection() throws IOException {
  155.         final String name = super.exitSection();
  156.         --level;
  157.         indent();
  158.         writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, END_TAG, name));
  159.         return name;
  160.     }

  161.     /** Indent line.
  162.      * @throws IOException if an I/O error occurs.
  163.      */
  164.     private void indent() throws IOException {
  165.         for (int i = 0; i < level * indentation; ++i) {
  166.             writeRawData(' ');
  167.         }
  168.     }

  169. }