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

[APHL-798][APHL-799] release and package should throw an error if a ValueSet doesn't have a condition #756

Merged
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -601,14 +601,20 @@ public Bundle createReleaseBundle(IdType idType, String releaseLabel, String ver
// removed duplicates and add
List<RelatedArtifact> distinctResolvedRelatedArtifacts = new ArrayList<>();
for (RelatedArtifact resolvedRelatedArtifact: rootArtifactAdapter.getRelatedArtifact()) {
if (!distinctResolvedRelatedArtifacts.stream().anyMatch(distinctRelatedArtifact -> distinctRelatedArtifact.getResource().equals(resolvedRelatedArtifact.getResource()) && distinctRelatedArtifact.getType().equals(resolvedRelatedArtifact.getType()))) {
boolean isDistinct = !distinctResolvedRelatedArtifacts.stream().anyMatch(distinctRelatedArtifact -> {
boolean referenceNotInArray = distinctRelatedArtifact.getResource().equals(resolvedRelatedArtifact.getResource());
boolean typeMatches = distinctRelatedArtifact.getType().equals(resolvedRelatedArtifact.getType());
return referenceNotInArray && typeMatches;
});
if (isDistinct) {
distinctResolvedRelatedArtifacts.add(resolvedRelatedArtifact);
// preserve Extensions if found
originalDependenciesWithExtensions
.stream()
.filter(originalDep -> originalDep.getResource().equals(resolvedRelatedArtifact.getResource()))
.findFirst()
.ifPresent(dep -> {
checkIfValueSetNeedsCondition(null, dep, fhirDal);
resolvedRelatedArtifact.getExtension().addAll(dep.getExtension());
originalDependenciesWithExtensions.removeIf(ra -> ra.getResource().equals(resolvedRelatedArtifact.getResource()));
});
Expand Down Expand Up @@ -840,7 +846,7 @@ public Bundle createPackageBundle(IdType id, FhirDal fhirDal, List<String> capab
}
setCorrectBundleType(count,offset,packagedBundle);
pageBundleBasedOnCountAndOffset(count, offset, packagedBundle);
handleValueSetReferenceExtensions(resource, packagedBundle.getEntry());
handleValueSetReferenceExtensions(resource, packagedBundle.getEntry(), fhirDal);
return packagedBundle;
}
/**
Expand Down Expand Up @@ -893,12 +899,35 @@ private void setCorrectBundleType(Integer count, Integer offset, Bundle bundle)
bundle.setType(BundleType.TRANSACTION);
}
}
private void checkIfValueSetNeedsCondition(MetadataResource resource, RelatedArtifact relatedArtifact, FhirDal fhirDal) throws UnprocessableEntityException {
if (resource == null
&& relatedArtifact != null
&& relatedArtifact.hasResource()
&& Canonicals.getResourceType(relatedArtifact.getResource()).equals("ValueSet")) {
List<MetadataResource> searchResults = getResourcesFromBundle(searchResourceByUrl(relatedArtifact.getResource(), fhirDal));
if (searchResults.size() > 0) {
resource = searchResults.get(0);
}
}
if (resource != null && resource.getResourceType() == ResourceType.ValueSet) {
ValueSet valueSet = (ValueSet)resource;
boolean isLeaf = !valueSet.hasCompose() || (valueSet.hasCompose() && valueSet.getCompose().getIncludeFirstRep().getValueSet().size() == 0);
Optional<Extension> maybeConditionExtension = Optional.ofNullable(relatedArtifact)
.map(RelatedArtifact::getExtension)
.map(list -> {
return list.stream().filter(ext -> ext.getUrl().equalsIgnoreCase(valueSetConditionUrl)).findFirst().orElse(null);
});
if (isLeaf && !maybeConditionExtension.isPresent()) {
throw new UnprocessableEntityException("Missing condition on ValueSet : " + valueSet.getUrl());
}
}
}
/**
* ValueSets can be part of multiple artifacts at the same time. Certain properties are tracked/managed in the manifest to avoid conflicts with other artifacts. This function sets those properties on the ValueSets themselves at export / $package time
* @param manifest the resource containing all RelatedArtifact references
* @param bundleEntries the list of packaged resources to modify according to the extensions on the manifest relatedArtifact references
*/
private void handleValueSetReferenceExtensions(MetadataResource manifest, List<BundleEntryComponent> bundleEntries) throws UnprocessableEntityException, IllegalArgumentException {
private void handleValueSetReferenceExtensions(MetadataResource manifest, List<BundleEntryComponent> bundleEntries, FhirDal fhirDal) throws UnprocessableEntityException, IllegalArgumentException {
KnowledgeArtifactAdapter<MetadataResource> adapter = new KnowledgeArtifactAdapter<MetadataResource>(manifest);
List<RelatedArtifact> relatedArtifactsWithPreservedExtension = getRelatedArtifactsWithPreservedExtensions(adapter.getDependencies());
bundleEntries.stream()
Expand All @@ -908,24 +937,20 @@ private void handleValueSetReferenceExtensions(MetadataResource manifest, List<B
// remove any existing Priority and Conditions
List<UsageContext> usageContexts = removeExistingReferenceExtensionData(valueSet.getUseContext());
valueSet.setUseContext(usageContexts);
// List<UsageContext> usageContexts = valueSet.getUseContext();
Optional<RelatedArtifact> maybeVSRelatedArtifact = relatedArtifactsWithPreservedExtension.stream().filter(ra -> Canonicals.getUrl(ra.getResource()).equals(valueSet.getUrl())).findFirst();
checkIfValueSetNeedsCondition(valueSet, maybeVSRelatedArtifact.orElse(null), fhirDal);
// If leaf valueset
if (!valueSet.hasCompose()
|| (valueSet.hasCompose() && valueSet.getCompose().getIncludeFirstRep().getValueSet().size() == 0)) {
// If Condition extension is present
maybeVSRelatedArtifact
.map(ra -> ra.getExtension())
.ifPresentOrElse(
.ifPresent(
// add Conditions
exts -> {
exts.stream()
.filter(ext -> ext.getUrl().equalsIgnoreCase(valueSetConditionUrl))
.forEach(ext -> tryAddCondition(usageContexts, (CodeableConcept) ext.getValue()));
},
// else throw error
() -> {
throw new UnprocessableEntityException("Missing condition for ValueSet : " + valueSet.getUrl());
});
}
// update Priority
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,31 @@ void release_preserve_extensions() {
Extension condition = maybeRelatedArtifactWithUseContextExtension.get().getExtensionByUrl(KnowledgeArtifactProcessor.valueSetConditionUrl);
assertTrue(((CodeableConcept) condition.getValue()).getCoding().get(0).getCode().equals("49649001"));
}

@Test
void release_test_condition_missing() {
loadTransaction("ersd-small-approved-draft-no-conditions.json");
loadResource("artifactAssessment-search-parameter.json");
Parameters params = parameters(
part("version", new StringType("1.2.3.23")),
part("versionBehavior", new StringType("default"))
);
UnprocessableEntityException noConditionExtension = null;
try {
getClient().operation()
.onInstance(specificationLibReference)
.named("$release")
.withParameters(params)
.returnResourceType(Bundle.class)
.execute();
} catch (UnprocessableEntityException e) {
// TODO: handle exception
noConditionExtension = e;
}
assertNotNull(noConditionExtension);
assertTrue(noConditionExtension.getMessage().contains("Missing condition"));
}

@Test
void release_test_artifactComment_updated() {
loadTransaction("ersd-release-missing-approvalDate-validation-bundle.json");
Expand Down Expand Up @@ -1295,6 +1320,26 @@ void packageOperation_big_bundle() {
assertTrue(packagedBundle.getEntry().size() == loadedBundle.getEntry().size());
}

@Test
void package_test_condition_missing() {
loadTransaction("ersd-small-approved-draft-no-conditions.json");
loadResource("artifactAssessment-search-parameter.json");
UnprocessableEntityException noConditionExtension = null;
try {
getClient().operation()
.onInstance(specificationLibReference)
.named("$package")
.withNoParameters(Parameters.class)
.returnResourceType(Bundle.class)
.execute();
} catch (UnprocessableEntityException e) {
// TODO: handle exception
noConditionExtension = e;
}
assertNotNull(noConditionExtension);
assertTrue(noConditionExtension.getMessage().contains("Missing condition"));
}

@Test
void validateOperation() {
Bundle ersdExampleSpecBundle = (Bundle) loadResource("ersd-bundle-example.json");
Expand Down
Loading