Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes bugs with erroneous messages from output logs, duplicate records in collections, and handling of high_instrument_saturation special constants #859

Merged
merged 10 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ public synchronized Document parseAndValidate(ProblemHandler handler, URL url)

SAXSource saxSource = new SAXSource(Utility.getInputSourceByURL(url));
saxSource.setSystemId(url.toString());
TreeInfo docInfo = LabelParser.parse(saxSource);
TreeInfo docInfo = LabelParser.parse(saxSource, false);
for (DocumentValidator dv : documentValidators) {
dv.validate(handler, docInfo.getRootNode());
}
Expand Down
20 changes: 17 additions & 3 deletions src/main/java/gov/nasa/pds/tools/util/LabelParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,35 @@
// $Id$
package gov.nasa.pds.tools.util;

import java.util.function.Function;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.ErrorReporter;
import net.sf.saxon.lib.ParseOptions;
import net.sf.saxon.om.TreeInfo;
import net.sf.saxon.s9api.XmlProcessingError;
import net.sf.saxon.xpath.XPathEvaluator;

public class LabelParser {

public class LabelParser implements ErrorReporter {
private static class Factory implements Function<Configuration,ErrorReporter> {
final ErrorReporter ignorer = new LabelParser();
@Override
public ErrorReporter apply(Configuration t) {
return ignorer;
}
}
/**
* Parses a label.
*
* @param source the source to parse.
* @return a DocumentInfo object.
* @throws TransformerException
*/
public static TreeInfo parse(Source source) throws TransformerException {
public static TreeInfo parse(Source source, boolean ignoreErrors) throws TransformerException {
XPathEvaluator xpath = new XPathEvaluator();
Configuration configuration = xpath.getConfiguration();
if (ignoreErrors) configuration.setErrorReporterFactory(new Factory());
configuration.setLineNumbering(true);
configuration.setXIncludeAware(Utility.supportXincludes());
ParseOptions options = new ParseOptions();
Expand All @@ -40,4 +50,8 @@ public static TreeInfo parse(Source source) throws TransformerException {
options.withXIncludeAware(Utility.supportXincludes());
return configuration.buildDocumentTree(source, options);
}
@Override
public void report(XmlProcessingError error) {
// do nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,11 @@ private static boolean tagMatches(URL url, String tagCheck, boolean ignoreErrors
// xmlns:pds="http://pds.nasa.gov/pds4/pds/v1"
boolean tagMatchedFlag = false;

if (!url.getPath().endsWith(".xml")) {
tagMatchedFlag = false;
}
try {
InputSource source = Utility.getInputSourceByURL(url);
SAXSource saxSource = new SAXSource(source);
saxSource.setSystemId(url.toString());
TreeInfo docInfo = LabelParser.parse(saxSource); // Parses a label.
TreeInfo docInfo = LabelParser.parse(saxSource, ignoreErrors); // Parses a label.
LOG.debug("tagMatches:docInfo {},{}", docInfo, docInfo.getClass());
List<TinyNodeImpl> xmlModels = new ArrayList<>();
try {
Expand Down Expand Up @@ -209,7 +206,7 @@ public static ArrayList<String> getTargetContent(URL url, String nodeCheck, Stri
InputSource source = Utility.getInputSourceByURL(url);
SAXSource saxSource = new SAXSource(source);
saxSource.setSystemId(url.toString());
TreeInfo docInfo = LabelParser.parse(saxSource); // Parses a label.
TreeInfo docInfo = LabelParser.parse(saxSource, false); // Parses a label.
LOG.debug("getTargetContent:docInfo {},{}", docInfo, docInfo.getClass());
List<TinyNodeImpl> xmlModels = new ArrayList<>();
try {
Expand Down Expand Up @@ -254,7 +251,7 @@ public static boolean isTargetALabel(URL url) {
InputSource source = Utility.getInputSourceByURL(url);
SAXSource saxSource = new SAXSource(source);
saxSource.setSystemId(url.toString());
TreeInfo docInfo = LabelParser.parse(saxSource); // Parses a label.
TreeInfo docInfo = LabelParser.parse(saxSource, true); // Parses a label.
@SuppressWarnings("unused")
List<TinyNodeImpl> xmlModels = new ArrayList<>();
XMLExtractor extractor = new XMLExtractor(docInfo.getRootNode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ private static boolean sameContent (Number number, String constant_repr) {
if (number instanceof Integer) number = BigInteger.valueOf(number.intValue());
if (number instanceof Long) number = BigInteger.valueOf(number.longValue());
if (number instanceof Short) number = BigInteger.valueOf(number.shortValue());
boolean repr_decimal = constant_repr.contains (".") || constant_repr.contains("E") || constant_repr.contains("e");
boolean repr_decimal = constant_repr.contains (".") ||
((constant_repr.contains("E") || constant_repr.contains("e")) &&
!(constant_repr.startsWith("0x") || constant_repr.startsWith("0X")));
if (repr_decimal) {
BigDecimal constant = SpecialConstantBitPatternTransforms.asBigDecimal(constant_repr);
return constant.equals (number);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
Expand Down Expand Up @@ -50,20 +50,20 @@ public static void uniqueCollectionRefs (ProblemListener listener, URL aggregate
}
}
private static void checkAllUnique(List<String> ids, ProblemListener listener, URL aggregate) {
HashSet<String> uniqueIDs = new HashSet<String>(ids);
if (ids.size() != uniqueIDs.size()) {
int dups = ids.size() - uniqueIDs.size();
for (String uid : uniqueIDs) {
int copies = Collections.frequency (ids, uid);
if (1 < copies) {
dups = dups - copies + 1;
listener.addProblem(new ValidationProblem(
new ProblemDefinition(ExceptionType.ERROR, ProblemType.INVENTORY_DUPLICATE_LIDVID,
"Inventory contains " + Integer.toString(copies) + "' instances of LIDVID " + uid),
aggregate));
}
if (dups < 1) break; // shortcut the for loop
}
HashSet<String> dups = new HashSet<String>();
HashMap<String,Integer> counts = new HashMap<String,Integer>();
for (String id : ids) {
Integer count = counts.getOrDefault(id, Integer.valueOf(0));
counts.put(id, ++count);
if (count > 1) {
dups.add(id);
}
}
for (String id : dups) {
listener.addProblem(new ValidationProblem(
new ProblemDefinition(ExceptionType.ERROR, ProblemType.INVENTORY_DUPLICATE_LIDVID,
"Inventory contains " + Integer.toString(counts.get(id)) + " instances of LIDVID " + id),
aggregate));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void validateFileReferences() {
DOMSource source = new DOMSource(label);
source.setSystemId(uri.toString());
try {
TreeInfo xml = LabelParser.parse(source);
TreeInfo xml = LabelParser.parse(source, false);
LOG.debug("FileReferenceValidationRule:validateFileReferences:uri {}", uri);
validate(xml.getRootNode());
} catch (TransformerException te) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/gov/nasa/pds/validate/ri/UserInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private boolean isLabel (String cliArg) {
if (file.exists()) {
try {
SAXSource saxSource = new SAXSource(new InputSource(new FileReader(file)));
TreeInfo docInfo = LabelParser.parse(saxSource); // Parses a label.
TreeInfo docInfo = LabelParser.parse(saxSource, true); // Parses a label.
List<TinyNodeImpl> xmlModels = new ArrayList<>();
XMLExtractor extractor = new XMLExtractor(docInfo.getRootNode());
xmlModels = extractor.getNodesFromDoc("//logical_identifier");
Expand Down
6 changes: 6 additions & 0 deletions src/test/resources/features/developer.feature
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Scenario Outline: Execute validate command for tests below.
Examples:
| testName | testDir | messageCount | messageText | problemEnum | resourceDir | reportDir | commandArgs | refOutputValue |

# Validate#849
|"NASA-PDS/validate#849 Fails inventory with duplicate entries" | "github849" | 2 | "2 errors expected" | "INVENTORY_DUPLICATE_LIDVID" | "src/test/resources" | "target/test" | "-r {reportDir}/report_github849.json -s json --skip-context-validation -t {resourceDir}/github849/collection_uvs_data_raw.xml" | "report_github849.json" |

# Validate#831
|"NASA-PDS/validate#831 Success high instrument saturation" | "github831" | 0 | "0 errors expected" | "totalErrors" | "src/test/resources" | "target/test" | "-r {reportDir}/report_github831.json -s json --skip-context-validation -t {resourceDir}/github831/kplo.xml" | "report_github831.json" |

# Validate#824
|"NASA-PDS/validate#824 Success PDF vs PDF/A" | "github824" | 0 | "0 errors expected" | "totalErrors" | "src/test/resources" | "target/test" | "-r {reportDir}/report_github824.json -s json --skip-context-validation -t {resourceDir}/github824/1203_12.xml" | "report_github824.json" |

Expand Down
Binary file added src/test/resources/github831/kplo.cub
Binary file not shown.
154 changes: 154 additions & 0 deletions src/test/resources/github831/kplo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1L00.sch" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-model href="https://pds.nasa.gov/pds4/disp/v1/PDS4_DISP_1L00_1510.sch" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-model href="https://pds.nasa.gov/pds4/img/v1/PDS4_IMG_1L00_1890.sch" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-model href="https://pds.nasa.gov/pds4/geom/v1/PDS4_GEOM_1L00_1970.sch" schematypens="http://purl.oclc.org/dsdl/schematron"?>

<Product_Observational
xmlns="http://pds.nasa.gov/pds4/pds/v1"
xmlns:disp="http://pds.nasa.gov/pds4/disp/v1"
xmlns:img="http://pds.nasa.gov/pds4/img/v1"
xmlns:geom="http://pds.nasa.gov/pds4/geom/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://pds.nasa.gov/pds4/pds/v1 https://pds.nasa.gov/pds4/pds/v1/PDS4_PDS_1L00.xsd
http://pds.nasa.gov/pds4/disp/v1 https://pds.nasa.gov/pds4/disp/v1/PDS4_DISP_1L00_1510.xsd
http://pds.nasa.gov/pds4/img/v1 https://pds.nasa.gov/pds4/img/v1/PDS4_IMG_1L00_1890.xsd
http://pds.nasa.gov/pds4/geom/v1 https://pds.nasa.gov/pds4/geom/v1/PDS4_GEOM_1L00_1970.xsd">

<Identification_Area>
<logical_identifier>urn:nasa:pds:kplo-shadowcam:observation:e004246319sc</logical_identifier>
<version_id>1.0</version_id>
<title>Korea Pathfinder Lunar Orbiter ShadowCam Calibrated Product</title>
<information_model_version>1.21.0.0</information_model_version>
<product_class>Product_Observational</product_class>
<Modification_History>
<Modification_Detail>
<modification_date>2024-01-27T22:53:08.112700Z</modification_date>
<version_id>1.0</version_id>
<description>
Initial Release
</description>
</Modification_Detail>
</Modification_History>
</Identification_Area>
<Observation_Area>
<Time_Coordinates>
<start_date_time>2022-09-23T02:39:59.931890Z</start_date_time>
<stop_date_time>2022-09-23T02:40:42.952997Z</stop_date_time>
</Time_Coordinates>
<Primary_Result_Summary>
<purpose>Science</purpose>
<processing_level>Calibrated</processing_level>
<description>ShadowCam is a Time Delay Integration(TDI) pushbroom imager
</description>
</Primary_Result_Summary>
<Investigation_Area>
<name>KOREA PATHFINDER LUNAR ORBITER</name>
<type>Mission</type>
<Internal_Reference>
<lid_reference>urn:kari:kpds:context:investigation:mission.kplo</lid_reference>
<reference_type>data_to_investigation</reference_type>
<comment>This is the PDS4 logical identifier for KPLO</comment>
</Internal_Reference>
</Investigation_Area>
<Observing_System>
<Observing_System_Component>
<name>Korea Pathfinder Lunar Orbiter (Danuri)</name>
<type>Host</type>
<Internal_Reference>
<lid_reference>urn:kari:kpds:context:instrument_host:spacecraft.kplo</lid_reference>
<reference_type>is_instrument_host</reference_type>
</Internal_Reference>
</Observing_System_Component>
<Observing_System_Component>
<name>SHADOWCAM</name>
<type>Instrument</type>
<Internal_Reference>
<lid_reference>urn:kari:kpds:context:instrument:kplo.shc</lid_reference>
<reference_type>is_instrument</reference_type>
</Internal_Reference>
</Observing_System_Component>
</Observing_System>
<Target_Identification>
<name>Earth</name>
<type>Planet</type>
<Internal_Reference>
<lid_reference>urn:nasa:pds:context:target:planet.earth</lid_reference>
<reference_type>data_to_target</reference_type>
</Internal_Reference>
</Target_Identification>
<Target_Identification>
<name>Moon</name>
<type>Satellite</type>
<Internal_Reference>
<lid_reference>urn:nasa:pds:context:target:satellite.earth.moon</lid_reference>
<reference_type>data_to_target</reference_type>
</Internal_Reference>
</Target_Identification>
<Mission_Area>
</Mission_Area>
<Discipline_Area>
<img:Imaging>
<Local_Internal_Reference>
<local_identifier_reference>DATA_FILE</local_identifier_reference>
<local_reference_type>imaging_parameters_to_image_object</local_reference_type>
</Local_Internal_Reference>
<img:Optical_Filter>
<img:bandwidth unit="nm">300</img:bandwidth>
<img:center_filter_wavelength unit="nm">600</img:center_filter_wavelength>
</img:Optical_Filter>
</img:Imaging>
<disp:Display_Settings>
<Local_Internal_Reference>
<local_identifier_reference>Array_2D_Image</local_identifier_reference>
<local_reference_type>display_settings_to_array</local_reference_type>
</Local_Internal_Reference>
<disp:Display_Direction>
<disp:horizontal_display_axis>Sample</disp:horizontal_display_axis>
<disp:horizontal_display_direction>Left to Right</disp:horizontal_display_direction>
<disp:vertical_display_axis>Line</disp:vertical_display_axis>
<disp:vertical_display_direction>Top to Bottom</disp:vertical_display_direction>
</disp:Display_Direction>
</disp:Display_Settings>
</Discipline_Area>
</Observation_Area>
<File_Area_Observational>
<File>
<file_name>kplo.cub</file_name>
<local_identifier>DATA_FILE</local_identifier>
<creation_date_time>2024-02-02T23:19:08.197538Z</creation_date_time>
<file_size unit="byte">513</file_size>
<!--md5_checksum>80393407b982ed98f6f1ce99f5af7638</md5_checksum-->
<comment>Korea Pathfinder Lunar Orbiter Calibrated Product.</comment>
</File>
<Array_2D_Image>
<local_identifier>Array_2D_Image</local_identifier>
<offset unit="byte">0</offset>
<axes>2</axes>
<axis_index_order>Last Index Fastest</axis_index_order>
<Element_Array>
<data_type>IEEE754LSBSingle</data_type>
<unit>Radiance</unit>
</Element_Array>
<Axis_Array>
<axis_name>Line</axis_name>
<elements>16</elements>
<sequence_number>1</sequence_number>
</Axis_Array>
<Axis_Array>
<axis_name>Sample</axis_name>
<elements>8</elements>
<sequence_number>2</sequence_number>
</Axis_Array>
<Special_Constants>
<missing_constant>0xFF7FFFFB</missing_constant>
<high_instrument_saturation>0xFF7FFFFE</high_instrument_saturation>
<high_representation_saturation>0xFF7FFFFF</high_representation_saturation>
<valid_minimum>0xFF7FFFFA</valid_minimum>
<low_instrument_saturation>0xFF7FFFFD</low_instrument_saturation>
<low_representation_saturation>0xFF7FFFFC</low_representation_saturation>
</Special_Constants>
</Array_2D_Image>
</File_Area_Observational>
</Product_Observational>
Loading