Commit 08b755af authored by mvanel's avatar mvanel
Browse files

Issue 777 : WRITER

- Writer for CDM
- Parser change for comments reading for xml for the writer development
- RTN covariance change to avoid duplication of variables
parent 9c5bb21e
Pipeline #1882 failed with stages
in 1 minute and 45 seconds
......@@ -20,6 +20,7 @@ import org.orekit.annotation.DefaultDataContext;
import org.orekit.data.DataContext;
import org.orekit.files.ccsds.ndm.adm.aem.AemWriter;
import org.orekit.files.ccsds.ndm.adm.apm.ApmWriter;
import org.orekit.files.ccsds.ndm.cdm.CdmWriter;
import org.orekit.files.ccsds.ndm.odm.ocm.OcmWriter;
import org.orekit.files.ccsds.ndm.odm.oem.OemWriter;
import org.orekit.files.ccsds.ndm.odm.omm.OmmWriter;
......@@ -148,4 +149,11 @@ public class WriterBuilder extends AbstractBuilder<WriterBuilder> {
return new TdmWriter(getConventions(), getDataContext(), getRangeUnitsConverter());
}
/** Build a writer for {@link org.orekit.files.ccsds.ndm.cdm.Cdm Conjunction Data Messages}.
* @return a new writer
*/
public CdmWriter buildCdmWriter() {
return new CdmWriter(getConventions(), getDataContext());
}
}
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.files.ccsds.ndm.cdm;
import java.io.IOException;
import org.orekit.files.ccsds.definitions.Units;
import org.orekit.files.ccsds.section.AbstractWriter;
import org.orekit.files.ccsds.utils.generation.Generator;
import org.orekit.utils.units.Unit;
/**
* Writer for additional parameters data block for CCSDS Conjunction Data Messages.
*
* @author Melina Vanel
* @since 11.2
*/
public class AdditionalParametersWriter extends AbstractWriter {
/** Additional parameters block. */
private final AdditionalParameters additionalParameters;
/** Create a writer.
* @param xmlTag name of the XML tag surrounding the section
* @param kvnTag name of the KVN tag surrounding the section (may be null)
* @param additionalParameters additional parameters data to write
*/
AdditionalParametersWriter(final String xmlTag, final String kvnTag,
final AdditionalParameters additionalParameters) {
super(xmlTag, kvnTag);
this.additionalParameters = additionalParameters;
}
/** {@inheritDoc} */
@Override
protected void writeContent(final Generator generator) throws IOException {
generator.writeComments(additionalParameters.getComments());
// additional parameters
generator.writeEntry(AdditionalParametersKey.AREA_PC.name(), additionalParameters.getAreaPC(), Units.M2, false);
generator.writeEntry(AdditionalParametersKey.AREA_DRG.name(), additionalParameters.getAreaDRG(), Units.M2, false);
generator.writeEntry(AdditionalParametersKey.AREA_SRP.name(), additionalParameters.getAreaSRP(), Units.M2, false);
generator.writeEntry(AdditionalParametersKey.MASS.name(), additionalParameters.getMass(), Unit.KILOGRAM, false);
generator.writeEntry(AdditionalParametersKey.CD_AREA_OVER_MASS.name(), additionalParameters.getCDAreaOverMass(), Units.M2_PER_KG, false);
generator.writeEntry(AdditionalParametersKey.CR_AREA_OVER_MASS.name(), additionalParameters.getCRAreaOverMass(), Units.M2_PER_KG, false);
generator.writeEntry(AdditionalParametersKey.THRUST_ACCELERATION.name(), additionalParameters.getThrustAcceleration(), Units.M_PER_S2, false);
generator.writeEntry(AdditionalParametersKey.SEDR.name(), additionalParameters.getSedr(), Units.W_PER_KG, false);
}
}
......@@ -20,7 +20,6 @@ import java.util.List;
import org.orekit.data.DataContext;
import org.orekit.files.ccsds.ndm.NdmConstituent;
import org.orekit.files.ccsds.section.Segment;
import org.orekit.utils.IERSConventions;
/**
......@@ -30,7 +29,7 @@ import org.orekit.utils.IERSConventions;
* @author Melina Vanel
* @since 11.2
*/
public class Cdm extends NdmConstituent<CdmHeader, Segment<CdmMetadata, CdmData>> {
public class Cdm extends NdmConstituent<CdmHeader, CdmSegment> {
/** Root element for XML files. */
public static final String ROOT = "cdm";
......@@ -44,7 +43,7 @@ public class Cdm extends NdmConstituent<CdmHeader, Segment<CdmMetadata, CdmData>
* @param conventions IERS conventions
* @param dataContext used for creating frames, time scales, etc.
*/
public Cdm(final CdmHeader header, final List<Segment<CdmMetadata, CdmData>> segments,
public Cdm(final CdmHeader header, final List<CdmSegment> segments,
final IERSConventions conventions, final DataContext dataContext) {
super(header, segments, conventions, dataContext);
}
......
......@@ -106,7 +106,7 @@ public class CdmData implements Data {
/** Get the covariance matrix logical block.
* @return covariance matrix block
*/
public RTNCovariance getCovarianceMatrixBlock() {
public RTNCovariance getRTNCovarianceBlock() {
return covarianceMatrixBlock;
}
......
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.files.ccsds.ndm.cdm;
import java.io.IOException;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import org.orekit.files.ccsds.definitions.TimeConverter;
import org.orekit.files.ccsds.section.HeaderKey;
import org.orekit.files.ccsds.section.Segment;
import org.orekit.files.ccsds.section.XmlStructureKey;
import org.orekit.files.ccsds.utils.ContextBinding;
import org.orekit.files.ccsds.utils.FileFormat;
import org.orekit.files.ccsds.utils.generation.Generator;
import org.orekit.files.ccsds.utils.generation.MessageWriter;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.DateTimeComponents;
import org.orekit.time.TimeComponents;
import org.orekit.time.TimeScale;
/** Cdm message writer.
* @author Melina Vanel
* @since 11.2
*/
public abstract class CdmMessageWriter implements MessageWriter<CdmHeader, CdmSegment, Cdm> {
/** Default value for {@link HeaderKey#ORIGINATOR}. */
public static final String DEFAULT_ORIGINATOR = "OREKIT";
/** Root element for XML files. */
private final String root;
/** Key for format version. */
private final String formatVersionKey;
/** Default format version. */
private final double defaultVersion;
/** Current context binding. */
private ContextBinding context;
/** Current converter for dates. */
private TimeConverter timeConverter;
/** Current format version. */
private double version;
/** Boolean to ensure relative metadata will be written only once. */
private boolean isrelativemetadataWritten;
/**
* Constructor used to create a new NDM writer configured with the necessary parameters
* to successfully fill in all required fields that aren't part of a standard object.
* <p>
* If creation date and originator are not present in header, built-in defaults will be used
* </p>
* @param root root element for XML files
* @param formatVersionKey key for format version
* @param defaultVersion default format version
* @param context context binding (may be reset for each segment)
*/
public CdmMessageWriter(final String root, final String formatVersionKey,
final double defaultVersion, final ContextBinding context) {
this.root = root;
this.defaultVersion = defaultVersion;
this.formatVersionKey = formatVersionKey;
this.version = defaultVersion;
this.isrelativemetadataWritten = false;
setContext(context);
}
/** Reset context binding.
* @param context context binding to use
*/
public void setContext(final ContextBinding context) {
this.context = context;
this.timeConverter = context.getTimeSystem().getConverter(context);
}
/** Get the current context.
* @return current context
*/
public ContextBinding getContext() {
return context;
}
/** Get the current time converter.
* @return current time converter
*/
public TimeConverter getTimeConverter() {
return timeConverter;
}
/** Get the default format version.
* @return default format version
*/
public double getDefaultVersion() {
return defaultVersion;
}
/** {@inheritDoc} */
@Override
public void writeHeader(final Generator generator, final CdmHeader header) throws IOException {
final ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
final TimeScale utc = context.getDataContext().getTimeScales().getUTC();
final AbsoluteDate date = new AbsoluteDate(zdt.getYear(), zdt.getMonthValue(), zdt.getDayOfMonth(),
zdt.getHour(), zdt.getMinute(), zdt.getSecond(),
utc);
// validate before writing
if (header != null) {
if (!Double.isNaN(header.getFormatVersion())) {
// save format version for validating segments
version = header.getFormatVersion();
}
if (header.getCreationDate() == null) {
header.setCreationDate(date);
}
if (header.getOriginator() == null) {
header.setOriginator(DEFAULT_ORIGINATOR);
}
header.validate(version);
}
generator.startMessage(root, formatVersionKey, version);
if (generator.getFormat() == FileFormat.XML) {
generator.enterSection(XmlStructureKey.header.name());
}
// comments are optional
if (header != null) {
generator.writeComments(header.getComments());
}
// creation date is informational only, but mandatory and always in UTC
final DateTimeComponents creationDate = ((header == null) ? date : header.getCreationDate()).getComponents(utc);
final DateComponents dc = creationDate.getDate();
final TimeComponents tc = creationDate.getTime();
generator.writeEntry(HeaderKey.CREATION_DATE.name(),
generator.dateToString(dc.getYear(), dc.getMonth(), dc.getDay(),
tc.getHour(), tc.getMinute(), tc.getSecond()),
null, true);
// Use built-in default if mandatory originator not present
generator.writeEntry(HeaderKey.ORIGINATOR.name(),
header == null ? DEFAULT_ORIGINATOR : header.getOriginator(),
null, true);
if (header != null) {
generator.writeEntry(CdmHeaderKey.MESSAGE_FOR.name(), header.getMessageFor(), null, false);
}
if (header != null) {
generator.writeEntry(HeaderKey.MESSAGE_ID.name(), header.getMessageId(), null, false);
}
if (generator.getFormat() == FileFormat.XML) {
generator.exitSection();
}
// add an empty line for presentation
generator.newLine();
if (generator.getFormat() == FileFormat.XML) {
generator.enterSection(XmlStructureKey.body.name());
}
}
/** {@inheritDoc} */
@Override
public void writeSegment(final Generator generator, final CdmSegment segment) throws IOException {
// validate before writing
segment.getMetadata().validate(version);
segment.getData().validate(version);
// relative metadata should only be written once after the header at the beginning of the body
if (!isrelativemetadataWritten) {
writeRelativeMetadataContent(generator, version, segment.getMetadata().getRelativeMetadata());
isrelativemetadataWritten = true;
}
if (generator.getFormat() == FileFormat.XML) {
generator.enterSection(XmlStructureKey.segment.name());
}
writeSegmentContent(generator, version, segment);
if (generator.getFormat() == FileFormat.XML) {
generator.exitSection();
}
}
/** Write RelativeMetadata part only once after header.
* @param generator generator to use for producing output
* @param formatVersion format version to use
* @param relativeMetadata relative metadata to write
* @throws IOException if any buffer writing operations fails
*/
public abstract void writeRelativeMetadataContent(Generator generator, double formatVersion,
CdmRelativeMetadata relativeMetadata) throws IOException;
/** Write one segment content (without XML wrapping).
* @param generator generator to use for producing output
* @param formatVersion format version to use
* @param segment segment to write
* @throws IOException if any buffer writing operations fails
*/
public abstract void writeSegmentContent(Generator generator, double formatVersion,
Segment<CdmMetadata, CdmData> segment) throws IOException;
/** {@inheritDoc} */
@Override
public void writeFooter(final Generator generator) throws IOException {
if (generator.getFormat() == FileFormat.XML) {
generator.exitSection();
}
generator.endMessage(root);
}
}
......@@ -114,6 +114,7 @@ public class CdmMetadata extends Metadata {
*/
public CdmMetadata() {
super(null);
}
/** {@inheritDoc} */
......
/* Copyright 2002-2022 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.files.ccsds.ndm.cdm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.orekit.files.ccsds.definitions.BodyFacade;
import org.orekit.files.ccsds.section.AbstractWriter;
import org.orekit.files.ccsds.section.XmlStructureKey;
import org.orekit.files.ccsds.utils.generation.Generator;
/**
* Writer for Metadata for CCSDS Conjunction Data Messages.
*
* @author Melina Vanel
* @since 11.2
*/
public class CdmMetadataWriter extends AbstractWriter {
/** Constant for boolean translation. */
private static final String YES = "YES";
/** Constant for boolean translation. */
private static final String NO = "NO";
/** Metadata. */
private final CdmMetadata metadata;
/** Simple constructor.
* @param metadata metadata to write
*/
public CdmMetadataWriter(final CdmMetadata metadata) {
super(XmlStructureKey.metadata.name(), null);
this.metadata = metadata;
}
/** {@inheritDoc} */
@Override
protected void writeContent(final Generator generator) throws IOException {
generator.writeComments(metadata.getComments());
// object
generator.writeEntry(CdmMetadataKey.OBJECT.name(),
metadata.getObject(), null, true);
generator.writeEntry(CdmMetadataKey.OBJECT_DESIGNATOR.name(),
metadata.getObjectDesignator(), null, true);
generator.writeEntry(CdmMetadataKey.CATALOG_NAME.name(),
metadata.getCatalogName(), null, true);
generator.writeEntry(CdmMetadataKey.OBJECT_NAME.name(),
metadata.getObjectName(), null, true);
generator.writeEntry(CdmMetadataKey.INTERNATIONAL_DESIGNATOR.name(),
metadata.getInternationalDes(), null, true);
generator.writeEntry(CdmMetadataKey.OBJECT_TYPE.name(),
metadata.getObjectType(), false);
// originator
generator.writeEntry(CdmMetadataKey.OPERATOR_CONTACT_POSITION.name(),
metadata.getOperatorContactPosition(), null, false);
generator.writeEntry(CdmMetadataKey.OPERATOR_ORGANIZATION.name(),
metadata.getOperatorOrganization(), null, false);
generator.writeEntry(CdmMetadataKey.OPERATOR_PHONE.name(),
metadata.getOperatorPhone(), null, false);
generator.writeEntry(CdmMetadataKey.OPERATOR_EMAIL.name(),
metadata.getOperatorEmail(), null, false);
// other information
generator.writeEntry(CdmMetadataKey.EPHEMERIS_NAME.name(),
metadata.getEphemName(), null, true);
generator.writeEntry(CdmMetadataKey.COVARIANCE_METHOD.name(),
metadata.getCovarianceMethod(), true);
generator.writeEntry(CdmMetadataKey.MANEUVERABLE.name(),
metadata.getManeuverable(), true);
if (metadata.getOrbitCenter() != null) {
generator.writeEntry(CdmMetadataKey.ORBIT_CENTER.name(),
metadata.getOrbitCenter().getName(), null, false);
}
generator.writeEntry(CdmMetadataKey.REF_FRAME.name(),
metadata.getRefFrame().getName(), null, true);
// gravity
if (metadata.getGravityModel() != null) {
final String model =
new StringBuilder().
append(metadata.getGravityModel()).
append(": ").
append(metadata.getGravityDegree()).
append("D ").
append(metadata.getGravityOrder()).
append('O').
toString();
generator.writeEntry(CdmMetadataKey.GRAVITY_MODEL.name(), model, null, false);
}
// atmosphere
generator.writeEntry(CdmMetadataKey.ATMOSPHERIC_MODEL.name(), metadata.getAtmosphericModel(), null, false);
// N body perturbation
if (metadata.getNBodyPerturbations() != null && !metadata.getNBodyPerturbations().isEmpty()) {
final List<String> names = new ArrayList<>();
for (BodyFacade bf : metadata.getNBodyPerturbations()) {
names.add(bf.getName());
}
generator.writeEntry(CdmMetadataKey.N_BODY_PERTURBATIONS.name(), names, false);
}
// other perturbations
generator.writeEntry(CdmMetadataKey.SOLAR_RAD_PRESSURE.name(), metadata.getSolarRadiationPressure() ? YES : NO, null, false);
generator.writeEntry(CdmMetadataKey.EARTH_TIDES.name(), metadata.getEarthTides() ? YES : NO, null, false);
generator.writeEntry(CdmMetadataKey.INTRACK_THRUST.name(), metadata.getIntrackThrust() ? YES : NO, null, false);
}
}
......@@ -25,7 +25,6 @@ import org.orekit.files.ccsds.ndm.ParsedUnitsBehavior;
import org.orekit.files.ccsds.section.CommentsContainer;
import org.orekit.files.ccsds.section.KvnStructureProcessingState;
import org.orekit.files.ccsds.section.MetadataKey;
import org.orekit.files.ccsds.section.Segment;
import org.orekit.files.ccsds.section.XmlStructureProcessingState;
import org.orekit.files.ccsds.utils.ContextBinding;
import org.orekit.files.ccsds.utils.FileFormat;
......@@ -65,7 +64,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
private CdmHeader header;
/** File segments. */
private List<Segment<CdmMetadata, CdmData>> segments;
private List<CdmSegment> segments;
/** CDM metadata being read. */
private CdmMetadata metadata;
......@@ -76,7 +75,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
/** Context binding valid for current metadata. */
private ContextBinding context;
/** CDM general comments block being read. */
/** CDM general data comments block being read. */
private CommentsContainer commentsBlock;
/** CDM OD parameters logical block being read. */
......@@ -136,9 +135,9 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
addParameters = null;
stateVector = null;
covMatrix = null;
commentsBlock = null;
if (fileFormat == FileFormat.XML) {
structureProcessor = new XmlStructureProcessingState(Cdm.ROOT, this);
commentsBlock = new CommentsContainer();
reset(fileFormat, structureProcessor);
} else {
structureProcessor = new KvnStructureProcessingState(this);
......@@ -182,6 +181,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
}
metadata = new CdmMetadata();
metadata.setRelativeMetadata(relativeMetadata);
// As no time system is defined in CDM because all dates are given in UTC,
// time system is set here to UTC, we use relative metadata and not metadata
// because setting time system on metadata implies refusingfurthercomments
......@@ -216,6 +216,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
// stateVector and RTNCovariance blocks are 2 mandatory data blocks
stateVector = new StateVector();
covMatrix = new RTNCovariance();
// initialize comments block for general data comments
commentsBlock = new CommentsContainer();
anticipateNext(getFileFormat() == FileFormat.XML ? this::processXmlSubStructureToken : this::processGeneralCommentToken);
return true;
......@@ -224,7 +225,6 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
/** {@inheritDoc} */
@Override
public boolean inData() {
return true;
}
......@@ -244,9 +244,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
addParameters = null;
stateVector = null;
covMatrix = null;
if (getFileFormat() != FileFormat.XML) {
commentsBlock = null;
}
commentsBlock = null;
return true;
}
......@@ -266,6 +264,7 @@ public class CdmParser extends AbstractConstituentParser<Cdm, CdmParser> {
*/