diff --git a/rest-api/src/main/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidator.java b/rest-api/src/main/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidator.java index dd598587d..5cb0ba1eb 100644 --- a/rest-api/src/main/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidator.java +++ b/rest-api/src/main/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidator.java @@ -28,17 +28,21 @@ public SpecPiiValidator(PcfValidationInfoMap file) { @Override public void validateApmTinNpiCombination(Node node, NodeValidator validator) { - validateInvalidApmCombinations(node, validator); - validateMissingApmCombinations(node, validator); + List npiList = Arrays.asList( + node.getValue(NATIONAL_PROVIDER_IDENTIFIER).split(",")); + List tinList = Arrays.asList( + node.getValue(TAX_PAYER_IDENTIFICATION_NUMBER).split(",")); + if (npiList.size() != tinList.size()) { + validator.addError(Detail.forProblemAndNode(ProblemCode.INCORRECT_API_NPI_COMBINATION, node)); + } else { + validateInvalidApmCombinations(node, validator, npiList, tinList); + validateMissingApmCombinations(node, validator, npiList, tinList); + } } - private void validateInvalidApmCombinations(Node node, NodeValidator validator) { + private void validateInvalidApmCombinations(Node node, NodeValidator validator, List npiList, List tinList) { String program = node.getValue(PROGRAM_NAME); String apm = getApmEntityId(node, program); - List npiList = Arrays.asList( - node.getValue(NATIONAL_PROVIDER_IDENTIFIER).split(",")); - List tinList = Arrays.asList( - node.getValue(TAX_PAYER_IDENTIFICATION_NUMBER).split(",")); Map>> apmToTinNpiMap = file.getApmTinNpiCombinationMap(); if (apmToTinNpiMap == null || StringUtils.isEmpty(apm)) { @@ -59,16 +63,14 @@ private void validateInvalidApmCombinations(Node node, NodeValidator validator) } } - private void validateMissingApmCombinations(Node node, NodeValidator validator) { + private void validateMissingApmCombinations(Node node, NodeValidator validator, List npiList, List tinList) { String program = node.getValue(PROGRAM_NAME); String apm = getApmEntityId(node, program); - List npiList = Arrays.asList( - node.getValue(NATIONAL_PROVIDER_IDENTIFIER).split(",")); - List tinList = Arrays.asList( - node.getValue(TAX_PAYER_IDENTIFICATION_NUMBER).split(",")); List tinNpiCombinations = createTinNpiMap(tinList, npiList); + // Adding some sonar exclusions, to avoid cognitive complexity. + // The conditions here would probably need to be checked in the specific order Map>> apmToTinNpiMap = file.getApmTinNpiCombinationMap(); if (apmToTinNpiMap == null || StringUtils.isEmpty(apm)) { validator.addWarning(Detail.forProblemAndNode(ProblemCode.MISSING_API_TIN_NPI_FILE, node)); @@ -77,25 +79,29 @@ private void validateMissingApmCombinations(Node node, NodeValidator validator) if (tinNpisMap != null) { for(final Map.Entry> currentEntry: tinNpisMap.entrySet()) { for (final String currentNpi : currentEntry.getValue()) { - boolean combinationExists = false; - for (TinNpiCombination currentCombination : tinNpiCombinations) { - if (currentEntry.getKey().equalsIgnoreCase((currentCombination.getTin())) && - currentNpi.equalsIgnoreCase(currentCombination.getNpi())) { - combinationExists = true; - break; - } - } - if (!combinationExists) { - LocalizedProblem error = ProblemCode.PCF_MISSING_COMBINATION - .format(currentNpi, getMaskedTin(currentEntry.getKey()), apm); - validator.addWarning(Detail.forProblemAndNode(error, node)); - } + checkTinNpiCombinations(node, validator, apm, currentEntry, tinNpiCombinations, currentNpi); } } } } } + private void checkTinNpiCombinations(Node node, NodeValidator validator, String apm, Map.Entry> currentEntry, List tinNpiCombinations, String currentNpi) { + boolean combinationExists = false; + for (TinNpiCombination currentCombination : tinNpiCombinations) { + if (currentEntry.getKey().equalsIgnoreCase((currentCombination.getTin())) && + currentNpi.equalsIgnoreCase(currentCombination.getNpi())) { + combinationExists = true; + break; + } + } + if (!combinationExists) { + LocalizedProblem error = ProblemCode.PCF_MISSING_COMBINATION + .format(currentNpi, getMaskedTin(currentEntry.getKey()), apm); + validator.addWarning(Detail.forProblemAndNode(error, node)); + } + } + private String getApmEntityId(final Node node, final String program) { String apm; if (PCF_PROGRAM_NAME.equalsIgnoreCase(program)) { diff --git a/rest-api/src/test/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidatorTest.java b/rest-api/src/test/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidatorTest.java index 7072efe69..ae6063a7f 100644 --- a/rest-api/src/test/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidatorTest.java +++ b/rest-api/src/test/java/gov/cms/qpp/conversion/api/internal/pii/SpecPiiValidatorTest.java @@ -110,6 +110,21 @@ protected void performValidation(Node node) { Truth.assertThat(nodeValidator.viewWarnings().get(0).getErrorCode()).isEqualTo(108); } + @Test + void testNpiTinSizeMismatch() throws Exception { + SpecPiiValidator validator = validator("DogCow_APM", "DogCow_NPI"); + Node node = node("Invalid_Apm", "DogCow_NPI,DogCow_NPI2", "DogCow", PCF_PROGRAM_NAME); + System.out.println(node); + NodeValidator nodeValidator = new NodeValidator() { + @Override + protected void performValidation(Node node) { + // Empty Function. Just adding a comment to avoid sonar flag. + } + }; + validator.validateApmTinNpiCombination(node, nodeValidator); + Truth.assertThat(nodeValidator.viewWarnings().get(0).getErrorCode()).isEqualTo(80); + } + private SpecPiiValidator validator(String apm, String npi) throws Exception { return new SpecPiiValidator(createSpecFile(apm, npi)); }