1   /* Copyright 2002-2018 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (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;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.net.MalformedURLException;
22  import java.net.URISyntaxException;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.hamcrest.CoreMatchers;
27  import org.junit.Assert;
28  import org.junit.Before;
29  import org.junit.Test;
30  import org.orekit.Utils;
31  import org.orekit.errors.OrekitException;
32  import org.orekit.errors.OrekitMessages;
33  import org.orekit.files.ccsds.TDMParser.TDMFileFormat;
34  import org.orekit.frames.FramesFactory;
35  import org.orekit.time.AbsoluteDate;
36  import org.orekit.time.TimeScale;
37  import org.orekit.time.TimeScalesFactory;
38  
39  /**
40   * Test class for CCSDS Tracking Data Message parsing.<p>
41   * Examples are taken from Annexe D of
42   * <a href="https://public.ccsds.org/Pubs/503x0b1c1.pdf">CCSDS 503.0-B-1 recommended standard [1]</a> ("Tracking Data Message", Blue Book, Version 1.0, November 2007).<p>
43   * Both KeyValue and XML formats are tested here on equivalent files.
44   * @author mjournot
45   *
46   */
47  public class TDMParserTest {
48  
49      @Before
50      public void setUp()
51                      throws Exception {
52          Utils.setDataRoot("regular-data");
53      }
54  
55      @Test
56      public void testParseTdmExternalResourceIssue368() throws OrekitException {
57          // setup
58          TDMParser parser = new TDMParser().withFileFormat(TDMFileFormat.XML);
59          String name = "/ccsds/XML/TDM-external-doctype.xml";
60          InputStream in = TDMParserTest.class.getResourceAsStream(name);
61  
62          try {
63              // action
64              parser.parse(in, name);
65  
66              // verify
67              Assert.fail("Expected Exception");
68          } catch (OrekitException e) {
69              // Malformed URL exception indicates external resource was disabled
70              // file not found exception indicates parser tried to load the resource
71              Assert.assertThat(e.getCause(),
72                      CoreMatchers.instanceOf(MalformedURLException.class));
73          }
74      }
75  
76      @Test
77      public void testParseTdmKeyValueExample2() throws OrekitException, IOException {
78          // Example 2 of [1]
79          // See Figure D-2: TDM Example: One-Way Data w/Frequency Offset
80          // Data lines number was cut down to 7
81          final String ex = "/ccsds/TDMExample2.txt";
82          final InputStream inEntry = getClass().getResourceAsStream(ex);
83          final TDMParser parser = new TDMParser().withFileFormat(TDMParser.TDMFileFormat.KEYVALUE);
84          final TDMFile file = parser.parse(inEntry, ex);
85          validateTDMExample2(file);
86      }
87  
88      @Test
89      public void testParseTdmKeyValueExample4() throws OrekitException, IOException {
90  
91          // Example 4 of [1]
92          // See Figure D-4: TDM Example: Two-Way Ranging Data Only
93          // Data lines number was cut down to 20
94          final String ex = "/ccsds/TDMExample4.txt";
95          final InputStream inEntry = getClass().getResourceAsStream(ex);
96          final TDMParser parser = new TDMParser();
97          final TDMFile file = parser.parseKeyValue(inEntry, ex);
98          validateTDMExample4(file);
99      }
100 
101     @Test
102     public void testParseTdmKeyValueExample6() throws OrekitException, IOException {
103 
104         // Example 6 of [1]
105         // See Figure D-6: TDM Example: Four-Way Data
106         // Data lines number was cut down to 16
107         final String ex = "/ccsds/TDMExample6.txt";
108         final InputStream inEntry = getClass().getResourceAsStream(ex);
109         final TDMParser parser = new TDMParser();
110         final TDMFile file = parser.parse(inEntry, ex);
111         validateTDMExample6(file);
112     }
113 
114     @Test
115     public void testParseTdmKeyValueExample8() throws OrekitException, IOException {
116 
117         // Example 8 of [1]
118         // See Figure D-8: TDM Example: Angles, Range, Doppler Combined in Single TDM
119         // Data lines number was cut down to 18
120         final String ex = "/ccsds/TDMExample8.txt";
121         final InputStream inEntry = getClass().getResourceAsStream(ex);
122         final TDMParser parser = new TDMParser();
123         final TDMFile file = parser.parse(inEntry, ex);
124         validateTDMExample8(file);
125     }
126 
127     @Test
128     public void testParseTdmKeyValueExample15() throws OrekitException, IOException {
129 
130         // Example 15 of [1]
131         // See Figure D-15: TDM Example: Clock Bias/Drift Only
132         final String ex = "/ccsds/TDMExample15.txt";
133         final InputStream inEntry = getClass().getResourceAsStream(ex);
134         final TDMParser parser = new TDMParser();
135         final TDMFile file = parser.parse(inEntry, ex);
136         validateTDMExample15(file);
137     }
138 
139     @Test
140     public void testParseTdmKeyValueExampleAllKeywords() throws OrekitException, IOException {
141 
142         // Testing all TDM keywords
143         final String ex = "/ccsds/TDMExampleAllKeywords.txt";
144         final InputStream inEntry = getClass().getResourceAsStream(ex);
145         final TDMParser parser = new TDMParser();
146         final TDMFile file = parser.parse(inEntry, ex);
147         validateTDMExampleAllKeywords(file);
148     }
149 
150     @Test
151     public void testParseTdmXmlExample2() throws OrekitException, IOException {
152 
153         // Example 2 of [1]
154         // See Figure D-2: TDM Example: One-Way Data w/Frequency Offset
155         // Data lines number was cut down to 7
156         final String ex = "/ccsds/XML/TDMExample2.xml";
157         final InputStream inEntry = getClass().getResourceAsStream(ex);
158         final TDMParser parser = new TDMParser().withFileFormat(TDMParser.TDMFileFormat.XML);
159         final TDMFile file = parser.parse(inEntry, ex);
160         validateTDMExample2(file);
161     }
162 
163     @Test
164     public void testParseTdmXmlExample4() throws OrekitException, IOException {
165 
166         // Example 4 of [1]
167         // See Figure D-4: TDM Example: Two-Way Ranging Data Only
168         // Data lines number was cut down to 20
169         final String ex = "/ccsds/XML/TDMExample4.xml";
170         final InputStream inEntry = getClass().getResourceAsStream(ex);
171         final TDMParser parser = new TDMParser();
172         final TDMFile file = parser.parseXml(inEntry, ex);
173         validateTDMExample4(file);
174     }
175 
176     @Test
177     public void testParseTdmXmlExample6() throws OrekitException, IOException {
178 
179         // Example 6 of [1]
180         // See Figure D-6: TDM Example: Four-Way Data
181         // Data lines number was cut down to 16
182         final String ex = "/ccsds/XML/TDMExample6.xml";
183         final InputStream inEntry = getClass().getResourceAsStream(ex);
184         final TDMParser parser = new TDMParser();
185         final TDMFile file = parser.parse(inEntry, ex);
186         validateTDMExample6(file);
187     }
188 
189     @Test
190     public void testParseTdmXmlExample8() throws OrekitException, IOException {
191 
192         // Example 8 of [1]
193         // See Figure D-8: TDM Example: Angles, Range, Doppler Combined in Single TDM
194         // Data lines number was cut down to 18
195         final String ex = "/ccsds/XML/TDMExample8.xml";
196         final InputStream inEntry = getClass().getResourceAsStream(ex);
197         final TDMParser parser = new TDMParser();
198         final TDMFile file = parser.parse(inEntry, ex);
199         validateTDMExample8(file);
200     }
201 
202     @Test
203     public void testParseTdmXmlExample15() throws OrekitException, IOException {
204 
205         // Example 15 of [1]
206         // See Figure D-15: TDM Example: Clock Bias/Drift Only
207         final String ex = "/ccsds/XML/TDMExample15.xml";
208         final InputStream inEntry = getClass().getResourceAsStream(ex);
209         final TDMParser parser = new TDMParser();
210         final TDMFile file = parser.parse(inEntry, ex);
211         validateTDMExample15(file);
212     }
213 
214     @Test
215     public void testParseTdmXmlExampleAllKeywords() throws OrekitException, IOException {
216 
217         // Testing all TDM keywords
218         final String ex = "/ccsds/XML/TDMExampleAllKeywords.xml";
219         final InputStream inEntry = getClass().getResourceAsStream(ex);
220         final TDMParser parser = new TDMParser();
221         final TDMFile file = parser.parse(inEntry, ex);
222         validateTDMExampleAllKeywords(file);
223     }
224 
225     @Test
226     public void testDataNumberFormatErrorTypeKeyValue() {
227         try {
228             // Number format exception in data part
229             final String ex = "/ccsds/TDM-data-number-format-error.txt";
230             final InputStream inEntry = getClass().getResourceAsStream(ex);
231             final TDMParser parser = new TDMParser();
232             parser.parse(inEntry, ex);
233             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
234         } catch (OrekitException oe) {
235             Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
236             Assert.assertEquals(26, oe.getParts()[0]);
237             Assert.assertEquals("/ccsds/TDM-data-number-format-error.txt", oe.getParts()[1]);
238             Assert.assertEquals(String.format("\t%s","RECEIVE_FREQ_1 = 2005-159T17:41:03 this-is-not-a-number"), oe.getParts()[2]);
239         }
240     }
241 
242     @Test
243     public void testDataNumberFormatErrorTypeXml() {
244         try {
245             // Number format exception in data part
246             final String ex = "/ccsds/XML/TDM-data-number-format-error.xml";
247             final InputStream inEntry = getClass().getResourceAsStream(ex);
248             final TDMParser parser = new TDMParser();
249             parser.parse(inEntry, ex);
250             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
251         } catch (OrekitException oe) {
252             String specifier = String.format("%s\n%s",
253                                              "unable to parse line 47 of file /ccsds/XML/TDM-data-number-format-error.xml:",
254                                              "<RECEIVE_FREQ_1>this-is-not-a-number</RECEIVE_FREQ_1>");
255             Assert.assertEquals(specifier,oe.getMessage());
256         }
257     }
258 
259     @Test
260     public void testMetaDataNumberFormatErrorTypeKeyValue() {
261         try {
262             // Number format exception in metadata part
263             final String ex = "/ccsds/TDM-metadata-number-format-error.txt";
264             final InputStream inEntry = getClass().getResourceAsStream(ex);
265             final TDMParser parser = new TDMParser();
266             parser.parse(inEntry, ex);
267             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
268         } catch (OrekitException oe) {
269             Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
270             Assert.assertEquals(17, oe.getParts()[0]);
271             Assert.assertEquals("/ccsds/TDM-metadata-number-format-error.txt", oe.getParts()[1]);
272             Assert.assertEquals(String.format("\t%s","TRANSMIT_DELAY_1 = this-is-not-a-number"), oe.getParts()[2]);
273         }
274     }
275 
276     @Test
277     public void testMetaDataNumberFormatErrorTypeXml() {
278         try {
279             // Number format exception in metadata part
280             final String ex = "/ccsds/XML/TDM-metadata-number-format-error.xml";
281             final InputStream inEntry = getClass().getResourceAsStream(ex);
282             final TDMParser parser = new TDMParser();
283             parser.parse(inEntry, ex);
284             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
285         } catch (OrekitException oe) {
286             String specifier = String.format("%s\n%s",
287                                              "unable to parse line 26 of file /ccsds/XML/TDM-metadata-number-format-error.xml:",
288                                              "<TRANSMIT_DELAY_1>this-is-not-a-number</TRANSMIT_DELAY_1>");
289             Assert.assertEquals(specifier,oe.getMessage());
290         }
291     }
292 
293     @Test
294     public void testNonExistentFile() throws URISyntaxException {
295         // Try parsing a file that does not exist
296         final String realName = getClass().getResource("/ccsds/OEMExample2.txt").toURI().getPath();
297         final String wrongName = realName + "xxxxx";
298         try {
299             new TDMParser().parse(wrongName);
300             Assert.fail("An Orekit Exception \"UNABLE_TO_FIND_FILE\" should have been thrown");
301         } catch (OrekitException oe) {
302             Assert.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
303             Assert.assertEquals(wrongName, oe.getParts()[0]);
304         }
305     }
306 
307     @Test
308     public void testInconsistentTimeSystemsKeyValue() {
309         // Inconsistent time systems between two sets of data
310         try {
311             new TDMParser().withFileFormat(TDMFileFormat.KEYVALUE).parse(getClass().getResourceAsStream("/ccsds/TDM-inconsistent-time-systems.txt"));
312             Assert.fail("An Orekit Exception \"CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS\" should have been thrown");
313         } catch (OrekitException oe) {
314             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
315             Assert.assertEquals(CcsdsTimeScale.UTC, oe.getParts()[0]);
316             Assert.assertEquals(CcsdsTimeScale.TCG, oe.getParts()[1]);
317         }
318     }
319 
320     @Test
321     public void testInconsistentTimeSystemsXml() {
322         // Inconsistent time systems between two sets of data
323         try {
324             new TDMParser().withFileFormat(TDMFileFormat.XML).parse(getClass().getResourceAsStream("/ccsds/XML/TDM-inconsistent-time-systems.xml"));
325             Assert.fail("An Orekit Exception \"CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS\" should have been thrown");
326         } catch (OrekitException oe) {
327             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
328             Assert.assertEquals(CcsdsTimeScale.UTC, oe.getParts()[0]);
329             Assert.assertEquals(CcsdsTimeScale.TCG, oe.getParts()[1]);
330         }
331     }
332 
333     @Test
334     public void testWrongDataKeywordKeyValue()
335                     throws OrekitException, URISyntaxException {
336         // Unknown CCSDS keyword was read in data part
337         final String ex = "/ccsds/TDM-data-wrong-keyword.txt";
338         final InputStream inEntry = getClass().getResourceAsStream(ex);
339         try {
340             new TDMParser().parse(inEntry, ex);
341             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
342         } catch (OrekitException oe) {
343             Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
344             Assert.assertEquals(26, oe.getParts()[0]);
345             Assert.assertEquals("%s","/ccsds/TDM-data-wrong-keyword.txt", oe.getParts()[1]);
346             Assert.assertEquals(String.format("\t%s","WRONG_KEYWORD  = 2005-159T17:41:03 -294.9673"), oe.getParts()[2]);
347         }
348     }
349 
350     @Test
351     public void testWrongDataKeywordXml()
352                     throws OrekitException, URISyntaxException {
353         // Unknown CCSDS keyword was read in data part
354         final String ex = "/ccsds/XML/TDM-data-wrong-keyword.xml";
355         final InputStream inEntry = getClass().getResourceAsStream(ex);
356         try {
357             new TDMParser().parse(inEntry, ex);
358             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
359         } catch (OrekitException oe) {
360             String specifier = String.format("%s\n%s",
361                                              "unexpected keyword in CCSDS line number 47 of file /ccsds/XML/TDM-data-wrong-keyword.xml:",
362                                              "<WRONG_KEYWORD>");
363             Assert.assertEquals(specifier,oe.getMessage());
364         }
365     }
366 
367     @Test
368     public void testWrongMetaDataKeywordKeyValue()
369                     throws OrekitException, URISyntaxException {
370         // Unknown CCSDS keyword was read in data part
371         final String ex = "/ccsds/TDM-metadata-wrong-keyword.txt";
372         final InputStream inEntry = getClass().getResourceAsStream(ex);
373         try {
374             new TDMParser().parse(inEntry, ex);
375             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
376         } catch (OrekitException oe) {
377             Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
378             Assert.assertEquals(16, oe.getParts()[0]);
379             Assert.assertEquals("/ccsds/TDM-metadata-wrong-keyword.txt", oe.getParts()[1]);
380             Assert.assertEquals(String.format("\t%s", "WRONG_KEYWORD = 32021035200.0"), oe.getParts()[2]);
381         }
382     }
383 
384     @Test
385     public void testWrongMetaDataKeywordXml()
386                     throws OrekitException, URISyntaxException {
387         // Unknown CCSDS keyword was read in data part
388         final String ex = "/ccsds/XML/TDM-metadata-wrong-keyword.xml";
389         final InputStream inEntry = getClass().getResourceAsStream(ex);
390         try {
391             new TDMParser().parse(inEntry, ex);
392             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
393         } catch (OrekitException oe) {
394             String specifier = String.format("%s\n%s",
395                                              "unexpected keyword in CCSDS line number 15 of file /ccsds/XML/TDM-metadata-wrong-keyword.xml:",
396                                              "<WRONG_KEYWORD>");
397             Assert.assertEquals(specifier,oe.getMessage());
398         }
399     }
400 
401     @Test
402     public void testWrongTimeSystemKeyValue() {
403         // Time system not implemented CCSDS keyword was read in data part
404         final String ex = "/ccsds/TDM-metadata-timesystem-not-implemented.txt";
405         final InputStream inEntry = getClass().getResourceAsStream(ex);
406         try {
407             new TDMParser().parse(inEntry, ex);
408             Assert.fail("An exception \"CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED\"should have been thrown");
409         } catch (OrekitException oe) {
410             Assert.assertEquals(OrekitMessages.CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED, oe.getSpecifier());
411             Assert.assertEquals("WRONG-TIME-SYSTEM", oe.getParts()[0]);
412         }
413     }
414 
415     @Test
416     public void testWrongTimeSystemXml() {
417         // Time system not implemented CCSDS keyword was read in data part
418         final String ex = "/ccsds/XML/TDM-metadata-timesystem-not-implemented.xml";
419         final InputStream inEntry = getClass().getResourceAsStream(ex);
420         try {
421             new TDMParser().parse(inEntry, ex);
422             Assert.fail("An exception \"CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED\"should have been thrown");
423         } catch (OrekitException oe) {
424             String specifier = "use of time system WRONG-TIME-SYSTEM in CCSDS files requires an additional ICD and is not implemented in Orekit";
425             Assert.assertEquals(specifier,oe.getMessage());
426         }
427     }
428 
429     @Test
430     public void testInconsistentDataLineKeyValue() {
431         // Inconsistent data line in KeyValue file (3 fields after keyword instead of 2)
432         final String ex = "/ccsds/TDM-data-inconsistent-line.txt";
433         final InputStream inEntry = getClass().getResourceAsStream(ex);
434         try {
435             new TDMParser().parse(inEntry, ex);
436             Assert.fail("An exception \"CCSDS_TDM_INCONSISTENT_DATA_LINE\"should have been thrown");
437         } catch (OrekitException oe) {
438             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_DATA_LINE, oe.getSpecifier());
439             Assert.assertEquals(25, oe.getParts()[0]);
440             Assert.assertEquals("/ccsds/TDM-data-inconsistent-line.txt", oe.getParts()[1]);
441             Assert.assertEquals("RECEIVE_FREQ_1 = 2005-159T17:41:02 -333.0551 this-should-not-be-here", oe.getParts()[2]);
442         }
443     }
444 
445     @Test
446     public void testInconsistentDataBlockXml() {
447         // Inconsistent data block in XML file
448         final String ex = "/ccsds/XML/TDM-data-inconsistent-block.xml";
449         final InputStream inEntry = getClass().getResourceAsStream(ex);
450         try {
451             new TDMParser().parse(inEntry, ex);
452             Assert.fail("An exception \"CCSDS_TDM_XML_INCONSISTENT_DATA_BLOCK\"should have been thrown");
453         } catch (OrekitException oe) {
454             String specifier = String.format("%s\n%s\n\t%s\n\t\t%s\n\t\t%s\n\t%s",
455                                              "Inconsistent XML observation block at line 33 of TDM file /ccsds/XML/TDM-data-inconsistent-block.xml.",
456                                              "A TDM observation block should be as follows",
457                                              "<observation>","<EPOCH>epoch</EPOCH>","<KEYWORD>value</KEYWORD>","</observation>");
458             Assert.assertEquals(specifier,oe.getMessage());
459         }
460     }
461 
462     @Test
463     public void testUnknownFileFormat() {
464         // Unknown file format
465         final String ex = "/ccsds/TDM-unknown-file-format.unknown";
466         final InputStream inEntry = getClass().getResourceAsStream(ex);
467         try {
468             new TDMParser().parse(inEntry, ex);
469             Assert.fail("An exception \"CCSDS_TDM_UNKNOWN_FORMAT\"should have been thrown");
470         } catch (OrekitException oe) {
471             Assert.assertEquals(OrekitMessages.CCSDS_TDM_UNKNOWN_FORMAT, oe.getSpecifier());
472             Assert.assertEquals("/ccsds/TDM-unknown-file-format.unknown", oe.getParts()[0]);
473         }
474     }
475 
476     /**
477      * Validation function for example 2.
478      * @param file Parsed TDMFile to validate
479      * @throws OrekitException if UTC time scale cannot be retrieved
480      */
481     public static void validateTDMExample2(TDMFile file) throws OrekitException {
482         final TimeScale utc = TimeScalesFactory.getUTC();
483 
484         // Header
485         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
486         Assert.assertEquals(new AbsoluteDate("2005-160T20:15:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
487         Assert.assertEquals("NASA/JPL",file.getOriginator());
488         final List<String> headerComment = new ArrayList<String>();
489         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
490         headerComment.add("StarTrek 1-way data, Ka band down");
491         Assert.assertEquals(headerComment, file.getHeaderComment());
492 
493         // Meta-Data
494         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
495 
496         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
497         Assert.assertEquals(new AbsoluteDate("2005-159T17:41:00", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
498         Assert.assertEquals(new AbsoluteDate("2005-159T17:41:40", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
499         Assert.assertEquals("DSS-25", metaData.getParticipants().get(1));
500         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
501         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
502         Assert.assertEquals("2,1", metaData.getPath());
503         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
504         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
505         Assert.assertEquals(32021035200.0, metaData.getFreqOffset(), 0.0);
506         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(1), 0.0);
507         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(1), 0.0);
508         Assert.assertEquals("RAW", metaData.getDataQuality());
509         final List<String> metaDataComment = new ArrayList<String>();
510         metaDataComment.add("This is a meta-data comment");
511         Assert.assertEquals(metaDataComment, metaData.getComment());
512 
513         // Data
514         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
515 
516         // Reference data
517         final String[] keywords = {"TRANSMIT_FREQ_2", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1",
518             "RECEIVE_FREQ_1", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1"};
519 
520         final String[] epochs   = {"2005-159T17:41:00", "2005-159T17:41:00", "2005-159T17:41:01", "2005-159T17:41:02",
521             "2005-159T17:41:03", "2005-159T17:41:04", "2005-159T17:41:05"};
522 
523         final double[] values   = {32023442781.733, -409.2735, -371.1568, -333.0551,
524             -294.9673, -256.9054, -218.7951};
525         // Check consistency
526         for (int i = 0; i < keywords.length; i++) {
527             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
528             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
529             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
530         }
531 
532         // Comment
533         final List<String> dataComment = new ArrayList<String>();
534         dataComment.add("This is a data comment");
535         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
536     }
537 
538     /**
539      * Validation function for example 4.
540      * @param file Parsed TDMFile to validate
541      * @throws OrekitException if UTC time scale cannot be retrieved
542      */
543     public static void validateTDMExample4(TDMFile file) throws OrekitException {
544 
545         final TimeScale utc = TimeScalesFactory.getUTC();
546 
547         // Header
548         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
549         Assert.assertEquals(new AbsoluteDate("2005-191T23:00:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
550         Assert.assertEquals("NASA/JPL",file.getOriginator());
551         final List<String> headerComment = new ArrayList<String>();
552         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
553         Assert.assertEquals(headerComment, file.getHeaderComment());
554 
555         // Meta-Data
556         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
557 
558         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
559         Assert.assertEquals("DSS-24", metaData.getParticipants().get(1));
560         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
561         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
562         Assert.assertEquals("1,2,1", metaData.getPath());
563         Assert.assertEquals("START", metaData.getIntegrationRef());
564         Assert.assertEquals("COHERENT", metaData.getRangeMode());
565         Assert.assertEquals(2.0e+26, metaData.getRangeModulus(), 0.0);
566         Assert.assertEquals("RU", metaData.getRangeUnits());
567         Assert.assertEquals(7.7e-5, metaData.getTransmitDelays().get(1), 0.0);
568         Assert.assertEquals(0.0, metaData.getTransmitDelays().get(2), 0.0);
569         Assert.assertEquals(7.7e-5, metaData.getReceiveDelays().get(1), 0.0);
570         Assert.assertEquals(0.0, metaData.getReceiveDelays().get(2), 0.0);
571         Assert.assertEquals(46.7741, metaData.getCorrectionRange(), 0.0);
572         Assert.assertEquals("YES", metaData.getCorrectionsApplied());
573         final List<String> metaDataComment = new ArrayList<String>();
574         metaDataComment.add("Range correction applied is range calibration to DSS-24.");
575         metaDataComment.add("Estimated RTLT at begin of pass = 950 seconds");
576         metaDataComment.add("Antenna Z-height correction 0.0545 km applied to uplink signal");
577         metaDataComment.add("Antenna Z-height correction 0.0189 km applied to downlink signal");
578         Assert.assertEquals(metaDataComment, metaData.getComment());
579 
580         // Data
581         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
582 
583         // Reference data
584         final String[] keywords = {"TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
585             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
586             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
587             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0"};
588 
589         final String[] epochs   = {"2005-191T00:31:51", "2005-191T00:31:51", "2005-191T00:31:51", "2005-191T00:31:51",
590             "2005-191T00:34:48", "2005-191T00:34:48", "2005-191T00:34:48", "2005-191T00:34:48",
591             "2005-191T00:37:45", "2005-191T00:37:45", "2005-191T00:37:45", "2005-191T00:37:45",
592             "2005-191T00:40:42", "2005-191T00:40:42", "2005-191T00:40:42", "2005-191T00:40:42",
593             "2005-191T00:58:24", "2005-191T00:58:24", "2005-191T00:58:24", "2005-191T00:58:24"};
594 
595         final double[] values   = {7180064367.3536 , 0.59299, 39242998.5151986, 28.52538,
596             7180064472.3146 , 0.59305, 61172265.3115234, 28.39347,
597             7180064577.2756 , 0.59299, 15998108.8168328, 28.16193,
598             7180064682.2366 , 0.59299, 37938284.4138008, 29.44597,
599             7180065327.56141, 0.62085, 35478729.4012973, 30.48199};
600         // Check consistency
601         for (int i = 0; i < keywords.length; i++) {
602             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
603             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
604             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
605         }
606         // Comment
607         final List<String> dataComment = new ArrayList<String>();
608         dataComment.add("This is a data comment");
609         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
610     }
611 
612     /**
613      * Validation function for example 6.
614      * @param file Parsed TDMFile to validate
615      * @throws OrekitException if UTC time scale cannot be retrieved
616      */
617     public static void validateTDMExample6(TDMFile file) throws OrekitException {
618 
619         final TimeScale utc = TimeScalesFactory.getUTC();
620 
621         // Header
622         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
623         Assert.assertEquals(new AbsoluteDate("1998-06-10T01:00:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
624         Assert.assertEquals("JAXA",file.getOriginator());
625         final List<String> headerComment = new ArrayList<String>();
626         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (JAXA)");
627         Assert.assertEquals(headerComment, file.getHeaderComment());
628 
629         // Meta-Data
630         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
631 
632         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
633         Assert.assertEquals(new AbsoluteDate("1998-06-10T00:57:37", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
634         Assert.assertEquals(new AbsoluteDate("1998-06-10T00:57:44", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
635         Assert.assertEquals("NORTH", metaData.getParticipants().get(1));
636         Assert.assertEquals("F07R07", metaData.getParticipants().get(2));
637         Assert.assertEquals("E7", metaData.getParticipants().get(3));
638         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
639         Assert.assertEquals("1,2,3,2,1", metaData.getPath());
640         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
641         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
642         Assert.assertEquals("CONSTANT", metaData.getRangeMode());
643         Assert.assertEquals(0.0, metaData.getRangeModulus(), 0.0);
644         Assert.assertEquals("KM", metaData.getRangeUnits());
645         Assert.assertEquals("AZEL", metaData.getAngleType());
646 
647         // Data
648         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
649 
650         // Reference data
651         final String[] keywords = {"RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
652             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
653             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
654             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",};
655 
656         final String[] epochs   = {"1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37",
657             "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38",
658             "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39",
659             "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44",};
660 
661         final double[] values   = { 80452.7542, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
662             80452.7368, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
663             80452.7197, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
664             80452.6331, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0};
665         // Check consistency
666         for (int i = 0; i < keywords.length; i++) {
667             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
668             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
669             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
670         }
671         // Comment
672         final List<String> dataComment = new ArrayList<String>();
673         dataComment.add("This is a data comment");
674         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
675     }
676 
677     /**
678      * Validation function for example 8.
679      * @param file Parsed TDMFile to validate
680      * @throws OrekitException if UTC time scale cannot be retrieved
681      */
682     public static void validateTDMExample8(TDMFile file) throws OrekitException {
683 
684         final TimeScale utc = TimeScalesFactory.getUTC();
685 
686         // Header
687         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
688         Assert.assertEquals(new AbsoluteDate("2007-08-30T12:01:44.749", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
689         Assert.assertEquals("GSOC",file.getOriginator());
690         final List<String> headerComment = new ArrayList<String>();
691         headerComment.add("GEOSCX_INP");
692         Assert.assertEquals(headerComment, file.getHeaderComment());
693 
694         // Meta-Data 1
695         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
696 
697         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
698         Assert.assertEquals(new AbsoluteDate("2007-08-29T07:00:02.000", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
699         Assert.assertEquals(new AbsoluteDate("2007-08-29T14:00:02.000", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
700         Assert.assertEquals("HBSTK", metaData.getParticipants().get(1));
701         Assert.assertEquals("SAT", metaData.getParticipants().get(2));
702         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
703         Assert.assertEquals("1,2,1", metaData.getPath());
704         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
705         Assert.assertEquals("END", metaData.getIntegrationRef());
706         Assert.assertEquals("XSYE", metaData.getAngleType());
707         Assert.assertEquals("RAW", metaData.getDataQuality());
708         final List<String> metaDataComment = new ArrayList<String>();
709         metaDataComment.add("This is a meta-data comment");
710         Assert.assertEquals(metaDataComment, metaData.getComment());
711 
712         // Data 1
713         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
714 
715         // Reference data 1
716         final String[] keywords = {"DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
717             "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
718             "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2"};
719 
720         final String[] epochs   = {"2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000",
721             "2007-08-29T08:00:02.000", "2007-08-29T08:00:02.000", "2007-08-29T08:00:02.000",
722             "2007-08-29T14:00:02.000", "2007-08-29T14:00:02.000", "2007-08-29T14:00:02.000"};
723 
724         final double[] values   = {-1.498776048, 67.01312389, 18.28395556,
725             -2.201305217, 67.01982278, 21.19609167,
726             0.929545817, -89.35626083, 2.78791667};
727         // Check consistency
728         for (int i = 0; i < keywords.length; i++) {
729             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
730             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
731             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
732         }
733         // Comment
734         final List<String> dataComment = new ArrayList<String>();
735         dataComment.add("This is a data comment");
736         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
737 
738         // Meta-Data 2
739         final TDMFile.TDMMetaData metaData2 = file.getObservationsBlocks().get(1).getMetaData();
740 
741         Assert.assertEquals(CcsdsTimeScale.UTC, metaData2.getTimeSystem());
742         Assert.assertEquals("2007-08-29T06:00:02.000", metaData2.getStartTimeString());
743         Assert.assertEquals(new AbsoluteDate("2007-08-29T06:00:02.000", utc).durationFrom(metaData2.getStartTime()), 0.0, 0.0);
744         Assert.assertEquals("2007-08-29T13:00:02.000", metaData2.getStopTimeString());
745         Assert.assertEquals(new AbsoluteDate("2007-08-29T13:00:02.000", utc).durationFrom(metaData2.getStopTime()), 0.0, 0.0);
746         Assert.assertEquals("WHM1", metaData2.getParticipants().get(1));
747         Assert.assertEquals("SAT", metaData2.getParticipants().get(2));
748         Assert.assertEquals("SEQUENTIAL", metaData2.getMode());
749         Assert.assertEquals("1,2,1", metaData2.getPath());
750         Assert.assertEquals(1.0, metaData2.getIntegrationInterval(), 0.0);
751         Assert.assertEquals("END", metaData2.getIntegrationRef());
752         Assert.assertEquals("AZEL", metaData2.getAngleType());
753         Assert.assertEquals("RAW", metaData2.getDataQuality());
754         final List<String> metaDataComment2 = new ArrayList<String>();
755         metaDataComment2.add("This is a meta-data comment");
756         Assert.assertEquals(metaDataComment2, metaData2.getComment());
757 
758         // Data 2
759         final List<TDMFile.Observation> observations2 = file.getObservationsBlocks().get(1).getObservations();
760 
761         // Reference data 2
762         final String[] keywords2 = {"RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
763             "RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
764             "RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2"};
765 
766         final String[] epochs2   = {"2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000",
767             "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000",
768             "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000"};
769 
770         final double[] values2   = {4.00165248953670E+04, -0.885640091,  99.53204250, 1.26724167,
771             3.57238793591890E+04, -1.510223139, 103.33061750, 4.77875278,
772             3.48156855860090E+04,  1.504082291, 243.73365222, 8.78254167};
773         // Check consistency
774         for (int i = 0; i < keywords2.length; i++) {
775             Assert.assertEquals(keywords2[i], observations2.get(i).getKeyword());
776             Assert.assertEquals(new AbsoluteDate(epochs2[i], utc).durationFrom(observations2.get(i).getEpoch()), 0.0, 0.0);
777             Assert.assertEquals(values2[i], observations2.get(i).getMeasurement(), 0.0);
778         }
779         // Comment
780         final List<String> dataComment2 = new ArrayList<String>();
781         dataComment2.add("This is a data comment");
782         Assert.assertEquals(dataComment2, file.getObservationsBlocks().get(1).getObservationsComment());
783     }
784 
785     /**
786      * Validation function for example 15.
787      * @param file Parsed TDMFile to validate
788      * @throws OrekitException if UTC time scale cannot be retrieved
789      */
790     public static void validateTDMExample15(TDMFile file) throws OrekitException {
791 
792         final TimeScale utc = TimeScalesFactory.getUTC();
793 
794         // Header
795         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
796         Assert.assertEquals(new AbsoluteDate("2005-161T15:45:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
797         Assert.assertEquals("NASA/JPL",file.getOriginator());
798         final List<String> headerComment = new ArrayList<String>();
799         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
800         headerComment.add("The following are clock offsets, in seconds between the");
801         headerComment.add("clocks at each DSN complex relative to UTC(NIST). The offset");
802         headerComment.add("is a mean of readings using several GPS space vehicles in");
803         headerComment.add("common view. Value is \"station clock minus UTC”.");
804         Assert.assertEquals(headerComment, file.getHeaderComment());
805 
806         // Meta-Data 1
807         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
808 
809         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
810         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
811         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
812         Assert.assertEquals("DSS-10", metaData.getParticipants().get(1));
813         Assert.assertEquals("UTC-NIST", metaData.getParticipants().get(2));
814         final List<String> metaDataComment = new ArrayList<String>();
815         metaDataComment.add("Note: SPC10 switched back to Maser1 from Maser2 on 2005-142");
816         Assert.assertEquals(metaDataComment, metaData.getComment());
817 
818         // Data 1
819         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
820 
821         // Reference data 1
822         final String[] keywords = {"CLOCK_BIAS", "CLOCK_DRIFT",
823             "CLOCK_BIAS", "CLOCK_DRIFT",
824             "CLOCK_BIAS", "CLOCK_DRIFT",
825         "CLOCK_BIAS"};
826 
827         final String[] epochs   = {"2005-142T12:00:00", "2005-142T12:00:00",
828             "2005-143T12:00:00", "2005-143T12:00:00",
829             "2005-144T12:00:00", "2005-144T12:00:00",
830         "2005-145T12:00:00"};
831 
832         final double[] values   = {9.56e-7,  6.944e-14,
833             9.62e-7, -2.083e-13,
834             9.44e-7, -2.778e-13,
835             9.20e-7};
836         // Check consistency
837         for (int i = 0; i < keywords.length; i++) {
838             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
839             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
840             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
841         }
842         // Comment
843         final List<String> dataComment = new ArrayList<String>();
844         dataComment.add("This is a data comment");
845         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
846 
847 
848         // Meta-Data 2
849         final TDMFile.TDMMetaData metaData2 = file.getObservationsBlocks().get(1).getMetaData();
850 
851         Assert.assertEquals(CcsdsTimeScale.UTC, metaData2.getTimeSystem());
852         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData2.getStartTime()), 0.0, 0.0);
853         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData2.getStopTime()), 0.0, 0.0);
854         Assert.assertEquals("DSS-40", metaData2.getParticipants().get(1));
855         Assert.assertEquals("UTC-NIST", metaData2.getParticipants().get(2));
856         final List<String> metaDataComment2 = new ArrayList<String>();
857         metaDataComment2.add("This is a meta-data comment");
858         Assert.assertEquals(metaDataComment2, metaData2.getComment());
859 
860         // Data 2
861         final List<TDMFile.Observation> observations2 = file.getObservationsBlocks().get(1).getObservations();
862 
863         // Reference data 2
864         // Same keywords and dates than 1
865         final double[] values2   = {-7.40e-7, -3.125e-13,
866             -7.67e-7, -1.620e-13,
867             -7.81e-7, -4.745e-13,
868             -8.22e-7};
869         // Check consistency
870         for (int i = 0; i < keywords.length; i++) {
871             Assert.assertEquals(keywords[i], observations2.get(i).getKeyword());
872             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations2.get(i).getEpoch()), 0.0, 0.0);
873             Assert.assertEquals(values2[i], observations2.get(i).getMeasurement(), 0.0);
874         }
875         // Comment
876         final List<String> dataComment2 = new ArrayList<String>();
877         dataComment2.add("This is a data comment");
878         Assert.assertEquals(dataComment2, file.getObservationsBlocks().get(1).getObservationsComment());
879 
880 
881         // Meta-Data 3
882         final TDMFile.TDMMetaData metaData3 = file.getObservationsBlocks().get(2).getMetaData();
883 
884         Assert.assertEquals(CcsdsTimeScale.UTC, metaData3.getTimeSystem());
885         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData3.getStartTime()), 0.0, 0.0);
886         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData3.getStopTime()), 0.0, 0.0);
887         Assert.assertEquals("DSS-60", metaData3.getParticipants().get(1));
888         Assert.assertEquals("UTC-NIST", metaData3.getParticipants().get(2));
889         final List<String> metaDataComment3 = new ArrayList<String>();
890         metaDataComment3.add("This is a meta-data comment");
891         Assert.assertEquals(metaDataComment3, metaData3.getComment());
892 
893         // Data 3
894         final List<TDMFile.Observation> observations3 = file.getObservationsBlocks().get(2).getObservations();
895 
896         // Reference data 2
897         // Same keywords and dates than 1
898         final double[] values3   = {-1.782e-6, 1.736e-13,
899             -1.767e-6, 1.157e-14,
900             -1.766e-6, 8.102e-14,
901             -1.759e-6};
902         // Check consistency
903         for (int i = 0; i < keywords.length; i++) {
904             Assert.assertEquals(keywords[i], observations3.get(i).getKeyword());
905             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations3.get(i).getEpoch()), 0.0, 0.0);
906             Assert.assertEquals(values3[i], observations3.get(i).getMeasurement(), 0.0);
907         }
908         // Comment
909         final List<String> dataComment3 = new ArrayList<String>();
910         dataComment3.add("This is a data comment");
911         Assert.assertEquals(dataComment3, file.getObservationsBlocks().get(2).getObservationsComment());
912     }
913 
914     /**
915      * Validation function for example displaying all keywords.
916      * @param file Parsed TDMFile to validate
917      * @throws OrekitException if UTC time scale cannot be retrieved
918      */
919     public static void validateTDMExampleAllKeywords(TDMFile file) throws OrekitException {
920 
921         final TimeScale utc = TimeScalesFactory.getUTC();
922 
923         // Header
924         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
925         Assert.assertEquals(new AbsoluteDate("2017-06-14T10:53:00.000", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
926         Assert.assertEquals("CSSI",file.getOriginator());
927         final List<String> headerComment = new ArrayList<String>();
928         headerComment.add("TDM example created by CSSI");
929         headerComment.add("Testing all TDM known meta-data and data keywords");
930         Assert.assertEquals(headerComment, file.getHeaderComment());
931 
932         // Meta-Data
933         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
934 
935         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
936         Assert.assertEquals(new AbsoluteDate("2017-06-14T10:53:00.000", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
937         Assert.assertEquals("2017-06-14T10:53:00.000", metaData.getStartTimeString());
938         Assert.assertEquals(new AbsoluteDate("2017-06-15T10:53:00.000", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
939         Assert.assertEquals("2017-06-15T10:53:00.000", metaData.getStopTimeString());
940         Assert.assertEquals("DSS-25", metaData.getParticipants().get(1));
941         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
942         Assert.assertEquals("P3", metaData.getParticipants().get(3));
943         Assert.assertEquals("P4", metaData.getParticipants().get(4));
944         Assert.assertEquals("P5", metaData.getParticipants().get(5));
945         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
946         Assert.assertEquals("2,1", metaData.getPath());
947         Assert.assertEquals("4,5", metaData.getPath1());
948         Assert.assertEquals("3,2", metaData.getPath2());
949         Assert.assertEquals("S", metaData.getTransmitBand());
950         Assert.assertEquals("L", metaData.getReceiveBand());
951         Assert.assertEquals(240, metaData.getTurnaroundNumerator(), 0);
952         Assert.assertEquals(221, metaData.getTurnaroundDenominator(), 0);
953         Assert.assertEquals("TRANSMIT", metaData.getTimetagRef());
954         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
955         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
956         Assert.assertEquals(32021035200.0, metaData.getFreqOffset(), 0.0);
957         Assert.assertEquals("COHERENT", metaData.getRangeMode());
958         Assert.assertEquals(32768.0, metaData.getRangeModulus(), 0.0);
959         Assert.assertEquals("RU", metaData.getRangeUnits());
960         Assert.assertEquals("RADEC", metaData.getAngleType());
961         Assert.assertEquals("EME2000", metaData.getReferenceFrameString());
962         Assert.assertEquals(true,FramesFactory.getEME2000().equals(metaData.getReferenceFrame()));
963         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(1), 0.0);
964         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(2), 0.0);
965         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(3), 0.0);
966         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(4), 0.0);
967         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(5), 0.0);
968         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(1), 0.0);
969         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(2), 0.0);
970         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(3), 0.0);
971         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(4), 0.0);
972         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(5), 0.0);
973         Assert.assertEquals("RAW", metaData.getDataQuality());
974         Assert.assertEquals(1.0, metaData.getCorrectionAngle1(), 0.0);
975         Assert.assertEquals(2.0, metaData.getCorrectionAngle2(), 0.0);
976         Assert.assertEquals(3.0, metaData.getCorrectionDoppler(), 0.0);
977         Assert.assertEquals(4.0, metaData.getCorrectionRange(), 0.0);
978         Assert.assertEquals(5.0, metaData.getCorrectionReceive(), 0.0);
979         Assert.assertEquals(6.0, metaData.getCorrectionTransmit(), 0.0);
980         Assert.assertEquals("YES", metaData.getCorrectionsApplied());
981 
982         final List<String> metaDataComment = new ArrayList<String>();
983         metaDataComment.add("All known meta-data keywords displayed");
984         Assert.assertEquals(metaDataComment, metaData.getComment());
985 
986         // Data
987         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
988 
989         // Reference data
990         final String[] keywords = {"CARRIER_POWER", "DOPPLER_INSTANTANEOUS", "DOPPLER_INTEGRATED", "PC_N0", "PR_N0", "RANGE",
991                                    "RECEIVE_FREQ_1", "RECEIVE_FREQ_2", "RECEIVE_FREQ_3", "RECEIVE_FREQ_4", "RECEIVE_FREQ_5", "RECEIVE_FREQ",
992                                    "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_2", "TRANSMIT_FREQ_3", "TRANSMIT_FREQ_4","TRANSMIT_FREQ_5",
993                                    "TRANSMIT_FREQ_RATE_1", "TRANSMIT_FREQ_RATE_2", "TRANSMIT_FREQ_RATE_3", "TRANSMIT_FREQ_RATE_4", "TRANSMIT_FREQ_RATE_5",
994                                    "DOR", "VLBI_DELAY",
995                                    "ANGLE_1", "ANGLE_2",
996                                    "CLOCK_BIAS", "CLOCK_DRIFT",
997                                    "STEC", "TROPO_DRY", "TROPO_WET",
998                                    "PRESSURE", "RHUMIDITY", "TEMPERATURE"};
999 
1000         final AbsoluteDate epoch = new AbsoluteDate("2017-06-14T10:53:00.000", utc);
1001         // Check consistency
1002         for (int i = 0; i < keywords.length; i++) {
1003             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
1004             Assert.assertEquals(epoch.shiftedBy((double) (i+1)).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
1005             Assert.assertEquals((double) (i+1), observations.get(i).getMeasurement(), 0.0);
1006         }
1007 
1008         // Comment
1009         final List<String> dataComment = new ArrayList<String>();
1010         dataComment.add("Signal related Keywords");
1011         dataComment.add("VLBI/Delta-DOR Related Keywords");
1012         dataComment.add("Angle Related Keywords");
1013         dataComment.add("Time Related Keywords");
1014         dataComment.add("Media Related Keywords");
1015         dataComment.add("Meteorological Related Keywords");
1016         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
1017     }
1018 }