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.ndm;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.CharArrayWriter;
21  import java.io.IOException;
22  import java.nio.charset.StandardCharsets;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.List;
26  
27  import org.hipparchus.random.RandomGenerator;
28  import org.hipparchus.random.Well19937a;
29  import org.junit.Assert;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.orekit.Utils;
33  import org.orekit.data.DataSource;
34  import org.orekit.errors.OrekitException;
35  import org.orekit.errors.OrekitMessages;
36  import org.orekit.files.ccsds.utils.generation.Generator;
37  import org.orekit.files.ccsds.utils.generation.XmlGenerator;
38  import org.orekit.time.AbsoluteDate;
39  import org.orekit.time.TimeScalesFactory;
40  import org.orekit.utils.Constants;
41  
42  /**
43   * Test class for CCSDS Navigation Data Message writing.<p>
44   * @author Luc Maisonobe
45   */
46  public class NdmWriterTest {
47  
48      @Before
49      public void setUp() {
50          Utils.setDataRoot("regular-data");
51      }
52  
53      @Test
54      public void testOpm() throws IOException {
55          final String name = "/ccsds/ndm/NDM-opm.xml";
56          final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
57          final Ndm ndm = new ParserBuilder().buildNdmParser().parseMessage(source);
58          final NdmWriter writer = new WriterBuilder().buildNdmWriter();
59          final CharArrayWriter caw = new CharArrayWriter();
60          try (Generator generator = new XmlGenerator(caw, XmlGenerator.DEFAULT_INDENT, "dummy.xml", true)) {
61              writer.writeMessage(generator, ndm);
62          }
63          final byte[]      bytes  = caw.toString().getBytes(StandardCharsets.UTF_8);
64          final DataSource source2 = new DataSource(name, () -> new ByteArrayInputStream(bytes));
65          NdmTestUtils.checkContainer(ndm, new ParserBuilder().buildNdmParser().parseMessage(source2));
66      }
67  
68      @Test
69      public void testOpmApm() throws IOException {
70          final String name = "/ccsds/ndm/NDM-ocm-apm.xml";
71          final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
72          final Ndm ndm = new ParserBuilder().buildNdmParser().parseMessage(source);
73          final NdmWriter writer = new WriterBuilder().buildNdmWriter();
74          final CharArrayWriter caw  = new CharArrayWriter();
75          try (final Generator generator = new XmlGenerator(caw, XmlGenerator.DEFAULT_INDENT, "dummy.xml", true)) {
76              writer.writeMessage(generator, ndm);
77          }
78          final byte[]      bytes  = caw.toString().getBytes(StandardCharsets.UTF_8);
79          final DataSource source2 = new DataSource(name, () -> new ByteArrayInputStream(bytes));
80          NdmTestUtils.checkContainer(ndm, new ParserBuilder().buildNdmParser().parseMessage(source2));
81      }
82  
83      @Test
84      public void testMisplacedComments() throws IOException {
85          final String name = "/ccsds/ndm/NDM-opm.xml";
86          final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
87          final Ndm ndm = new ParserBuilder().buildNdmParser().parseMessage(source);
88          final NdmWriter writer = new WriterBuilder().buildNdmWriter();
89          final CharArrayWriter caw  = new CharArrayWriter();
90          try (final Generator generator = new XmlGenerator(caw, XmlGenerator.DEFAULT_INDENT, "dummy.xml", true)) {
91              for (final String comment : ndm.getComments()) {
92                  writer.writeComment(generator, comment);
93              }
94              for (final NdmConstituent<?, ?> constituent : ndm.getConstituents()) {
95                  writer.writeConstituent(generator, constituent);
96              }
97              try {
98                  writer.writeComment(generator, "we are not allowed to put comments after constituents");
99                  Assert.fail("an exception should have been thrown");
100             } catch (OrekitException oe) {
101                 Assert.assertEquals(OrekitMessages.ATTEMPT_TO_GENERATE_MALFORMED_FILE, oe.getSpecifier());
102                 Assert.assertEquals("dummy.xml", oe.getParts()[0]);
103             }
104         }
105     }
106 
107     @Test
108     public void testRandomizedNdm() throws IOException {
109 
110         final ParserBuilder pb = new ParserBuilder().
111                                       withParsedUnitsBehavior(ParsedUnitsBehavior.STRICT_COMPLIANCE).
112                                       withMu(Constants.EIGEN5C_EARTH_MU).
113                                       withMissionReferenceDate(new AbsoluteDate("1996-12-17T00:00:00.000", TimeScalesFactory.getUTC()));
114 
115         final WriterBuilder wb = new WriterBuilder().
116                                  withMissionReferenceDate(pb.getMissionReferenceDate());
117 
118         // pool of constituents
119         List<NdmConstituent<?, ?>> pool = buildPool(pb);
120 
121         RandomGenerator random = new Well19937a(0x4a21ffc6d5b7dbe6l);
122         for (int i = 0; i < 100; ++i) {
123 
124             final String[] comments = new String[random.nextInt(3)];
125             for (int k = 0; k < comments.length; ++k) {
126                 comments[k] = Integer.toString(random.nextInt());
127             }
128 
129             final NdmConstituent<?, ?>[] constituents = new NdmConstituent<?,?>[1 + random.nextInt(20)];
130             for (int k = 0; k < constituents.length; ++k) {
131                 constituents[k] = pool.get(random.nextInt(pool.size()));
132             }
133 
134             // create randomized NDM
135             final Ndm original = new Ndm(Arrays.asList(comments), Arrays.asList(constituents));
136 
137             // write it
138             final CharArrayWriter caw  = new CharArrayWriter();
139             try (final Generator generator = new XmlGenerator(caw, XmlGenerator.DEFAULT_INDENT, "dummy.xml", true)) {
140                 wb.buildNdmWriter().writeMessage(generator, original);
141             }
142 
143             // parse the written message back
144             final byte[]      bytes  = caw.toString().getBytes(StandardCharsets.UTF_8);
145             final DataSource source2 = new DataSource("dummy.xml", () -> new ByteArrayInputStream(bytes));
146             final Ndm rebuilt = pb.buildNdmParser().parseMessage(source2);
147 
148             // check we recovered the message properly
149             NdmTestUtils.checkContainer(original, rebuilt);
150 
151         }
152 
153     }
154 
155     /** build a pool of NdmConstituent.
156      * @param builder builder for constituents parsers
157      * @return pool of NdmConstituen
158      */
159     private List<NdmConstituent<?, ?>> buildPool(final ParserBuilder builder) {
160 
161         final List<NdmConstituent<?, ?>> pool = new ArrayList<>();
162 
163         // AEM files
164         for (final String name :
165             Arrays.asList("/ccsds/adm/aem/AEMExample01.txt", "/ccsds/adm/aem/AEMExample02.txt", "/ccsds/adm/aem/AEMExample03.txt",
166                           "/ccsds/adm/aem/AEMExample03.xml", "/ccsds/adm/aem/AEMExample04.txt", "/ccsds/adm/aem/AEMExample05.txt",
167                           "/ccsds/adm/aem/AEMExample07.txt", "/ccsds/adm/aem/AEMExample08.txt", "/ccsds/adm/aem/AEMExample09.txt",
168                           "/ccsds/adm/aem/AEMExample10.txt", "/ccsds/adm/aem/AEMExample11.xml", "/ccsds/adm/aem/AEMExample12.txt",
169                           "/ccsds/adm/aem/AEMExample13.xml")) {
170             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
171             pool.add(builder.buildAemParser().parseMessage(source));
172         }
173 
174         // APM files
175         for (final String name :
176             Arrays.asList("/ccsds/adm/apm/APMExample1.txt",  "/ccsds/adm/apm/APMExample2.txt",  "/ccsds/adm/apm/APMExample2.xml",
177                           "/ccsds/adm/apm/APMExample3.txt",  "/ccsds/adm/apm/APMExample4.txt",  "/ccsds/adm/apm/APMExample5.txt",
178                           "/ccsds/adm/apm/APMExample6.txt")) {
179             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
180             pool.add(builder.buildApmParser().parseMessage(source));
181         }
182 
183         // OCM files
184         for (final String name :
185             Arrays.asList("/ccsds/odm/ocm/OCMExample1.txt",  "/ccsds/odm/ocm/OCMExample2.txt",  "/ccsds/odm/ocm/OCMExample2.xml",
186                           "/ccsds/odm/ocm/OCMExample3.txt",  "/ccsds/odm/ocm/OCMExample4.txt")) {
187             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
188             pool.add(builder.buildOcmParser().parseMessage(source));
189         }
190 
191         // OEM files
192         for (final String name :
193             Arrays.asList("/ccsds/odm/oem/OEMExample1.txt",  "/ccsds/odm/oem/OEMExample2.txt",  "/ccsds/odm/oem/OEMExample3.txt",
194                           "/ccsds/odm/oem/OEMExample3.xml",  "/ccsds/odm/oem/OEMExample4.txt",  "/ccsds/odm/oem/OEMExample5.txt",
195                           "/ccsds/odm/oem/OEMExample6.txt",  "/ccsds/odm/oem/OEMExample8.txt")) {
196             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
197             pool.add(builder.buildOemParser().parseMessage(source));
198         }
199 
200         // OMM files
201         for (final String name :
202             Arrays.asList("/ccsds/odm/omm/OMMExample1.txt",  "/ccsds/odm/omm/OMMExample2.txt",  "/ccsds/odm/omm/OMMExample2.xml",
203                           "/ccsds/odm/omm/OMMExample3.txt",  "/ccsds/odm/omm/OMMExample4.txt",  "/ccsds/odm/omm/OMMExample4.xml")) {
204             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
205             pool.add(builder.buildOmmParser().parseMessage(source));
206         }
207 
208         // OPM files
209         for (final String name :
210             Arrays.asList("/ccsds/odm/opm/OPMExample1.txt",  "/ccsds/odm/opm/OPMExample2.txt",  "/ccsds/odm/opm/OPMExample3.txt",
211                           "/ccsds/odm/opm/OPMExample3.xml",  "/ccsds/odm/opm/OPMExample4.txt",  "/ccsds/odm/opm/OPMExample5.txt",
212                           "/ccsds/odm/opm/OPMExample6.txt",  "/ccsds/odm/opm/OPMExample6.txt",  "/ccsds/odm/opm/OPMExample8.txt")) {
213             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
214             pool.add(builder.buildOpmParser().parseMessage(source));
215         }
216 
217         // TDM files
218         for (final String name :
219             Arrays.asList("/ccsds/tdm/kvn/TDMExample15.txt", "/ccsds/tdm/kvn/TDMExample2.txt",  "/ccsds/tdm/kvn/TDMExample4.txt",
220                           "/ccsds/tdm/kvn/TDMExample6.txt",  "/ccsds/tdm/kvn/TDMExample8.txt",
221                           "/ccsds/tdm/xml/TDMExample15.xml", "/ccsds/tdm/xml/TDMExample2.xml",  "/ccsds/tdm/xml/TDMExample4.xml",
222                           "/ccsds/tdm/xml/TDMExample6.xml",  "/ccsds/tdm/xml/TDMExample8.xml")) {
223             final DataSource source = new DataSource(name, () -> NdmWriterTest.class.getResourceAsStream(name));
224             pool.add(builder.buildTdmParser().parseMessage(source));
225         }
226 
227         return pool;
228 
229     }
230 
231 }