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.utils.generation;
18
19 import java.io.IOException;
20 import java.util.List;
21
22 import org.hipparchus.util.FastMath;
23 import org.orekit.files.ccsds.utils.FileFormat;
24 import org.orekit.utils.AccurateFormatter;
25 import org.orekit.utils.units.Unit;
26
27 /** Generator for Key-Value Notation CCSDS messages.
28 * @author Luc Maisonobe
29 * @since 11.0
30 */
31 public class KvnGenerator extends AbstractGenerator {
32
33 /** Comment keyword. */
34 private static final String COMMENT = "COMMENT";
35
36 /** Start suffix for sections. */
37 private static final String START = "_START";
38
39 /** Stop suffix for sections. */
40 private static final String STOP = "_STOP";
41
42 /** String format used for all key/value pair lines. **/
43 private final String kvFormat;
44
45 /** Column number for aligning units. */
46 private final int unitsColumn;
47
48 /** String format used for all comment lines. **/
49 private final String commentFormat;
50
51 /** Simple constructor.
52 * @param output destination of generated output
53 * @param paddingWidth padding width for aligning the '=' sign
54 * (not counting the extra blank added before the '=' sign)
55 * @param outputName output name for error messages
56 * @param maxRelativeOffset maximum offset in seconds to use relative dates
57 * (if a date is too far from reference, it will be displayed as calendar elements)
58 * @param unitsColumn columns number for aligning units (if negative or zero, units are not output)
59 * @see org.orekit.files.ccsds.ndm.tdm.TdmWriter#KVN_PADDING_WIDTH TdmWriter.KVN_PADDING_WIDTH
60 * @see org.orekit.files.ccsds.ndm.adm.aem.AemWriter#KVN_PADDING_WIDTH AemWriter.KVN_PADDING_WIDTH
61 * @see org.orekit.files.ccsds.ndm.adm.apm.ApmWriter#KVN_PADDING_WIDTH ApmWriter.KVN_PADDING_WIDTH
62 * @see org.orekit.files.ccsds.ndm.odm.opm.OpmWriter#KVN_PADDING_WIDTH OpmWriter.KVN_PADDING_WIDTH
63 * @see org.orekit.files.ccsds.ndm.odm.omm.OmmWriter#KVN_PADDING_WIDTH OmmWriter.KVN_PADDING_WIDTH
64 * @see org.orekit.files.ccsds.ndm.odm.oem.OemWriter#KVN_PADDING_WIDTH OemWriter.KVN_PADDING_WIDTH
65 * @see org.orekit.files.ccsds.ndm.odm.ocm.OcmWriter#KVN_PADDING_WIDTH OcmWriter.KVN_PADDING_WIDTH
66 */
67 public KvnGenerator(final Appendable output, final int paddingWidth,
68 final String outputName, final double maxRelativeOffset,
69 final int unitsColumn) {
70 super(output, outputName, maxRelativeOffset, unitsColumn > 0);
71 kvFormat = "%-" + FastMath.max(1, paddingWidth) + "s = %s";
72 final StringBuilder builder = new StringBuilder(COMMENT);
73 builder.append(' ');
74 while (builder.length() < paddingWidth + 3) {
75 builder.append(' ');
76 }
77 builder.append("%s%n");
78 this.unitsColumn = unitsColumn;
79 this.commentFormat = builder.toString();
80 }
81
82 /** {@inheritDoc} */
83 @Override
84 public FileFormat getFormat() {
85 return FileFormat.KVN;
86 }
87
88 /** {@inheritDoc} */
89 @Override
90 public void startMessage(final String root, final String messageTypeKey, final double version) throws IOException {
91 writeEntry(messageTypeKey, String.format(AccurateFormatter.STANDARDIZED_LOCALE, "%.1f", version), null, true);
92 }
93
94 /** {@inheritDoc} */
95 @Override
96 public void endMessage(final String root) {
97 // nothing to do
98 }
99
100 /** {@inheritDoc} */
101 @Override
102 public void writeComments(final List<String> comments) throws IOException {
103 for (final String comment : comments) {
104 writeRawData(String.format(AccurateFormatter.STANDARDIZED_LOCALE, commentFormat, comment));
105 }
106 }
107
108 /** {@inheritDoc} */
109 @Override
110 public void writeEntry(final String key, final String value, final Unit unit, final boolean mandatory) throws IOException {
111 if (value == null) {
112 complain(key, mandatory);
113 } else {
114 final String s = String.format(AccurateFormatter.STANDARDIZED_LOCALE, kvFormat, key, value);
115 writeRawData(s);
116 if (writeUnits(unit)) {
117 for (int column = s.length(); column < unitsColumn; ++column) {
118 writeRawData(' ');
119 }
120 writeRawData('[');
121 writeRawData(siToCcsdsName(unit.getName()));
122 writeRawData(']');
123 }
124 newLine();
125 }
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public void enterSection(final String name) throws IOException {
131 writeRawData(name);
132 writeRawData(START);
133 newLine();
134 super.enterSection(name);
135 }
136
137 /** {@inheritDoc} */
138 @Override
139 public String exitSection() throws IOException {
140 final String name = super.exitSection();
141 writeRawData(name);
142 writeRawData(STOP);
143 newLine();
144 return name;
145 }
146
147 }