/**
*
*/
package org.yamcs.xtce.xml;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.utils.StringConverter;
import org.yamcs.xtce.AlarmLevels;
import org.yamcs.xtce.AlarmRanges;
import org.yamcs.xtce.BinaryDataEncoding;
import org.yamcs.xtce.BinaryParameterType;
import org.yamcs.xtce.BooleanParameterType;
import org.yamcs.xtce.Calibrator;
import org.yamcs.xtce.Comparison;
import org.yamcs.xtce.ComparisonList;
import org.yamcs.xtce.ContainerEntry;
import org.yamcs.xtce.DataEncoding;
import org.yamcs.xtce.DynamicIntegerValue;
import org.yamcs.xtce.EnumeratedParameterType;
import org.yamcs.xtce.EnumerationAlarm;
import org.yamcs.xtce.FixedIntegerValue;
import org.yamcs.xtce.FloatDataEncoding;
import org.yamcs.xtce.FloatParameterType;
import org.yamcs.xtce.FloatRange;
import org.yamcs.xtce.IntegerDataEncoding;
import org.yamcs.xtce.IntegerParameterType;
import org.yamcs.xtce.IntegerValue;
import org.yamcs.xtce.MatchCriteria;
import org.yamcs.xtce.NameDescription;
import org.yamcs.xtce.NameReference;
import org.yamcs.xtce.Repeat;
import org.yamcs.xtce.UnitType;
import org.yamcs.xtce.NameReference.ResolvedAction;
import org.yamcs.xtce.NameReference.Type;
import org.yamcs.xtce.NumericAlarm;
import org.yamcs.xtce.NumericContextAlarm;
import org.yamcs.xtce.OperatorType;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.ParameterEntry;
import org.yamcs.xtce.ParameterInstanceRef;
import org.yamcs.xtce.ParameterType;
import org.yamcs.xtce.PolynomialCalibrator;
import org.yamcs.xtce.SequenceContainer;
import org.yamcs.xtce.SequenceEntry;
import org.yamcs.xtce.SpaceSystem;
import org.yamcs.xtce.SplineCalibrator;
import org.yamcs.xtce.SplinePoint;
import org.yamcs.xtce.StringDataEncoding;
import org.yamcs.xtce.StringDataEncoding.SizeType;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import org.yamcs.xtce.StringParameterType;
import org.yamcs.xtce.ValueEnumerationRange;
import org.yamcs.xtce.Header;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartDocument;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
/**
* This class reads the XTCE XML files. XML document is accessed with the use of
* the Stax Iterator API.
*
* @author mu
*
*/
public class XtceStaxReader {
// XTCE Schema defined tags, to minimize the mistyping errors
private static final String XTCE_SpaceSystem = "SpaceSystem";
private static final String XTCE_AliasSet = "AliasSet";
private static final String XTCE_Alias = "Alias";
private static final String XTCE_LongDescription = "LongDescription";
private static final String XTCE_Header = "Header";
private static final String XTCE_AuthorSet = "AuthorSet";
private static final String XTCE_NoteSet = "NoteSet";
private static final String XTCE_HistorySet = "HistorySet";
private static final String XTCE_TelemetryMetaData = "TelemetryMetaData";
private static final String XTCE_ParameterTypeSet = "ParameterTypeSet";
private static final String XTCE_BooleanParameterType = "BooleanParameterType";
private static final String XTCE_EnumeratedParameterType = "EnumeratedParameterType";
private static final String XTCE_EnumerationList = "EnumerationList";
private static final String XTCE_Enumeration = "Enumeration";
private static final String XTCE_RangeEnumeration = "RangeEnumeration";
private static final String XTCE_IntegerParameterType = "IntegerParameterType";
private static final String XTCE_StringParameterType = "StringParameterType";
private static final String XTCE_BinaryParameterType = "BinaryParameterType";
private static final String XTCE_FloatParameterType = "FloatParameterType";
private static final String XTCE_RelativeTimeParameterType = "RelativeTimeParameterType";
private static final String XTCE_AbsoluteTimeParameterType = "AbsoluteTimeParameterType";
private static final String XTCE_ArrayParameterType = "ArrayParameterType";
private static final String XTCE_AggregateParameterType = "AggregateParameterType";
private static final String XTCE_ParameterSet = "ParameterSet";
private static final String XTCE_Parameter = "Parameter";
private static final String XTCE_ParameterRef = "ParameterRef";
private static final String XTCE_ParameterProperties = "ParameterProperties";
private static final String XTCE_ValidityCondition = "ValidityCondition";
private static final String XTCE_ComparisonList = "ComparisonList";
private static final String XTCE_Comparison = "Comparison";
private static final String XTCE_BooleanExpression = "BooleanExpression";
private static final String XTCE_CustomAlgorithm = "CustomAlgorithm";
private static final String XTCE_RestrictionCriteria = "RestrictionCriteria";
private static final String XTCE_SystemName = "SystemName";
private static final String XTCE_PhysicalAddressSet = "PhysicalAddressSet";
private static final String XTCE_TimeAssociation = "TimeAssociation";
private static final String XTCE_ContainerSet = "ContainerSet";
private static final String XTCE_BaseContainer = "BaseContainer";
private static final String XTCE_MessageSet = "MessageSet";
private static final String XTCE_StreamSet = "StreamSet";
private static final String XTCE_AlgorithmSet = "AlgorithmSet";
private static final String XTCE_CommandMetaData = "CommandMetaData";
private static final String XTCE_SequenceContainer = "SequenceContainer";
private static final String XTCE_EntryList = "EntryList";
private static final String XTCE_ParameterRefEntry = "ParameterRefEntry";
private static final String XTCE_LocationInContainerInBits = "LocationInContainerInBits";
private static final String XTCE_RepeatEntry = "RepeatEntry";
private static final String XTCE_IncludeCondition = "IncludeCondition";
private static final String XTCE_ParameterSegmentRefEntry = "ParameterSegmentRefEntry";
private static final String XTCE_ContainerRefEntry = "ContainerRefEntry";
private static final String XTCE_ContainerSegmentRefEntry = "ContainerSegmentRefEntry";
private static final String XTCE_StreamSegmentEntry = "StreamSegmentEntry";
private static final String XTCE_IndirectParameterRefEntry = "IndirectParameterRefEntry";
private static final String XTCE_ArrayParameterRefEntry = "ArrayParameterRefEntry";
private static final String XTCE_UnitSet = "UnitSet";
private static final String XTCE_Unit = "Unit";
private static final String XTCE_FloatDataEncoding = "FloatDataEncoding";
private static final String XTCE_BinaryDataEncoding = "BinaryDataEncoding";
private static final String XTCE_SizeInBits = "SizeInBits";
private static final String XTCE_FixedValue = "FixedValue";
private static final String XTCE_DynamicValue = "DynamicValue";
private static final String XTCE_DiscreteLookupList = "DiscreteLookupList";
private static final String XTCE_IntegerDataEncoding = "IntegerDataEncoding";
private static final String XTCE_StringDataEncoding = "StringDataEncoding";
private static final String XTCE_ContextAlarmList = "ContextAlarmList";
private static final String XTCE_ContextAlarm = "ContextAlarm";
private static final String XTCE_ContextMatch = "ContextMatch";
private static final String XTCE_DefaultCalibrator = "DefaultCalibrator";
private static final String XTCE_ContextCalibratorList = "ContextCalibratorList";
private static final String XTCE_SplineCalibrator = "SplineCalibrator";
private static final String XTCE_PolynomialCalibrator = "PolynomialCalibrator";
private static final String XTCE_MathOperationCalibrator = "MathOperationCalibrator";
private static final String XTCE_Term = "Term";
private static final String XTCE_SplinePoint = "SplinePoint";
private static final String XTCE_Count = "Count";
private static final String XTCE_IntegerValue = "IntegerValue";
private static final String XTCE_ParameterInstanceRef = "ParameterInstanceRef";
private static final String XTCE_StaticAlarmRanges = "StaticAlarmRanges";
private static final String XTCE_DefaultAlarm = "DefaultAlarm";
private static final String XTCE_Fixed = "Fixed";
private static final String XTCE_TerminationChar = "TerminationChar";
private static final String XTCE_LeadingSize = "LeadingSize";
/**
* Logging subsystem
*/
private static Logger log = LoggerFactory.getLogger(XtceStaxReader.class);
/**
* XML Event reader
*/
private XMLEventReader xmlEventReader = null;
/**
* XML Event
*/
private XMLEvent xmlEvent = null;
/**
* Statistics about the skipped sections. (good for overview about unimplemented features)
*/
private Map<String, Integer> xtceSkipStatistics = new HashMap<String, Integer>();
private Set<String> excludedContainers = new HashSet<String>();
/**
* Constructor
*/
public XtceStaxReader() {
}
/**
* Reading of the XML XTCE file
* @param fileName
*
* @return returns the SpaceSystem read from the XML file
* @throws XMLStreamException
* @throws IOException
*
*/
public SpaceSystem readXmlDocument(String fileName) throws XMLStreamException, IOException {
xmlEventReader = initEventReader(fileName);
xmlEvent = null;
SpaceSystem spaceSystem = null;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
int eventType = xmlEvent.getEventType();
if (eventType == XMLStreamConstants.COMMENT) {
continue;
}
if (eventType == XMLStreamConstants.START_DOCUMENT) {
onStartDocument((StartDocument) xmlEvent);
} else if (eventType == XMLStreamConstants.START_ELEMENT) {
spaceSystem = readSpaceSystem();
} else if (eventType == XMLStreamConstants.END_DOCUMENT) {
onEndDocument();
break;
} else if (isStartElementWithName(XTCE_SpaceSystem)) {
SpaceSystem ss = readSpaceSystem();
spaceSystem.addSpaceSystem(ss);
} else {
// something went wrong, all options should be handled by the
// upper if-branches
// log.error("XML document parser error, unhandled event type."
// + XMLStreamConstants.CHARACTERS);
// throw new IllegalStateException();
log.error("Unhandled event: {} ", xmlEvent);
}
if (xmlEventReader.peek() == null) {
// assert false; document must be closed gracefully
this.xmlEvent = null;
this.xmlEventReader.close();
this.xmlEventReader = null;
throw new IllegalStateException("XML file parsing error");
}
}
log.info("XTCE file parsing finished successfully");
return spaceSystem;
}
/**
* Method called on start document event. Currently just logs the
* information contained in the xml preamble of the parsed file.
*
* @param start
* Start document event object
*/
private void onStartDocument(StartDocument start) {
log.trace("XML version=\"" + start.getVersion() + "\" encoding: \""
+ start.getCharacterEncodingScheme() + "\"");
}
/**
* Start of reading at the root of the document. According to the XTCE
* schema the root element is <SpaceSystem>
*
* @throws XMLStreamException
*/
private SpaceSystem readSpaceSystem() throws XMLStreamException {
checkStartElementPreconditions();
String value = readAttribute("name", xmlEvent.asStartElement());
SpaceSystem spaceSystem = new SpaceSystem(value);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_AliasSet)) {
XtceAliasSet aliasSet=readXtceAliasSet();
spaceSystem.setAliasSet(aliasSet);
} else if (isStartElementWithName(XTCE_Header)) {
readXtceHeader(spaceSystem);
} else if (isStartElementWithName(XTCE_TelemetryMetaData)) {
readXtceTelemetryMetaData(spaceSystem);
} else if (isStartElementWithName(XTCE_CommandMetaData)) {
readXtceCommandMetaData(spaceSystem);
} else if (isStartElementWithName(XTCE_SpaceSystem)) {
SpaceSystem ss= readSpaceSystem();
spaceSystem.addSpaceSystem(ss);
} else if (isEndElementWithName(XTCE_SpaceSystem)) {
return spaceSystem;
}
}
}
/**
* Action taken on end of the document event
*/
private void onEndDocument() {
try {
log.trace("End of XML document");
if (xmlEventReader != null) {
xmlEventReader.close();
}
} catch (XMLStreamException e) {
// exception thrown by the close method
e.printStackTrace();
} finally {
xmlEventReader = null;
}
}
/**
* Extraction of the AliasSet section Current implementation does nothing,
* just skips whole section
*
* @return Set of aliases defined for the object
* @throws XMLStreamException
*/
private XtceAliasSet readXtceAliasSet() throws XMLStreamException {
log.trace(XTCE_AliasSet);
checkStartElementPreconditions();
XtceAliasSet xtceAliasSet = new XtceAliasSet();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
// <Alias> sections
if (isStartElementWithName(XTCE_Alias)) {
readXtceAlias(xtceAliasSet);
} else if (isEndElementWithName(XTCE_AliasSet)) {
return xtceAliasSet;
}
}
}
/**
* Extraction of the AliasSet section Current implementation does nothing,
* just skips whole section
*
* @throws XMLStreamException
*/
private void readXtceAlias(XtceAliasSet aliasSet) throws XMLStreamException {
log.trace(XTCE_Alias);
checkStartElementPreconditions();
String nameSpace = readAttribute("nameSpace", xmlEvent.asStartElement());
if (nameSpace == null) {
throw new XMLStreamException("Namespace attribute is missing");
}
nameSpace = nameSpace.intern();
String alias = readAttribute("alias", xmlEvent.asStartElement());
if (alias == null) {
throw new XMLStreamException("Alias attribute is missing");
}
aliasSet.addAlias(nameSpace, alias);
// read end element
xmlEvent = xmlEventReader.nextEvent();
if (!isEndElementWithName(XTCE_Alias)) {
throw new IllegalStateException(XTCE_Alias + " end element expected");
}
}
/**
* Extraction of the Header section Current implementation does nothing,
* just skips whole section
* @param spaceSystem
*
* @throws XMLStreamException
*/
private void readXtceHeader(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_Header);
checkStartElementPreconditions();
Header h=new Header();
String value = readAttribute("version", xmlEvent.asStartElement());
h.setVersion(value);
value = readAttribute("date", xmlEvent.asStartElement());
h.setDate(value);
spaceSystem.setHeader(h);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_AuthorSet)) {
skipXtceSection(XTCE_AuthorSet);
} else if (isStartElementWithName(XTCE_NoteSet)) {
skipXtceSection(XTCE_NoteSet);
} else if (isStartElementWithName(XTCE_HistorySet)) {
skipXtceSection(XTCE_HistorySet);
} else if (isEndElementWithName(XTCE_Header)) {
return;
}
}
}
/**
* Extraction of the TelemetryMetaData section Current implementation does
* nothing, just skips whole section
* @param spaceSystem
*
* @throws XMLStreamException
*/
private void readXtceTelemetryMetaData(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_TelemetryMetaData);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_ParameterTypeSet)) {
readXtceParameterTypeSet(spaceSystem);
} else if (isStartElementWithName(XTCE_ParameterSet)) {
readXtceParameterSet(spaceSystem);
} else if (isStartElementWithName(XTCE_ContainerSet)) {
readXtceContainerSet(spaceSystem); // the result is created by access to
// member variable
} else if (isStartElementWithName(XTCE_MessageSet)) {
readXtceMessageSet();
} else if (isStartElementWithName(XTCE_StreamSet)) {
readXtceStreamSet();
} else if (isStartElementWithName(XTCE_AlgorithmSet)) {
readXtceAlgorithmSet(spaceSystem);
} else if (isEndElementWithName(XTCE_TelemetryMetaData)) {
return;
}
}
}
/**
* @param spaceSystem
* @throws XMLStreamException
*/
private void readXtceParameterTypeSet(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ParameterTypeSet);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
ParameterType parameterType = null;
if (isStartElementWithName(XTCE_BooleanParameterType)) {
parameterType = readXtceBooleanParameterType();
} else if (isStartElementWithName(XTCE_EnumeratedParameterType)) {
parameterType = readXtceEnumeratedParameterType();
} else if (isStartElementWithName(XTCE_FloatParameterType)) {
parameterType = readXtceFloatParameterType(spaceSystem);
} else if (isStartElementWithName(XTCE_IntegerParameterType)) {
parameterType = readXtceIntegerParameterType(spaceSystem);
} else if (isStartElementWithName(XTCE_BinaryParameterType)) {
parameterType = readXtceBinaryParameterType(spaceSystem);
} else if (isStartElementWithName(XTCE_StringParameterType)) {
parameterType = readXtceStringParameterType(spaceSystem);
} else if (isStartElementWithName(XTCE_RelativeTimeParameterType)) {
parameterType = readXtceRelativeTimeParameterType();
} else if (isStartElementWithName(XTCE_AbsoluteTimeParameterType)) {
parameterType = readXtceAbsoluteTimeParameterType();
} else if (isStartElementWithName(XTCE_ArrayParameterType)) {
parameterType = readXtceArrayParameterType();
} else if (isStartElementWithName(XTCE_AggregateParameterType)) {
parameterType = readXtceAggregateParameterType();
}
if (parameterType != null) {
spaceSystem.addParameterType(parameterType);
}
if (isEndElementWithName(XTCE_ParameterTypeSet)) {
return;
}
}
}
private BooleanParameterType readXtceBooleanParameterType() throws IllegalStateException, XMLStreamException {
log.trace(XTCE_BooleanParameterType);
checkStartElementPreconditions();
// name attribute
BooleanParameterType boolParamType = null;
String name = readAttribute("name", xmlEvent.asStartElement());
if (name != null) {
boolParamType = new BooleanParameterType(name);
} else {
throw new XMLStreamException("Unnamed boolean parameter type");
}
// read all parameters
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
boolParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_IntegerDataEncoding)) {
boolParamType.setEncoding(readXtceIntegerDataEncoding());
} else if (isEndElementWithName(XTCE_BooleanParameterType)) {
return boolParamType;
}
}
}
private ParameterType readXtceAggregateParameterType() throws IllegalStateException,
XMLStreamException {
skipXtceSection(XTCE_AggregateParameterType);
return null;
}
private ParameterType readXtceArrayParameterType() throws IllegalStateException,
XMLStreamException {
skipXtceSection(XTCE_ArrayParameterType);
return null;
}
private ParameterType readXtceAbsoluteTimeParameterType() throws IllegalStateException,
XMLStreamException {
skipXtceSection(XTCE_AbsoluteTimeParameterType);
return null;
}
private ParameterType readXtceRelativeTimeParameterType() throws IllegalStateException,
XMLStreamException {
skipXtceSection(XTCE_RelativeTimeParameterType);
return null;
}
private FloatParameterType readXtceFloatParameterType(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
FloatParameterType floatParamType = null;
log.trace(XTCE_FloatParameterType);
checkStartElementPreconditions();
// name attribute
String value = readAttribute("name", xmlEvent.asStartElement());
if (value != null) {
floatParamType = new FloatParameterType(value);
} else {
throw new XMLStreamException("Unnamed float parameter type");
}
value = readAttribute("sizeInBits", xmlEvent.asStartElement());
if (value != null) {
int sizeInBits = Integer.parseInt(value);
if(sizeInBits!=32 && sizeInBits!=64){
throw new XMLStreamException("Float encoding "+sizeInBits+" not supported; Only 32 and 64 bits are supported");
}
floatParamType.setSizeInBits(sizeInBits);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
floatParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_IntegerDataEncoding)) {
floatParamType.setEncoding(readXtceIntegerDataEncoding());
} else if (isStartElementWithName(XTCE_FloatDataEncoding)) {
floatParamType.setEncoding(readXtceFloatDataEncoding());
} else if (isStartElementWithName(XTCE_DefaultAlarm)) {
floatParamType.setDefaultAlarm(readDefaultAlarm());
} else if (isStartElementWithName(XTCE_ContextAlarmList)) {
floatParamType.setContextAlarmList(readNumericContextAlarmList(spaceSystem));
} else if (isEndElementWithName(XTCE_FloatParameterType)) {
return floatParamType;
}
}
}
private FloatDataEncoding readXtceFloatDataEncoding() throws XMLStreamException {
log.trace(XTCE_FloatDataEncoding);
checkStartElementPreconditions();
FloatDataEncoding floatDataEncoding = null;
String name = "";
// sizeInBits attribute
String value = readAttribute("sizeInBits", xmlEvent.asStartElement());
if (value != null) {
floatDataEncoding = new FloatDataEncoding(Integer.parseInt(value));
} else {
// default value is 32
floatDataEncoding = new FloatDataEncoding(32);
}
// encoding attribute
value = readAttribute("encoding", xmlEvent.asStartElement());
if (value != null) {
if ("IEEE754_1985".equalsIgnoreCase(value)) {
// ok, this encoding is supported by the class implicitly
} else if ("MILSTD_1750A".equalsIgnoreCase(value)) {
log.error("Encoding MILSTD_1750A is not currently supported.");
throw new XMLStreamException("Encoding MILSTD_1750A is not currently supported.");
} else {
throw new XMLStreamException();
}
} else {
// default is IEEE754_1985
// this encoding is supported by the class implicitly
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_DefaultCalibrator)) {
floatDataEncoding.setDefaultCalibrator(readDefaultCalibrator());
} else if (isStartElementWithName(XTCE_ContextCalibratorList)) {
skipXtceSection(XTCE_ContextCalibratorList);
} else if (isEndElementWithName(XTCE_FloatDataEncoding)) {
return floatDataEncoding;
}
}
}
private List<NumericContextAlarm> readNumericContextAlarmList(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_ContextAlarmList);
List<NumericContextAlarm> contextAlarmList = new ArrayList<NumericContextAlarm>();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_ContextAlarm)) {
contextAlarmList.add(readNumericContextAlarm(spaceSystem));
} else if (isEndElementWithName(XTCE_ContextAlarmList)) {
return contextAlarmList;
}
}
}
private NumericAlarm readDefaultAlarm() throws XMLStreamException {
NumericAlarm na = new NumericAlarm();
readAlarmAttributes(na);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_DefaultAlarm)) {
return na;
} else if(xmlEvent.getEventType() == XMLStreamConstants.START_ELEMENT){
readNumericAlarmElement(na);
}
}
}
private NumericContextAlarm readNumericContextAlarm(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ContextAlarm);
NumericContextAlarm nca = new NumericContextAlarm();
readAlarmAttributes(nca);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_ContextMatch)) {
nca.setContextMatch(readMatchCriteria(spaceSystem));
} else if (isEndElementWithName(XTCE_ContextAlarm)) {
return nca;
} else if(xmlEvent.getEventType() == XMLStreamConstants.START_ELEMENT){
readNumericAlarmElement(nca);
}
}
}
private void readNumericAlarmElement(NumericAlarm numericAlarm) throws XMLStreamException {
if (isStartElementWithName(XTCE_StaticAlarmRanges)) {
numericAlarm.setStaticAlarmRanges(readAlarmRanges());
}
}
private AlarmRanges readAlarmRanges() throws XMLStreamException {
String tag = xmlEvent.asStartElement().getName().getLocalPart();
AlarmRanges ar = new AlarmRanges();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName("WatchRange")) {
ar.addWatchRange(readFloatRange());
} else if (isStartElementWithName("WarningRange")) {
ar.addWarningRange(readFloatRange());
} else if (isStartElementWithName("DistressRange")) {
ar.addDistressRange(readFloatRange());
} else if (isStartElementWithName("CriticalRange")) {
ar.addCriticalRange(readFloatRange());
} else if (isStartElementWithName("SevereRange")) {
ar.addSevereRange(readFloatRange());
} else if (isEndElementWithName(tag)) {
return ar;
}
}
}
private FloatRange readFloatRange() {
StartElement e = xmlEvent.asStartElement();
double minInclusive = Double.MIN_VALUE;
double maxInclusive = Double.MAX_VALUE;
String value = readAttribute("minInclusive", e);
if (value != null) {
minInclusive = Double.parseDouble(value);
}
value = readAttribute("maxInclusive", e);
if (value != null) {
maxInclusive = Double.parseDouble(value);
}
return new FloatRange(minInclusive, maxInclusive);
}
private void readAlarmAttributes(NumericAlarm numericAlarm) {
String value = readAttribute("minViolations", xmlEvent.asStartElement());
if (value != null) {
int minViolations = Integer.parseInt(value);
numericAlarm.setMinViolations(minViolations);
}
}
private BinaryParameterType readXtceBinaryParameterType(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_BinaryParameterType);
checkStartElementPreconditions();
// name attribute
BinaryParameterType binaryParamType = null;
String name = readAttribute("name", xmlEvent.asStartElement());
if (name != null) {
binaryParamType = new BinaryParameterType(name);
} else {
throw new XMLStreamException("Unnamed binary parameter type");
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
binaryParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_IntegerDataEncoding)) {
binaryParamType.setEncoding(readXtceIntegerDataEncoding());
} else if (isStartElementWithName(XTCE_BinaryDataEncoding)) {
binaryParamType.setEncoding(readXtceBinaryDataEncoding(spaceSystem));
} else if (isEndElementWithName(XTCE_BinaryParameterType)) {
return binaryParamType;
}
}
}
private DataEncoding readXtceBinaryDataEncoding(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_BinaryDataEncoding);
checkStartElementPreconditions();
BinaryDataEncoding binaryDataEncoding = null;
String name = "";
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_SizeInBits)) {
IntegerValue v = readXtceIntegerValue(spaceSystem);
if(v instanceof FixedIntegerValue) {
binaryDataEncoding = new BinaryDataEncoding(name, (int)((FixedIntegerValue) v).getValue());
} else {
throwException("Only FixedIntegerValue supported for sizeInBits");
}
} else if (isStartElementWithName("FromBinaryTransformAlgorithm")) {
skipXtceSection("FromBinaryTransformAlgorithm");
} else if (isStartElementWithName("ToBinaryTransformAlgorithm")) {
skipXtceSection("ToBinaryTransformAlgorithm");
} else if (isEndElementWithName(XTCE_BinaryDataEncoding)) {
return binaryDataEncoding;
}
}
}
private void throwException(String msg) throws XMLStreamException {
throw new XMLStreamException(msg+" at "+xmlEvent.getLocation().getLineNumber()+": "+xmlEvent.getLocation().getColumnNumber());
}
private int readIntegerValue() throws XMLStreamException {
checkStartElementPreconditions();
String tag = xmlEvent.asStartElement().getName().getLocalPart();
int sizeInBits = 0;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (xmlEvent.isCharacters()) {
sizeInBits = getIntegerCharacter();
} else if (isEndElementWithName(tag)) {
return sizeInBits;
}
}
}
int getIntegerCharacter() throws XMLStreamException {
if (xmlEvent.isCharacters()) {
String value = xmlEvent.asCharacters().getData();
try {
return Integer.parseInt(value);
} catch(NumberFormatException e) {
throw new XMLStreamException("Cannot parse integer '"+value+"' at "+xmlEvent.getLocation().getLineNumber()+":"+xmlEvent.getLocation().getColumnNumber());
}
} else {
throw new IllegalStateException();
}
}
private StringParameterType readXtceStringParameterType(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_IntegerParameterType);
checkStartElementPreconditions();
StringParameterType stringParamType = null;
// name attribute
String value = readAttribute("name", xmlEvent.asStartElement());
if (value != null) {
stringParamType = new StringParameterType(value);
} else {
throw new XMLStreamException("Unnamed string parameter type");
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
stringParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_StringDataEncoding)) {
stringParamType.setEncoding(readXtceStringDataEncoding(spaceSystem));
} else if (isStartElementWithName(XTCE_ContextAlarmList)) {
skipXtceSection(XTCE_ContextAlarmList);
} else if (isEndElementWithName(XTCE_StringParameterType)) {
return stringParamType;
}
}
}
private StringDataEncoding readXtceStringDataEncoding(SpaceSystem spaceSystem) throws XMLStreamException {
checkStartElementPreconditions();
StringDataEncoding stringDataEncoding = new StringDataEncoding();;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_SizeInBits)) {
readStringSizeInBits(spaceSystem, stringDataEncoding);
} else if (isEndElementWithName(XTCE_StringDataEncoding)) {
return stringDataEncoding;
}
}
}
private void readStringSizeInBits(SpaceSystem spaceSystem, StringDataEncoding stringDataEncoding) throws XMLStreamException {
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Fixed)) {
IntegerValue v = readXtceIntegerValue(spaceSystem);
if(v instanceof FixedIntegerValue) {
stringDataEncoding.setSizeType(SizeType.Fixed);
stringDataEncoding.setSizeInBits((int)((FixedIntegerValue) v).getValue());
} else {
throwException("Only FixedValue supported for string size in bits");
}
} else if (isStartElementWithName(XTCE_TerminationChar)) {
stringDataEncoding.setSizeType(SizeType.TerminationChar);
byte[] x = readHexBinary();
if(x==null || x.length!=1) {
throw new XMLStreamException("Terminated strings have to have the size of the termination character of 1");
}
stringDataEncoding.setTerminationChar(x[0]);
} else if (isStartElementWithName(XTCE_LeadingSize)) {
stringDataEncoding.setSizeType(SizeType.LeadingSize);
String value = readAttribute("sizeInBitsOfSizeTag", xmlEvent.asStartElement());
stringDataEncoding.setSizeInBitsOfSizeTag(Integer.valueOf(value));
} else if (isEndElementWithName(XTCE_SizeInBits)) {
return;
}
}
}
private byte[] readHexBinary() throws XMLStreamException {
checkStartElementPreconditions();
String tag = xmlEvent.asStartElement().getName().getLocalPart();
byte[] b=null;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (xmlEvent.isCharacters()) {
b = StringConverter.hexStringToArray(xmlEvent.asCharacters().getData());
} else if (isEndElementWithName(tag)) {
return b;
}
}
}
private IntegerParameterType readXtceIntegerParameterType(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
IntegerParameterType integerParamType;
log.trace(XTCE_IntegerParameterType);
checkStartElementPreconditions();
// name attribute
String value = readAttribute("name", xmlEvent.asStartElement());
if (value != null) {
integerParamType = new IntegerParameterType(value);
} else {
throw new XMLStreamException("Unnamed integer parameter type");
}
value = readAttribute("sizeInBits", xmlEvent.asStartElement());
if (value != null) {
int sizeInBits = Integer.parseInt(value);
integerParamType.setSizeInBits(sizeInBits);
}
value = readAttribute("signed", xmlEvent.asStartElement());
if (value != null) {
boolean signed = Boolean.parseBoolean(value);
integerParamType. setSigned(signed);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
integerParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_IntegerDataEncoding)) {
integerParamType.setEncoding(readXtceIntegerDataEncoding());
} else if (isStartElementWithName(XTCE_ContextAlarmList)) {
integerParamType.setContextAlarmList(readNumericContextAlarmList(spaceSystem));
} else if (isEndElementWithName(XTCE_IntegerParameterType)) {
return integerParamType;
}
}
}
private IntegerDataEncoding readXtceIntegerDataEncoding() throws IllegalStateException,
XMLStreamException {
log.trace(XTCE_IntegerDataEncoding);
checkStartElementPreconditions();
IntegerDataEncoding integerDataEncoding = null;
String name = "";
// sizeInBits attribute
String value = readAttribute("sizeInBits", xmlEvent.asStartElement());
if (value != null) {
integerDataEncoding = new IntegerDataEncoding(Integer.parseInt(value));
} else {
// default value is 8
integerDataEncoding = new IntegerDataEncoding(8);
}
// encoding attribute
value = readAttribute("encoding", xmlEvent.asStartElement());
if (value != null) {
if ("unsigned".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.unsigned);
} else if ("signMagnitude".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.signMagnitude);
} else if ("twosComplement".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.twosComplement);
} else if ("onesComplement".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.onesComplement);
} else if ("BCD".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.BCD);
} else if ("packedBCD".equalsIgnoreCase(value)) {
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.packedBCD);
} else if ("twosCompliment".equalsIgnoreCase(value)) { //this is for compatibility with CD-MCS/CGS SCOE XML exporter
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.twosComplement);
} else {
throwException("Unsupported encoding '"+value+"'");
}
} else {
// default is unsigned
integerDataEncoding.setEncoding(IntegerDataEncoding.Encoding.unsigned);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_DefaultCalibrator)) {
integerDataEncoding.setDefaultCalibrator(readDefaultCalibrator());
} else if (isStartElementWithName(XTCE_ContextCalibratorList)) {
skipXtceSection(XTCE_ContextCalibratorList);
} else if (isEndElementWithName(XTCE_IntegerDataEncoding)) {
return integerDataEncoding;
}
}
}
private Calibrator readDefaultCalibrator() throws IllegalStateException, XMLStreamException {
log.trace(XTCE_DefaultCalibrator);
checkStartElementPreconditions();
Calibrator calibrator = null;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_PolynomialCalibrator)) {
calibrator = readXtcePolynomialCalibrator();
} else if (isStartElementWithName(XTCE_MathOperationCalibrator)) {
skipXtceSection(XTCE_MathOperationCalibrator);
} else if (isStartElementWithName(XTCE_SplineCalibrator)) {
calibrator = readXtceSplineCalibrator();
} else if (isEndElementWithName(XTCE_DefaultCalibrator)) {
return calibrator;
}
}
}
/**
* Instantiate the SplineCalibrator element.
* @return
* @throws XMLStreamException
*/
private Calibrator readXtceSplineCalibrator() throws XMLStreamException {
log.trace(XTCE_SplineCalibrator);
checkStartElementPreconditions();
ArrayList<SplinePoint> splinePoints = new ArrayList<SplinePoint>();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_SplinePoint)) {
splinePoints.add(readXtceSplinePoint());
} else if (isEndElementWithName(XTCE_SplineCalibrator)) {
return new SplineCalibrator(splinePoints);
}
}
}
/**
* Instantiate SplinePoint element.
* This element has two required attributes: raw, calibrated
* @return
* @throws XMLStreamException
*/
private SplinePoint readXtceSplinePoint() throws XMLStreamException {
log.trace(XTCE_SplinePoint);
checkStartElementPreconditions();
double raw = 0.0d;
double calibrated = 0.0d;
String attributeValue = readAttribute("raw", xmlEvent.asStartElement());
if (attributeValue != null) {
raw = Double.parseDouble(attributeValue);
} else {
throw new XMLStreamException();
}
attributeValue = readAttribute("calibrated", xmlEvent.asStartElement());
if (attributeValue != null) {
calibrated = Double.parseDouble(attributeValue);
} else {
throw new XMLStreamException();
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_SplinePoint)) {
return new SplinePoint(raw, calibrated);
}
}
}
private Calibrator readXtcePolynomialCalibrator() throws XMLStreamException {
log.trace(XTCE_PolynomialCalibrator);
checkStartElementPreconditions();
int maxExponent = 0;
HashMap<Integer, Double> polynome = new HashMap<Integer, Double>();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Term)) {
XtceTerm term = readXtceTerm();
if (term.getExponent() > maxExponent) {
maxExponent = term.getExponent();
}
polynome.put(term.getExponent(), term.getCoefficient());
} else if (isEndElementWithName(XTCE_PolynomialCalibrator)) {
double[] coefficients = new double[maxExponent + 1];
for (Map.Entry<Integer, Double> entry:polynome.entrySet()) {
coefficients[entry.getKey()] = entry.getValue();
}
return new PolynomialCalibrator(coefficients);
}
}
}
private XtceTerm readXtceTerm() throws XMLStreamException {
log.trace(XTCE_Term);
checkStartElementPreconditions();
int exponent = 0;
double coefficient = 0.0;
String value = readAttribute("coefficient", xmlEvent.asStartElement());
if (value != null) {
coefficient = Double.parseDouble(value);
} else {
throw new XMLStreamException();
}
value = readAttribute("exponent", xmlEvent.asStartElement());
if (value != null) {
exponent = (int) Double.parseDouble(value);
} else {
throw new XMLStreamException();
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_Term)) {
return new XtceTerm(exponent, coefficient);
}
}
}
private List<UnitType> readXtceUnitSet() throws IllegalStateException, XMLStreamException {
log.trace(XTCE_UnitSet);
List<UnitType> units = new ArrayList<UnitType>();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Unit)) {
UnitType u = readXtceUnit();
units.add(u);
} else if (isEndElementWithName(XTCE_UnitSet)) {
return units;
}
}
}
private UnitType readXtceUnit() throws XMLStreamException {
log.trace(XTCE_Unit);
checkStartElementPreconditions();
StartElement element = xmlEvent.asStartElement();
String powerValue = readAttribute("power", element);
String factorValue = readAttribute("factor", element);
String descriptionValue = readAttribute("description", element);
String unit;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (xmlEvent.isCharacters()) {
unit = xmlEvent.asCharacters().getData();
break;
} else if (isEndElementWithName(XTCE_Unit)) {
return null;
}
}
UnitType unitType = new UnitType(unit);
if ( powerValue != null ) {
unitType.setPower( Double.parseDouble(powerValue));
}
if ( factorValue != null ) {
unitType.setFactor( factorValue );
}
if ( descriptionValue != null ) {
unitType.setDescription( descriptionValue );
}
return unitType;
}
private EnumeratedParameterType readXtceEnumeratedParameterType() throws IllegalStateException, XMLStreamException {
EnumeratedParameterType enumParamType = null;
log.trace(XTCE_EnumeratedParameterType);
checkStartElementPreconditions();
// name attribute
String value = readAttribute("name", xmlEvent.asStartElement());
if (value != null) {
enumParamType = new EnumeratedParameterType(value);
} else {
throw new XMLStreamException();
}
// defaultValue attribute
value = readAttribute("defaultValue", xmlEvent.asStartElement());
if (value != null) {
enumParamType.setInitialValue(value);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_UnitSet)) {
enumParamType.addAllUnits(readXtceUnitSet());
} else if (isStartElementWithName(XTCE_IntegerDataEncoding)) {
enumParamType.setEncoding(readXtceIntegerDataEncoding());
} else if (isStartElementWithName(XTCE_EnumerationList)) {
readXtceEnumerationList(enumParamType);
} else if (isStartElementWithName(XTCE_DefaultAlarm)) {
enumParamType.setDefaultAlarm(readXtceEnumerationAlarm(enumParamType));
} else if (isEndElementWithName(XTCE_EnumeratedParameterType)) {
return enumParamType;
}
}
}
private void readXtceEnumerationList(EnumeratedParameterType enumParamType) throws XMLStreamException {
log.trace(XTCE_EnumerationList);
checkStartElementPreconditions();
// initialValue attribute
String initialValue = readAttribute("initialValue", xmlEvent.asStartElement());
if (initialValue != null) {
enumParamType.setInitialValue(initialValue);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Enumeration)) {
readXtceEnumeration(enumParamType);
} else if (isStartElementWithName(XTCE_RangeEnumeration)) {
enumParamType.addEnumerationRange(readXtceRangeEnumeration());
} else if (isEndElementWithName(XTCE_EnumerationList)) {
return;
}
}
}
private EnumerationAlarm readXtceEnumerationAlarm(EnumeratedParameterType enumParamType) throws XMLStreamException {
checkStartElementPreconditions();
String tag = xmlEvent.asStartElement().getName().getLocalPart();
EnumerationAlarm alarm = new EnumerationAlarm();
// initialValue attribute
String v = readAttribute("minViolations", xmlEvent.asStartElement());
if (v != null) {
alarm.setMinViolations(Integer.parseInt(v));
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName("EnumerationAlarm")) {
String label = readAttribute("enumerationLabel", xmlEvent.asStartElement());
if(!enumParamType.hasLabel(label)) {
throw new XMLStreamException("Reference to invalid enumeration label '"+label+"'");
}
AlarmLevels level = getAlarmLevel(readAttribute("alarmLevel", xmlEvent.asStartElement()));
alarm.addAlarm(label, level);
} else if (isEndElementWithName(tag)) {
return alarm;
}
}
}
private AlarmLevels getAlarmLevel(String l) throws XMLStreamException {
try {
return AlarmLevels.valueOf(l.toLowerCase());
} catch (IllegalArgumentException e) {
throw new XMLStreamException("Invalid alarm level '"+l+"'; use one of: "+Arrays.toString(AlarmLevels.values()));
}
}
private ValueEnumerationRange readXtceRangeEnumeration() throws XMLStreamException {
log.trace(XTCE_RangeEnumeration);
checkStartElementPreconditions();
boolean isMinInclusive = true;
boolean isMaxInclusive = true;
double min = 0.0;
double max = 0.0;
String value = readAttribute("maxInclusive", xmlEvent.asStartElement());
if (value != null) {
max = Double.parseDouble(value);
isMaxInclusive = true;
}
value = readAttribute("minInclusive", xmlEvent.asStartElement());
if (value != null) {
isMinInclusive = true;
min = Double.parseDouble(value);
}
value = readAttribute("maxExclusive", xmlEvent.asStartElement());
if (value != null) {
max = Double.parseDouble(value);
isMaxInclusive = false;
}
value = readAttribute("minExclusive", xmlEvent.asStartElement());
if (value != null) {
isMinInclusive = false;
min = Double.parseDouble(value);
}
value = readAttribute("label", xmlEvent.asStartElement());
if (value == null) {
log.error("Attribute label is missing.");
value = "UNDEF";
}
ValueEnumerationRange range = new ValueEnumerationRange(min, max, isMinInclusive,
isMaxInclusive, value);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_RangeEnumeration)) {
return range;
}
}
}
private void readXtceEnumeration(EnumeratedParameterType enumParamType)
throws XMLStreamException {
log.trace(XTCE_Enumeration);
checkStartElementPreconditions();
long longValue = 0;
String value = readAttribute("value", xmlEvent.asStartElement());
if (value != null) {
longValue = Long.parseLong(value);
} else {
throw new XMLStreamException();
}
value = readAttribute("label", xmlEvent.asStartElement());
if (value == null) {
throw new XMLStreamException();
}
enumParamType.addEnumerationValue(longValue, value);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_Enumeration)) {
return;
}
}
}
/**
* @param spaceSystem
* @todo Must be implemented to be able to read current XTCE files
*/
private void readXtceParameterSet(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_ParameterSet);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Parameter)) {
readXtceParameter(spaceSystem); // the parameter is registered inside
} else if (isStartElementWithName(XTCE_ParameterRef)) {
readXtceParameterRef();
} else if (isEndElementWithName(XTCE_ParameterSet)) {
return;
}
}
}
/**
* @todo
* @return
* @throws IllegalStateException
* @throws XMLStreamException
*/
private XtceNotImplemented readXtceParameterRef() throws IllegalStateException, XMLStreamException {
skipXtceSection(XTCE_ParameterRef);
return null;
}
/**
*
* @return Parameter instance
* @throws IllegalStateException
* @throws XMLStreamException
*/
private Parameter readXtceParameter(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_Parameter);
checkStartElementPreconditions();
Parameter parameter = null;
// name
StartElement element = xmlEvent.asStartElement();
String value = readAttribute("name", element);
if (value != null) {
parameter = new Parameter(value);
} else {
throw new XMLStreamException("Missing name for the parameter");
}
// parameterTypeRef
value = readAttribute("parameterTypeRef", element);
if (value != null) {
ParameterType ptype = spaceSystem.getParameterType(value);
if(ptype!=null) {
parameter.setParameterType(ptype);
} else {
final Parameter p=parameter;
NameReference nr=new NameReference(value, Type.PARAMETER_TYPE,
new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
p.setParameterType((ParameterType) nd);
return true;
}
});
spaceSystem.addUnresolvedReference(nr);
}
} else {
throw new XMLStreamException("Cannot find parameterTypeRef in element: "+element);
}
// shortDescription
value = readAttribute("shortDescription", element);
parameter.setShortDescription(value);
// register the parameter now, because parameter can refer to
// self in the parameter properties
spaceSystem.addParameter(parameter);
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_AliasSet)) {
parameter.setAliasSet(readXtceAliasSet());
} else if (isStartElementWithName(XTCE_ParameterProperties)) {
readXtceParameterProperties(spaceSystem);
} else if (isStartElementWithName(XTCE_LongDescription)) {
parameter.setLongDescription(readXtceLongDescription(spaceSystem));
} else if (isEndElementWithName(XTCE_Parameter)) {
return parameter;
}
}
}
private XtceParameterProperties readXtceParameterProperties(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ParameterProperties);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
//MatchCriteria criteria = null;
if (isStartElementWithName(XTCE_ValidityCondition)) {
readMatchCriteria(spaceSystem);
} else if (isStartElementWithName(XTCE_PhysicalAddressSet)) {
skipXtceSection(XTCE_PhysicalAddressSet);
} else if (isStartElementWithName(XTCE_SystemName)) {
skipXtceSection(XTCE_SystemName);
} else if (isStartElementWithName(XTCE_TimeAssociation)) {
skipXtceSection(XTCE_TimeAssociation);
} else if (isEndElementWithName(XTCE_ParameterProperties)) {
return null;
}
}
}
private String readXtceLongDescription(SpaceSystem spaceSystem) throws XMLStreamException {
checkStartElementPreconditions();
StringBuilder longDescr = new StringBuilder();
while(true) {
xmlEvent = xmlEventReader.nextEvent();
if(isEndElementWithName(XTCE_LongDescription)) {
break;
}
if(!xmlEvent.isCharacters()) {
throw new IllegalStateException(XTCE_LongDescription + " characters or end element expected but instead got "+xmlEvent);
}
longDescr.append(xmlEvent.asCharacters().getData());
}
return longDescr.toString();
}
private MatchCriteria readMatchCriteria(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace("MatchCriteria");
checkStartElementPreconditions();
String tag = xmlEvent.asStartElement().getName().getLocalPart();
MatchCriteria criteria = null;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Comparison)) {
criteria = readXtceComparison(spaceSystem);
} else if (isStartElementWithName(XTCE_ComparisonList)) {
criteria = readXtceComparisonList(spaceSystem);
} else if (isStartElementWithName(XTCE_BooleanExpression)) {
skipXtceSection(XTCE_BooleanExpression);
} else if (isStartElementWithName(XTCE_CustomAlgorithm)) {
skipXtceSection(XTCE_CustomAlgorithm);
} else if (isEndElementWithName(tag)) {
return criteria;
}
}
}
private ComparisonList readXtceComparisonList(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ComparisonList);
checkStartElementPreconditions();
ComparisonList list = new ComparisonList();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Comparison)) {
list.addComparison(readXtceComparison(spaceSystem));
} else if (isEndElementWithName(XTCE_ComparisonList)) {
return list;
}
}
}
/**
* Reads the definition of the containers
* @param spaceSystem
*
* @todo Must be implemented to be able to read current XTCE files
* @return
* @throws IllegalStateException
* @throws XMLStreamException
*/
private void readXtceContainerSet(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_ContainerSet);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_SequenceContainer)) {
SequenceContainer sc = readXtceSequenceContainer(spaceSystem);
if(excludedContainers.contains(sc.getName())) {
log.debug("Not adding '"+sc.getName()+"' to the SpaceSystem because excluded by configuration");
} else {
spaceSystem.addSequenceContainer(sc);
}
if((sc.getBaseContainer()==null) && (spaceSystem.getRootSequenceContainer()==null)) {
spaceSystem.setRootSequenceContainer(sc);
}
} else if (isEndElementWithName(XTCE_ContainerSet)) {
return;
}
}
}
private SequenceContainer readXtceSequenceContainer(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_SequenceContainer);
checkStartElementPreconditions();
SequenceContainer seqContainer = null;
String value = readAttribute("name", xmlEvent.asStartElement());
if (value != null) {
seqContainer = new SequenceContainer(value);
} else {
throw new XMLStreamException("Name is missing for container");
}
value = readAttribute("shortDescription", xmlEvent.asStartElement());
if (value != null) {
seqContainer.setShortDescription(value);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_AliasSet)) {
seqContainer.setAliasSet(readXtceAliasSet());
} else if (isStartElementWithName(XTCE_EntryList)) {
readXtceEntryList(spaceSystem, seqContainer);
} else if (isStartElementWithName(XTCE_BaseContainer)) {
readXtceBaseContainer(spaceSystem, seqContainer);
} else if (isStartElementWithName(XTCE_LongDescription)) {
seqContainer.setLongDescription(readXtceLongDescription(spaceSystem));
} else if (isEndElementWithName(XTCE_SequenceContainer)) {
return seqContainer;
}
}
}
private void readXtceBaseContainer(SpaceSystem spaceSystem, SequenceContainer seqContainer) throws IllegalStateException, XMLStreamException {
log.trace(XTCE_BaseContainer);
checkStartElementPreconditions();
String refName = readAttribute("containerRef", xmlEvent.asStartElement());
if (refName != null) {
if(excludedContainers.contains(refName)) {
log.debug("adding "+seqContainer.getName()+" to the list of the excluded containers because its parent is excluded");
excludedContainers.add(seqContainer.getName());
} else {
// find base container in the set of already defined containers
SequenceContainer baseContainer = spaceSystem.getSequenceContainer(refName);
if (baseContainer != null) {
seqContainer.setBaseContainer(baseContainer);
} else { //must come from somwhere else
final SequenceContainer finalsc=seqContainer;
NameReference nr=new NameReference(refName, Type.SEQUENCE_CONTAINTER, new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
finalsc.setBaseContainer((SequenceContainer) nd);
return true;
}
});
spaceSystem.addUnresolvedReference(nr);
}
}
} else {
throw new XMLStreamException("Reference on base container is missing");
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_RestrictionCriteria)) {
MatchCriteria criteria = readMatchCriteria(spaceSystem);
seqContainer.setRestrictionCriteria(criteria);
} else if (isEndElementWithName(XTCE_BaseContainer)) {
return;
}
}
}
private void readXtceEntryList(SpaceSystem spaceSystem, SequenceContainer seqContainer) throws XMLStreamException {
log.trace(XTCE_EntryList);
checkStartElementPreconditions();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_ParameterRefEntry)) {
SequenceEntry entry = readXtceParameterRefEntry(spaceSystem);
entry.setSequenceContainer(seqContainer);
seqContainer.addEntry(entry);
} else if (isStartElementWithName(XTCE_ParameterSegmentRefEntry)) {
skipXtceSection(XTCE_ParameterSegmentRefEntry);
} else if (isStartElementWithName(XTCE_ContainerRefEntry)) {
ContainerEntry entry = readXtceConteinerRefEntry(spaceSystem);
entry.setSequenceContainer(seqContainer);
seqContainer.addEntry(entry);
} else if (isStartElementWithName(XTCE_ContainerSegmentRefEntry)) {
skipXtceSection(XTCE_ContainerSegmentRefEntry);
} else if (isStartElementWithName(XTCE_StreamSegmentEntry)) {
skipXtceSection(XTCE_StreamSegmentEntry);
} else if (isStartElementWithName(XTCE_IndirectParameterRefEntry)) {
skipXtceSection(XTCE_IndirectParameterRefEntry);
} else if (isStartElementWithName(XTCE_ArrayParameterRefEntry)) {
skipXtceSection(XTCE_ArrayParameterRefEntry);
} else if (isEndElementWithName(XTCE_EntryList)) {
return;
}
}
}
private SequenceEntry readXtceParameterRefEntry(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ParameterRefEntry);
checkStartElementPreconditions();
String refName = readAttribute("parameterRef", xmlEvent.asStartElement());
if (refName == null) {
throw new XMLStreamException("Reference to parameter is missing");
}
SequenceEntry.ReferenceLocationType locationType = SequenceEntry.ReferenceLocationType.previousEntry; //default
Parameter parameter = spaceSystem.getParameter(refName);
ParameterEntry parameterEntry=null;
if (parameter != null) {
parameterEntry = new ParameterEntry(-1, null, 0, locationType, parameter);
} else {
parameterEntry = new ParameterEntry(-1, null, 0, locationType);
final ParameterEntry finalpe=parameterEntry;
NameReference nr=new NameReference(refName, Type.PARAMETER_TYPE,
new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
finalpe.setParameter((Parameter) nd);
return true;
}
});
spaceSystem.addUnresolvedReference(nr);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_LocationInContainerInBits)) {
readXtceLocationInContainerInBits(parameterEntry);
} else if (isStartElementWithName(XTCE_RepeatEntry)) {
Repeat r = readXtceRepeatEntry(spaceSystem);
parameterEntry.setRepeatEntry(r);
} else if (isStartElementWithName(XTCE_IncludeCondition)) {
skipXtceSection(XTCE_IncludeCondition);
} else if (isEndElementWithName(XTCE_ParameterRefEntry)) {
return parameterEntry;
}
}
}
private ContainerEntry readXtceConteinerRefEntry(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ContainerRefEntry);
checkStartElementPreconditions();
String refName = readAttribute("containerRef", xmlEvent.asStartElement());
if (refName == null) {
throw new XMLStreamException("Reference to container is missing");
}
SequenceEntry.ReferenceLocationType locationType = SequenceEntry.ReferenceLocationType.previousEntry; //default
SequenceContainer container = spaceSystem.getSequenceContainer(refName);
ContainerEntry containerEntry=null;
if (container != null) {
containerEntry = new ContainerEntry(-1, null, 0, locationType, container);
} else {
containerEntry = new ContainerEntry(-1, null, 0, locationType);
final ContainerEntry finalce = containerEntry;
NameReference nr=new NameReference(refName, Type.SEQUENCE_CONTAINTER, new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
finalce.setRefContainer((SequenceContainer) nd);
return true;
}
});
spaceSystem.addUnresolvedReference(nr);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_LocationInContainerInBits)) {
readXtceLocationInContainerInBits(containerEntry);
} else if (isStartElementWithName(XTCE_RepeatEntry)) {
Repeat r = readXtceRepeatEntry(spaceSystem);
containerEntry.setRepeatEntry(r);
} else if (isStartElementWithName(XTCE_IncludeCondition)) {
skipXtceSection(XTCE_IncludeCondition);
} else if (isEndElementWithName(XTCE_ContainerRefEntry)) {
return containerEntry;
}
}
}
private Repeat readXtceRepeatEntry(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_RepeatEntry);
Repeat r = new Repeat();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_Count)) {
r.setCount(readXtceIntegerValue(spaceSystem));
} else if (isStartElementWithName("FromBinaryTransformAlgorithm")) {
skipXtceSection("FromBinaryTransformAlgorithm");
} else if (isStartElementWithName("ToBinaryTransformAlgorithm")) {
skipXtceSection("ToBinaryTransformAlgorithm");
} else if (isEndElementWithName(XTCE_RepeatEntry)) {
return r;
}
}
}
private IntegerValue readXtceIntegerValue(SpaceSystem spaceSystem) throws XMLStreamException {
String tag = xmlEvent.asStartElement().getName().getLocalPart();
checkStartElementPreconditions();
IntegerValue v = null;
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_FixedValue)) {
v = new FixedIntegerValue(readIntegerValue());
} else if (isStartElementWithName(XTCE_DynamicValue)) {
v = readDynamicValue(spaceSystem);
} else if (isEndElementWithName(tag)) {
return v;
}
}
}
private DynamicIntegerValue readDynamicValue(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_DynamicValue);
checkStartElementPreconditions();
DynamicIntegerValue v = new DynamicIntegerValue();
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_ParameterInstanceRef)) {
ParameterInstanceRef pir = readXtceParameterInstanceRef(spaceSystem);
v.setParameterInstanceRef(pir);
} else if (isEndElementWithName(XTCE_DynamicValue)) {
return v;
}
}
}
private ParameterInstanceRef readXtceParameterInstanceRef(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_ParameterInstanceRef);
String paramRef = readAttribute("parameterRef", xmlEvent.asStartElement());
if(paramRef==null) {
throw new XMLStreamException("Reference to parameter is missing");
}
final ParameterInstanceRef instanceRef = new ParameterInstanceRef(true);
NameReference nr=new NameReference(paramRef, Type.PARAMETER_TYPE,
new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
instanceRef.setParameter((Parameter) nd);
return true;
}
});
Parameter parameter = spaceSystem.getParameter(paramRef);
if(parameter!=null) {
if(!nr.resolved(parameter)) {
spaceSystem.addUnresolvedReference(nr);
}
} else {
spaceSystem.addUnresolvedReference(nr);
}
return instanceRef;
}
private void readXtceLocationInContainerInBits(SequenceEntry entry) throws XMLStreamException {
log.trace(XTCE_LocationInContainerInBits);
checkStartElementPreconditions();
int locationInContainerInBits = 0;
String value = readAttribute("referenceLocation", xmlEvent.asStartElement());
if (value == null) {
value = "previousEntry"; // default
}
if (value.equalsIgnoreCase("previousEntry")) {
entry.setReferenceLocation(SequenceEntry.ReferenceLocationType.previousEntry);
} else if (value.equalsIgnoreCase("containerStart")) {
entry.setReferenceLocation(SequenceEntry.ReferenceLocationType.containerStart);
} else {
throw new XMLStreamException("Currently unsupported reference location: " + value);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(XTCE_FixedValue)) {
locationInContainerInBits = readIntegerValue();
} else if (isStartElementWithName(XTCE_DynamicValue)) {
skipXtceSection(XTCE_DynamicValue);
} else if (isStartElementWithName(XTCE_DiscreteLookupList)) {
skipXtceSection(XTCE_DiscreteLookupList);
} else if (isEndElementWithName(XTCE_LocationInContainerInBits)) {
entry.setLocationInContainerInBits(locationInContainerInBits);
return;
}
}
}
private Comparison readXtceComparison(SpaceSystem spaceSystem) throws XMLStreamException {
log.trace(XTCE_Comparison);
checkStartElementPreconditions();
String paramRef = readAttribute("parameterRef", xmlEvent.asStartElement());
if(paramRef==null) {
throw new XMLStreamException("Reference to parameter is missing");
}
String value = readAttribute("comparisonOperator", xmlEvent.asStartElement());
if (value == null) {
value = "=="; // default value
}
OperatorType optype = Comparison.stringToOperator(value);
String theValue;
theValue = readAttribute("value", xmlEvent.asStartElement());
if (theValue == null) {
throw new XMLStreamException("Value for comparison is missing");
}
boolean useCalibratedValue = true; // default value
value = readAttribute("useCalibratedValue", xmlEvent.asStartElement());
if (value != null) {
useCalibratedValue = value.equalsIgnoreCase("true");
}
final ParameterInstanceRef instanceRef = new ParameterInstanceRef(useCalibratedValue);
Comparison comparison = new Comparison(instanceRef, theValue, optype);
NameReference nr = new NameReference(paramRef, Type.PARAMETER, new ResolvedAction() {
@Override
public boolean resolved(NameDescription nd) {
Parameter p=(Parameter)nd;
instanceRef.setParameter((Parameter) nd);
if(p.getParameterType()==null) {
return false;
}
comparison.resolveValueType();
return true;
}
});
Parameter parameter = spaceSystem.getParameter(paramRef);
if(parameter!=null) {
if(!nr.resolved(parameter)) {
spaceSystem.addUnresolvedReference(nr);
}
} else {
spaceSystem.addUnresolvedReference(nr);
}
while (true) {
xmlEvent = xmlEventReader.nextEvent();
if (isEndElementWithName(XTCE_Comparison)) {
return comparison;
}
}
}
/**
* Just skips the whole section.
*
* @return
* @throws IllegalStateException
* @throws XMLStreamException
*/
private XtceNotImplemented readXtceMessageSet() throws IllegalStateException,
XMLStreamException {
skipXtceSection(XTCE_MessageSet);
return null;
}
/**
* Just skips the whole section.
*
* @return
* @throws IllegalStateException
* @throws XMLStreamException
*/
private XtceNotImplemented readXtceStreamSet() throws IllegalStateException, XMLStreamException {
skipXtceSection(XTCE_StreamSet);
return null;
}
/**
* Just skips the whole section.
* @param spaceSystem
*
* @return
* @throws IllegalStateException
* @throws XMLStreamException
*/
private XtceNotImplemented readXtceAlgorithmSet(SpaceSystem spaceSystem) throws IllegalStateException, XMLStreamException {
skipXtceSection(XTCE_AlgorithmSet);
return null;
}
/**
* Extraction of the CommandMetaData section Current implementation does
* nothing, just skips whole section
* @param spaceSystem
*
* @throws XMLStreamException
*/
private void readXtceCommandMetaData(SpaceSystem spaceSystem) throws XMLStreamException {
skipXtceSection(XTCE_CommandMetaData);
}
/**
* Increase the skip statistics for the section.
* @param xtceSectionName Name of the skipped section.
*/
private void addToSkipStatistics(String xtceSectionName) {
Integer count = xtceSkipStatistics.get(xtceSectionName);
if (count == null) {
xtceSkipStatistics.put(xtceSectionName, new Integer(1));
} else {
xtceSkipStatistics.put(xtceSectionName, count + 1);
}
}
/**
* Write statistics.
*/
public void writeStatistics() {
log.info("------------------");
log.info("Statistics of skipped elements: ");
for (Map.Entry<String, Integer> entry : xtceSkipStatistics.entrySet()) {
log.info(">> " + entry.getKey() + ": " + entry.getValue());
}
log.info("------------------");
}
/**
* Skips whole section in the document.
*
* @param sectionName
* name of the section to skip
* @throws XMLStreamException
* @throws IllegalStateException
* Exception on algorithm error
*/
private void skipXtceSection(String sectionName) throws XMLStreamException,
IllegalStateException {
log.trace(sectionName);
checkStartElementPreconditions();
addToSkipStatistics(sectionName);
while (true) {
// just skip whole section, read events until the
// end element of the section occurs
try {
xmlEvent = xmlEventReader.nextEvent();
if (isStartElementWithName(sectionName)) {
// skip wrapped sections with the same name
skipXtceSection(sectionName);
} else if (isEndElementWithName(sectionName)) {
log.info("Section <" + sectionName + "> skipped");
return;
}
} catch (NoSuchElementException e) {
throw new IllegalStateException("End of section unreachable: " + sectionName);
}
}
}
/**
*
* @param filename
* @return
* @throws FileNotFoundException
* @throws XMLStreamException
*/
private XMLEventReader initEventReader(String filename) throws FileNotFoundException, XMLStreamException {
InputStream in = new FileInputStream(new File(filename));
XMLInputFactory factory = XMLInputFactory.newInstance();
return factory.createXMLEventReader(in);
}
/**
* Examines element for presence of attributes
*
* @param element
* Element to be examined, should not be null
* @return True, if the element contains attributes, otherwise false
*/
@SuppressWarnings("unused")
private boolean hasAttributes(StartElement element) {
if (element == null) {
log.info("element param is null");
return false;
}
return element.getAttributes().hasNext();
}
/**
* Check if xml element is a start element with particular name
*
* @param localName
* Name of the element
* @return True if element is start element with the given name, otherwise
* false
*/
private boolean isStartElementWithName(String localName) {
return (xmlEvent.getEventType() == XMLStreamConstants.START_ELEMENT && xmlEvent
.asStartElement().getName().getLocalPart().equals(localName));
}
/**
* Test if the xmlEvent is of type END_ELEMENT and has particular local
* name. This test is used to identify the end of section.
*
* @param localName
* Local name of the element (we neglect namespace for now)
* @return True if current xmlEvent is of type END_ELEMENT and has
* particular local name, otherwise false
*/
private boolean isEndElementWithName(String localName) {
return (xmlEvent.getEventType() == XMLStreamConstants.END_ELEMENT && xmlEvent
.asEndElement().getName().getLocalPart().equals(localName));
}
/**
* Checks preconditions before the dedicated code for section reading will
* run
*
* @throws IllegalStateException If the conditions are not met
*/
private void checkStartElementPreconditions() throws IllegalStateException {
if (xmlEvent == null) {
throw new IllegalStateException("xmlEvent is null");
}
if (xmlEvent.getEventType() != XMLStreamConstants.START_ELEMENT) {
throw new IllegalStateException("xmlEvent type is not start element");
}
}
/**
* Get attribute values as string
*
* @param attName
* Name of the attribute
* @param element
* Start element which the attribute is read from
* @return Attribute's value as string
*/
private String readAttribute(String attName, StartElement element) {
Attribute attribute = element.getAttributeByName(new QName(attName));
if (attribute != null) {
return attribute.getValue();
}
return null;
}
/**
* Test method.
* @param args XTCE document to load.
* @throws Exception
*/
public static void main(String[] args) throws Exception {
XtceStaxReader reader = new XtceStaxReader();
if (args.length == 1) {
reader.readXmlDocument(args[0]);
reader.writeStatistics();
} else {
System.out.println("Wrong arguments, exactly one argument allowed");
}
}
public void setExcludedContainers(Set<String> excludedContainers) {
this.excludedContainers = excludedContainers;
}
}