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  package org.orekit.files.ccsds.ndm.cdm;
18  
19  import java.util.List;
20  
21  import org.orekit.bodies.CelestialBody;
22  import org.orekit.data.DataContext;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.files.ccsds.definitions.BodyFacade;
26  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
27  import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
28  import org.orekit.files.ccsds.definitions.FrameFacade;
29  import org.orekit.files.ccsds.definitions.TimeSystem;
30  import org.orekit.files.ccsds.definitions.YesNoUnknown;
31  import org.orekit.files.ccsds.ndm.odm.ocm.ObjectType;
32  import org.orekit.files.ccsds.section.Metadata;
33  import org.orekit.frames.Frame;
34  
35  /**
36   * This class gathers the meta-data present in the Conjunction Data Message (CDM).
37   * @author Melina Vanel
38   * @since 11.2
39   */
40  public class CdmMetadata extends Metadata {
41  
42      /** CDM relative metadata. */
43      private CdmRelativeMetadata relativeMetadata;
44  
45      /** Refering to object 1 or 2. */
46      private String object;
47  
48      /** Unique satellite identification designator for the object. */
49      private String objectDesignator;
50  
51      /** Specification of satellite catalog source. */
52      private String catalogName;
53  
54      /** Object name. */
55      private String objectName;
56  
57      /** International designator for the object as assigned by the UN Committee
58       * on Space Research (COSPAR) and the US National Space Science Data Center (NSSDC). */
59      private String internationalDesignator;
60  
61      /** Type of object. */
62      private ObjectType objectType;
63  
64      /** Operator contact position for the space object. */
65      private String operatorContact;
66  
67      /** Operator organization for the space object. */
68      private String operatorOrganization;
69  
70      /** Operator phone for the space object. */
71      private String operatorPhone;
72  
73      /** Operator email for the space object. */
74      private String operatorEmail;
75  
76      /** Unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message. */
77      private String odmMsgLink;
78  
79      /** Unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message. */
80      private String admMsgLink;
81  
82      /** Unique name of the external ephemeris file used for the object or NONE. */
83      private String ephemName;
84  
85      /** Flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
86       * specified by CONJUNCTION_ID. */
87      private YesNoUnknown obsBeforeNextMessage;
88  
89      /** Operator email for the space object. */
90      private CovarianceMethod covarianceMethod;
91  
92      /** Maneuver capacity. */
93      private Maneuvrable maneuverable;
94  
95      /** Central body around which Object1 and 2 are orbiting. */
96      private BodyFacade orbitCenter;
97  
98      /** Reference frame in which state vector data are given. */
99      private FrameFacade refFrame;
100 
101     /** Gravity model name. */
102     private String gravityModel;
103 
104     /** Degree of the gravity model. */
105     private int gravityDegree;
106 
107     /** Order of the gravity model. */
108     private int gravityOrder;
109 
110     /** Name of atmospheric model. */
111     private String atmosphericModel;
112 
113     /** N-body perturbation bodies. */
114     private List<BodyFacade> nBodyPerturbations;
115 
116     /** Is solar radiation pressure taken into account or not ? STANDARD CCSDS saying YES/NO choice and optional */
117     private YesNoUnknown isSolarRadPressure;
118 
119     /** Is solid Earth and ocean tides taken into account or not. STANDARD CCSDS saying YES/NO choice and optional */
120     private YesNoUnknown isEarthTides;
121 
122     /** Is in-track thrust modelling used or not. STANDARD CCSDS saying YES/NO choice and optional */
123     private YesNoUnknown isIntrackThrustModeled;
124 
125     /** The source from which the covariance data used in the report for both Object 1 and Object 2 originates. */
126     private String covarianceSource;
127 
128     /** Flag indicating the type of alternate covariance information provided. */
129     private AltCovarianceType altCovType;
130 
131     /** Reference frame in which the alternate covariance data are given. */
132     private FrameFacade altCovRefFrame;
133 
134     /** Simple constructor.
135      *
136      * @param dataContext data context
137      * @param frameMapper for creating an Orekit {@link Frame}.
138      * @since 13.1.5
139      */
140     public CdmMetadata(final DataContext dataContext,
141                        final CcsdsFrameMapper frameMapper) {
142         super(null, frameMapper);
143         final CelestialBody earth = dataContext.getCelestialBodies().getEarth();
144         orbitCenter = new BodyFacade(earth.getName().toUpperCase(), earth);
145     }
146 
147     /** {@inheritDoc} */
148     @Override
149     public void validate(final double version) {
150         // We only check values that are mandatory in a cdm file
151         checkNotNull(object,                  CdmMetadataKey.OBJECT.name());
152         checkNotNull(objectDesignator,        CdmMetadataKey.OBJECT_DESIGNATOR.name());
153         checkNotNull(catalogName,             CdmMetadataKey.CATALOG_NAME.name());
154         checkNotNull(objectName,              CdmMetadataKey.OBJECT_NAME.name());
155         checkNotNull(internationalDesignator, CdmMetadataKey.INTERNATIONAL_DESIGNATOR.name());
156         checkNotNull(ephemName,               CdmMetadataKey.EPHEMERIS_NAME.name());
157         checkNotNull(covarianceMethod,        CdmMetadataKey.COVARIANCE_METHOD.name());
158         checkNotNull(maneuverable,            CdmMetadataKey.MANEUVERABLE.name());
159         checkNotNull(refFrame,                CdmMetadataKey.REF_FRAME.name());
160     }
161 
162     /**
163      * Get the relative metadata following header, they are the common metadata for the CDM.
164      * @return relativeMetadata relative metadata
165      */
166     public CdmRelativeMetadata getRelativeMetadata() {
167         return relativeMetadata;
168     }
169 
170     /**
171      * Set the relative metadata following header, they are the common metadata for the CDM.
172      * @param relativeMetadata relative metadata
173      */
174     public void setRelativeMetadata(final CdmRelativeMetadata relativeMetadata) {
175         this.relativeMetadata = relativeMetadata;
176     }
177 
178     /**
179      * Get the object name for which metadata are given.
180      * @return the object name
181      */
182     public String getObject() {
183         return object;
184     }
185 
186     /**
187      * Set the object name for which metadata are given.
188      * @param object = object 1 or 2 to be set
189      */
190     public void setObject(final String object) {
191         this.setTimeSystem(TimeSystem.UTC);
192         refuseFurtherComments();
193         this.object = object;
194     }
195 
196     /**
197      * Get the object satellite catalog designator for which metadata are given.
198      * @return the satellite catalog designator for the object
199      */
200     public String getObjectDesignator() {
201         return objectDesignator;
202     }
203 
204     /**
205      * Set the satellite designator for the object for which metadata are given.
206      * @param objectDesignator for the spacecraft to be set
207      */
208     public void setObjectDesignator(final String objectDesignator) {
209         refuseFurtherComments();
210         this.objectDesignator = objectDesignator;
211     }
212 
213     /**
214      * Get the satellite catalog used for the object.
215      * @return the catalog name
216      */
217     public String getCatalogName() {
218         return catalogName;
219     }
220 
221     /**
222      * Set the satellite catalog name used for object.
223      * @param catalogName for the spacecraft to be set
224      */
225     public void setCatalogName(final String catalogName) {
226         refuseFurtherComments();
227         this.catalogName = catalogName;
228     }
229 
230     /**
231      * Get the spacecraft name for the object.
232      * @return the spacecraft name
233      */
234     public String getObjectName() {
235         return objectName;
236     }
237 
238     /**
239      * Set the spacecraft name used for object.
240      * @param objectName for the spacecraft to be set
241      */
242     public void setObjectName(final String objectName) {
243         refuseFurtherComments();
244         this.objectName = objectName;
245     }
246 
247     /**
248      * Get the international designator for the object.
249      * @return the international designator
250      */
251     public String getInternationalDes() {
252         return internationalDesignator;
253     }
254 
255     /**
256      * Set the international designator used for object.
257      * @param internationalDes for the object to be set
258      */
259     public void setInternationalDes(final String internationalDes) {
260         refuseFurtherComments();
261         this.internationalDesignator = internationalDes;
262     }
263 
264     /**
265      * Get the type of object.
266      * @return the object type
267      */
268     public ObjectType getObjectType() {
269         return objectType;
270     }
271 
272     /**
273      * Set the type of object.
274      * @param objectType type of object
275      */
276     public void setObjectType(final ObjectType objectType) {
277         refuseFurtherComments();
278         this.objectType = objectType;
279     }
280 
281     /**
282      * Get the contact position of the owner / operator of the object.
283      * @return the contact position
284      */
285     public String getOperatorContactPosition() {
286         return operatorContact;
287     }
288 
289     /**
290      * Set the contact position for the object owner / operator.
291      * @param opContact for the object to be set
292      */
293     public void setOperatorContactPosition(final String opContact) {
294         refuseFurtherComments();
295         this.operatorContact = opContact;
296     }
297 
298     /**
299      * Get the contact organisation of the object.
300      * @return the contact organisation
301      */
302     public String getOperatorOrganization() {
303         return operatorOrganization;
304     }
305 
306     /**
307      * Set the contact organisation of the object.
308      * @param operatorOrganization contact organisation for the object to be set
309      */
310     public void setOperatorOrganization(final String operatorOrganization) {
311         refuseFurtherComments();
312         this.operatorOrganization = operatorOrganization;
313     }
314 
315     /**
316      * Get the contact phone of the operator of the object.
317      * @return the operator phone
318      */
319     public String getOperatorPhone() {
320         return operatorPhone;
321     }
322 
323     /**
324      * Set the operator phone of the object.
325      * @param operatorPhone contact phone for the object to be set
326      */
327     public void setOperatorPhone(final String operatorPhone) {
328         refuseFurtherComments();
329         this.operatorPhone = operatorPhone;
330     }
331 
332     /**
333      * Get the email of the operator of the object.
334      * @return the operator email
335      */
336     public String getOperatorEmail() {
337         return operatorEmail;
338     }
339 
340     /**
341      * Set the object operator email.
342      * @param operatorEmail operator email for the object to be set
343      */
344     public void setOperatorEmail(final String operatorEmail) {
345         refuseFurtherComments();
346         this.operatorEmail = operatorEmail;
347     }
348 
349     /**
350      * Get the unique name of the external ephemeris used for OD.
351      * @return the name of ephemeris used
352      */
353     public String getEphemName() {
354         return ephemName;
355     }
356 
357     /**
358      * Set the name of external ephemeris used for OD.
359      * @param ephemName me of external ephemeris used
360      */
361     public void setEphemName(final String ephemName) {
362         refuseFurtherComments();
363         this.ephemName = ephemName;
364     }
365 
366     /**
367      * Get the method name used to calculate covariance during OD.
368      * @return the name of covariance calculation method
369      */
370     public CovarianceMethod getCovarianceMethod() {
371         return covarianceMethod;
372     }
373 
374     /**
375      * Set the method name used to calculate covariance during OD.
376      * @param covarianceMethod method name for covariance calculation
377      */
378     public void setCovarianceMethod(final CovarianceMethod covarianceMethod) {
379         refuseFurtherComments();
380         this.covarianceMethod = covarianceMethod;
381     }
382 
383     /**
384      * Get the ability of object to maneuver or not.
385      * @return the ability to maneuver
386      */
387     public Maneuvrable getManeuverable() {
388         return maneuverable;
389     }
390 
391     /**
392      * Set the object maneuver ability.
393      * @param maneuverable ability to maneuver
394      */
395     public void setManeuverable(final Maneuvrable maneuverable) {
396         refuseFurtherComments();
397         this.maneuverable = maneuverable;
398     }
399 
400     /**
401      * Get the central body for object 1 and 2.
402      * @return the name of the central body
403      */
404     public BodyFacade getOrbitCenter() {
405         return orbitCenter;
406     }
407 
408     /**
409      * Set the central body name for object 1 and 2.
410      * @param orbitCenter name of the central body
411      */
412     public void setOrbitCenter(final BodyFacade orbitCenter) {
413         refuseFurtherComments();
414         this.orbitCenter = orbitCenter;
415     }
416 
417     /**
418      * Get the reference frame in which data are given: used for state vector and
419      * Keplerian elements data (and for the covariance reference frame if none is given).
420      *
421      * @return the reference frame
422      */
423     public Frame getFrame() {
424         // CDM format does not allow specifying frame epoch
425         return getFrameMapper().buildCcsdsFrame(getOrbitCenter(), getRefFrame(), null);
426     }
427 
428     /**
429      * Get the value of {@code REF_FRAME} as an Orekit {@link Frame}. The {@code
430      * ORBIT_CENTER} key word has not been applied yet, so the returned frame may not
431      * correspond to the reference frame of the data in the file.
432      * @return the reference frame
433      */
434     public FrameFacade getRefFrame() {
435         return refFrame;
436     }
437 
438     /**
439      * Set the name of the reference frame in which the state vector data are given.
440      * @param refFrame reference frame
441      */
442     public void setRefFrame(final FrameFacade refFrame) {
443         refuseFurtherComments();
444         this.refFrame = refFrame;
445     }
446 
447     /** Get gravity model name.
448      * @return gravity model name
449      */
450     public String getGravityModel() {
451         return gravityModel;
452     }
453 
454     /** Get degree of the gravity model.
455      * @return degree of the gravity model
456      */
457     public int getGravityDegree() {
458         return gravityDegree;
459     }
460 
461     /** Get order of the gravity model.
462      * @return order of the gravity model
463      */
464     public int getGravityOrder() {
465         return gravityOrder;
466     }
467 
468     /** Set gravity model.
469      * @param name name of the model
470      * @param degree degree of the model
471      * @param order order of the model
472      */
473     public void setGravityModel(final String name, final int degree, final int order) {
474         refuseFurtherComments();
475         this.gravityModel  = name;
476         this.gravityDegree = degree;
477         this.gravityOrder  = order;
478     }
479 
480     /** Get name of atmospheric model.
481      * @return name of atmospheric model
482      */
483     public String getAtmosphericModel() {
484         return atmosphericModel;
485     }
486 
487     /** Set name of atmospheric model.
488      * @param atmosphericModel name of atmospheric model
489      */
490     public void setAtmosphericModel(final String atmosphericModel) {
491         refuseFurtherComments();
492         this.atmosphericModel = atmosphericModel;
493     }
494 
495     /** Get n-body perturbation bodies.
496      * @return n-body perturbation bodies
497      */
498     public List<BodyFacade> getNBodyPerturbations() {
499         return nBodyPerturbations;
500     }
501 
502     /** Set n-body perturbation bodies.
503      * @param nBody n-body perturbation bodies
504      */
505     public void setNBodyPerturbations(final List<BodyFacade> nBody) {
506         refuseFurtherComments();
507         this.nBodyPerturbations = nBody;
508     }
509 
510     /**
511      * Get Enum YesNoUnknown that indicates if Solar Radiation Pressure is taken into account or not.
512      * @return isSolarRadPressure YesNoUnknown
513      */
514     public YesNoUnknown getSolarRadiationPressure() {
515         return isSolarRadPressure;
516     }
517 
518     /**
519      * Set Enum that indicates if Solar Radiation Pressure is taken into account or not.
520      * @param isSolRadPressure YesNoUnknown
521      */
522     public void setSolarRadiationPressure(final YesNoUnknown isSolRadPressure) {
523         refuseFurtherComments();
524         this.isSolarRadPressure = isSolRadPressure;
525     }
526 
527     /**
528      * Get Enum YesNoUnknown that indicates if Earth and ocean tides are taken into account or not.
529      * @return isEarthTides YesNoUnknown
530      */
531     public YesNoUnknown getEarthTides() {
532         return isEarthTides;
533     }
534 
535     /**
536      * Set Enum YesNoUnknown that indicates if Earth and ocean tides are taken into account or not.
537      * @param EarthTides YesNoUnknown
538      */
539     public void setEarthTides(final YesNoUnknown EarthTides) {
540         refuseFurtherComments();
541         this.isEarthTides = EarthTides;
542     }
543 
544     /**
545      * Get Enum YesNoUnknown that indicates if intrack thrust modeling was into account or not.
546      * @return isEarthTides YesNoUnknown
547      */
548     public YesNoUnknown getIntrackThrust() {
549         return isIntrackThrustModeled;
550     }
551 
552     /**
553      * Set boolean that indicates if intrack thrust modeling was into account or not.
554      * @param IntrackThrustModeled YesNoUnknown
555      */
556     public void setIntrackThrust(final YesNoUnknown IntrackThrustModeled) {
557         refuseFurtherComments();
558         this.isIntrackThrustModeled = IntrackThrustModeled;
559     }
560 
561     /** Get the source of the covariance data.
562      * @return the covarianceSource
563      */
564     public String getCovarianceSource() {
565         return covarianceSource;
566     }
567 
568     /** Set the source of the covariance data.
569      * @param covarianceSource the covarianceSource to set
570      */
571     public void setCovarianceSource(final String covarianceSource) {
572         refuseFurtherComments();
573         this.covarianceSource = covarianceSource;
574     }
575 
576     /** Get the flag indicating the type of alternate covariance information provided.
577      * @return the altCovType
578      */
579     public AltCovarianceType getAltCovType() {
580         return altCovType;
581     }
582 
583     /** Set the flag indicating the type of alternate covariance information provided.
584      * @param altCovType the altCovType to set
585      */
586     public void setAltCovType(final AltCovarianceType altCovType) {
587         refuseFurtherComments();
588         this.altCovType = altCovType;
589     }
590 
591      /**
592      * Get the value of {@code ALT_COV_REF_FRAME} as an Orekit {@link Frame}.
593      * @return the reference frame
594      */
595     public FrameFacade getAltCovRefFrame() {
596         return altCovRefFrame;
597     }
598 
599     /**
600      * Set the name of the reference frame in which the alternate covariance data are given.
601      * @param altCovRefFrame alternate covariance reference frame
602      */
603     public void setAltCovRefFrame(final FrameFacade altCovRefFrame) {
604         refuseFurtherComments();
605 
606         if (getAltCovType() == null) {
607             throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmMetadataKey.ALT_COV_TYPE);
608         }
609 
610         if (altCovRefFrame.asFrame() == null) {
611             throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, altCovRefFrame.getName());
612         }
613 
614         // Only set the frame if within the allowed options: GCRF, EME2000, ITRF
615         if ( altCovRefFrame.asCelestialBodyFrame() == CelestialBodyFrame.GCRF ||
616                  altCovRefFrame.asCelestialBodyFrame() == CelestialBodyFrame.EME2000 ||
617                      altCovRefFrame.asCelestialBodyFrame().name().contains("ITRF") ) {
618             this.altCovRefFrame = altCovRefFrame;
619         } else {
620             throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, altCovRefFrame.getName());
621         }
622     }
623 
624     /**
625      * Get the reference frame in which the alternative covariance data is
626      * given.
627      *
628      * @return alternative covariance reference frame.
629      * @see #getAltCovType()
630      * @see #getAltCovRefFrame()
631      * @since 13.1.5
632      */
633     public Frame getAltCovFrame() {
634         // Epoch of AltCovRefFrame can't be specified.
635         return getFrameMapper().buildCcsdsFrame(getAltCovRefFrame(), null);
636     }
637 
638     /** Get the unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message.
639      * @return the odmMsgLink
640      */
641     public String getOdmMsgLink() {
642         return odmMsgLink;
643     }
644 
645     /** Set the unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message.
646      * @param odmMsgLink the odmMsgLink to set
647      */
648     public void setOdmMsgLink(final String odmMsgLink) {
649         refuseFurtherComments();
650         this.odmMsgLink = odmMsgLink;
651     }
652 
653     /** Get the unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message.
654      * @return the admMsgLink
655      */
656     public String getAdmMsgLink() {
657         return admMsgLink;
658     }
659 
660     /** Set the unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message.
661      * @param admMsgLink the admMsgLink to set
662      */
663     public void setAdmMsgLink(final String admMsgLink) {
664         refuseFurtherComments();
665         this.admMsgLink = admMsgLink;
666     }
667 
668     /** Get the flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
669      * specified by CONJUNCTION_ID.
670      * @return the obsBeforeNextMessage
671      */
672     public YesNoUnknown getObsBeforeNextMessage() {
673         return obsBeforeNextMessage;
674     }
675 
676     /** Set the flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
677      * specified by CONJUNCTION_ID.
678      * @param obsBeforeNextMessage the obsBeforeNextMessage to set
679      */
680     public void setObsBeforeNextMessage(final YesNoUnknown obsBeforeNextMessage) {
681         refuseFurtherComments();
682         this.obsBeforeNextMessage = obsBeforeNextMessage;
683     }
684 }