|
19 | 19 | import java.util.Optional; |
20 | 20 | import org.hl7.fhir.dstu3.model.Bundle; |
21 | 21 | import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; |
| 22 | +import org.hl7.fhir.dstu3.model.CodeType; |
22 | 23 | import org.hl7.fhir.dstu3.model.Enumerations; |
| 24 | +import org.hl7.fhir.dstu3.model.Extension; |
23 | 25 | import org.hl7.fhir.dstu3.model.IdType; |
24 | 26 | import org.hl7.fhir.dstu3.model.Library; |
25 | 27 | import org.hl7.fhir.dstu3.model.Parameters; |
26 | 28 | import org.hl7.fhir.dstu3.model.Period; |
27 | 29 | import org.hl7.fhir.dstu3.model.PlanDefinition; |
| 30 | +import org.hl7.fhir.dstu3.model.Reference; |
28 | 31 | import org.hl7.fhir.dstu3.model.RelatedArtifact; |
29 | 32 | import org.hl7.fhir.dstu3.model.StringType; |
| 33 | +import org.hl7.fhir.dstu3.model.UriType; |
30 | 34 | import org.hl7.fhir.dstu3.model.ValueSet; |
31 | 35 | import org.junit.jupiter.api.BeforeEach; |
32 | 36 | import org.junit.jupiter.api.Test; |
33 | 37 | import org.opencds.cqf.fhir.cr.visitor.DraftVisitor; |
| 38 | +import org.opencds.cqf.fhir.cr.visitor.ReleaseVisitor; |
34 | 39 | import org.opencds.cqf.fhir.utility.Canonicals; |
| 40 | +import org.opencds.cqf.fhir.utility.Constants; |
35 | 41 | import org.opencds.cqf.fhir.utility.adapter.IKnowledgeArtifactAdapter; |
36 | 42 | import org.opencds.cqf.fhir.utility.adapter.ILibraryAdapter; |
37 | 43 | import org.opencds.cqf.fhir.utility.adapter.dstu3.AdapterFactory; |
@@ -239,4 +245,170 @@ void draftOperation_version_format_test() { |
239 | 245 | assertNull(versionException, "Non-semver version '" + version + "' should not throw for format"); |
240 | 246 | } |
241 | 247 | } |
| 248 | + |
| 249 | + private static Parameters getContainedParameters(Library library, String reference) { |
| 250 | + return (Parameters) library.getContained().stream() |
| 251 | + .filter(contained -> contained.getId().equals(reference.substring(1))) |
| 252 | + .findFirst() |
| 253 | + .orElse(null); |
| 254 | + } |
| 255 | + |
| 256 | + @Test |
| 257 | + void draft_should_restore_authored_expansion_params_after_release() { |
| 258 | + var bundle = (Bundle) jsonParser.parseResource( |
| 259 | + DraftVisitorTests.class.getResourceAsStream("Bundle-versioned-and-unversioned-dependency.json")); |
| 260 | + repo.transaction(bundle); |
| 261 | + var releaseVisitor = new ReleaseVisitor(repo); |
| 262 | + var originalLibrary = repo.read(Library.class, new IdType("Library/SpecificationLibrary")) |
| 263 | + .copy(); |
| 264 | + var releaseLibraryAdapter = new AdapterFactory().createLibrary(originalLibrary.copy()); |
| 265 | + var releaseParams = |
| 266 | + parameters(part("version", new StringType("1.2.3")), part("versionBehavior", new CodeType("force"))); |
| 267 | + var releaseReturnBundle = (Bundle) releaseLibraryAdapter.accept(releaseVisitor, releaseParams); |
| 268 | + var maybeReleasedLib = releaseReturnBundle.getEntry().stream() |
| 269 | + .filter(entry -> entry.getResponse().getLocation().contains("Library/SpecificationLibrary")) |
| 270 | + .findFirst(); |
| 271 | + assertTrue(maybeReleasedLib.isPresent()); |
| 272 | + var releasedLibrary = repo.read( |
| 273 | + Library.class, new IdType(maybeReleasedLib.get().getResponse().getLocation())); |
| 274 | + |
| 275 | + // Sanity check the release step actually captured the author's input separately from the |
| 276 | + // processing timen exp-params |
| 277 | + var releasedInputExt = releasedLibrary.getExtensionByUrl(Constants.CQF_INPUT_EXPANSION_PARAMETERS); |
| 278 | + assertNotNull(releasedInputExt); |
| 279 | + var releasedInputParams = |
| 280 | + getContainedParameters(releasedLibrary, ((Reference) releasedInputExt.getValue()).getReference()); |
| 281 | + assertEquals(1, releasedInputParams.getParameter().size()); |
| 282 | + var releasedExpExt = releasedLibrary.getExtensionByUrl(Constants.CQF_EXPANSION_PARAMETERS); |
| 283 | + assertNotNull(releasedExpExt); |
| 284 | + var releasedExpParams = |
| 285 | + getContainedParameters(releasedLibrary, ((Reference) releasedExpExt.getValue()).getReference()); |
| 286 | + assertEquals(3, releasedExpParams.getParameter().size()); |
| 287 | + |
| 288 | + // Now draft the released library and confirm exp-params is reset to the 1 authored |
| 289 | + // parameter, and input-exp-params (and its extension) are gone |
| 290 | + var draftLibraryAdapter = new AdapterFactory().createLibrary(releasedLibrary.copy()); |
| 291 | + var draftVisitor = new DraftVisitor(repo); |
| 292 | + var draftParams = parameters(part("version", new StringType("1.2.4"))); |
| 293 | + var draftReturnBundle = (Bundle) draftLibraryAdapter.accept(draftVisitor, draftParams); |
| 294 | + var maybeDraftLib = draftReturnBundle.getEntry().stream() |
| 295 | + .filter(entry -> entry.getResponse().getLocation().contains("Library")) |
| 296 | + .map(entry -> |
| 297 | + repo.read(Library.class, new IdType(entry.getResponse().getLocation()))) |
| 298 | + .filter(lib -> originalLibrary.getUrl().equals(lib.getUrl())) |
| 299 | + .findFirst(); |
| 300 | + assertTrue(maybeDraftLib.isPresent()); |
| 301 | + var draftLibrary = maybeDraftLib.get(); |
| 302 | + |
| 303 | + assertNull(draftLibrary.getExtensionByUrl(Constants.CQF_INPUT_EXPANSION_PARAMETERS)); |
| 304 | + assertNull(getContainedParameters(draftLibrary, "#input-exp-params")); |
| 305 | + var draftExpExt = draftLibrary.getExtensionByUrl(Constants.CQF_EXPANSION_PARAMETERS); |
| 306 | + assertNotNull(draftExpExt); |
| 307 | + var draftExpParams = getContainedParameters(draftLibrary, ((Reference) draftExpExt.getValue()).getReference()); |
| 308 | + assertEquals(1, draftExpParams.getParameter().size()); |
| 309 | + assertEquals( |
| 310 | + "http://loinc.org|2.76", |
| 311 | + ((UriType) draftExpParams.getParameter().get(0).getValue()).getValue()); |
| 312 | + } |
| 313 | + |
| 314 | + @Test |
| 315 | + void restoreInputExpansionParams_copies_authored_params_and_cleans_up() { |
| 316 | + var library = new Library(); |
| 317 | + library.setId("test-library"); |
| 318 | + |
| 319 | + var inputExpParams = new Parameters(); |
| 320 | + inputExpParams.setId("input-exp-params"); |
| 321 | + inputExpParams.addParameter().setName("authored-param").setValue(new StringType("authored-value")); |
| 322 | + library.addContained(inputExpParams); |
| 323 | + library.addExtension( |
| 324 | + new Extension(Constants.CQF_INPUT_EXPANSION_PARAMETERS, new Reference("#input-exp-params"))); |
| 325 | + |
| 326 | + var expParams = new Parameters(); |
| 327 | + expParams.setId("exp-params"); |
| 328 | + expParams.addParameter().setName("system-version").setValue(new StringType("http://example.com|1.0.0")); |
| 329 | + expParams.addParameter().setName("system-version").setValue(new StringType("http://example.com/other|2.0.0")); |
| 330 | + library.addContained(expParams); |
| 331 | + library.addExtension(new Extension(Constants.CQF_EXPANSION_PARAMETERS, new Reference("#exp-params"))); |
| 332 | + |
| 333 | + var adapter = new AdapterFactory().createLibrary(library); |
| 334 | + org.opencds.cqf.fhir.cr.visitor.dstu3.DraftVisitor.restoreInputExpansionParams(adapter); |
| 335 | + |
| 336 | + // assert input-exp-params contained element and extension have been removed |
| 337 | + assertNull(library.getExtensionByUrl(Constants.CQF_INPUT_EXPANSION_PARAMETERS)); |
| 338 | + assertNull(getContainedParameters(library, "#input-exp-params")); |
| 339 | + |
| 340 | + // assert params from input-exp-params have been copied to exp-params |
| 341 | + var restoredExpParamsExt = library.getExtensionByUrl(Constants.CQF_EXPANSION_PARAMETERS); |
| 342 | + assertNotNull(restoredExpParamsExt); |
| 343 | + var restoredExpParams = |
| 344 | + getContainedParameters(library, ((Reference) restoredExpParamsExt.getValue()).getReference()); |
| 345 | + assertEquals(1, restoredExpParams.getParameter().size()); |
| 346 | + assertEquals( |
| 347 | + "authored-value", |
| 348 | + ((StringType) restoredExpParams.getParameter().get(0).getValue()).getValue()); |
| 349 | + } |
| 350 | + |
| 351 | + @Test |
| 352 | + void restoreInputExpansionParams_resets_to_empty_when_author_specified_none() { |
| 353 | + var library = new Library(); |
| 354 | + library.setId("test-library"); |
| 355 | + |
| 356 | + // Author's captured input had zero parameters |
| 357 | + var inputExpParams = new Parameters(); |
| 358 | + inputExpParams.setId("input-exp-params"); |
| 359 | + library.addContained(inputExpParams); |
| 360 | + library.addExtension( |
| 361 | + new Extension(Constants.CQF_INPUT_EXPANSION_PARAMETERS, new Reference("#input-exp-params"))); |
| 362 | + |
| 363 | + // exp-params has processing-time entries which should be overwritten |
| 364 | + var expParams = new Parameters(); |
| 365 | + expParams.setId("exp-params"); |
| 366 | + expParams.addParameter().setName("system-version").setValue(new StringType("http://example.com|1.0.0")); |
| 367 | + library.addContained(expParams); |
| 368 | + library.addExtension(new Extension(Constants.CQF_EXPANSION_PARAMETERS, new Reference("#exp-params"))); |
| 369 | + |
| 370 | + var adapter = new AdapterFactory().createLibrary(library); |
| 371 | + org.opencds.cqf.fhir.cr.visitor.dstu3.DraftVisitor.restoreInputExpansionParams(adapter); |
| 372 | + |
| 373 | + // assert input-exp-params contained element and extension have been removed |
| 374 | + assertNull(library.getExtensionByUrl(Constants.CQF_INPUT_EXPANSION_PARAMETERS)); |
| 375 | + assertNull(getContainedParameters(library, "#input-exp-params")); |
| 376 | + |
| 377 | + // assert empty params from input-exp-params have been copied to exp-params |
| 378 | + var restoredExpParamsExt = library.getExtensionByUrl(Constants.CQF_EXPANSION_PARAMETERS); |
| 379 | + assertNotNull(restoredExpParamsExt); |
| 380 | + var restoredExpParams = |
| 381 | + getContainedParameters(library, ((Reference) restoredExpParamsExt.getValue()).getReference()); |
| 382 | + assertTrue(restoredExpParams.getParameter().isEmpty()); |
| 383 | + } |
| 384 | + |
| 385 | + @Test |
| 386 | + void restoreInputExpansionParams_removes_dangling_extension_when_contained_resource_missing() { |
| 387 | + var library = new Library(); |
| 388 | + library.setId("test-library"); |
| 389 | + // Extension references a contained resource that was never actually added |
| 390 | + library.addExtension( |
| 391 | + new Extension(Constants.CQF_INPUT_EXPANSION_PARAMETERS, new Reference("#input-exp-params"))); |
| 392 | + |
| 393 | + var adapter = new AdapterFactory().createLibrary(library); |
| 394 | + org.opencds.cqf.fhir.cr.visitor.dstu3.DraftVisitor.restoreInputExpansionParams(adapter); |
| 395 | + |
| 396 | + // assert dangling extension was removed |
| 397 | + assertNull(library.getExtensionByUrl(Constants.CQF_INPUT_EXPANSION_PARAMETERS)); |
| 398 | + // Nothing to restore from, so exp-params should never have been created |
| 399 | + assertNull(library.getExtensionByUrl(Constants.CQF_EXPANSION_PARAMETERS)); |
| 400 | + assertTrue(library.getContained().isEmpty()); |
| 401 | + } |
| 402 | + |
| 403 | + @Test |
| 404 | + void restoreInputExpansionParams_is_noop_when_no_extension_present() { |
| 405 | + var library = new Library(); |
| 406 | + library.setId("test-library"); |
| 407 | + |
| 408 | + var adapter = new AdapterFactory().createLibrary(library); |
| 409 | + org.opencds.cqf.fhir.cr.visitor.dstu3.DraftVisitor.restoreInputExpansionParams(adapter); |
| 410 | + |
| 411 | + assertTrue(library.getExtension().isEmpty()); |
| 412 | + assertTrue(library.getContained().isEmpty()); |
| 413 | + } |
242 | 414 | } |
0 commit comments