1   /* Copyright 2022-2026 Luc Maisonobe
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.adm.acm;
19  
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Optional;
23  
24  import org.orekit.annotation.Nullable;
25  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
26  import org.orekit.files.ccsds.ndm.adm.AdmMetadata;
27  import org.orekit.files.ccsds.ndm.adm.AdmMetadataKey;
28  import org.orekit.files.ccsds.section.MetadataKey;
29  import org.orekit.frames.Frame;
30  import org.orekit.time.AbsoluteDate;
31  
32  /** Meta-data for {@link AcmMetadata Attitude Comprehensive Message}.
33   * @since 12.0
34   */
35  public class AcmMetadata extends AdmMetadata {
36  
37      /** Specification of satellite catalog source. */
38      @Nullable
39      private String catalogName;
40  
41      /** Unique satellite identification designator for the object. */
42      @Nullable
43      private String objectDesignator;
44  
45      /** Programmatic Point Of Contact at originator. */
46      @Nullable
47      private String originatorPOC;
48  
49      /** Position of Programmatic Point Of Contact at originator. */
50      @Nullable
51      private String originatorPosition;
52  
53      /** Phone number of Programmatic Point Of Contact at originator. */
54      @Nullable
55      private String originatorPhone;
56  
57      /** Email address of Programmatic Point Of Contact at originator. */
58      @Nullable
59      private String originatorEmail;
60  
61      /** Address of Programmatic Point Of Contact at originator. */
62      @Nullable
63      private String originatorAddress;
64  
65      /** Unique identifier of Orbit Data Message linked to this Orbit Data Message. */
66      @Nullable
67      private String odmMessageLink;
68  
69      /** Epoch to which <em>all</em> relative times are referenced in data blocks;
70       * unless overridden by block-specific {@code EPOCH_TZERO} values. */
71      private AbsoluteDate epochT0;
72  
73      /** List of elements of information data blocks included in this message. */
74      private List<AcmElements> acmDataElements;
75  
76      /** Time of the earliest data contained in the OCM. */
77      @Nullable
78      private AbsoluteDate startTime;
79  
80      /** Time of the latest data contained in the OCM. */
81      @Nullable
82      private AbsoluteDate stopTime;
83  
84      /** Difference (TAI – UTC) in seconds at epoch {@link #epochT0}. */
85      @Nullable
86      private Double taimutcT0;
87  
88      /** Epoch of next leap second. */
89      @Nullable
90      private AbsoluteDate nextLeapEpoch;
91  
92      /** Difference (TAI – UTC) in seconds incorporated at {@link #nextLeapEpoch}. */
93      @Nullable
94      private Double nextLeapTaimutc;
95  
96      /**
97       * Create a new meta-data.
98       *
99       * @param frameMapper for creating an Orekit {@link Frame}.
100      * @since 13.1.5
101      */
102     public AcmMetadata(final CcsdsFrameMapper frameMapper) {
103         super(frameMapper);
104         acmDataElements = Collections.emptyList();
105     }
106 
107     /** {@inheritDoc} */
108     @Override
109     public void validate(final double version) {
110         // we don't call super.checkMandatoryEntries() because
111         // all of the parameters considered mandatory at ADM level
112         // for APM and AEM are in fact optional in ACM
113         // only OBJECT_NAME, TIME_SYSTEM and EPOCH_TZERO are mandatory
114         checkNotNull(getObjectName(), AdmMetadataKey.OBJECT_NAME.name());
115         checkNotNull(getTimeSystem(), MetadataKey.TIME_SYSTEM.name());
116         checkNotNull(epochT0,         AcmMetadataKey.EPOCH_TZERO.name());
117         if (nextLeapEpoch != null) {
118             checkNotNaN(nextLeapTaimutc, AcmMetadataKey.NEXT_LEAP_TAIMUTC.name());
119         }
120     }
121 
122     /** Get the international designator for the object.
123      * @return international designator for the object
124      */
125     public String getInternationalDesignator() {
126         return getObjectID();
127     }
128 
129     /** Set the international designator for the object.
130      * @param internationalDesignator international designator for the object
131      */
132     public void setInternationalDesignator(final String internationalDesignator) {
133         setObjectID(internationalDesignator);
134     }
135 
136     /** Get the specification of satellite catalog source.
137      * @return specification of satellite catalog source
138      */
139     public Optional<String> getCatalogName() {
140         return Optional.ofNullable(catalogName);
141     }
142 
143     /** Set the specification of satellite catalog source.
144      * @param catalogName specification of satellite catalog source
145      */
146     public void setCatalogName(final String catalogName) {
147         refuseFurtherComments();
148         this.catalogName = catalogName;
149     }
150 
151     /** Get the unique satellite identification designator for the object.
152      * @return unique satellite identification designator for the object.
153      */
154     public Optional<String> getObjectDesignator() {
155         return Optional.ofNullable(objectDesignator);
156     }
157 
158     /** Set the unique satellite identification designator for the object.
159      * @param objectDesignator unique satellite identification designator for the object
160      */
161     public void setObjectDesignator(final String objectDesignator) {
162         refuseFurtherComments();
163         this.objectDesignator = objectDesignator;
164     }
165 
166     /** Get the programmatic Point Of Contact at originator.
167      * @return programmatic Point Of Contact at originator
168      */
169     public Optional<String> getOriginatorPOC() {
170         return Optional.ofNullable(originatorPOC);
171     }
172 
173     /** Set the programmatic Point Of Contact at originator.
174      * @param originatorPOC programmatic Point Of Contact at originator
175      */
176     public void setOriginatorPOC(final String originatorPOC) {
177         refuseFurtherComments();
178         this.originatorPOC = originatorPOC;
179     }
180 
181     /** Get the position of Programmatic Point Of Contact at originator.
182      * @return position of Programmatic Point Of Contact at originator
183      */
184     public Optional<String> getOriginatorPosition() {
185         return Optional.ofNullable(originatorPosition);
186     }
187 
188     /** Set the position of Programmatic Point Of Contact at originator.
189      * @param originatorPosition position of Programmatic Point Of Contact at originator
190      */
191     public void setOriginatorPosition(final String originatorPosition) {
192         refuseFurtherComments();
193         this.originatorPosition = originatorPosition;
194     }
195 
196     /** Get the phone number of Programmatic Point Of Contact at originator.
197      * @return phone number of Programmatic Point Of Contact at originator
198      */
199     public Optional<String> getOriginatorPhone() {
200         return Optional.ofNullable(originatorPhone);
201     }
202 
203     /** Set the phone number of Programmatic Point Of Contact at originator.
204      * @param originatorPhone phone number of Programmatic Point Of Contact at originator
205      */
206     public void setOriginatorPhone(final String originatorPhone) {
207         refuseFurtherComments();
208         this.originatorPhone = originatorPhone;
209     }
210 
211     /** Get the email address of Programmatic Point Of Contact at originator.
212      * @return email address of Programmatic Point Of Contact at originator
213      */
214     public Optional<String> getOriginatorEmail() {
215         return Optional.ofNullable(originatorEmail);
216     }
217 
218     /** Set the email address of Programmatic Point Of Contact at originator.
219      * @param originatorEmail email address of Programmatic Point Of Contact at originator
220      */
221     public void setOriginatorEmail(final String originatorEmail) {
222         refuseFurtherComments();
223         this.originatorEmail = originatorEmail;
224     }
225 
226     /** Get the address of Programmatic Point Of Contact at originator.
227      * @return address of Programmatic Point Of Contact at originator
228      */
229     public Optional<String> getOriginatorAddress() {
230         return Optional.ofNullable(originatorAddress);
231     }
232 
233     /** Set the address of Programmatic Point Of Contact at originator.
234      * @param originatorAddress address of Programmatic Point Of Contact at originator
235      */
236     public void setOriginatorAddress(final String originatorAddress) {
237         refuseFurtherComments();
238         this.originatorAddress = originatorAddress;
239     }
240 
241     /** Get the Unique identifier of Orbit Data Message linked to this Attitude Data Message.
242      * @return Unique identifier of Orbit Data Message linked to this Attitude Data Message
243      */
244     public Optional<String> getOdmMessageLink() {
245         return Optional.ofNullable(odmMessageLink);
246     }
247 
248     /** Set the Unique identifier of Orbit Data Message linked to this Attitude Data Message.
249      * @param odmMessageLink Unique identifier of Orbit Data Message linked to this Attitude Data Message
250      */
251     public void setOdmMessageLink(final String odmMessageLink) {
252         refuseFurtherComments();
253         this.odmMessageLink = odmMessageLink;
254     }
255 
256     /** Get the epoch to which <em>all</em> relative times are referenced in data blocks.
257      * @return epoch to which <em>all</em> relative times are referenced in data blocks
258      */
259     public AbsoluteDate getEpochT0() {
260         return epochT0;
261     }
262 
263     /** Set the epoch to which <em>all</em> relative times are referenced in data blocks.
264      * @param epochT0 epoch to which <em>all</em> relative times are referenced in data blocks
265      */
266     public void setEpochT0(final AbsoluteDate epochT0) {
267         refuseFurtherComments();
268         this.epochT0 = epochT0;
269     }
270 
271     /** Get the list of elements of information data blocks included in this message.
272      * @return list of elements of information data blocks included in this message
273      */
274     public List<AcmElements> getAcmDataElements() {
275         return acmDataElements;
276     }
277 
278     /** Set the list of elements of information data blocks included in this message.
279      * @param acmDataElements list of elements of information data blocks included in this message
280      */
281     public void setAcmDataElements(final List<AcmElements> acmDataElements) {
282         refuseFurtherComments();
283         this.acmDataElements = acmDataElements;
284     }
285 
286     /** Get the time of the earliest data contained in the OCM.
287      * @return time of the earliest data contained in the OCM
288      */
289     public Optional<AbsoluteDate> getStartTime() {
290         return Optional.ofNullable(startTime);
291     }
292 
293     /** Set the time of the earliest data contained in the OCM.
294      * @param startTime time of the earliest data contained in the OCM
295      */
296     public void setStartTime(final AbsoluteDate startTime) {
297         refuseFurtherComments();
298         this.startTime = startTime;
299     }
300 
301     /** Get the time of the latest data contained in the OCM.
302      * @return time of the latest data contained in the OCM
303      */
304     public Optional<AbsoluteDate> getStopTime() {
305         return Optional.ofNullable(stopTime);
306     }
307 
308     /** Set the time of the latest data contained in the OCM.
309      * @param stopTime time of the latest data contained in the OCM
310      */
311     public void setStopTime(final AbsoluteDate stopTime) {
312         refuseFurtherComments();
313         this.stopTime = stopTime;
314     }
315 
316     /** Get the difference (TAI – UTC) in seconds at epoch {@link #getEpochT0()}.
317      * @return difference (TAI – UTC) in seconds at epoch {@link #getEpochT0()}
318      */
319     public Optional<Double> getTaimutcT0() {
320         return Optional.ofNullable(taimutcT0);
321     }
322 
323     /** Set the difference (TAI – UTC) in seconds at epoch {@link #getEpochT0()}.
324      * @param taimutcT0 difference (TAI – UTC) in seconds at epoch {@link #getEpochT0()}
325      */
326     public void setTaimutcT0(final double taimutcT0) {
327         refuseFurtherComments();
328         this.taimutcT0 = taimutcT0;
329     }
330 
331     /** Get the epoch of next leap second.
332      * @return epoch of next leap second
333      */
334     public Optional<AbsoluteDate> getNextLeapEpoch() {
335         return Optional.ofNullable(nextLeapEpoch);
336     }
337 
338     /** Set the epoch of next leap second.
339      * @param nextLeapEpoch epoch of next leap second
340      */
341     public void setNextLeapEpoch(final AbsoluteDate nextLeapEpoch) {
342         refuseFurtherComments();
343         this.nextLeapEpoch = nextLeapEpoch;
344     }
345 
346     /** Get the difference (TAI – UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}.
347      * @return difference (TAI – UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}
348      */
349     public Optional<Double> getNextLeapTaimutc() {
350         return Optional.ofNullable(nextLeapTaimutc);
351     }
352 
353     /** Set the difference (TAI – UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}.
354      * @param nextLeapTaimutc difference (TAI – UTC) in seconds incorporated at epoch {@link #getNextLeapEpoch()}
355      */
356     public void setNextLeapTaimutc(final double nextLeapTaimutc) {
357         refuseFurtherComments();
358         this.nextLeapTaimutc = nextLeapTaimutc;
359     }
360 
361 }