1   /* Copyright 2002-2026 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  
18  package org.orekit.files.ccsds.ndm.odm.ocm;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Optional;
23  
24  import org.orekit.annotation.Nullable;
25  import org.orekit.data.DataContext;
26  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
27  import org.orekit.files.ccsds.definitions.TimeSystem;
28  import org.orekit.files.ccsds.ndm.odm.OdmMetadata;
29  import org.orekit.files.ccsds.section.MetadataKey;
30  import org.orekit.frames.Frame;
31  import org.orekit.time.AbsoluteDate;
32  
33  /** Meta-data for {@link OcmMetadata Orbit Comprehensive Message}.
34   * @since 11.0
35   */
36  public class OcmMetadata extends OdmMetadata {
37  
38      /** Default value for SCLK_OFFSET_AT_EPOCH.
39       * @since 12.0
40       */
41      public static final double DEFAULT_SCLK_OFFSET_AT_EPOCH = 0.0;
42  
43      /** Default value for SCLK_SEC_PER_SI_SEC.
44       * @since 12.0
45       */
46      public static final double DEFAULT_SCLK_SEC_PER_SI_SEC = 1.0;
47  
48      /** International designator for the object as assigned by the UN Committee
49       * on Space Research (COSPAR) and the US National Space Science Data Center (NSSDC). */
50      @Nullable
51      private String internationalDesignator;
52  
53      /** Specification of satellite catalog source. */
54      @Nullable
55      private String catalogName;
56  
57      /** Unique satellite identification designator for the object. */
58      @Nullable
59      private String objectDesignator;
60  
61      /** Alternate names for this space object. */
62      private List<String> alternateNames;
63  
64      /** Programmatic Point Of Contact at originator. */
65      @Nullable
66      private String originatorPOC;
67  
68      /** Position of Programmatic Point Of Contact at originator. */
69      @Nullable
70      private String originatorPosition;
71  
72      /** Phone number of Programmatic Point Of Contact at originator. */
73      @Nullable
74      private String originatorPhone;
75  
76      /** Email address of Programmatic Point Of Contact at originator.
77       * @since 11.2
78       */
79      @Nullable
80      private String originatorEmail;
81  
82      /** Address of Programmatic Point Of Contact at originator. */
83      @Nullable
84      private String originatorAddress;
85  
86      /** Creating agency or operator. */
87      @Nullable
88      private String techOrg;
89  
90      /** Technical Point Of Contact at originator. */
91      @Nullable
92      private String techPOC;
93  
94      /** Position of Technical Point Of Contact at originator. */
95      @Nullable
96      private String techPosition;
97  
98      /** Phone number of Technical Point Of Contact at originator. */
99      @Nullable
100     private String techPhone;
101 
102     /** Email address of Technical Point Of Contact at originator.
103      * @since 11.2
104      */
105     @Nullable
106     private String techEmail;
107 
108     /** Address of Technical Point Of Contact at originator. */
109     @Nullable
110     private String techAddress;
111 
112     /** Unique ID identifying previous message from a given originator. */
113     @Nullable
114     private String previousMessageID;
115 
116     /** Unique ID identifying next message from a given originator. */
117     @Nullable
118     private String nextMessageID;
119 
120     /** Unique identifier of Attitude Data Message linked to this Orbit Data Message. */
121     @Nullable
122     private String admMessageLink;
123 
124     /** Unique identifier of Conjunction Data Message linked to this Orbit Data Message. */
125     @Nullable
126     private String cdmMessageLink;
127 
128     /** Unique identifier of Pointing Request Message linked to this Orbit Data Message. */
129     @Nullable
130     private String prmMessageLink;
131 
132     /** Unique identifier of Reentry Data Messages linked to this Orbit Data Message. */
133     @Nullable
134     private String rdmMessageLink;
135 
136     /** Unique identifier of Tracking Data Messages linked to this Orbit Data Message. */
137     @Nullable
138     private String tdmMessageLink;
139 
140     /** Operator of the space object. */
141     @Nullable
142     private String operator;
143 
144     /** Owner of the space object. */
145     @Nullable
146     private String owner;
147 
148     /** Name of the country where the space object owner is based. */
149     @Nullable
150     private String country;
151 
152     /** Name of the constellation this space object belongs to. */
153     @Nullable
154     private String constellation;
155 
156     /** Type of object. */
157     @Nullable
158     private ObjectType objectType;
159 
160     /** Epoch to which <em>all</em> relative times are referenced in data blocks;
161      * unless overridden by block-specific {@code EPOCH_TZERO} values. */
162     private AbsoluteDate epochT0;
163 
164     /** Operational status. */
165     @Nullable
166     private OpsStatus opsStatus;
167 
168     /** Orbit category. */
169     @Nullable
170     private OrbitCategory orbitCategory;
171 
172     /** List of elements of information data blocks included in this message. */
173     private List<OcmElements> ocmDataElements;
174 
175     /** Spacecraft clock count at {@link #getEpochT0()}.
176      * Never null because of default value.
177      */
178     private double sclkOffsetAtEpoch;
179 
180     /** Number of spacecraft clock seconds occurring during one SI second.
181      * Never null because of default value.
182      */
183     private double sclkSecPerSISec;
184 
185     /** Creation date of previous message from a given originator. */
186     @Nullable
187     private AbsoluteDate previousMessageEpoch;
188 
189     /** Creation date of next message from a given originator. */
190     @Nullable
191     private AbsoluteDate nextMessageEpoch;
192 
193     /** Time of the earliest data contained in the OCM. */
194     @Nullable
195     private AbsoluteDate startTime;
196 
197     /** Time of the latest data contained in the OCM. */
198     @Nullable
199     private AbsoluteDate stopTime;
200 
201     /** Span of time that the OCM covers. */
202     @Nullable
203     private Double timeSpan;
204 
205     /** Difference (TAI - UTC) in seconds at epoch {@link #epochT0}. */
206     @Nullable
207     private Double taimutcT0;
208 
209     /** Epoch of next leap second.
210      * @since 11.2
211      */
212     @Nullable
213     private AbsoluteDate nextLeapEpoch;
214 
215     /** Difference (TAI - UTC) in seconds incorporated at {@link #nextLeapEpoch}.
216      * @since 11.2
217      */
218     @Nullable
219     private Double nextLeapTaimutc;
220 
221     /** Difference (UT1 - UTC) in seconds at epoch {@link #epochT0}. */
222     @Nullable
223     private Double ut1mutcT0;
224 
225     /** Source and version of Earth Orientation Parameters. */
226     @Nullable
227     private String eopSource;
228 
229     /** Interpolation method for Earth Orientation Parameters. */
230     @Nullable
231     private String interpMethodEOP;
232 
233     /** Source and version of celestial body (e.g. Sun/Earth/Planetary). */
234     @Nullable
235     private String celestialSource;
236 
237     /** Data context.
238      * @since 12.0
239      */
240     private final DataContext dataContext;
241 
242     /**
243      * Create a new meta-data.
244      *
245      * @param dataContext data context
246      * @param frameMapper for creating an Orekit {@link Frame}.
247      * @since 13.1.5
248      */
249     public OcmMetadata(final DataContext dataContext,
250                        final CcsdsFrameMapper frameMapper) {
251 
252         // set up the few fields that have default values as per CCSDS standard
253         super(TimeSystem.UTC, frameMapper);
254         this.sclkOffsetAtEpoch = DEFAULT_SCLK_OFFSET_AT_EPOCH; // Default value if absent
255         this.sclkSecPerSISec   = DEFAULT_SCLK_SEC_PER_SI_SEC; // Default value if absent
256         this.dataContext       = dataContext;
257         this.ocmDataElements   = new ArrayList<>();
258         this.alternateNames    = new ArrayList<>();
259     }
260 
261     /** {@inheritDoc} */
262     @Override
263     public void validate(final double version) {
264         // we don't call super.checkMandatoryEntries() because
265         // all of the parameters considered mandatory at ODM level
266         // for OPM, OMM and OEM are in fact optional in OCM
267         // only TIME_SYSTEM and EPOCH_TZERO are mandatory
268         checkNotNull(getTimeSystem(), MetadataKey.TIME_SYSTEM.name());
269         checkNotNull(epochT0,         OcmMetadataKey.EPOCH_TZERO.name());
270         if (nextLeapEpoch != null) {
271             checkNotNaN(nextLeapTaimutc != null ? nextLeapTaimutc : Double.NaN, OcmMetadataKey.NEXT_LEAP_TAIMUTC.name());
272         }
273     }
274 
275     /** Get the international designator for the object.
276      * @return international designator for the object
277      */
278     public Optional<String> getInternationalDesignator() {
279         return Optional.ofNullable(internationalDesignator);
280     }
281 
282     /** Set the international designator for the object.
283      * @param internationalDesignator international designator for the object
284      */
285     public void setInternationalDesignator(final String internationalDesignator) {
286         refuseFurtherComments();
287         this.internationalDesignator = internationalDesignator;
288     }
289 
290     /** Get the specification of satellite catalog source.
291      * @return specification of satellite catalog source
292      */
293     public Optional<String> getCatalogName() {
294         return Optional.ofNullable(catalogName);
295     }
296 
297     /** Set the specification of satellite catalog source.
298      * @param catalogName specification of satellite catalog source
299      */
300     public void setCatalogName(final String catalogName) {
301         refuseFurtherComments();
302         this.catalogName = catalogName;
303     }
304 
305     /** Get the unique satellite identification designator for the object.
306      * @return unique satellite identification designator for the object.
307      */
308     public Optional<String> getObjectDesignator() {
309         return Optional.ofNullable(objectDesignator);
310     }
311 
312     /** Set the unique satellite identification designator for the object.
313      * @param objectDesignator unique satellite identification designator for the object
314      */
315     public void setObjectDesignator(final String objectDesignator) {
316         refuseFurtherComments();
317         this.objectDesignator = objectDesignator;
318     }
319 
320     /** Get the alternate names for this space object.
321      * @return alternate names
322      */
323     public List<String> getAlternateNames() {
324         return alternateNames;
325     }
326 
327     /** Set the alternate names for this space object.
328      * @param alternateNames alternate names
329      */
330     public void setAlternateNames(final List<String> alternateNames) {
331         refuseFurtherComments();
332         this.alternateNames = alternateNames;
333     }
334 
335     /** Get the programmatic Point Of Contact at originator.
336      * @return programmatic Point Of Contact at originator
337      */
338     public Optional<String> getOriginatorPOC() {
339         return Optional.ofNullable(originatorPOC);
340     }
341 
342     /** Set the programmatic Point Of Contact at originator.
343      * @param originatorPOC programmatic Point Of Contact at originator
344      */
345     public void setOriginatorPOC(final String originatorPOC) {
346         refuseFurtherComments();
347         this.originatorPOC = originatorPOC;
348     }
349 
350     /** Get the position of Programmatic Point Of Contact at originator.
351      * @return position of Programmatic Point Of Contact at originator
352      */
353     public Optional<String> getOriginatorPosition() {
354         return Optional.ofNullable(originatorPosition);
355     }
356 
357     /** Set the position of Programmatic Point Of Contact at originator.
358      * @param originatorPosition position of Programmatic Point Of Contact at originator
359      */
360     public void setOriginatorPosition(final String originatorPosition) {
361         refuseFurtherComments();
362         this.originatorPosition = originatorPosition;
363     }
364 
365     /** Get the phone number of Programmatic Point Of Contact at originator.
366      * @return phone number of Programmatic Point Of Contact at originator
367      */
368     public Optional<String> getOriginatorPhone() {
369         return Optional.ofNullable(originatorPhone);
370     }
371 
372     /** Set the phone number of Programmatic Point Of Contact at originator.
373      * @param originatorPhone phone number of Programmatic Point Of Contact at originator
374      */
375     public void setOriginatorPhone(final String originatorPhone) {
376         refuseFurtherComments();
377         this.originatorPhone = originatorPhone;
378     }
379 
380     /** Get the email address of Programmatic Point Of Contact at originator.
381      * @return email address of Programmatic Point Of Contact at originator
382      * @since 11.2
383      */
384     public Optional<String> getOriginatorEmail() {
385         return Optional.ofNullable(originatorEmail);
386     }
387 
388     /** Set the email address of Programmatic Point Of Contact at originator.
389      * @param originatorEmail email address of Programmatic Point Of Contact at originator
390      * @since 11.2
391      */
392     public void setOriginatorEmail(final String originatorEmail) {
393         refuseFurtherComments();
394         this.originatorEmail = originatorEmail;
395     }
396 
397     /** Get the address of Programmatic Point Of Contact at originator.
398      * @return address of Programmatic Point Of Contact at originator
399      */
400     public Optional<String> getOriginatorAddress() {
401         return Optional.ofNullable(originatorAddress);
402     }
403 
404     /** Set the address of Programmatic Point Of Contact at originator.
405      * @param originatorAddress address of Programmatic Point Of Contact at originator
406      */
407     public void setOriginatorAddress(final String originatorAddress) {
408         refuseFurtherComments();
409         this.originatorAddress = originatorAddress;
410     }
411 
412     /** Get the creating agency or operator.
413      * @return creating agency or operator
414      */
415     public Optional<String> getTechOrg() {
416         return Optional.ofNullable(techOrg);
417     }
418 
419     /** Set the creating agency or operator.
420      * @param techOrg creating agency or operator
421      */
422     public void setTechOrg(final String techOrg) {
423         refuseFurtherComments();
424         this.techOrg = techOrg;
425     }
426 
427     /** Get the Technical Point Of Contact at originator.
428      * @return Technical Point Of Contact at originator
429      */
430     public Optional<String> getTechPOC() {
431         return Optional.ofNullable(techPOC);
432     }
433 
434     /** Set the Technical Point Of Contact at originator.
435      * @param techPOC Technical Point Of Contact at originator
436      */
437     public void setTechPOC(final String techPOC) {
438         refuseFurtherComments();
439         this.techPOC = techPOC;
440     }
441 
442     /** Get the position of Technical Point Of Contact at originator.
443      * @return position of Technical Point Of Contact at originator
444      */
445     public Optional<String> getTechPosition() {
446         return Optional.ofNullable(techPosition);
447     }
448 
449     /** Set the position of Technical Point Of Contact at originator.
450      * @param techPosition position of Technical Point Of Contact at originator
451      */
452     public void setTechPosition(final String techPosition) {
453         refuseFurtherComments();
454         this.techPosition = techPosition;
455     }
456 
457     /** Get the phone number of Technical Point Of Contact at originator.
458      * @return phone number of Technical Point Of Contact at originator
459      */
460     public Optional<String> getTechPhone() {
461         return Optional.ofNullable(techPhone);
462     }
463 
464     /** Set the phone number of Technical Point Of Contact at originator.
465      * @param techPhone phone number of Technical Point Of Contact at originator
466      */
467     public void setTechPhone(final String techPhone) {
468         refuseFurtherComments();
469         this.techPhone = techPhone;
470     }
471 
472     /** Get the email address of Technical Point Of Contact at originator.
473      * @return email address of Technical Point Of Contact at originator
474      * @since 11.2
475      */
476     public Optional<String> getTechEmail() {
477         return Optional.ofNullable(techEmail);
478     }
479 
480     /** Set the email address of Technical Point Of Contact at originator.
481      * @param techEmail email address of Technical Point Of Contact at originator
482      * @since 11.2
483      */
484     public void setTechEmail(final String techEmail) {
485         refuseFurtherComments();
486         this.techEmail = techEmail;
487     }
488 
489     /** Get the address of Technical Point Of Contact at originator.
490      * @return address of Technical Point Of Contact at originator
491      */
492     public Optional<String> getTechAddress() {
493         return Optional.ofNullable(techAddress);
494     }
495 
496     /** Set the address of Technical Point Of Contact at originator.
497      * @param techAddress address of Technical Point Of Contact at originator
498      */
499     public void setTechAddress(final String techAddress) {
500         refuseFurtherComments();
501         this.techAddress = techAddress;
502     }
503 
504     /** Get the unique ID identifying previous message from a given originator.
505      * @return unique ID identifying previous message from a given originator
506      */
507     public Optional<String> getPreviousMessageID() {
508         return Optional.ofNullable(previousMessageID);
509     }
510 
511     /** Set the unique ID identifying previous message from a given originator.
512      * @param previousMessageID unique ID identifying previous message from a given originator
513      */
514     public void setPreviousMessageID(final String previousMessageID) {
515         refuseFurtherComments();
516         this.previousMessageID = previousMessageID;
517     }
518 
519     /** Get the unique ID identifying next message from a given originator.
520      * @return unique ID identifying next message from a given originator
521      */
522     public Optional<String> getNextMessageID() {
523         return Optional.ofNullable(nextMessageID);
524     }
525 
526     /** Set the unique ID identifying next message from a given originator.
527      * @param nextMessageID unique ID identifying next message from a given originator
528      */
529     public void setNextMessageID(final String nextMessageID) {
530         refuseFurtherComments();
531         this.nextMessageID = nextMessageID;
532     }
533 
534     /** Get the Unique identifier of Attitude Data Message linked to this Orbit Data Message.
535      * @return Unique identifier of Attitude Data Message linked to this Orbit Data Message
536      */
537     public Optional<String> getAdmMessageLink() {
538         return Optional.ofNullable(admMessageLink);
539     }
540 
541     /** Set the Unique identifier of Attitude Data Message linked to this Orbit Data Message.
542      * @param admMessageLink Unique identifier of Attitude Data Message linked to this Orbit Data Message
543      */
544     public void setAdmMessageLink(final String admMessageLink) {
545         refuseFurtherComments();
546         this.admMessageLink = admMessageLink;
547     }
548 
549     /** Get the Unique identifier of Conjunction Data Message linked to this Orbit Data Message.
550      * @return Unique identifier of Conjunction Data Message linked to this Orbit Data Message
551      */
552     public Optional<String> getCdmMessageLink() {
553         return Optional.ofNullable(cdmMessageLink);
554     }
555 
556     /** Set the Unique identifier of Conjunction Data Message linked to this Orbit Data Message.
557      * @param cdmMessageLink Unique identifier of Conjunction Data Message linked to this Orbit Data Message
558      */
559     public void setCdmMessageLink(final String cdmMessageLink) {
560         refuseFurtherComments();
561         this.cdmMessageLink = cdmMessageLink;
562     }
563 
564     /** Get the Unique identifier of Pointing Request Message linked to this Orbit Data Message.
565      * @return Unique identifier of Pointing Request Message linked to this Orbit Data Message
566      */
567     public Optional<String> getPrmMessageLink() {
568         return Optional.ofNullable(prmMessageLink);
569     }
570 
571     /** Set the Unique identifier of Pointing Request Message linked to this Orbit Data Message.
572      * @param prmMessageLink Unique identifier of Pointing Request Message linked to this Orbit Data Message
573      */
574     public void setPrmMessageLink(final String prmMessageLink) {
575         refuseFurtherComments();
576         this.prmMessageLink = prmMessageLink;
577     }
578 
579     /** Get the Unique identifier of Reentry Data Message linked to this Orbit Data Message.
580      * @return Unique identifier of Reentry Data Message linked to this Orbit Data Message
581      */
582     public Optional<String> getRdmMessageLink() {
583         return Optional.ofNullable(rdmMessageLink);
584     }
585 
586     /** Set the Unique identifier of Reentry Data Message linked to this Orbit Data Message.
587      * @param rdmMessageLink Unique identifier of Reentry Data Message linked to this Orbit Data Message
588      */
589     public void setRdmMessageLink(final String rdmMessageLink) {
590         refuseFurtherComments();
591         this.rdmMessageLink = rdmMessageLink;
592     }
593 
594     /** Get the Unique identifier of Tracking Data Message linked to this Orbit Data Message.
595      * @return Unique identifier of Tracking Data Message linked to this Orbit Data Message
596      */
597     public Optional<String> getTdmMessageLink() {
598         return Optional.ofNullable(tdmMessageLink);
599     }
600 
601     /** Set the Unique identifier of Tracking Data Message linked to this Orbit Data Message.
602      * @param tdmMessageLink Unique identifier of Tracking Data Message linked to this Orbit Data Message
603      */
604     public void setTdmMessageLink(final String tdmMessageLink) {
605         refuseFurtherComments();
606         this.tdmMessageLink = tdmMessageLink;
607     }
608 
609     /** Get the operator of the space object.
610      * @return operator of the space object
611      */
612     public Optional<String> getOperator() {
613         return Optional.ofNullable(operator);
614     }
615 
616     /** Set the operator of the space object.
617      * @param operator operator of the space object
618      */
619     public void setOperator(final String operator) {
620         refuseFurtherComments();
621         this.operator = operator;
622     }
623 
624     /** Get the owner of the space object.
625      * @return owner of the space object
626      */
627     public Optional<String> getOwner() {
628         return Optional.ofNullable(owner);
629     }
630 
631     /** Set the owner of the space object.
632      * @param owner owner of the space object
633      */
634     public void setOwner(final String owner) {
635         refuseFurtherComments();
636         this.owner = owner;
637     }
638 
639     /** Get the name of the country where the space object owner is based.
640      * @return name of the country where the space object owner is based
641      */
642     public Optional<String> getCountry() {
643         return Optional.ofNullable(country);
644     }
645 
646     /** Set the name of the country where the space object owner is based.
647      * @param country name of the country where the space object owner is based
648      */
649     public void setCountry(final String country) {
650         refuseFurtherComments();
651         this.country = country;
652     }
653 
654     /** Get the name of the constellation this space object belongs to.
655      * @return name of the constellation this space object belongs to
656      */
657     public Optional<String> getConstellation() {
658         return Optional.ofNullable(constellation);
659     }
660 
661     /** Set the name of the constellation this space object belongs to.
662      * @param constellation name of the constellation this space object belongs to
663      */
664     public void setConstellation(final String constellation) {
665         refuseFurtherComments();
666         this.constellation = constellation;
667     }
668 
669     /** Get the type of object.
670      * @return type of object
671      */
672     public Optional<ObjectType> getObjectType() {
673         return Optional.ofNullable(objectType);
674     }
675 
676     /** Set the type of object.
677      * @param objectType type of object
678      */
679     public void setObjectType(final ObjectType objectType) {
680         refuseFurtherComments();
681         this.objectType = objectType;
682     }
683 
684     /** Get the epoch to which <em>all</em> relative times are referenced in data blocks.
685      * @return epoch to which <em>all</em> relative times are referenced in data blocks
686      */
687     public AbsoluteDate getEpochT0() {
688         return epochT0;
689     }
690 
691     /** Set the epoch to which <em>all</em> relative times are referenced in data blocks.
692      * @param epochT0 epoch to which <em>all</em> relative times are referenced in data blocks
693      */
694     public void setEpochT0(final AbsoluteDate epochT0) {
695         refuseFurtherComments();
696         this.epochT0 = epochT0;
697     }
698 
699     /** Get the operational status.
700      * @return operational status
701      */
702     public Optional<OpsStatus> getOpsStatus() {
703         return Optional.ofNullable(opsStatus);
704     }
705 
706     /** Set the operational status.
707      * @param opsStatus operational status
708      */
709     public void setOpsStatus(final OpsStatus opsStatus) {
710         refuseFurtherComments();
711         this.opsStatus = opsStatus;
712     }
713 
714     /** Get the orbit category.
715      * @return orbit category
716      */
717     public Optional<OrbitCategory> getOrbitCategory() {
718         return Optional.ofNullable(orbitCategory);
719     }
720 
721     /** Set the orbit category.
722      * @param orbitCategory orbit category
723      */
724     public void setOrbitCategory(final OrbitCategory orbitCategory) {
725         refuseFurtherComments();
726         this.orbitCategory = orbitCategory;
727     }
728 
729     /** Get the list of elements of information data blocks included in this message.
730      * @return list of elements of information data blocks included in this message
731      */
732     public List<OcmElements> getOcmDataElements() {
733         return ocmDataElements;
734     }
735 
736     /** Set the list of elements of information data blocks included in this message.
737      * @param ocmDataElements list of elements of information data blocks included in this message
738      */
739     public void setOcmDataElements(final List<OcmElements> ocmDataElements) {
740         refuseFurtherComments();
741         this.ocmDataElements = ocmDataElements;
742     }
743 
744     /** Get the spacecraft clock count at {@link #getEpochT0()}.
745      * @return spacecraft clock count at {@link #getEpochT0()}
746      */
747     public double getSclkOffsetAtEpoch() {
748         return sclkOffsetAtEpoch;
749     }
750 
751     /** Set the spacecraft clock count at {@link #getEpochT0()}.
752      * @param sclkOffsetAtEpoch spacecraft clock count at {@link #getEpochT0()}
753      */
754     public void setSclkOffsetAtEpoch(final double sclkOffsetAtEpoch) {
755         refuseFurtherComments();
756         this.sclkOffsetAtEpoch = sclkOffsetAtEpoch;
757     }
758 
759     /** Get the number of spacecraft clock seconds occurring during one SI second.
760      * @return number of spacecraft clock seconds occurring during one SI second
761      */
762     public double getSclkSecPerSISec() {
763         return sclkSecPerSISec;
764     }
765 
766     /** Set the number of spacecraft clock seconds occurring during one SI second.
767      * @param secClockPerSISec number of spacecraft clock seconds occurring during one SI second
768      */
769     public void setSclkSecPerSISec(final double secClockPerSISec) {
770         refuseFurtherComments();
771         this.sclkSecPerSISec = secClockPerSISec;
772     }
773 
774     /** Get the creation date of previous message from a given originator.
775      * @return creation date of previous message from a given originator
776      */
777     public Optional<AbsoluteDate> getPreviousMessageEpoch() {
778         return Optional.ofNullable(previousMessageEpoch);
779     }
780 
781     /** Set the creation date of previous message from a given originator.
782      * @param previousMessageEpoch creation date of previous message from a given originator
783      */
784     public void setPreviousMessageEpoch(final AbsoluteDate previousMessageEpoch) {
785         refuseFurtherComments();
786         this.previousMessageEpoch = previousMessageEpoch;
787     }
788 
789     /** Get the creation date of next message from a given originator.
790      * @return creation date of next message from a given originator
791      */
792     public Optional<AbsoluteDate> getNextMessageEpoch() {
793         return Optional.ofNullable(nextMessageEpoch);
794     }
795 
796     /** Set the creation date of next message from a given originator.
797      * @param nextMessageEpoch creation date of next message from a given originator
798      */
799     public void setNextMessageEpoch(final AbsoluteDate nextMessageEpoch) {
800         refuseFurtherComments();
801         this.nextMessageEpoch = nextMessageEpoch;
802     }
803 
804     /** Get the time of the earliest data contained in the OCM.
805      * @return time of the earliest data contained in the OCM
806      */
807     public Optional<AbsoluteDate> getStartTime() {
808         return Optional.ofNullable(startTime);
809     }
810 
811     /** Set the time of the earliest data contained in the OCM.
812      * @param startTime time of the earliest data contained in the OCM
813      */
814     public void setStartTime(final AbsoluteDate startTime) {
815         refuseFurtherComments();
816         this.startTime = startTime;
817     }
818 
819     /** Get the time of the latest data contained in the OCM.
820      * @return time of the latest data contained in the OCM
821      */
822     public Optional<AbsoluteDate> getStopTime() {
823         return Optional.ofNullable(stopTime);
824     }
825 
826     /** Set the time of the latest data contained in the OCM.
827      * @param stopTime time of the latest data contained in the OCM
828      */
829     public void setStopTime(final AbsoluteDate stopTime) {
830         refuseFurtherComments();
831         this.stopTime = stopTime;
832     }
833 
834     /** Get the span of time in seconds that the OCM covers.
835      * @return span of time in seconds that the OCM covers
836      */
837     public Optional<Double> getTimeSpan() {
838         return Optional.ofNullable(timeSpan);
839     }
840 
841     /** Set the span of time in seconds that the OCM covers.
842      * @param timeSpan span of time in seconds that the OCM covers
843      */
844     public void setTimeSpan(final double timeSpan) {
845         refuseFurtherComments();
846         this.timeSpan = timeSpan;
847     }
848 
849     /** Get the difference (TAI - UTC) in seconds at epoch {@link #getEpochT0()}.
850      * @return difference (TAI - UTC) in seconds at epoch {@link #getEpochT0()}
851      */
852     public Optional<Double> getTaimutcT0() {
853         return Optional.ofNullable(taimutcT0);
854     }
855 
856     /** Set the difference (TAI - UTC) in seconds at epoch {@link #getEpochT0()}.
857      * @param taimutcT0 difference (TAI - UTC) in seconds at epoch {@link #getEpochT0()}
858      */
859     public void setTaimutcT0(final double taimutcT0) {
860         refuseFurtherComments();
861         this.taimutcT0 = taimutcT0;
862     }
863 
864     /** Get the epoch of next leap second.
865      * @return epoch of next leap second
866      * @since 11.2
867      */
868     public Optional<AbsoluteDate> getNextLeapEpoch() {
869         return Optional.ofNullable(nextLeapEpoch);
870     }
871 
872     /** Set the epoch of next leap second.
873      * @param nextLeapEpoch epoch of next leap second
874      * @since 11.2
875      */
876     public void setNextLeapEpoch(final AbsoluteDate nextLeapEpoch) {
877         refuseFurtherComments();
878         this.nextLeapEpoch = nextLeapEpoch;
879     }
880 
881     /** Get the difference (TAI - UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}.
882      * @return difference (TAI - UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}
883      * @since 11.2
884      */
885     public Optional<Double> getNextLeapTaimutc() {
886         return Optional.ofNullable(nextLeapTaimutc);
887     }
888 
889     /** Set the difference (TAI - UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}.
890      * @param nextLeapTaimutc difference (TAI - UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}
891      * @since 11.2
892      */
893     public void setNextLeapTaimutc(final double nextLeapTaimutc) {
894         refuseFurtherComments();
895         this.nextLeapTaimutc = nextLeapTaimutc;
896     }
897 
898     /** Get the difference (UT1 - UTC) in seconds at epoch {@link #getEpochT0()}.
899      * @return difference (UT1 - UTC) in seconds at epoch {@link #getEpochT0()}
900      */
901     public Optional<Double> getUt1mutcT0() {
902         return Optional.ofNullable(ut1mutcT0);
903     }
904 
905     /** Set the difference (UT1 - UTC) in seconds at epoch {@link #getEpochT0()}.
906      * @param ut1mutcT0 difference (UT1 - UTC) in seconds at epoch {@link #getEpochT0()}
907      */
908     public void setUt1mutcT0(final double ut1mutcT0) {
909         refuseFurtherComments();
910         this.ut1mutcT0 = ut1mutcT0;
911     }
912 
913     /** Get the source and version of Earth Orientation Parameters.
914      * @return source and version of Earth Orientation Parameters
915      */
916     public Optional<String> getEopSource() {
917         return Optional.ofNullable(eopSource);
918     }
919 
920     /** Set the source and version of Earth Orientation Parameters.
921      * @param eopSource source and version of Earth Orientation Parameters
922      */
923     public void setEopSource(final String eopSource) {
924         refuseFurtherComments();
925         this.eopSource = eopSource;
926     }
927 
928     /** Get the interpolation method for Earth Orientation Parameters.
929      * @return interpolation method for Earth Orientation Parameters
930      */
931     public Optional<String> getInterpMethodEOP() {
932         return Optional.ofNullable(interpMethodEOP);
933     }
934 
935     /** Set the interpolation method for Earth Orientation Parameters.
936      * @param interpMethodEOP interpolation method for Earth Orientation Parameters
937      */
938     public void setInterpMethodEOP(final String interpMethodEOP) {
939         refuseFurtherComments();
940         this.interpMethodEOP = interpMethodEOP;
941     }
942 
943     /** Get the source and version of celestial body (e.g. Sun/Earth/Planetary).
944      * @return source and version of celestial body (e.g. Sun/Earth/Planetary)
945      */
946     public Optional<String> getCelestialSource() {
947         return Optional.ofNullable(celestialSource);
948     }
949 
950     /** Set the source and version of celestial body (e.g. Sun/Earth/Planetary).
951      * @param celestialSource source and version of celestial body (e.g. Sun/Earth/Planetary)
952      */
953     public void setCelestialSource(final String celestialSource) {
954         refuseFurtherComments();
955         this.celestialSource = celestialSource;
956     }
957 
958     /** Copy the instance, making sure mandatory fields have been initialized.
959      * <p>
960      * Message ID, previous/next references, start and stop times are not copied.
961      * </p>
962      * @param version format version
963      * @return a new copy
964      * @since 12.0
965      */
966     public OcmMetadata copy(final double version) {
967 
968         validate(version);
969 
970         // allocate new instance
971         final OcmMetadata copy = new OcmMetadata(dataContext, getFrameMapper());
972 
973         // copy comments
974         for (String comment : getComments()) {
975             copy.addComment(comment);
976         }
977 
978         // copy metadata
979         getInternationalDesignator().ifPresent(copy::setInternationalDesignator);
980         getCatalogName().ifPresent(copy::setCatalogName);
981         getObjectDesignator().ifPresent(copy::setObjectDesignator);
982         copy.setAlternateNames(getAlternateNames());
983         getOriginatorPOC().ifPresent(copy::setOriginatorPOC);
984         getOriginatorPosition().ifPresent(copy::setOriginatorPosition);
985         getOriginatorPhone().ifPresent(copy::setOriginatorPhone);
986         getOriginatorEmail().ifPresent(copy::setOriginatorEmail);
987         getOriginatorAddress().ifPresent(copy::setOriginatorAddress);
988         getTechOrg().ifPresent(copy::setTechOrg);
989         getTechPOC().ifPresent(copy::setTechPOC);
990         getTechPosition().ifPresent(copy::setTechPosition);
991         getTechPhone().ifPresent(copy::setTechPhone);
992         getTechEmail().ifPresent(copy::setTechEmail);
993         getTechAddress().ifPresent(copy::setTechAddress);
994         getAdmMessageLink().ifPresent(copy::setAdmMessageLink);
995         getCdmMessageLink().ifPresent(copy::setCdmMessageLink);
996         getPrmMessageLink().ifPresent(copy::setPrmMessageLink);
997         getRdmMessageLink().ifPresent(copy::setRdmMessageLink);
998         getTdmMessageLink().ifPresent(copy::setTdmMessageLink);
999         getOperator().ifPresent(copy::setOperator);
1000         getOwner().ifPresent(copy::setOwner);
1001         getCountry().ifPresent(copy::setCountry);
1002         getConstellation().ifPresent(copy::setConstellation);
1003         getObjectType().ifPresent(copy::setObjectType);
1004         copy.setEpochT0(getEpochT0());
1005         getOpsStatus().ifPresent(copy::setOpsStatus);
1006         getOrbitCategory().ifPresent(copy::setOrbitCategory);
1007         copy.setOcmDataElements(getOcmDataElements());
1008         copy.setSclkOffsetAtEpoch(getSclkOffsetAtEpoch());
1009         copy.setSclkSecPerSISec(getSclkSecPerSISec());
1010         getTaimutcT0().ifPresent(copy::setTaimutcT0);
1011         getNextLeapEpoch().ifPresent(copy::setNextLeapEpoch);
1012         getNextLeapTaimutc().ifPresent(copy::setNextLeapTaimutc);
1013         getUt1mutcT0().ifPresent(copy::setUt1mutcT0);
1014         getEopSource().ifPresent(copy::setEopSource);
1015         getInterpMethodEOP().ifPresent(copy::setInterpMethodEOP);
1016         getCelestialSource().ifPresent(copy::setCelestialSource);
1017 
1018         return copy;
1019 
1020     }
1021 
1022 }