Skip to content

Commit

Permalink
Update package operation output to distinguish collection and transac…
Browse files Browse the repository at this point in the history
…tion (#749)

* [APHL-778] update package output to distinguish collection and transaction

* [APHL-778] Updated tests

* [APHL-778] no total for transactions

---------

Co-authored-by: taha.attari@smilecdr.com <taha.attari@smilecdr.com>
  • Loading branch information
TahaAttari and taha.attari@smilecdr.com authored Nov 14, 2023
1 parent da22352 commit bd562ab
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.CodeType;
Expand Down Expand Up @@ -764,9 +765,12 @@ public Bundle createPackageBundle(IdType id, FhirDal fhirDal, List<String> capab
if (packageOnly != null) {
throw new NotImplementedOperationException("This repository is not implementing packageOnly at this time");
}
if (count != null && count < 0) {
throw new UnprocessableEntityException("'count' must be non-negative");
}
MetadataResource resource = (MetadataResource) fhirDal.read(id);
// TODO: In the case of a released (active) root Library we can depend on the relatedArtifacts as a comprehensive manifest
Bundle packagedBundle = new Bundle().setType(Bundle.BundleType.COLLECTION);
Bundle packagedBundle = new Bundle();
if (include != null
&& include.size() == 1
&& include.stream().anyMatch((includedType) -> includedType.equals("artifact"))) {
Expand All @@ -782,33 +786,58 @@ public Bundle createPackageBundle(IdType id, FhirDal fhirDal, List<String> capab
List<BundleEntryComponent> included = findUnsupportedInclude(packagedBundle.getEntry(),include);
packagedBundle.setEntry(included);
}
packagedBundle.setTotal(packagedBundle.getEntry().size());
setCorrectBundleType(count,offset,packagedBundle);
pageBundleBasedOnCountAndOffset(count, offset, packagedBundle);
handlePriority(resource, packagedBundle.getEntry());
return packagedBundle;
}
private void pageBundleBasedOnCountAndOffset(Integer count, Integer offset, Bundle bundle) {
if (offset != null) {
List<BundleEntryComponent> entries = packagedBundle.getEntry();
List<BundleEntryComponent> entries = bundle.getEntry();
Integer bundleSize = entries.size();
if (offset < bundleSize) {
packagedBundle.setEntry(entries.subList(offset, bundleSize));
bundle.setEntry(entries.subList(offset, bundleSize));
} else {
packagedBundle.setEntry(Arrays.asList());
bundle.setEntry(Arrays.asList());
}
}
if (count != null) {
// repeat these two from earlier because we might modify / replace
// the entries list at any time
List<BundleEntryComponent> entries = packagedBundle.getEntry();
List<BundleEntryComponent> entries = bundle.getEntry();
Integer bundleSize = entries.size();
if (count < bundleSize){
packagedBundle.setEntry(entries.subList(0, count));
bundle.setEntry(entries.subList(0, count));
} else {
// there are not enough entries in the bundle to page, so
// we return all of them no change
}
}
handlePriority(resource, packagedBundle.getEntry());
return packagedBundle;
}

void handlePriority(MetadataResource resource, List<BundleEntryComponent> bundleEntries) {
private void setCorrectBundleType(Integer count, Integer offset, Bundle bundle) {
// if the bundle is paged then it must be of type = collection
// and modified to follow bundle.type constraints
// if not, set type = transaction
// special case of count = 0 -> set type = searchset so we can display bundle.total
if (count != null && count == 0) {
bundle.setType(BundleType.SEARCHSET);
bundle.setTotal(bundle.getEntry().size());
} else if (
(offset != null && offset > 0) ||
(count != null && count < bundle.getEntry().size())
) {
bundle.setType(BundleType.COLLECTION);
List<BundleEntryComponent> removedRequest = bundle.getEntry().stream()
.map(entry -> {
entry.setRequest(null);
return entry;
}).collect(Collectors.toList());
bundle.setEntry(removedRequest);
} else {
bundle.setType(BundleType.TRANSACTION);
}
}
private void handlePriority(MetadataResource resource, List<BundleEntryComponent> bundleEntries) {
KnowledgeArtifactAdapter<MetadataResource> adapter = new KnowledgeArtifactAdapter<MetadataResource>(resource);
List<ValueSet> valueSets = bundleEntries.stream()
.filter(entry -> entry.getResource().getResourceType().equals(ResourceType.ValueSet))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.CodeableConcept;
Expand Down Expand Up @@ -1013,6 +1014,8 @@ void packageOperation_should_respect_count_offset() {
.returnResourceType(Bundle.class)
.execute();
assertTrue(offset4Bundle.getEntry().size() == (countZeroBundle.getTotal() - 4));
assertTrue(offset4Bundle.getType() == BundleType.COLLECTION);
assertTrue(offset4Bundle.hasTotal() == false);
Parameters offsetMaxParams = parameters(
part("offset", new IntegerType(countZeroBundle.getTotal()))
);
Expand All @@ -1036,6 +1039,72 @@ void packageOperation_should_respect_count_offset() {
assertTrue(offsetMaxRandomCountBundle.getEntry().size() == 0);
}
@Test
void packageOperation_different_bundle_types() {
loadTransaction("ersd-small-active-bundle.json");
Parameters countZeroParams = parameters(
part("count", new IntegerType(0))
);
Bundle countZeroBundle = getClient().operation()
.onInstance(specificationLibReference)
.named("$crmi.package")
.withParameters(countZeroParams)
.returnResourceType(Bundle.class)
.execute();
assertTrue(countZeroBundle.getType() == BundleType.SEARCHSET);
Parameters countSevenParams = parameters(
part("count", new IntegerType(7))
);
Bundle countSevenBundle = getClient().operation()
.onInstance(specificationLibReference)
.named("$crmi.package")
.withParameters(countSevenParams)
.returnResourceType(Bundle.class)
.execute();
assertTrue(countSevenBundle.getType() == BundleType.TRANSACTION);
Parameters countFourParams = parameters(
part("count", new IntegerType(4))
);
Bundle countFourBundle = getClient().operation()
.onInstance(specificationLibReference)
.named("$crmi.package")
.withParameters(countFourParams)
.returnResourceType(Bundle.class)
.execute();
assertTrue(countFourBundle.getType() == BundleType.COLLECTION);
// these assertions test for Bundle base profile conformance when type = collection
assertFalse(countFourBundle.getEntry().stream().anyMatch(entry -> entry.hasRequest()));
assertFalse(countFourBundle.hasTotal());
Parameters offsetOneParams = parameters(
part("offset", new IntegerType(1))
);
Bundle offsetOneBundle = getClient().operation()
.onInstance(specificationLibReference)
.named("$crmi.package")
.withParameters(offsetOneParams)
.returnResourceType(Bundle.class)
.execute();
assertTrue(offsetOneBundle.getType() == BundleType.COLLECTION);
// these assertions test for Bundle base profile conformance when type = collection
assertFalse(offsetOneBundle.getEntry().stream().anyMatch(entry -> entry.hasRequest()));
assertFalse(offsetOneBundle.hasTotal());

Parameters countOneOffsetOneParams = parameters(
part("count", new IntegerType(1)),
part("offset", new IntegerType(1))
);
Bundle countOneOffsetOneBundle = getClient().operation()
.onInstance(specificationLibReference)
.named("$crmi.package")
.withParameters(countOneOffsetOneParams)
.returnResourceType(Bundle.class)
.execute();
assertTrue(countOneOffsetOneBundle.getType() == BundleType.COLLECTION);
// these assertions test for Bundle base profile conformance when type = collection
assertFalse(countOneOffsetOneBundle.getEntry().stream().anyMatch(entry -> entry.hasRequest()));
assertFalse(countOneOffsetOneBundle.hasTotal());

}
@Test
void packageOperation_should_conditionally_create() {
loadTransaction("ersd-small-active-bundle.json");
Parameters emptyParams = parameters();
Expand Down

0 comments on commit bd562ab

Please sign in to comment.