Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions src/main/java/gov/nasa/pds/tools/util/FlagsUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public class FlagsUtil {
/** Flag to enable/disable stack trace printing. */
private static boolean stackPrintingFlag = false;

/** Flag to downgrade member_not_found from ERROR to WARNING (for accumulating bundles). */
private static boolean skipStrictCollectionMembership = false;

/**
* Initialize flags to their default states
*
Expand All @@ -48,6 +51,7 @@ public static void initialize() {
FlagsUtil.contentValidationFlag = true;
FlagsUtil.skipProductValidation = false;
FlagsUtil.stackPrintingFlag = false;
FlagsUtil.skipStrictCollectionMembership = false;
LOG.debug("initialize:contentValidationFlag {}", FlagsUtil.contentValidationFlag);
LOG.debug("initialize:skipProductValidation {}", FlagsUtil.skipProductValidation);
}
Expand Down Expand Up @@ -115,6 +119,15 @@ public static boolean getSkipProductValidation() {
return (FlagsUtil.skipProductValidation);
}

public static void setSkipStrictCollectionMembership(boolean flag) {
FlagsUtil.skipStrictCollectionMembership = flag;
LOG.debug("setSkipStrictCollectionMembership: {}", FlagsUtil.skipStrictCollectionMembership);
}

public static boolean getSkipStrictCollectionMembership() {
return FlagsUtil.skipStrictCollectionMembership;
}

/**
* Set the severity value
*
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/gov/nasa/pds/tools/validate/ProblemType.java
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ public enum ProblemType {

MEMBER_NOT_FOUND("warning.integrity.member_not_found"),

MEMBER_NOT_FOUND_ERROR("error.integrity.member_not_found"),

INTEGRITY_PDS4_VERSION_MISMATCH("warning.integrity.pds4_version_mismatch",
ProblemCategory.GENERAL),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import gov.nasa.pds.tools.util.EveryNCounter;
import gov.nasa.pds.tools.util.ReferentialIntegrityUtil;
import gov.nasa.pds.tools.util.Utility;
import gov.nasa.pds.tools.util.FlagsUtil;
import gov.nasa.pds.tools.util.XMLExtractor;
import gov.nasa.pds.tools.validate.Identifier;
import gov.nasa.pds.tools.validate.ProblemDefinition;
Expand Down Expand Up @@ -172,9 +173,12 @@ private void getBundleMembers(URL bundle) {
}
if (matchingMembers.isEmpty() && "Primary".equalsIgnoreCase(memberStatus)) {
LOG.debug("getBundleMembers:MATCHING_MEMBER_ID_IS_EMPTY {}", id);
boolean downgradeToWarning = FlagsUtil.getSkipStrictCollectionMembership();
getListener()
.addProblem(new ValidationProblem(new ProblemDefinition(ExceptionType.WARNING,
ProblemType.MEMBER_NOT_FOUND, "The member '" + id + "' could not be found in "
.addProblem(new ValidationProblem(new ProblemDefinition(
downgradeToWarning ? ExceptionType.WARNING : ExceptionType.ERROR,
downgradeToWarning ? ProblemType.MEMBER_NOT_FOUND : ProblemType.MEMBER_NOT_FOUND_ERROR,
"The member '" + id + "' could not be found in "
+ "any product within the given target."),
bundle));
} else if (matchingMembers.size() == 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import gov.nasa.pds.tools.inventory.reader.InventoryReaderException;
import gov.nasa.pds.tools.inventory.reader.InventoryTableReader;
import gov.nasa.pds.tools.label.ExceptionType;
import gov.nasa.pds.tools.util.FlagsUtil;
import gov.nasa.pds.tools.util.ReferentialIntegrityUtil;
import gov.nasa.pds.tools.util.Utility;
import gov.nasa.pds.tools.util.XMLExtractor;
Expand Down Expand Up @@ -205,11 +206,14 @@ private void validateEntry(URL collection, int numOfCollectionMembers, Inventory
"getCollectionMembers: id,matchingMembers.isEmpty(),entry.getMemberStatus() {},{},{}",
id, matchingMembers.isEmpty(), entry.getMemberStatus());
if (matchingMembers.isEmpty() && "P".equalsIgnoreCase(entry.getMemberStatus())) {
boolean downgradeToWarning = FlagsUtil.getSkipStrictCollectionMembership();
getListener()
.addProblem(new ValidationProblem(new ProblemDefinition(ExceptionType.WARNING,
ProblemType.MEMBER_NOT_FOUND, "The member '" + id + "' could not be found in "
.addProblem(new ValidationProblem(new ProblemDefinition(
downgradeToWarning ? ExceptionType.WARNING : ExceptionType.ERROR,
downgradeToWarning ? ProblemType.MEMBER_NOT_FOUND : ProblemType.MEMBER_NOT_FOUND_ERROR,
"The member '" + id + "' could not be found in "
+ "any product within the given target."),
collection));
collection));
} else if (matchingMembers.size() == 1) {
super.verifyLidPrefix(id.getLid(), this.lid, entry.getMemberStatus(), collection);
getListener()
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/gov/nasa/pds/validate/ValidateLauncher.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ public class ValidateLauncher {

private boolean allowUnlabeledFiles;

private boolean skipStrictCollectionMembership;

private File registeredProductsFile;

private File nonRegisteredProductsFile;
Expand Down Expand Up @@ -288,6 +290,7 @@ public ValidateLauncher() throws TransformerConfigurationException {
contextMismatchAsWarn = true;
spotCheckData = -1;
allowUnlabeledFiles = false;
skipStrictCollectionMembership = false;
registeredAndNonRegistedProducts = new HashMap<>();
registeredProductsFile = new File(
System.getProperty("resources.home") + File.separator + ToolInfo.getOutputFileName());
Expand Down Expand Up @@ -477,6 +480,9 @@ public void query(CommandLine line) throws Exception {
setSpotCheckData(value);
} else if (Flag.ALLOW_UNLABELED_FILES.getLongName().equals(o.getLongOpt())) {
setAllowUnlabeledFiles(true);
} else if (Flag.SKIP_STRICT_COLLECTION_MEMBERSHIP.getLongName().equals(o.getLongOpt())) {
setSkipStrictCollectionMembership(true);
FlagsUtil.setSkipStrictCollectionMembership(true);
} else if (Flag.LATEST_JSON_FILE.getLongName().equals(o.getLongOpt())) {
setUpdateRegisteredProducts(true);
} else if (Flag.NONREGPROD_JSON_FILE.getLongName().equals(o.getLongOpt())) {
Expand Down Expand Up @@ -852,6 +858,10 @@ public void query(File configuration) throws ConfigurationException {
if (config.containsKey(ConfigKey.ALLOW_UNLABELED_FILES)) {
setAllowUnlabeledFiles(true);
}
if (config.containsKey(ConfigKey.SKIP_STRICT_COLLECTION_MEMBERSHIP)) {
setSkipStrictCollectionMembership(true);
FlagsUtil.setSkipStrictCollectionMembership(true);
}
if (config.containsKey(ConfigKey.LATEST_JSON_FILE)) {
setUpdateRegisteredProducts(true);
}
Expand Down Expand Up @@ -1160,6 +1170,10 @@ public void setAllowUnlabeledFiles(boolean flag) {
this.allowUnlabeledFiles = flag;
}

public void setSkipStrictCollectionMembership(boolean flag) {
this.skipStrictCollectionMembership = flag;
}

private void setRegisteredProducts() {
URL url = null;

Expand Down Expand Up @@ -1396,6 +1410,8 @@ public void setupReport(String cliArgs[]) throws IOException {
|| validationRule.equalsIgnoreCase("pds4.collection"))) {
report.addParameter("allowUnlabeledFiles", "Allow Unlabeled Files",
String.valueOf(allowUnlabeledFiles));
report.addParameter("skipStrictCollectionMembership", "Allow Unlisted Members",
String.valueOf(skipStrictCollectionMembership));
}
report.addParameter("maxErrors", "Max Errors", String.valueOf(maxErrors));
report.addParameter("registeredContextsFile", "Registered Contexts File",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ public class ConfigKey {
*/
public static final String ALLOW_UNLABELED_FILES = "validate.allowUnlabeledFiles";

/**
* Property to downgrade member_not_found from ERROR to WARNING (for accumulating bundles).
*/
public static final String SKIP_STRICT_COLLECTION_MEMBERSHIP = "validate.skipStrictCollectionMembership";

/**
* Property to download the latest Registered Context Products JSON file and replace the existing
* file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ public enum Flag {
ALLOW_UNLABELED_FILES(null, "allow-unlabeled-files",
"Tells the tool to not check for unlabeled files in a bundle or collection."),

SKIP_STRICT_COLLECTION_MEMBERSHIP(null, "skip-strict-collection-membership",
"When set, collection inventory members not found in the target are reported as warnings instead of errors. "
+ "Use when validating partial or accumulating bundles where prior-release products are intentionally absent."),

RULE("R", "rule", "validation rule name", String.class,
"Specifies the validation rules to apply. (pds4.bundle|pds4.collection|pds4.folder|pds4.label|pds3.volume)."
+ " Default is pds4.label"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public class FlagOptions {
options.addOption(new ToolsOption(Flag.NO_DATA));
options.addOption(new ToolsOption(Flag.SPOT_CHECK_DATA));
options.addOption(new ToolsOption(Flag.ALLOW_UNLABELED_FILES));
options.addOption(new ToolsOption(Flag.SKIP_STRICT_COLLECTION_MEMBERSHIP));
options.addOption(new ToolsOption(Flag.LATEST_JSON_FILE));
options.addOption(new ToolsOption(Flag.NONREGPROD_JSON_FILE));
options.addOption(new ToolsOption(Flag.SKIP_CONTEXT_VALIDATION));
Expand Down
12 changes: 12 additions & 0 deletions src/site/markdown/operate/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,18 @@ and is in line with the other bundle data.
% validate --skip-product-validation --rule pds4.bundle --target path/to/staged/bundle_v2 --alternate_file_paths path/to/online/bundle_v1
```

#### Validating Partial/Incremental Bundle Deliveries

By default, validate reports an **error** (`error.integrity.member_not_found`) when a collection inventory lists a primary member product that cannot be found in the validation target. This is the correct behavior for complete bundles.

When validating a partial or incremental delivery of an accumulating bundle β€” where prior-release products are intentionally absent from the local target β€” use the `--skip-strict-collection-membership` flag to downgrade this condition to a warning:

```
% validate --skip-strict-collection-membership --rule pds4.bundle --target path/to/incremental/bundle
```

This flag should only be used when you have a legitimate reason for missing members (e.g., products delivered in a previous release). For standard bundle validation, the default error behavior is correct and should not be suppressed.

#### Example of using multiple-flags to improve performance

Here is one example of how to
Expand Down
15 changes: 15 additions & 0 deletions src/test/resources/features/4.2.x.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Feature: 4.2.x
Scenario Outline: NASA-PDS/validate#<issueNumber>-<subtest>
Given validate issue <issueNumber>, test <subtest>, and test data at <datasrc>
When execute validate with <args>
Then compare to the expected outcome <expectation>.
@4.2.x
Examples:
| issueNumber | subtest | datasrc | args | expectation |
#begin

# github1601: member_not_found should be ERROR by default; --skip-strict-collection-membership downgrades to WARNING
| 1601 | 1 | "github1601" | "-R pds4.bundle --skip-context-validation -t {datasrc}/bundle_test_1601.xml" | "summary:totalErrors=1,summary:referentialIntegrity:failed=1,summary:messageTypes:error.integrity.member_not_found=1" |
| 1601 | 2 | "github1601" | "-R pds4.bundle --skip-context-validation --skip-strict-collection-membership -t {datasrc}/bundle_test_1601.xml" | "summary:totalWarnings=1,summary:messageTypes:warning.integrity.member_not_found=1" |

#end
Loading
Loading