From ec0021cd409cd821826a6e113684c4ab35a753a2 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 18 Jun 2024 10:25:07 -0400 Subject: [PATCH 01/19] Add error checker for duplicate codesystem codes (#6014) * Add error checker * Add changelog * Address review comment --- ...6014-add-codesystem-dupe-code-checker.yaml | 7 ++++ .../term/TermCodeSystemStorageSvcImpl.java | 28 +++++++++++++ .../r4/FhirResourceDaoR4CodeSystemTest.java | 42 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6014-add-codesystem-dupe-code-checker.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6014-add-codesystem-dupe-code-checker.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6014-add-codesystem-dupe-code-checker.yaml new file mode 100644 index 00000000000..e951d583b90 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6014-add-codesystem-dupe-code-checker.yaml @@ -0,0 +1,7 @@ +--- +type: add +issue: 6014 +title: "When uploading an invalid CodeSystem to the JPA server containing + duplicate codes, the server responded with an unhelpful error message + referring to a database constraint error. This has been fixed so that + a more informative error message is returned." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java index 15998b0e8e6..af01a692a32 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermCodeSystemStorageSvcImpl.java @@ -50,8 +50,10 @@ import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.ObjectUtil; +import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.ValidateUtil; import jakarta.annotation.Nonnull; import jakarta.persistence.EntityManager; @@ -294,6 +296,8 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc { theResourceEntity.getIdDt().getValue(), theCodeSystem.getContentElement().getValueAsString()); + detectDuplicatesInCodeSystem(theCodeSystem); + Long pid = (Long) theCodeSystem.getUserData(RESOURCE_PID_KEY); assert pid != null; JpaPid codeSystemResourcePid = JpaPid.fromId(pid); @@ -339,6 +343,30 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc { } } + private static void detectDuplicatesInCodeSystem(CodeSystem theCodeSystem) { + detectDuplicatesInCodeSystem(theCodeSystem.getConcept(), new HashSet<>()); + } + + private static void detectDuplicatesInCodeSystem( + List theCodeList, Set theFoundCodesBuffer) { + for (var next : theCodeList) { + if (isNotBlank(next.getCode())) { + if (!theFoundCodesBuffer.add(next.getCode())) { + /* + * Note: We could possibly modify this behaviour to be forgiving, and just + * ignore duplicates. The only issue is that concepts can have properties, + * designations, etc. and it could be dangerous to just pick one and ignore the + * other. So the safer thing seems to be to just throw an error. + */ + throw new PreconditionFailedException(Msg.code(2528) + "Duplicate concept detected in CodeSystem: " + + UrlUtil.sanitizeUrlPart(next.getCode())); + } + } + // Test child concepts within the parent concept + detectDuplicatesInCodeSystem(next.getConcept(), theFoundCodesBuffer); + } + } + @Override @Transactional public IIdType storeNewCodeSystemVersion( diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4CodeSystemTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4CodeSystemTest.java index ae5650ba3be..b2b3ba4f4a3 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4CodeSystemTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4CodeSystemTest.java @@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; import ca.uhn.fhir.jpa.test.Batch2JobHelper; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.CodeSystem; @@ -20,6 +21,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test { @@ -191,6 +193,46 @@ public class FhirResourceDaoR4CodeSystemTest extends BaseJpaR4Test { return id; } + @Test + public void testCodeSystemWithDuplicateCode() { + CodeSystem cs = new CodeSystem(); + cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); + cs.setUrl("http://foo"); + cs.setVersion("1.0"); + cs.addConcept().setCode("CODE0").setDisplay("Code0"); + cs.addConcept().setCode("CODE1").setDisplay("Code1"); + cs.addConcept().setCode("CODE1").setDisplay("Code1"); + cs.addConcept().setCode("CODE2").setDisplay("Code2"); + + try { + myCodeSystemDao.create(cs, mySrd); + fail(); + } catch (PreconditionFailedException e) { + assertThat(e.getMessage()).contains("Duplicate concept detected in CodeSystem: CODE1"); + } + } + + @Test + public void testCodeSystemWithDuplicateCodeInChild() { + CodeSystem cs = new CodeSystem(); + cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); + cs.setUrl("http://foo"); + cs.setVersion("1.0"); + + CodeSystem.ConceptDefinitionComponent parent = cs.addConcept().setCode("CODE0").setDisplay("Code0"); + parent.addConcept().setCode("CODE1").setDisplay("Code1"); + parent.addConcept().setCode("CODE1").setDisplay("Code1"); + cs.addConcept().setCode("CODE2").setDisplay("Code2"); + + try { + myCodeSystemDao.create(cs, mySrd); + fail(); + } catch (PreconditionFailedException e) { + assertThat(e.getMessage()).contains("Duplicate concept detected in CodeSystem: CODE1"); + } + } + + @AfterAll public static void afterClassClearContext() { TermReindexingSvcImpl.setForceSaveDeferredAlwaysForUnitTest(false); From 47d6e357b63c5e969ac7ef4efc862b221e33f13c Mon Sep 17 00:00:00 2001 From: James Agnew Date: Tue, 18 Jun 2024 13:05:29 -0400 Subject: [PATCH 02/19] Fix JPA nullable primitive columns (#5926) * Fix JPA nullable primitive columns * Add changelog * Spotless * License headers * Migration fix * Spotless * Cleanup * Cleanup * Add task skipping * Update docs * CLeanup * Spotless * Address review comments * Test fix * HAPI FHIR version bump --- hapi-deployable-pom/pom.xml | 2 +- hapi-fhir-android/pom.xml | 2 +- hapi-fhir-base/pom.xml | 2 +- hapi-fhir-bom/pom.xml | 4 +- hapi-fhir-checkstyle/pom.xml | 2 +- hapi-fhir-cli/hapi-fhir-cli-api/pom.xml | 2 +- .../cli/BaseFlywayMigrateDatabaseCommand.java | 14 +- hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 2 +- hapi-fhir-cli/pom.xml | 2 +- hapi-fhir-client-okhttp/pom.xml | 2 +- hapi-fhir-client/pom.xml | 2 +- hapi-fhir-converter/pom.xml | 2 +- hapi-fhir-dist/pom.xml | 2 +- hapi-fhir-docs/pom.xml | 2 +- ...26-fix-jpa-nullable-primitive-columns.yaml | 4 + ...5926-skip-migrators-when-initializing.yaml | 7 + hapi-fhir-jacoco/pom.xml | 2 +- hapi-fhir-jaxrsserver-base/pom.xml | 2 +- hapi-fhir-jpa/pom.xml | 2 +- hapi-fhir-jpaserver-base/pom.xml | 2 +- .../jpa/entity/Batch2JobInstanceEntity.java | 4 +- .../jpa/entity/Batch2WorkChunkEntity.java | 10 +- .../jpa/entity/HapiFhirEnversRevision.java | 2 +- .../ca/uhn/fhir/jpa/entity/TermConcept.java | 3 +- .../tasks/HapiFhirJpaMigrationTasks.java | 273 +++++++++++++----- .../reindex/InstanceReindexServiceImpl.java | 8 +- .../pom.xml | 2 +- hapi-fhir-jpaserver-hfql/pom.xml | 2 +- hapi-fhir-jpaserver-ips/pom.xml | 2 +- hapi-fhir-jpaserver-mdm/pom.xml | 2 +- hapi-fhir-jpaserver-model/pom.xml | 2 +- .../jpa/model/entity/BinaryStorageEntity.java | 2 +- .../model/entity/ResourceHistoryTable.java | 4 +- .../ResourceIndexedComboStringUnique.java | 4 +- .../ResourceIndexedSearchParamCoords.java | 17 +- .../fhir/jpa/model/entity/ResourceTable.java | 20 +- hapi-fhir-jpaserver-searchparam/pom.xml | 2 +- hapi-fhir-jpaserver-subscription/pom.xml | 2 +- hapi-fhir-jpaserver-test-dstu2/pom.xml | 2 +- hapi-fhir-jpaserver-test-dstu3/pom.xml | 2 +- hapi-fhir-jpaserver-test-r4/pom.xml | 2 +- hapi-fhir-jpaserver-test-r4b/pom.xml | 2 +- hapi-fhir-jpaserver-test-r5/pom.xml | 2 +- hapi-fhir-jpaserver-test-utilities/pom.xml | 2 +- hapi-fhir-jpaserver-uhnfhirtest/pom.xml | 2 +- hapi-fhir-server-cds-hooks/pom.xml | 2 +- hapi-fhir-server-mdm/pom.xml | 2 +- hapi-fhir-server-openapi/pom.xml | 2 +- hapi-fhir-server/pom.xml | 2 +- .../hapi-fhir-caching-api/pom.xml | 2 +- .../hapi-fhir-caching-caffeine/pom.xml | 4 +- .../hapi-fhir-caching-guava/pom.xml | 2 +- .../hapi-fhir-caching-testing/pom.xml | 2 +- hapi-fhir-serviceloaders/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../hapi-fhir-spring-boot-samples/pom.xml | 2 +- .../hapi-fhir-spring-boot-starter/pom.xml | 2 +- hapi-fhir-spring-boot/pom.xml | 2 +- hapi-fhir-sql-migrate/pom.xml | 2 +- .../ca/uhn/fhir/jpa/migrate/HapiMigrator.java | 47 ++- .../fhir/jpa/migrate/MigrationTaskList.java | 9 + .../jpa/migrate/MigrationTaskSkipper.java | 3 +- .../jpa/migrate/taskdef/AddColumnTask.java | 7 +- .../migrate/taskdef/AddTableByColumnTask.java | 2 +- .../jpa/migrate/taskdef/ArbitrarySqlTask.java | 3 + .../fhir/jpa/migrate/taskdef/BaseTask.java | 140 ++++----- .../taskdef/ForceIdMigrationFixTask.java | 7 + .../migrate/taskdef/InitializeSchemaTask.java | 11 +- .../jpa/migrate/taskdef/ModifyColumnTask.java | 5 +- .../jpa/migrate/taskdef/RenameTableTask.java | 1 + .../tasks/SchemaInitializationProvider.java | 9 +- .../fhir/jpa/migrate/tasks/api/Builder.java | 80 +++-- .../jpa/migrate/tasks/api/TaskFlagEnum.java | 65 +++++ .../migrate/HapiMigrationStorageSvcTest.java | 2 +- .../uhn/fhir/jpa/migrate/HapiMigratorIT.java | 110 ++++++- .../taskdef/AddTableByColumnTaskTest.java | 2 +- .../jpa/migrate/taskdef/ModifyColumnTest.java | 17 +- .../hapi-migrator-it-init-schema/h2.sql | 6 + hapi-fhir-storage-batch2-jobs/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-storage-batch2/pom.xml | 2 +- hapi-fhir-storage-cr/pom.xml | 2 +- hapi-fhir-storage-mdm/pom.xml | 2 +- hapi-fhir-storage-test-utilities/pom.xml | 2 +- hapi-fhir-storage/pom.xml | 2 +- hapi-fhir-structures-dstu2.1/pom.xml | 2 +- hapi-fhir-structures-dstu2/pom.xml | 2 +- hapi-fhir-structures-dstu3/pom.xml | 2 +- hapi-fhir-structures-hl7org-dstu2/pom.xml | 2 +- hapi-fhir-structures-r4/pom.xml | 2 +- hapi-fhir-structures-r4b/pom.xml | 2 +- hapi-fhir-structures-r5/pom.xml | 2 +- hapi-fhir-test-utilities/pom.xml | 2 +- .../jpa/JpaModelScannerAndVerifier.java | 21 +- hapi-fhir-testpage-overlay/pom.xml | 2 +- .../pom.xml | 2 +- hapi-fhir-validation-resources-dstu2/pom.xml | 2 +- hapi-fhir-validation-resources-dstu3/pom.xml | 2 +- hapi-fhir-validation-resources-r4/pom.xml | 2 +- hapi-fhir-validation-resources-r4b/pom.xml | 2 +- hapi-fhir-validation-resources-r5/pom.xml | 2 +- hapi-fhir-validation/pom.xml | 2 +- hapi-tinder-plugin/pom.xml | 2 +- hapi-tinder-test/pom.xml | 2 +- pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- 111 files changed, 723 insertions(+), 354 deletions(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-fix-jpa-nullable-primitive-columns.yaml create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-skip-migrators-when-initializing.yaml create mode 100644 hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/TaskFlagEnum.java create mode 100644 hapi-fhir-sql-migrate/src/test/resources/hapi-migrator-it-init-schema/h2.sql diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index 30e1ccb5d6d..259a53de8ae 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index 9060665d1b3..2319bf9a4cc 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index fcc60e05e2b..03e4d113f4c 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 3a00980cded..1dec9586365 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT pom HAPI FHIR BOM @@ -12,7 +12,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index 2a21a1796fe..4bdbe08114a 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index 3555f67f63c..e53b6e39633 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseFlywayMigrateDatabaseCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseFlywayMigrateDatabaseCommand.java index 5d049b79246..dbc5be5ad41 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseFlywayMigrateDatabaseCommand.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseFlywayMigrateDatabaseCommand.java @@ -26,8 +26,6 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.List; @@ -40,12 +38,12 @@ import static org.apache.commons.lang3.StringUtils.defaultString; * NB since 2019-12-05: This class is kind of weirdly named now, since it can either use Flyway or not use Flyway */ public abstract class BaseFlywayMigrateDatabaseCommand extends BaseCommand { - private static final Logger ourLog = LoggerFactory.getLogger(BaseFlywayMigrateDatabaseCommand.class); public static final String MIGRATE_DATABASE = "migrate-database"; public static final String NO_COLUMN_SHRINK = "no-column-shrink"; - public static final String STRICT_ORDER = "strict-order"; public static final String SKIP_VERSIONS = "skip-versions"; + public static final String ENABLE_HEAVYWEIGHT_MIGRATIONS = "enable-heavyweight-migrations"; + private Set myFlags; private String myMigrationTableName; @@ -100,6 +98,12 @@ public abstract class BaseFlywayMigrateDatabaseCommand extends B SKIP_VERSIONS, "Versions", "A comma separated list of schema versions to skip. E.g. 4_1_0.20191214.2,4_1_0.20191214.4"); + addOptionalOption( + retVal, + null, + ENABLE_HEAVYWEIGHT_MIGRATIONS, + false, + "If this flag is set, additional migration tasks will be executed that are considered unnecessary to execute on a database with a significant amount of data loaded. This option is not generally necessary."); return retVal; } @@ -125,6 +129,7 @@ public abstract class BaseFlywayMigrateDatabaseCommand extends B boolean dryRun = theCommandLine.hasOption("r"); boolean noColumnShrink = theCommandLine.hasOption(BaseFlywayMigrateDatabaseCommand.NO_COLUMN_SHRINK); + boolean runHeavyweight = theCommandLine.hasOption(ENABLE_HEAVYWEIGHT_MIGRATIONS); String flags = theCommandLine.getOptionValue("x"); myFlags = Arrays.stream(defaultString(flags).split(",")) @@ -139,6 +144,7 @@ public abstract class BaseFlywayMigrateDatabaseCommand extends B migrator.createMigrationTableIfRequired(); migrator.setDryRun(dryRun); + migrator.setRunHeavyweightSkippableTasks(runHeavyweight); migrator.setNoColumnShrink(noColumnShrink); String skipVersions = theCommandLine.getOptionValue(BaseFlywayMigrateDatabaseCommand.SKIP_VERSIONS); addTasks(migrator, skipVersions); diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index b6c73678960..45ecdebddca 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index 6745d62518b..2eb4c555392 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index 9a7ac810865..b2fa315c0ee 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index de0d7f14afe..b5667ad3e0c 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index 9883e898092..3cfc40c6258 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index 9e001be27ab..f008db1fd69 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index ba6c6912dbc..ab973c0f6b8 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-fix-jpa-nullable-primitive-columns.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-fix-jpa-nullable-primitive-columns.yaml new file mode 100644 index 00000000000..a444a25f548 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-fix-jpa-nullable-primitive-columns.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 5926 +title: "A number of columns in the JPA schema use primitive types (and therefore can never have a null value) but aren't marked as non-null." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-skip-migrators-when-initializing.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-skip-migrators-when-initializing.yaml new file mode 100644 index 00000000000..cd3506ee7af --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/5926-skip-migrators-when-initializing.yaml @@ -0,0 +1,7 @@ +--- +type: fix +issue: 5926 +title: "A regression in HAPI FHIR 6.4.0 meant that ther JPA server schema migrator ran all tasks + even when the database was initially empty and the schema was being initialized by script. + This did not produce any incorrect results, but did impact the amount of time taken to initialize + an empty database. This has been corrected." diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index 7d35c5c03fa..7cc8d05502a 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index aa02e821f97..300c0cb720b 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index 145cdb4224f..5885d7a365e 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index d628e03ee5c..230c0a53a73 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2JobInstanceEntity.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2JobInstanceEntity.java index bcf0a6cc0d9..3da31581d26 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2JobInstanceEntity.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2JobInstanceEntity.java @@ -119,13 +119,13 @@ public class Batch2JobInstanceEntity implements Serializable { @Column(name = "WORK_CHUNKS_PURGED", nullable = false) private boolean myWorkChunksPurged; - @Column(name = "PROGRESS_PCT") + @Column(name = "PROGRESS_PCT", nullable = false) private double myProgress; @Column(name = "ERROR_MSG", length = ERROR_MSG_MAX_LENGTH, nullable = true) private String myErrorMessage; - @Column(name = "ERROR_COUNT") + @Column(name = "ERROR_COUNT", nullable = false) private int myErrorCount; @Column(name = "EST_REMAINING", length = TIME_REMAINING_LENGTH, nullable = true) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2WorkChunkEntity.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2WorkChunkEntity.java index db60706f476..26bccd58bf9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2WorkChunkEntity.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/Batch2WorkChunkEntity.java @@ -138,6 +138,10 @@ public class Batch2WorkChunkEntity implements Serializable { /** * The number of times the work chunk has had its state set back to POLL_WAITING. + *

+ * TODO: Note that this column was added in 7.2.0, so it is nullable in order to + * account for existing rows that were added before the column was added. In + * the future we should make this non-null. */ @Column(name = "POLL_ATTEMPTS", nullable = true) private Integer myPollAttempts; @@ -145,7 +149,9 @@ public class Batch2WorkChunkEntity implements Serializable { /** * Default constructor for Hibernate. */ - public Batch2WorkChunkEntity() {} + public Batch2WorkChunkEntity() { + myPollAttempts = 0; + } /** * Projection constructor for no-data path. @@ -184,7 +190,7 @@ public class Batch2WorkChunkEntity implements Serializable { myRecordsProcessed = theRecordsProcessed; myWarningMessage = theWarningMessage; myNextPollTime = theNextPollTime; - myPollAttempts = thePollAttempts; + myPollAttempts = thePollAttempts != null ? thePollAttempts : 0; } public static Batch2WorkChunkEntity fromWorkChunk(WorkChunk theWorkChunk) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/HapiFhirEnversRevision.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/HapiFhirEnversRevision.java index 3a930be0e27..68c7ac12f7e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/HapiFhirEnversRevision.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/HapiFhirEnversRevision.java @@ -58,7 +58,7 @@ public class HapiFhirEnversRevision implements Serializable { @SequenceGenerator(name = "SEQ_HFJ_REVINFO", sequenceName = "SEQ_HFJ_REVINFO") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_HFJ_REVINFO") @RevisionNumber - @Column(name = "REV") + @Column(name = "REV", nullable = false) private long myRev; @RevisionTimestamp diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java index d238278bcfe..5f056979fea 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java @@ -117,11 +117,12 @@ public class TermConcept implements Serializable { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn( name = "CODESYSTEM_PID", + nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID")) private TermCodeSystemVersion myCodeSystem; - @Column(name = "CODESYSTEM_PID", insertable = false, updatable = false) + @Column(name = "CODESYSTEM_PID", insertable = false, updatable = false, nullable = false) @GenericField(name = "myCodeSystemVersionPid") private long myCodeSystemVersionPid; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index 0db112c60fd..7bcebb19fda 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -25,7 +25,6 @@ import ca.uhn.fhir.jpa.entity.BulkImportJobEntity; import ca.uhn.fhir.jpa.entity.Search; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.taskdef.ArbitrarySqlTask; -import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; import ca.uhn.fhir.jpa.migrate.taskdef.CalculateHashesTask; import ca.uhn.fhir.jpa.migrate.taskdef.CalculateOrdinalDatesTask; import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum; @@ -33,6 +32,7 @@ import ca.uhn.fhir.jpa.migrate.taskdef.ForceIdMigrationCopyTask; import ca.uhn.fhir.jpa.migrate.taskdef.ForceIdMigrationFixTask; import ca.uhn.fhir.jpa.migrate.tasks.api.BaseMigrationTasks; import ca.uhn.fhir.jpa.migrate.tasks.api.Builder; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam; import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable; @@ -135,6 +135,121 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { .toColumn("RES_ID") .references("HFJ_RESOURCE", "RES_ID"); } + + /* + * Make a bunch of columns non-nullable. Note that we won't actually apply this migration + * on the live system as it would take a loooooong time to execute these on heavily loaded + * databases. + */ + // Skipping numbers 20240601.1 and 20240601.2 as they were found to not + // be needed during code review. + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.3", "SP_HAS_LINKS") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.4", "SP_COORDS_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.5", "SP_DATE_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.6", "SP_NUMBER_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.7", "SP_QUANTITY_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.8", "SP_QUANTITY_NRML_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.9", "SP_STRING_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.10", "SP_TOKEN_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.11", "SP_URI_PRESENT") + .nonNullable() + .withType(ColumnTypeEnum.BOOLEAN) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_RESOURCE") + .modifyColumn("20240601.12", "RES_VER") + .nonNullable() + .withType(ColumnTypeEnum.LONG) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("TRM_CONCEPT") + .modifyColumn("20240601.13", "CODESYSTEM_PID") + .nonNullable() + .withType(ColumnTypeEnum.LONG) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("BT2_JOB_INSTANCE") + .modifyColumn("20240601.14", "PROGRESS_PCT") + .nonNullable() + .withType(ColumnTypeEnum.DOUBLE) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("BT2_JOB_INSTANCE") + .modifyColumn("20240601.15", "ERROR_COUNT") + .nonNullable() + .withType(ColumnTypeEnum.INT) + .heavyweightSkipByDefault() + .failureAllowed(); + version.onTable("HFJ_BINARY_STORAGE_BLOB") + .modifyColumn("20240601.16", "BLOB_SIZE") + .nonNullable() + .withType(ColumnTypeEnum.LONG) + .heavyweightSkipByDefault() + .failureAllowed(); + + /* + * Add RES_ID to two indexes on HFJ_RES_VER which support history operations. + * This makes server and type level _history work properly on large databases + * on postgres. These are both marked as heavyweightSkipByDefault because the + * necessary reindexing would be very expensive for a rarely used FHIR feature. + */ + version.onTable("HFJ_RES_VER") + .dropIndex("20240601.17", "IDX_RESVER_TYPE_DATE") + .heavyweightSkipByDefault(); + version.onTable("HFJ_RES_VER") + .addIndex("20240601.18", "IDX_RESVER_TYPE_DATE") + .unique(false) + .withColumns("RES_TYPE", "RES_UPDATED", "RES_ID") + .heavyweightSkipByDefault(); + version.onTable("HFJ_RES_VER") + .dropIndex("20240601.19", "IDX_RESVER_DATE") + .heavyweightSkipByDefault(); + version.onTable("HFJ_RES_VER") + .addIndex("20240601.20", "IDX_RESVER_DATE") + .unique(false) + .withColumns("RES_UPDATED", "RES_ID") + .heavyweightSkipByDefault(); } protected void init720() { @@ -162,15 +277,15 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { binaryStorageBlobTable .renameColumn("20240404.1", "BLOB_ID", "CONTENT_ID") .getLastAddedTask() - .ifPresent(BaseTask::doNothing); + .ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING)); binaryStorageBlobTable .renameColumn("20240404.2", "BLOB_SIZE", "CONTENT_SIZE") .getLastAddedTask() - .ifPresent(BaseTask::doNothing); + .ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING)); binaryStorageBlobTable .renameColumn("20240404.3", "BLOB_HASH", "CONTENT_HASH") .getLastAddedTask() - .ifPresent(BaseTask::doNothing); + .ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING)); binaryStorageBlobTable .modifyColumn("20240404.4", "BLOB_DATA") @@ -262,7 +377,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { // Move forced_id constraints to hfj_resource and the new fhir_id column // Note: we leave the HFJ_FORCED_ID.IDX_FORCEDID_TYPE_FID index in place to support old writers for a while. - version.addTask(new ForceIdMigrationCopyTask(version.getRelease(), "20231018.1").setDoNothing(true)); + version.addTask( + new ForceIdMigrationCopyTask(version.getRelease(), "20231018.1").addFlag(TaskFlagEnum.DO_NOTHING)); Builder.BuilderWithTableName hfjResource = version.onTable("HFJ_RESOURCE"); // commented out to make numeric space for the fix task below. @@ -331,7 +447,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { } // This fix was bad for MSSQL, it has been set to do nothing. - version.addTask(new ForceIdMigrationFixTask(version.getRelease(), "20231213.1").setDoNothing(true)); + version.addTask( + new ForceIdMigrationFixTask(version.getRelease(), "20231213.1").addFlag(TaskFlagEnum.DO_NOTHING)); // This fix will work for MSSQL or Oracle. version.addTask(new ForceIdMigrationFixTask(version.getRelease(), "20231222.1")); @@ -814,8 +931,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_RES_VER") .modifyColumn("20230421.1", "RES_TEXT_VC") .nullable() - .failureAllowed() - .withType(ColumnTypeEnum.TEXT); + .withType(ColumnTypeEnum.TEXT) + .failureAllowed(); { // add hash_norm to res_id to speed up joins on a second string. @@ -1751,8 +1868,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_RES_LINK") .modifyColumn("20210505.1", "SRC_PATH") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 500); + .withType(ColumnTypeEnum.STRING, 500) + .failureAllowed(); } private void init530() { @@ -1813,8 +1930,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { quantityTable .modifyColumn("20210116.1", "SP_VALUE") .nullable() - .failureAllowed() - .withType(ColumnTypeEnum.DOUBLE); + .withType(ColumnTypeEnum.DOUBLE) + .failureAllowed(); // HFJ_RES_LINK version.onTable("HFJ_RES_LINK") @@ -2011,8 +2128,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_RES_VER") .modifyColumn("20200220.1", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); // // Drop unused column @@ -2168,38 +2285,38 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_SPIDX_STRING") .modifyColumn("20200420.36", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_COORDS") .modifyColumn("20200420.37", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_NUMBER") .modifyColumn("20200420.38", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_TOKEN") .modifyColumn("20200420.39", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_DATE") .modifyColumn("20200420.40", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_URI") .modifyColumn("20200420.41", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); version.onTable("HFJ_SPIDX_QUANTITY") .modifyColumn("20200420.42", "SP_MISSING") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.BOOLEAN); + .withType(ColumnTypeEnum.BOOLEAN) + .failureAllowed(); // Add support for integer comparisons during day-precision date search. Builder.BuilderWithTableName spidxDate = version.onTable("HFJ_SPIDX_DATE"); @@ -2309,38 +2426,38 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_SPIDX_NUMBER") .modifyColumn("20190920.1", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_COORDS") .modifyColumn("20190920.2", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_TOKEN") .modifyColumn("20190920.3", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_STRING") .modifyColumn("20190920.4", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_DATE") .modifyColumn("20190920.5", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_QUANTITY") .modifyColumn("20190920.6", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); version.onTable("HFJ_SPIDX_URI") .modifyColumn("20190920.7", "RES_ID") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.LONG); + .withType(ColumnTypeEnum.LONG) + .failureAllowed(); // HFJ_SEARCH version.onTable("HFJ_SEARCH") @@ -2469,33 +2586,33 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_RESOURCE") .modifyColumn("20191002.1", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); version.onTable("HFJ_RES_VER") .modifyColumn("20191002.2", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); version.onTable("HFJ_HISTORY_TAG") .modifyColumn("20191002.3", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); version.onTable("HFJ_RES_LINK") .modifyColumn("20191002.4", "SOURCE_RESOURCE_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); version.onTable("HFJ_RES_LINK") .modifyColumn("20191002.5", "TARGET_RESOURCE_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); version.onTable("HFJ_RES_TAG") .modifyColumn("20191002.6", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 40); + .withType(ColumnTypeEnum.STRING, 40) + .failureAllowed(); // TermConceptDesignation version.startSectionWithMessage("Processing table: TRM_CONCEPT_DESIG"); @@ -2765,18 +2882,18 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_SPIDX_COORDS") .modifyColumn("20190814.9", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_DATE") .modifyColumn("20190814.10", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_STRING") .modifyColumn("20190814.11", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_STRING") .addColumn("20190814.12", "HASH_IDENTITY") .nullable() @@ -2788,50 +2905,50 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.onTable("HFJ_SPIDX_COORDS") .modifyColumn("20190814.14", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_QUANTITY") .modifyColumn("20190814.15", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_QUANTITY").dropColumn("20190814.16", "HASH_UNITS_AND_VALPREFIX"); version.onTable("HFJ_SPIDX_QUANTITY").dropColumn("20190814.17", "HASH_VALPREFIX"); version.onTable("HFJ_SPIDX_NUMBER") .modifyColumn("20190814.18", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_TOKEN") .modifyColumn("20190814.19", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_URI") .modifyColumn("20190814.20", "RES_TYPE") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 100); + .withType(ColumnTypeEnum.STRING, 100) + .failureAllowed(); version.onTable("HFJ_SPIDX_URI") .modifyColumn("20190814.21", "SP_URI") .nullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 254); + .withType(ColumnTypeEnum.STRING, 254) + .failureAllowed(); version.onTable("TRM_CODESYSTEM") .modifyColumn("20190814.22", "CODE_SYSTEM_URI") .nonNullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 200); + .withType(ColumnTypeEnum.STRING, 200) + .failureAllowed(); version.onTable("TRM_CODESYSTEM") .modifyColumn("20190814.23", "CS_NAME") .nullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 200); + .withType(ColumnTypeEnum.STRING, 200) + .failureAllowed(); version.onTable("TRM_CODESYSTEM_VER") .modifyColumn("20190814.24", "CS_VERSION_ID") .nullable() - .failureAllowed() - .withType(ColumnTypeEnum.STRING, 200); + .withType(ColumnTypeEnum.STRING, 200) + .failureAllowed(); } private void init360() { // 20180918 - 20181112 diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java index 8a69d6ef8e0..aeb8b9e31cd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java @@ -524,8 +524,12 @@ public class InstanceReindexServiceImpl implements IInstanceReindexService { String theParamTypeName) { Parameters.ParametersParameterComponent retVal = super.addIndexValue(theAction, theParent, theParam, theParamTypeName); - retVal.addPart().setName("Latitude").setValue(new DecimalType(theParam.getLatitude())); - retVal.addPart().setName("Longitude").setValue(new DecimalType(theParam.getLongitude())); + if (theParam.getLatitude() != null) { + retVal.addPart().setName("Latitude").setValue(new DecimalType(theParam.getLatitude())); + } + if (theParam.getLongitude() != null) { + retVal.addPart().setName("Longitude").setValue(new DecimalType(theParam.getLongitude())); + } return retVal; } } diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml index e3ba27996ee..f0f55e9506f 100644 --- a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-hfql/pom.xml b/hapi-fhir-jpaserver-hfql/pom.xml index 2ae9ad02678..aaa57b40118 100644 --- a/hapi-fhir-jpaserver-hfql/pom.xml +++ b/hapi-fhir-jpaserver-hfql/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-ips/pom.xml b/hapi-fhir-jpaserver-ips/pom.xml index 88e32f7e2d6..2aea1bf2f19 100644 --- a/hapi-fhir-jpaserver-ips/pom.xml +++ b/hapi-fhir-jpaserver-ips/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index 669f52ea6ba..7a7c9f7ab64 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 1df82dac9f4..c453a3c30ab 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BinaryStorageEntity.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BinaryStorageEntity.java index c6b046e0bff..f6d77040763 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BinaryStorageEntity.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/BinaryStorageEntity.java @@ -45,7 +45,7 @@ public class BinaryStorageEntity { @Column(name = "RESOURCE_ID", length = 100, nullable = false) private String myResourceId; - @Column(name = "BLOB_SIZE", nullable = true) + @Column(name = "BLOB_SIZE", nullable = false) private long mySize; @Column(name = "CONTENT_TYPE", nullable = false, length = 100) diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java index 6348ce579b3..8ef37d8cdca 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceHistoryTable.java @@ -60,9 +60,9 @@ import java.util.Collection; columnNames = {"RES_ID", "RES_VER"}) }, indexes = { - @Index(name = "IDX_RESVER_TYPE_DATE", columnList = "RES_TYPE,RES_UPDATED"), + @Index(name = "IDX_RESVER_TYPE_DATE", columnList = "RES_TYPE,RES_UPDATED,RES_ID"), @Index(name = "IDX_RESVER_ID_DATE", columnList = "RES_ID,RES_UPDATED"), - @Index(name = "IDX_RESVER_DATE", columnList = "RES_UPDATED") + @Index(name = "IDX_RESVER_DATE", columnList = "RES_UPDATED,RES_ID") }) public class ResourceHistoryTable extends BaseHasResource implements Serializable { public static final String IDX_RESVER_ID_VER = "IDX_RESVER_ID_VER"; diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java index 830fc6270aa..e61941cb611 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java @@ -135,12 +135,14 @@ public class ResourceIndexedComboStringUnique extends BasePartitionable myIndexString = theIndexString; } + @Override public ResourceTable getResource() { return myResource; } + @Override public void setResource(ResourceTable theResource) { - Validate.notNull(theResource); + Validate.notNull(theResource, "theResource must not be null"); myResource = theResource; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamCoords.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamCoords.java index 40718b09df8..a66e5f6f564 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamCoords.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamCoords.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.model.entity; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.model.api.IQueryParameterType; +import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import jakarta.persistence.Entity; @@ -56,13 +57,11 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP private static final long serialVersionUID = 1L; - @Column(name = "SP_LATITUDE") - // @FullTextField - public double myLatitude; + @Column(name = "SP_LATITUDE", nullable = true) + public Double myLatitude; - @Column(name = "SP_LONGITUDE") - // @FullTextField - public double myLongitude; + @Column(name = "SP_LONGITUDE", nullable = true) + public Double myLongitude; @Id @SequenceGenerator(name = "SEQ_SPIDX_COORDS", sequenceName = "SEQ_SPIDX_COORDS") @@ -162,7 +161,8 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP myId = theId; } - public double getLatitude() { + @Nullable + public Double getLatitude() { return myLatitude; } @@ -171,7 +171,8 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP return this; } - public double getLongitude() { + @Nullable + public Double getLongitude() { return myLongitude; } diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java index 39f85198aec..e897ae71786 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceTable.java @@ -142,7 +142,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private String myHashSha256; - @Column(name = "SP_HAS_LINKS") + @Column(name = "SP_HAS_LINKS", nullable = false) @OptimisticLock(excluded = true) private boolean myHasLinks; @@ -203,7 +203,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsCoords; - @Column(name = "SP_COORDS_PRESENT") + @Column(name = "SP_COORDS_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsCoordsPopulated; @@ -215,7 +215,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsDate; - @Column(name = "SP_DATE_PRESENT") + @Column(name = "SP_DATE_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsDatePopulated; @@ -227,7 +227,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas orphanRemoval = false) private Collection myParamsNumber; - @Column(name = "SP_NUMBER_PRESENT") + @Column(name = "SP_NUMBER_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsNumberPopulated; @@ -239,7 +239,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsQuantity; - @Column(name = "SP_QUANTITY_PRESENT") + @Column(name = "SP_QUANTITY_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsQuantityPopulated; @@ -260,7 +260,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas * NOTE : use Boolean class instead of boolean primitive, in order to set the existing rows to null * since 5.3.0 */ - @Column(name = "SP_QUANTITY_NRML_PRESENT") + @Column(name = "SP_QUANTITY_NRML_PRESENT", nullable = false) @OptimisticLock(excluded = true) private Boolean myParamsQuantityNormalizedPopulated = Boolean.FALSE; @@ -272,7 +272,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsString; - @Column(name = "SP_STRING_PRESENT") + @Column(name = "SP_STRING_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsStringPopulated; @@ -284,7 +284,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsToken; - @Column(name = "SP_TOKEN_PRESENT") + @Column(name = "SP_TOKEN_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsTokenPopulated; @@ -296,7 +296,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas @OptimisticLock(excluded = true) private Collection myParamsUri; - @Column(name = "SP_URI_PRESENT") + @Column(name = "SP_URI_PRESENT", nullable = false) @OptimisticLock(excluded = true) private boolean myParamsUriPopulated; @@ -404,7 +404,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas private Boolean mySearchUrlPresent = false; @Version - @Column(name = "RES_VER") + @Column(name = "RES_VER", nullable = false) private long myVersion; @OneToMany(mappedBy = "myResourceTable", fetch = FetchType.LAZY) diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 675432baedc..7199a9ad0bc 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index 928e4754d88..3840df8a715 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu2/pom.xml b/hapi-fhir-jpaserver-test-dstu2/pom.xml index 6d526c2967a..ed44b54b06d 100644 --- a/hapi-fhir-jpaserver-test-dstu2/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu3/pom.xml b/hapi-fhir-jpaserver-test-dstu3/pom.xml index 75747b68a7f..ebf988b81f9 100644 --- a/hapi-fhir-jpaserver-test-dstu3/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu3/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4/pom.xml b/hapi-fhir-jpaserver-test-r4/pom.xml index 9ac14b62183..a05fcda4c4b 100644 --- a/hapi-fhir-jpaserver-test-r4/pom.xml +++ b/hapi-fhir-jpaserver-test-r4/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml index 75d284dddda..5ad8360e422 100644 --- a/hapi-fhir-jpaserver-test-r4b/pom.xml +++ b/hapi-fhir-jpaserver-test-r4b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r5/pom.xml b/hapi-fhir-jpaserver-test-r5/pom.xml index d8ed3a11ea3..0585c6f87aa 100644 --- a/hapi-fhir-jpaserver-test-r5/pom.xml +++ b/hapi-fhir-jpaserver-test-r5/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 323a1e00051..ea643589d1b 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index da796517f5b..174a429705a 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-cds-hooks/pom.xml b/hapi-fhir-server-cds-hooks/pom.xml index 3bef5a5c5df..adbe430ad0f 100644 --- a/hapi-fhir-server-cds-hooks/pom.xml +++ b/hapi-fhir-server-cds-hooks/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index bddca577b5b..b7e48476ad6 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index c1f03e6eca8..c9f0f0a14c7 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index bc844b33a29..84c16998ebc 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml index a4eb90d2992..288431d981c 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml index 614cfc967b7..46a455edf0a 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ ca.uhn.hapi.fhir hapi-fhir-caching-api - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml index 322eb544e6c..1629077b0fd 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml index 782403fec87..d805e44028c 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml @@ -7,7 +7,7 @@ hapi-fhir ca.uhn.hapi.fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../pom.xml diff --git a/hapi-fhir-serviceloaders/pom.xml b/hapi-fhir-serviceloaders/pom.xml index 9a56ecfd799..87384aa0ef1 100644 --- a/hapi-fhir-serviceloaders/pom.xml +++ b/hapi-fhir-serviceloaders/pom.xml @@ -5,7 +5,7 @@ hapi-deployable-pom ca.uhn.hapi.fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 3e2354e4901..e49c57173a6 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index 12079ac6303..b042bb09416 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index f7631efb99b..0d55565aa40 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index e7be98afcd8..9776f578481 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index 3172d609d8a..b83b51ba012 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index ff62090b5d1..9c63563684f 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index afb870730a1..aa18dfb90ff 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index ce8c9c06fe6..a7cc58ab8fe 100644 --- a/hapi-fhir-sql-migrate/pom.xml +++ b/hapi-fhir-sql-migrate/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrator.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrator.java index dd8afdce598..17ee41c8032 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrator.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/HapiMigrator.java @@ -23,6 +23,7 @@ import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.migrate.dao.HapiMigrationDao; import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; import ca.uhn.fhir.jpa.migrate.taskdef.InitializeSchemaTask; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import ca.uhn.fhir.system.HapiSystemProperties; import ca.uhn.fhir.util.StopWatch; import com.google.common.annotations.VisibleForTesting; @@ -44,6 +45,7 @@ public class HapiMigrator { private static final Logger ourLog = LoggerFactory.getLogger(HapiMigrator.class); private final MigrationTaskList myTaskList = new MigrationTaskList(); private boolean myDryRun; + private boolean myRunHeavyweightSkippableTasks; private boolean myNoColumnShrink; private final DriverTypeEnum myDriverType; private final DataSource myDataSource; @@ -69,6 +71,24 @@ public class HapiMigrator { myDryRun = theDryRun; } + /** + * Should we run the tasks marked with {@link ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum#HEAVYWEIGHT_SKIP_BY_DEFAULT} + * + * @since 7.4.0 + */ + public boolean isRunHeavyweightSkippableTasks() { + return myRunHeavyweightSkippableTasks; + } + + /** + * Should we run the tasks marked with {@link ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum#HEAVYWEIGHT_SKIP_BY_DEFAULT} + * + * @since 7.4.0 + */ + public void setRunHeavyweightSkippableTasks(boolean theRunHeavyweightSkippableTasks) { + myRunHeavyweightSkippableTasks = theRunHeavyweightSkippableTasks; + } + public boolean isNoColumnShrink() { return myNoColumnShrink; } @@ -131,14 +151,27 @@ public class HapiMigrator { try (DriverTypeEnum.ConnectionProperties connectionProperties = getDriverType().newConnectionProperties(getDataSource())) { - newTaskList.forEach(next -> { + if (!isRunHeavyweightSkippableTasks()) { + newTaskList.removeIf(BaseTask::isHeavyweightSkippableTask); + } + + boolean initializedSchema = false; + for (BaseTask next : newTaskList) { + if (initializedSchema && !next.hasFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION)) { + ourLog.info("Skipping task {} because schema is being initialized", next.getMigrationVersion()); + recordTaskAsCompletedIfNotDryRun(next, 0L, true); + continue; + } + next.setDriverType(getDriverType()); next.setDryRun(isDryRun()); next.setNoColumnShrink(isNoColumnShrink()); next.setConnectionProperties(connectionProperties); executeTask(next, retval); - }); + + initializedSchema |= next.initializedSchema(); + } } } catch (Exception e) { ourLog.error("Migration failed", e); @@ -167,13 +200,13 @@ public class HapiMigrator { } preExecute(theTask); theTask.execute(); - postExecute(theTask, sw, true); + recordTaskAsCompletedIfNotDryRun(theTask, sw.getMillis(), true); theMigrationResult.changes += theTask.getChangesCount(); theMigrationResult.executedStatements.addAll(theTask.getExecutedStatements()); theMigrationResult.succeededTasks.add(theTask); } catch (SQLException | HapiMigrationException e) { theMigrationResult.failedTasks.add(theTask); - postExecute(theTask, sw, false); + recordTaskAsCompletedIfNotDryRun(theTask, sw.getMillis(), false); String description = theTask.getDescription(); if (isBlank(description)) { description = theTask.getClass().getSimpleName(); @@ -187,9 +220,9 @@ public class HapiMigrator { myCallbacks.forEach(action -> action.preExecution(theTask)); } - private void postExecute(BaseTask theNext, StopWatch theStopWatch, boolean theSuccess) { + private void recordTaskAsCompletedIfNotDryRun(BaseTask theNext, long theExecutionMillis, boolean theSuccess) { if (!theNext.isDryRun()) { - myHapiMigrationStorageSvc.saveTask(theNext, Math.toIntExact(theStopWatch.getMillis()), theSuccess); + myHapiMigrationStorageSvc.saveTask(theNext, Math.toIntExact(theExecutionMillis), theSuccess); } } @@ -211,7 +244,7 @@ public class HapiMigrator { } public void setCallbacks(@Nonnull List theCallbacks) { - Validate.notNull(theCallbacks); + Validate.notNull(theCallbacks, "theCallbacks must not be null"); myCallbacks = theCallbacks; } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskList.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskList.java index 668b51095c9..17a56f5a48b 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskList.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskList.java @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Collectors; public class MigrationTaskList implements Iterable { @@ -95,4 +96,12 @@ public class MigrationTaskList implements Iterable { .reduce((first, second) -> second) .orElse(null); } + + public void removeIf(Predicate theFilter) { + myTasks.removeIf(theFilter); + } + + public BaseTask[] toTaskArray() { + return myTasks.toArray(new BaseTask[0]); + } } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskSkipper.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskSkipper.java index 0e74e504380..6de5b05fe3d 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskSkipper.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/MigrationTaskSkipper.java @@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.migrate; import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +50,7 @@ public class MigrationTaskSkipper { for (BaseTask task : theTasks) { if (skippedVersionSet.contains(task.getMigrationVersion())) { ourLog.info("Will skip {}: {}", task.getMigrationVersion(), task.getDescription()); - task.setDoNothing(true); + task.addFlag(TaskFlagEnum.DO_NOTHING); } } } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java index d1e6ed52064..933b81d3e8a 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddColumnTask.java @@ -35,12 +35,6 @@ public class AddColumnTask extends BaseTableColumnTypeTask { return new AddColumnTask(null, null, ColumnNameCase.ALL_LOWER, theColumnDriverMappingOverrides); } - public AddColumnTask() { - this(null, null); - setDryRun(true); - myCheckForExistingTables = false; - } - public AddColumnTask(String theProductVersion, String theSchemaVersion) { super(theProductVersion, theSchemaVersion); } @@ -84,6 +78,7 @@ public class AddColumnTask extends BaseTableColumnTypeTask { break; case DERBY_EMBEDDED: case POSTGRES_9_4: + case COCKROACHDB_21_1: sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + typeStatement; break; case MSSQL_2012: diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTask.java index abf38c1672a..969a05b21c0 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTask.java @@ -56,7 +56,7 @@ public class AddTableByColumnTask extends BaseTableTask { this(theProductVersion, theSchemaVersion, null); } - private AddTableByColumnTask( + public AddTableByColumnTask( String theProductVersion, String theSchemaVersion, Comparator theColumnSortingRules) { super(theProductVersion, theSchemaVersion); myColumnSortingRules = theColumnSortingRules; diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java index e3b9459fe06..41dedf315a7 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTask.java @@ -46,6 +46,9 @@ public class ArbitrarySqlTask extends BaseTask { private String myExecuteOnlyIfTableExists; private List myConditionalOnExistenceOf = new ArrayList<>(); + /** + * Constructor + */ public ArbitrarySqlTask(VersionEnum theRelease, String theVersion, String theTableName, String theDescription) { super(theRelease.toString(), theVersion); myTableName = theTableName; diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java index 50b7859a0a9..f652fa0a938 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/BaseTask.java @@ -22,10 +22,14 @@ package ca.uhn.fhir.jpa.migrate.taskdef; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.HapiMigrationException; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import ca.uhn.fhir.system.HapiSystemProperties; +import jakarta.annotation.Nonnull; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.flywaydb.core.api.MigrationVersion; import org.intellij.lang.annotations.Language; import org.slf4j.Logger; @@ -38,6 +42,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,11 +56,42 @@ public abstract class BaseTask { private static final Pattern versionPattern = Pattern.compile(MIGRATION_VERSION_PATTERN); private final String myProductVersion; private final String mySchemaVersion; + private final List myPreconditions = new ArrayList<>(); + private final EnumSet myFlags = EnumSet.noneOf(TaskFlagEnum.class); + private final List myExecutedStatements = new ArrayList<>(); + /** + * Whether to check for existing tables + * before generating SQL + */ + protected boolean myCheckForExistingTables = true; + /** + * Whether to generate the SQL in a 'readable format' + */ + protected boolean myPrettyPrint = false; + private DriverTypeEnum.ConnectionProperties myConnectionProperties; private DriverTypeEnum myDriverType; private String myDescription; private Integer myChangesCount = 0; private boolean myDryRun; + private boolean myTransactional = true; + private Set myOnlyAppliesToPlatforms = new HashSet<>(); + private boolean myNoColumnShrink; + + protected BaseTask(String theProductVersion, String theSchemaVersion) { + myProductVersion = theProductVersion; + mySchemaVersion = theSchemaVersion; + } + + /** + * Adds a flag if it's not already present, otherwise this call is ignored. + * + * @param theFlag The flag, must not be null + */ + public BaseTask addFlag(@Nonnull TaskFlagEnum theFlag) { + myFlags.add(theFlag); + return this; + } /** * Some migrations can not be run in a transaction. @@ -65,48 +101,12 @@ public abstract class BaseTask { myTransactional = theTransactional; } - private boolean myTransactional = true; - private boolean myDoNothing; - private List myExecutedStatements = new ArrayList<>(); - private Set myOnlyAppliesToPlatforms = new HashSet<>(); - private boolean myNoColumnShrink; - private boolean myFailureAllowed; - private boolean myRunDuringSchemaInitialization; - /** - * Whether or not to check for existing tables - * before generating SQL - */ - protected boolean myCheckForExistingTables = true; - - /** - * Whether or not to generate the SQL in a 'readable format' - */ - protected boolean myPrettyPrint = false; - - protected BaseTask(String theProductVersion, String theSchemaVersion) { - myProductVersion = theProductVersion; - mySchemaVersion = theSchemaVersion; - } - - public boolean isRunDuringSchemaInitialization() { - return myRunDuringSchemaInitialization; - } - public void setPrettyPrint(boolean thePrettyPrint) { myPrettyPrint = thePrettyPrint; } - /** - * Should this task run even if we're doing the very first initialization of an empty schema. By - * default we skip most tasks during that pass, since they just take up time and the - * schema should be fully initialized by the {@link InitializeSchemaTask} - */ - public void setRunDuringSchemaInitialization(boolean theRunDuringSchemaInitialization) { - myRunDuringSchemaInitialization = theRunDuringSchemaInitialization; - } - public void setOnlyAppliesToPlatforms(Set theOnlyAppliesToPlatforms) { - Validate.notNull(theOnlyAppliesToPlatforms); + Validate.notNull(theOnlyAppliesToPlatforms, "theOnlyAppliesToPlatforms must not be null"); myOnlyAppliesToPlatforms = theOnlyAppliesToPlatforms; } @@ -188,7 +188,7 @@ public abstract class BaseTask { private Integer doExecuteSqlList(List theSqlStatements) { int changesCount = 0; - for (String nextSql : theSqlStatements) { + for (@Language("SQL") String nextSql : theSqlStatements) { changesCount += doExecuteSql(nextSql); } @@ -206,7 +206,7 @@ public abstract class BaseTask { } return changesCount; } catch (DataAccessException e) { - if (myFailureAllowed) { + if (myFlags.contains(TaskFlagEnum.FAILURE_ALLOWED)) { ourLog.info("Task {} did not exit successfully, but task is allowed to fail", getMigrationVersion()); ourLog.debug("Error was: {}", e.getMessage(), e); return 0; @@ -219,7 +219,7 @@ public abstract class BaseTask { protected void captureExecutedStatement( String theTableName, @Language("SQL") String theSql, Object... theArguments) { - myExecutedStatements.add(new ExecutedStatement(theTableName, theSql, theArguments)); + myExecutedStatements.add(new ExecutedStatement(mySchemaVersion, theTableName, theSql, theArguments)); } public DriverTypeEnum.ConnectionProperties getConnectionProperties() { @@ -250,10 +250,8 @@ public abstract class BaseTask { return getConnectionProperties().newJdbcTemplate(); } - private final List myPreconditions = new ArrayList<>(); - public void execute() throws SQLException { - if (myDoNothing) { + if (myFlags.contains(TaskFlagEnum.DO_NOTHING)) { ourLog.info("Skipping stubbed task: {}", getDescription()); return; } @@ -278,14 +276,6 @@ public abstract class BaseTask { protected abstract void doExecute() throws SQLException; - protected boolean isFailureAllowed() { - return myFailureAllowed; - } - - public void setFailureAllowed(boolean theFailureAllowed) { - myFailureAllowed = theFailureAllowed; - } - public String getMigrationVersion() { String releasePart = myProductVersion; if (releasePart.startsWith("V")) { @@ -296,6 +286,7 @@ public abstract class BaseTask { return migrationVersion.getVersion(); } + @SuppressWarnings("StringConcatenationArgumentToLogCall") protected void logInfo(Logger theLog, String theFormattedMessage, Object... theArguments) { theLog.info(getMigrationVersion() + ": " + theFormattedMessage, theArguments); } @@ -308,23 +299,6 @@ public abstract class BaseTask { } } - public void doNothing() { - setDoNothing(true); - } - - public void failureAllowed() { - setFailureAllowed(true); - } - - public boolean isDoNothing() { - return myDoNothing; - } - - public BaseTask setDoNothing(boolean theDoNothing) { - myDoNothing = theDoNothing; - return this; - } - public void addPrecondition(ExecuteTaskPrecondition thePrecondition) { myPreconditions.add(thePrecondition); } @@ -343,7 +317,6 @@ public abstract class BaseTask { if (theObject == null || getClass().equals(theObject.getClass()) == false) { return false; } - @SuppressWarnings("unchecked") BaseTask otherObject = (BaseTask) theObject; EqualsBuilder b = new EqualsBuilder(); @@ -357,17 +330,35 @@ public abstract class BaseTask { return false; } + public boolean isDoNothing() { + return myFlags.contains(TaskFlagEnum.DO_NOTHING); + } + + public boolean isHeavyweightSkippableTask() { + return myFlags.contains(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT); + } + + public boolean hasFlag(TaskFlagEnum theFlag) { + return myFlags.contains(theFlag); + } + public static class ExecutedStatement { private final String mySql; private final List myArguments; private final String myTableName; + private final String mySchemaVersion; - public ExecutedStatement(String theDescription, String theSql, Object[] theArguments) { + public ExecutedStatement(String theSchemaVersion, String theDescription, String theSql, Object[] theArguments) { + mySchemaVersion = theSchemaVersion; myTableName = theDescription; mySql = theSql; myArguments = theArguments != null ? Arrays.asList(theArguments) : Collections.emptyList(); } + public String getSchemaVersion() { + return mySchemaVersion; + } + public String getTableName() { return myTableName; } @@ -379,5 +370,14 @@ public abstract class BaseTask { public List getArguments() { return myArguments; } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("tableName", myTableName) + .append("sql", mySql) + .append("arguments", myArguments) + .toString(); + } } } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ForceIdMigrationFixTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ForceIdMigrationFixTask.java index 7f29d3ba38b..07607a90845 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ForceIdMigrationFixTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ForceIdMigrationFixTask.java @@ -113,6 +113,13 @@ public class ForceIdMigrationFixTask extends BaseTask { switch (getDriverType()) { case MSSQL_2012: return " where (fhir_id is null or DATALENGTH(fhir_id) > LEN(fhir_id)) "; + case H2_EMBEDDED: + case DERBY_EMBEDDED: + case MARIADB_10_1: + case MYSQL_5_7: + case POSTGRES_9_4: + case ORACLE_12C: + case COCKROACHDB_21_1: default: return " where (fhir_id is null or fhir_id <> trim(fhir_id)) "; } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java index a2eeb639bf9..9fe4aa996ce 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/InitializeSchemaTask.java @@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.JdbcUtils; import ca.uhn.fhir.jpa.migrate.tasks.api.ISchemaInitializationProvider; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.slf4j.Logger; @@ -44,11 +45,7 @@ public class InitializeSchemaTask extends BaseTask { super(theProductVersion, theSchemaVersion); mySchemaInitializationProvider = theSchemaInitializationProvider; setDescription(DESCRIPTION_PREFIX + mySchemaInitializationProvider.getSchemaDescription()); - } - - @Override - public boolean isRunDuringSchemaInitialization() { - return true; + addFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION); } @Override @@ -102,12 +99,12 @@ public class InitializeSchemaTask extends BaseTask { @Override protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) { InitializeSchemaTask otherObject = (InitializeSchemaTask) theOtherObject; - theBuilder.append(mySchemaInitializationProvider, otherObject.mySchemaInitializationProvider); + theBuilder.append(getSchemaInitializationProvider(), otherObject.getSchemaInitializationProvider()); } @Override protected void generateHashCode(HashCodeBuilder theBuilder) { - theBuilder.append(mySchemaInitializationProvider); + theBuilder.append(getSchemaInitializationProvider()); } public ISchemaInitializationProvider getSchemaInitializationProvider() { diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTask.java index 70dc3d2c0d1..574ac66ae8a 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTask.java @@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.migrate.JdbcUtils; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import org.intellij.lang.annotations.Language; import org.slf4j.Logger; @@ -159,8 +160,8 @@ public class ModifyColumnTask extends BaseTableColumnTypeTask { throw new IllegalStateException(Msg.code(67) + "Dont know how to handle " + getDriverType()); } - if (!isFailureAllowed() && isShrinkOnly) { - setFailureAllowed(true); + if (isShrinkOnly) { + addFlag(TaskFlagEnum.FAILURE_ALLOWED); } logInfo(ourLog, "Updating column {} on table {} to type {}", getColumnName(), getTableName(), type); diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/RenameTableTask.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/RenameTableTask.java index 4b90ea91ac3..e9007755ce0 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/RenameTableTask.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/RenameTableTask.java @@ -99,6 +99,7 @@ public class RenameTableTask extends BaseTableTask { return retVal; } + @Override protected void generateHashCode(HashCodeBuilder theBuilder) { super.generateHashCode(theBuilder); theBuilder.append(myOldTableName); diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java index 083e90ab9b1..5dad63f92d8 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/SchemaInitializationProvider.java @@ -23,6 +23,7 @@ import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.tasks.api.ISchemaInitializationProvider; +import ca.uhn.fhir.util.ClasspathUtil; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import jakarta.annotation.Nonnull; @@ -71,11 +72,7 @@ public class SchemaInitializationProvider implements ISchemaInitializationProvid String initScript = mySchemaFileClassPath + "/" + getInitScript(theDriverType); try { - InputStream sqlFileInputStream = SchemaInitializationProvider.class.getResourceAsStream(initScript); - if (sqlFileInputStream == null) { - throw new ConfigurationException( - Msg.code(49) + "Schema initialization script " + initScript + " not found on classpath"); - } + InputStream sqlFileInputStream = ClasspathUtil.loadResourceAsStream(initScript); // Assumes no escaped semicolons... String sqlString = IOUtils.toString(sqlFileInputStream, Charsets.UTF_8); parseSqlFileIntoIndividualStatements(theDriverType, retval, sqlString); @@ -91,7 +88,7 @@ public class SchemaInitializationProvider implements ISchemaInitializationProvid String sqlString = theSqlString.replaceAll("--.*", ""); String sqlStringNoComments = preProcessSqlString(theDriverType, sqlString); - String[] statements = sqlStringNoComments.split("\\;"); + String[] statements = sqlStringNoComments.split(";"); for (String statement : statements) { String cleanedStatement = preProcessSqlStatement(theDriverType, statement); if (!isBlank(cleanedStatement)) { diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java index 53741f65e5a..7639e486a8d 100644 --- a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java @@ -85,18 +85,17 @@ public class Builder { } public BuilderCompleteTask executeRawSql(String theVersion, @Language("SQL") String theSql) { - ExecuteRawSqlTask task = executeRawSqlOptional(false, theVersion, theSql); + ExecuteRawSqlTask task = executeRawSqlOptional(theVersion, theSql); return new BuilderCompleteTask(task); } public void executeRawSqlStub(String theVersion, @Language("SQL") String theSql) { - executeRawSqlOptional(true, theVersion, theSql); + BuilderCompleteTask task = executeRawSql(theVersion, theSql); + task.withFlag(TaskFlagEnum.DO_NOTHING); } - private ExecuteRawSqlTask executeRawSqlOptional( - boolean theDoNothing, String theVersion, @Language("SQL") String theSql) { + private ExecuteRawSqlTask executeRawSqlOptional(String theVersion, @Language("SQL") String theSql) { ExecuteRawSqlTask task = new ExecuteRawSqlTask(myRelease, theVersion).addSql(theSql); - task.setDoNothing(theDoNothing); mySink.addTask(task); return task; } @@ -172,10 +171,10 @@ public class Builder { addTask(task); } - public DropIdGeneratorTask dropIdGenerator(String theVersion, String theIdGeneratorName) { + public BuilderCompleteTask dropIdGenerator(String theVersion, String theIdGeneratorName) { DropIdGeneratorTask task = new DropIdGeneratorTask(myRelease, theVersion, theIdGeneratorName); addTask(task); - return task; + return new BuilderCompleteTask(task); } public void addNop(String theVersion) { @@ -199,7 +198,7 @@ public class Builder { } public BuilderCompleteTask dropIndex(String theVersion, String theIndexName) { - BaseTask task = dropIndexOptional(false, theVersion, theIndexName); + BaseTask task = dropIndexOptional(theVersion, theIndexName); return new BuilderCompleteTask(task); } @@ -207,20 +206,20 @@ public class Builder { * Drop index without taking write lock on PG, Oracle, MSSQL. */ public BuilderCompleteTask dropIndexOnline(String theVersion, String theIndexName) { - DropIndexTask task = dropIndexOptional(false, theVersion, theIndexName); + DropIndexTask task = dropIndexOptional(theVersion, theIndexName); task.setOnline(true); return new BuilderCompleteTask(task); } public void dropIndexStub(String theVersion, String theIndexName) { - dropIndexOptional(true, theVersion, theIndexName); + DropIndexTask task = dropIndexOptional(theVersion, theIndexName); + task.addFlag(TaskFlagEnum.DO_NOTHING); } - private DropIndexTask dropIndexOptional(boolean theDoNothing, String theVersion, String theIndexName) { + private DropIndexTask dropIndexOptional(String theVersion, String theIndexName) { DropIndexTask task = new DropIndexTask(myRelease, theVersion); task.setIndexName(theIndexName); task.setTableName(myTableName); - task.setDoNothing(theDoNothing); addTask(task); return task; } @@ -230,24 +229,24 @@ public class Builder { */ @Deprecated public void renameIndex(String theVersion, String theOldIndexName, String theNewIndexName) { - renameIndexOptional(false, theVersion, theOldIndexName, theNewIndexName); + renameIndexOptional(theVersion, theOldIndexName, theNewIndexName); } /** * @deprecated Do not rename indexes - It is too hard to figure out what happened if something goes wrong */ public void renameIndexStub(String theVersion, String theOldIndexName, String theNewIndexName) { - renameIndexOptional(true, theVersion, theOldIndexName, theNewIndexName); + RenameIndexTask task = renameIndexOptional(theVersion, theOldIndexName, theNewIndexName); + task.addFlag(TaskFlagEnum.DO_NOTHING); } - private void renameIndexOptional( - boolean theDoNothing, String theVersion, String theOldIndexName, String theNewIndexName) { + private RenameIndexTask renameIndexOptional(String theVersion, String theOldIndexName, String theNewIndexName) { RenameIndexTask task = new RenameIndexTask(myRelease, theVersion); task.setOldIndexName(theOldIndexName); task.setNewIndexName(theNewIndexName); task.setTableName(myTableName); - task.setDoNothing(theDoNothing); addTask(task); + return task; } public void dropThisTable(String theVersion) { @@ -388,27 +387,22 @@ public class Builder { } public void withColumnsStub(String... theColumnNames) { - withColumnsOptional(true, theColumnNames); + BuilderCompleteTask task = withColumns(theColumnNames); + task.withFlag(TaskFlagEnum.DO_NOTHING); } public BuilderCompleteTask withColumns(String... theColumnNames) { - BaseTask task = withColumnsOptional(false, theColumnNames); - return new BuilderCompleteTask(task); - } - - private AddIndexTask withColumnsOptional(boolean theDoNothing, String... theColumnNames) { AddIndexTask task = new AddIndexTask(myRelease, myVersion); task.setTableName(myTableName); task.setIndexName(myIndexName); task.setUnique(myUnique); task.setColumns(theColumnNames); - task.setDoNothing(theDoNothing); task.setOnline(myOnline); if (myIncludeColumns != null) { task.setIncludeColumns(myIncludeColumns); } addTask(task); - return task; + return new BuilderCompleteTask(task); } public BuilderAddIndexUnique includeColumns(String... theIncludeColumns) { @@ -453,18 +447,17 @@ public class Builder { public class BuilderModifyColumnWithNameAndNullable { private final String myVersion; private final boolean myNullable; - private boolean myFailureAllowed; public BuilderModifyColumnWithNameAndNullable(String theVersion, boolean theNullable) { myVersion = theVersion; myNullable = theNullable; } - public void withType(ColumnTypeEnum theColumnType) { - withType(theColumnType, null); + public BuilderCompleteTask withType(ColumnTypeEnum theColumnType) { + return withType(theColumnType, null); } - public void withType(ColumnTypeEnum theColumnType, Integer theLength) { + public BuilderCompleteTask withType(ColumnTypeEnum theColumnType, Integer theLength) { if (theColumnType == ColumnTypeEnum.STRING) { if (theLength == null || theLength == 0) { throw new IllegalArgumentException( @@ -478,6 +471,7 @@ public class Builder { } ModifyColumnTask task = new ModifyColumnTask(myRelease, myVersion); + task.setColumnName(myColumnName); task.setTableName(myTableName); if (theLength != null) { @@ -485,13 +479,8 @@ public class Builder { } task.setNullable(myNullable); task.setColumnType(theColumnType); - task.setFailureAllowed(myFailureAllowed); addTask(task); - } - - public BuilderModifyColumnWithNameAndNullable failureAllowed() { - myFailureAllowed = true; - return this; + return new BuilderCompleteTask(task); } } } @@ -596,12 +585,12 @@ public class Builder { } public BuilderCompleteTask failureAllowed() { - myTask.setFailureAllowed(true); + myTask.addFlag(TaskFlagEnum.FAILURE_ALLOWED); return this; } public BuilderCompleteTask doNothing() { - myTask.setDoNothing(true); + myTask.addFlag(TaskFlagEnum.DO_NOTHING); return this; } @@ -646,7 +635,7 @@ public class Builder { } public BuilderCompleteTask runEvenDuringSchemaInitialization() { - myTask.setRunDuringSchemaInitialization(true); + myTask.addFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION); return this; } @@ -654,6 +643,16 @@ public class Builder { myTask.setTransactional(theFlag); return this; } + + public BuilderCompleteTask heavyweightSkipByDefault() { + myTask.addFlag(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT); + return this; + } + + public BuilderCompleteTask withFlag(TaskFlagEnum theFlag) { + myTask.addFlag(theFlag); + return this; + } } public class BuilderAddTableRawSql { @@ -707,9 +706,8 @@ public class Builder { } } - public BuilderAddTableByColumns failureAllowed() { - myTask.setFailureAllowed(true); - return this; + public BuilderCompleteTask withFlags() { + return new BuilderCompleteTask(myTask); } } diff --git a/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/TaskFlagEnum.java b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/TaskFlagEnum.java new file mode 100644 index 00000000000..73041b1a053 --- /dev/null +++ b/hapi-fhir-sql-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/TaskFlagEnum.java @@ -0,0 +1,65 @@ +/*- + * #%L + * HAPI FHIR Server - SQL Migration + * %% + * Copyright (C) 2014 - 2024 Smile CDR, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package ca.uhn.fhir.jpa.migrate.tasks.api; + +import ca.uhn.fhir.jpa.migrate.taskdef.InitializeSchemaTask; + +public enum TaskFlagEnum { + + /** + * This task should be skipped by default on live system migrations. Use this flag + * in cases where the benefit of applying a migration doesn't justify the effort, and + * only use this flag in cases where skipping the task will not leave the system in + * an unusable state. + *

+ * This flag is intended for situations where a change to the schema would be useful + * to add to the default initialized schema, but would not be worth the effort of + * applying in-place to large databases due to the outsized effort it would take. + *

+ *

+ * USE THIS FLAG WITH CAUTION: It means that the migrator unit tests will execute the + * task, but live migrations probably won't. So think long and hard before you set it! + *

+ */ + HEAVYWEIGHT_SKIP_BY_DEFAULT, + + /** + * Should this task run even if we're doing the very first initialization of an empty schema. By + * default, we skip most tasks during that pass, since they just take up time and the + * schema should be fully initialized by the {@link InitializeSchemaTask} + */ + RUN_DURING_SCHEMA_INITIALIZATION, + + /** + * This task is allowed to fail, and failure won't abort the migration. Upon any + * detected failures, the task will still be recorded as having been successfully + * complected. A failure in this context means that the SQL statement(s) being + * executed returned a non-successful response, or timed out. + */ + FAILURE_ALLOWED, + + /** + * This task should not actually do anything, and will always be recorded as + * a success. Use this flag for tasks that are no longer needed, e.g. because + * they are superseded by later tasks or because they turned out to be a bad + * idea. + */ + DO_NOTHING +} diff --git a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvcTest.java b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvcTest.java index ca5175d585d..e0c919a952f 100644 --- a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvcTest.java +++ b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigrationStorageSvcTest.java @@ -128,7 +128,7 @@ class HapiMigrationStorageSvcTest extends BaseMigrationTest { return taskList; } - public Builder forVersion(MigrationTaskList theTaskList) { + public static Builder forVersion(MigrationTaskList theTaskList) { BaseMigrationTasks.IAcceptsTasks sink = theTask -> { theTask.validate(); theTaskList.add(theTask); diff --git a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java index cf0a125698d..252df0cfd05 100644 --- a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java +++ b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/HapiMigratorIT.java @@ -3,7 +3,11 @@ package ca.uhn.fhir.jpa.migrate; import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.jpa.migrate.dao.HapiMigrationDao; import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask; +import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum; import ca.uhn.fhir.jpa.migrate.taskdef.NopTask; +import ca.uhn.fhir.jpa.migrate.tasks.SchemaInitializationProvider; +import ca.uhn.fhir.jpa.migrate.tasks.api.Builder; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import ca.uhn.test.concurrency.IPointcutLatch; import ca.uhn.test.concurrency.PointcutLatch; import jakarta.annotation.Nonnull; @@ -13,6 +17,8 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; @@ -23,12 +29,15 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +@SuppressWarnings("SqlDialectInspection") class HapiMigratorIT { private static final Logger ourLog = LoggerFactory.getLogger(HapiMigratorIT.class); private static final String MIGRATION_TABLENAME = "TEST_MIGRATOR_TABLE"; @@ -42,6 +51,7 @@ class HapiMigratorIT { HapiMigrator migrator = buildMigrator(); migrator.createMigrationTableIfRequired(); Integer count = myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME, Integer.class); + assertNotNull(count); assertTrue(count > 0); HapiMigrationDao migrationDao = new HapiMigrationDao(myDataSource, DriverTypeEnum.H2_EMBEDDED, MIGRATION_TABLENAME); myMigrationStorageSvc = new HapiMigrationStorageSvc(migrationDao); @@ -56,6 +66,62 @@ class HapiMigratorIT { System.clearProperty(HapiMigrationLock.CLEAR_LOCK_TABLE_WITH_DESCRIPTION); } + @Test + public void testInitializeSchema() { + SchemaInitializationProvider schemaInitProvider = new SchemaInitializationProvider( + "A schema", + "/hapi-migrator-it-init-schema", + "HFJ_RES_REINDEX_JOB", + true + ); + + MigrationTaskList taskList = new MigrationTaskList(); + Builder version = HapiMigrationStorageSvcTest.forVersion(taskList); + + version.initializeSchema("1", schemaInitProvider); + + Builder.BuilderAddTableByColumns nonSchemaInit = version.addTableByColumns("2", "NON_SCHEMA_INIT", "PID"); + nonSchemaInit.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG); + + Builder.BuilderAddTableByColumns schemaInit = version.addTableByColumns("3", "SCHEMA_INIT", "PID"); + schemaInit.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG); + schemaInit.withFlags().runEvenDuringSchemaInitialization(); + + HapiMigrator migrator; + MigrationResult outcome; + + /* + * Run the migrator for the first time. This should execute 2 tasks: the initial + * schema initialization, and the task set to run even during initialization. Task + * 2 should not run. + */ + migrator = buildMigrator(taskList.toTaskArray()); + outcome = migrator.migrate(); + assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).containsExactly("1", "3"); + + /* + * Run again - Nothing should happen since we've already finished the migration + */ + migrator = buildMigrator(taskList.toTaskArray()); + outcome = migrator.migrate(); + assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).isEmpty(); + + /* + * Add another pair of tasks - Both should run + */ + Builder.BuilderAddTableByColumns nonSchemaInit2 = version.addTableByColumns("4", "NON_SCHEMA_INIT_2", "PID"); + nonSchemaInit2.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG); + + Builder.BuilderAddTableByColumns schemaInit2 = version.addTableByColumns("5", "SCHEMA_INIT_2", "PID"); + schemaInit2.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG); + schemaInit2.withFlags().runEvenDuringSchemaInitialization(); + + migrator = buildMigrator(taskList.toTaskArray()); + outcome = migrator.migrate(); + assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).containsExactly("4", "5"); + + } + @Test void test_onecall_noblock() throws InterruptedException, ExecutionException { @@ -65,7 +131,7 @@ class HapiMigratorIT { HapiMigrator migrator = buildMigrator(latchMigrationTask); latchMigrationTask.setExpectedCount(1); - Future future = executor.submit(() -> migrator.migrate()); + Future future = executor.submit(migrator::migrate); latchMigrationTask.awaitExpected(); latchMigrationTask.release("1"); @@ -91,7 +157,7 @@ class HapiMigratorIT { // is released, the first one will have already run so there will be nothing to do latchMigrationTask1.setExpectedCount(1); - Future future1 = executor.submit(() -> migrator1.migrate()); + Future future1 = executor.submit(migrator1::migrate); latchMigrationTask1.awaitExpected(); // We wait until the first migration is in the middle of executing the migration task before we start the second one @@ -101,7 +167,7 @@ class HapiMigratorIT { latchMigrationTask1.release("1"); latchMigrationTask2.setExpectedCount(1); - Future future2 = executor.submit(() -> migrator2.migrate()); + Future future2 = executor.submit(migrator2::migrate); latchMigrationTask2.awaitExpected(); // This second call shouldn't be necessary, but it will help the test fail faster with a clearer error @@ -127,7 +193,7 @@ class HapiMigratorIT { { latchMigrationTask.setExpectedCount(1); - Future future = executor.submit(() -> migrator.migrate()); + Future future = executor.submit(migrator::migrate); latchMigrationTask.awaitExpected(); assertEquals(1, countLockRecords()); latchMigrationTask.release("1"); @@ -138,7 +204,7 @@ class HapiMigratorIT { } { - Future future = executor.submit(() -> migrator.migrate()); + Future future = executor.submit(migrator::migrate); MigrationResult result = future.get(); assertEquals(0, countLockRecords()); @@ -147,7 +213,6 @@ class HapiMigratorIT { } - @Test void test_oldLockFails_block() { HapiMigrationLock.setMaxRetryAttempts(0); @@ -176,7 +241,31 @@ class HapiMigratorIT { assertThat(result.succeededTasks).hasSize(1); } + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void test_HeavyweightSkippable(boolean theShouldRun) throws InterruptedException, ExecutionException { + ExecutorService executor = Executors.newSingleThreadExecutor(); + LatchMigrationTask latchMigrationTask = new LatchMigrationTask("only", "1"); + latchMigrationTask.addFlag(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT); + + HapiMigrator migrator = buildMigrator(latchMigrationTask); + int expectedInvocations = 0; + if (theShouldRun) { + migrator.setRunHeavyweightSkippableTasks(true); + expectedInvocations = 1; + } + latchMigrationTask.setExpectedCount(expectedInvocations); + + Future future = executor.submit(migrator::migrate); + latchMigrationTask.awaitExpected(); + latchMigrationTask.release("1"); + + MigrationResult result = future.get(); + assertThat(result.succeededTasks).hasSize(expectedInvocations); + } + + @SuppressWarnings("DataFlowIssue") private int countLockRecords() { return myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME + " WHERE \"installed_rank\" = " + HapiMigrationLock.LOCK_PID, Integer.class); } @@ -195,8 +284,15 @@ class HapiMigratorIT { return new HapiMigrator(MIGRATION_TABLENAME, myDataSource, DriverTypeEnum.H2_EMBEDDED); } + private static @Nonnull String toTaskStatementDescriptions(MigrationResult outcome) { + return "Statements:\n * " + outcome.executedStatements.stream().map(BaseTask.ExecutedStatement::toString).collect(Collectors.joining("\n * ")); + } - private class LatchMigrationTask extends BaseTask implements IPointcutLatch { + private static @Nonnull List toTaskVersionList(MigrationResult outcome) { + return outcome.executedStatements.stream().map(BaseTask.ExecutedStatement::getSchemaVersion).toList(); + } + + private static class LatchMigrationTask extends BaseTask implements IPointcutLatch { private final PointcutLatch myLatch; private final PointcutLatch myWaitLatch; diff --git a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java index d9944f10f08..91f39e556af 100644 --- a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java +++ b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java @@ -108,7 +108,7 @@ public class AddTableByColumnTaskTest extends BaseTest { return theTask1.getColumnName().compareTo(theTask2.getColumnName()); }; - final AddTableByColumnTask addTableByColumnTask = new AddTableByColumnTask(comparator); + final AddTableByColumnTask addTableByColumnTask = new AddTableByColumnTask("1", "1", comparator); addTableByColumnTask.setTableName(tableName); addTableByColumnTask.setDriverType(driverType); addTableByColumnTask.setPkColumns(Collections.singletonList(columnNameId)); diff --git a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTest.java b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTest.java index 13ca3290722..c6cdce4098e 100644 --- a/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTest.java +++ b/hapi-fhir-sql-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ModifyColumnTest.java @@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef; import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; import ca.uhn.fhir.jpa.migrate.HapiMigrationException; import ca.uhn.fhir.jpa.migrate.JdbcUtils; +import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum; import jakarta.annotation.Nonnull; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -17,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +@SuppressWarnings("SqlDialectInspection") public class ModifyColumnTest extends BaseTest { @ParameterizedTest(name = "{index}: {0}") @@ -232,14 +234,11 @@ public class ModifyColumnTest extends BaseTest { @SuppressWarnings("EnumSwitchStatementWhichMissesCases") @Nonnull private JdbcUtils.ColumnType getLongColumnType(Supplier theTestDatabaseDetails) { - switch (theTestDatabaseDetails.get().getDriverType()) { - case H2_EMBEDDED: - return new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 64); - case DERBY_EMBEDDED: - return new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 19); - default: - throw new UnsupportedOperationException(); - } + return switch (theTestDatabaseDetails.get().getDriverType()) { + case H2_EMBEDDED -> new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 64); + case DERBY_EMBEDDED -> new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 19); + default -> throw new UnsupportedOperationException(); + }; } @ParameterizedTest(name = "{index}: {0}") @@ -270,11 +269,11 @@ public class ModifyColumnTest extends BaseTest { executeSql("insert into SOMETABLE (TEXTCOL) values ('HELLO')"); ModifyColumnTask task = new ModifyColumnTask("1", "1"); + task.addFlag(TaskFlagEnum.FAILURE_ALLOWED); task.setTableName("SOMETABLE"); task.setColumnName("TEXTCOL"); task.setColumnType(ColumnTypeEnum.LONG); task.setNullable(true); - task.setFailureAllowed(true); getMigrator().addTask(task); getMigrator().migrate(); diff --git a/hapi-fhir-sql-migrate/src/test/resources/hapi-migrator-it-init-schema/h2.sql b/hapi-fhir-sql-migrate/src/test/resources/hapi-migrator-it-init-schema/h2.sql new file mode 100644 index 00000000000..1105f9aa68f --- /dev/null +++ b/hapi-fhir-sql-migrate/src/test/resources/hapi-migrator-it-init-schema/h2.sql @@ -0,0 +1,6 @@ + +create table HFJ_RES_REINDEX_JOB ( + PID bigint not null, + RES_TYPE varchar(100), + primary key (PID) +); diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml index 951683d6335..f1113e6dca9 100644 --- a/hapi-fhir-storage-batch2-jobs/pom.xml +++ b/hapi-fhir-storage-batch2-jobs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-test-utilities/pom.xml b/hapi-fhir-storage-batch2-test-utilities/pom.xml index 499a9c799f5..0ef577ce1d2 100644 --- a/hapi-fhir-storage-batch2-test-utilities/pom.xml +++ b/hapi-fhir-storage-batch2-test-utilities/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index b9445f9c590..d91e6d799af 100644 --- a/hapi-fhir-storage-batch2/pom.xml +++ b/hapi-fhir-storage-batch2/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-cr/pom.xml b/hapi-fhir-storage-cr/pom.xml index 8c717536d95..a31d5be77fe 100644 --- a/hapi-fhir-storage-cr/pom.xml +++ b/hapi-fhir-storage-cr/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index ebd4cf3cf89..56ae8033745 100644 --- a/hapi-fhir-storage-mdm/pom.xml +++ b/hapi-fhir-storage-mdm/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index b67d78bb04d..3fe9e63c42f 100644 --- a/hapi-fhir-storage-test-utilities/pom.xml +++ b/hapi-fhir-storage-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index 5aa1daab056..5374ed9f355 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index d83f98ec648..ad0198154b0 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index 5d8654e87ba..400c371bdb2 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index 11a5d0e063a..daf1d9ab7b7 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index 1d849cbeba1..95115731b44 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index 4a90cf8be3d..c5622f8473c 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml index cca72114d9c..9d400c1fa0c 100644 --- a/hapi-fhir-structures-r4b/pom.xml +++ b/hapi-fhir-structures-r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 99f5b18a411..168f2c2c4e7 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index bcc6eda773a..365d17d1ba9 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/jpa/JpaModelScannerAndVerifier.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/jpa/JpaModelScannerAndVerifier.java index 224d2c42371..a9f4e2588aa 100644 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/jpa/JpaModelScannerAndVerifier.java +++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/jpa/JpaModelScannerAndVerifier.java @@ -187,7 +187,8 @@ public class JpaModelScannerAndVerifier { scan(nextField, theNames, theIsSuperClass, isView); Id id = nextField.getAnnotation(Id.class); - if (id != null) { + boolean isId = id != null; + if (isId) { Validate.isTrue(!foundId, "Multiple fields annotated with @Id"); foundId = true; @@ -241,12 +242,24 @@ public class JpaModelScannerAndVerifier { int columnLength = 16; String columnName = null; + boolean nullable = false; if (hasColumn) { - columnName = nextField.getAnnotation(Column.class).name(); - columnLength = nextField.getAnnotation(Column.class).length(); + Column column = nextField.getAnnotation(Column.class); + columnName = column.name(); + columnLength = column.length(); + nullable = column.nullable(); } if (hasJoinColumn) { - columnName = nextField.getAnnotation(JoinColumn.class).name(); + JoinColumn joinColumn = nextField.getAnnotation(JoinColumn.class); + columnName = joinColumn.name(); + nullable = joinColumn.nullable(); + } + if (isId) { + nullable = false; + } + + if (nullable && !isView) { + Validate.isTrue(!nextField.getType().isPrimitive(), "Field [%s] has a nullable primitive type: %s", nextField.getName(), nextField.getType()); } if (columnName != null) { diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 7834ca35c4a..22081db8948 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index 0790e96f1df..8cf8d41169b 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 71f137c80ba..05c35297aed 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 1d0819a3af0..ace33e92751 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index b81fd93c621..2b43d5b4223 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4b/pom.xml b/hapi-fhir-validation-resources-r4b/pom.xml index f0b2c9fe7b1..256726e6a6e 100644 --- a/hapi-fhir-validation-resources-r4b/pom.xml +++ b/hapi-fhir-validation-resources-r4b/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index 61828536241..89d01c817e5 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 91a608190b8..867ac8fab61 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 454a4537616..5be411f6d6d 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index d1f52593bf5..73cb280486c 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 915a1c75af2..60eabdcfcaf 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index 99ebdb57ef7..e190bc932e2 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index c7a989f642b..87b69d1ce57 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index da5b9aadeeb..223943c80a0 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.3.7-SNAPSHOT + 7.3.8-SNAPSHOT ../../pom.xml From 61b5103535381fd70be2463f05f983e41af42459 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Tue, 18 Jun 2024 13:46:09 -0700 Subject: [PATCH 03/19] Final hamcrest conversions (#6015) * wip * wip * revert' * Delete existing things * docs * removing last of hamcrest * removing last of hamcrest * manual fix * remove matchers used in awaitility * remove matchers used in awaitility * Final checkstyle removals * Disable suppression rule for mdm checkstyle * Fix some awaitility, remove dead matchers * manual fixes * manual fixes * filter all hamcrest mentions --------- Co-authored-by: Ken Stevens --- .../hapi-base-checkstyle-suppression.xml | 3 - .../src/checkstyle/hapi-base-checkstyle.xml | 4 +- .../r4/ResourceProviderR4ElasticTest.java | 65 ++++-- .../ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java | 60 +---- .../matcher/BaseGoldenResourceMatcher.java | 82 ------- .../matcher/GoldenResourceMatchingAssert.java | 215 ++++++++++++++++++ .../uhn/fhir/jpa/mdm/matcher/IsLinkedTo.java | 48 ---- .../matcher/IsMatchedToAGoldenResource.java | 38 ---- .../mdm/matcher/IsPossibleDuplicateOf.java | 62 ----- .../jpa/mdm/matcher/IsPossibleLinkedTo.java | 48 ---- .../jpa/mdm/matcher/IsPossibleMatchWith.java | 61 ----- .../mdm/matcher/IsSameGoldenResourceAs.java | 47 ---- ...MdmProviderMergeGoldenResourcesR4Test.java | 23 +- .../svc/MdmGoldenResourceMergerSvcTest.java | 10 +- .../MdmMatchLinkSvcMultipleEidModeTest.java | 47 ++-- .../fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java | 167 +++++++------- .../dao/dstu2/FhirResourceDaoDstu2Test.java | 2 - .../jpa/dao/dstu2/FhirSystemDaoDstu2Test.java | 4 +- .../provider/ResourceProviderDstu2Test.java | 4 +- .../search/SearchCoordinatorSvcImplTest.java | 3 +- .../email/EmailSubscriptionDstu2Test.java | 5 +- .../FhirResourceDaoDstu3SearchFtTest.java | 2 +- .../dstu3/ResourceProviderDstu3Test.java | 4 +- .../bulk/imprt/svc/BulkDataImportR4Test.java | 1 - .../r4/FhirResourceDaoR4QueryCountTest.java | 1 - .../dao/r4/FhirResourceDaoR4SearchFtTest.java | 6 +- .../r4/FhirResourceDaoR4SearchNoFtTest.java | 2 +- .../FhirResourceDaoR4SearchOptimizedTest.java | 1 - .../r4/FhirResourceDaoR4SearchSqlTest.java | 1 - ...hirResourceDaoR4UpdateTagSnapshotTest.java | 1 - ...ResourceDaoR4ValueSetMultiVersionTest.java | 1 - .../dao/r4/FhirResourceDaoSearchListTest.java | 2 +- .../fhir/jpa/dao/r4/FhirSystemDaoR4Test.java | 5 +- .../jpa/dao/r4/PartitioningSqlR4Test.java | 1 - .../PartitioningInterceptorR4Test.java | 1 - ...TerminologyTranslationInterceptorTest.java | 1 - .../packages/JpaPackageCacheSearchR4Test.java | 1 - .../r4/ResourceProviderConcurrencyR4Test.java | 12 +- .../r4/ResourceProviderInterceptorR4Test.java | 8 +- ...roviderMeaningfulOutcomeMessageR4Test.java | 4 +- ...oviderOnlySomeResourcesProvidedR4Test.java | 2 - .../r4/ResourceProviderR4EverythingTest.java | 4 +- ...eProviderR4SearchVariousScenariosTest.java | 5 +- ...rCapabilityStatementProviderJpaR4Test.java | 1 - .../stresstest/GiantTransactionPerfTest.java | 1 - .../fhir/jpa/stresstest/StressTestR4Test.java | 1 - .../jpa/term/TerminologySvcImplR4Test.java | 1 - .../provider/r4b/ResourceProviderR4BTest.java | 1 - .../provider/r5/ResourceProviderR5Test.java | 1 - .../ca/uhn/fhir/jpa/dao/TestDaoSearch.java | 27 +-- .../jpa/sched/SchedulerServiceImplTest.java | 16 +- .../ResourceLinkPredicateBuilderTest.java | 13 +- .../fhir/parser/JsonParserDstu2_1Test.java | 2 - .../ServerUsingOldTypesDstu2_1Test.java | 1 - ...tThymeleafNarrativeGeneratorDstu2Test.java | 1 - .../uhn/fhir/parser/JsonParserDstu2Test.java | 1 - .../fhir/rest/client/ETagClientDstu2Test.java | 1 - .../InterceptorUserDataMapDstu2Test.java | 13 +- .../LoggingInterceptorDstu2Test.java | 1 - .../server/ServerUsingOldTypesDstu3Test.java | 1 - .../fhir/util/ParametersUtilDstu3Test.java | 1 - .../model/BaseDateTimeTypeDstu3Test.java | 1 - .../fhir/parser/XmlParserHl7OrgDstu2Test.java | 3 - .../uhn/fhir/rest/client/ETagClientTest.java | 1 - ...aultThymeleafNarrativeGeneratorR4Test.java | 1 - .../ca/uhn/fhir/rest/client/ClientR4Test.java | 2 - .../rest/client/ExceptionHandlingTest.java | 1 - .../fhir/rest/client/GenericClientR4Test.java | 1 - .../rest/server/BlockingContentR4Test.java | 3 +- .../CapabilityStatementCacheR4Test.java | 5 +- .../fhir/rest/server/PlainProviderR4Test.java | 2 - .../ca/uhn/fhir/rest/server/PreferTest.java | 2 +- .../server/ServerInvalidDefinitionR4Test.java | 1 - .../ExceptionHandlingInterceptorTest.java | 1 - hapi-fhir-test-utilities/pom.xml | 1 + .../HasGetterOrSetterForAllJsonFields.java | 157 ------------- .../java/ca/uhn/test/util/LogEventAssert.java | 3 - .../util/LogbackCaptureTestExtension.java | 197 ---------------- .../ca/uhn/test/util/LogbackEventMatcher.java | 83 ------- .../StaticLogbackCaptureTestExtension.java | 116 ---------- ...RequestValidatingInterceptorDstu3Test.java | 1 - ...esponseValidatingInterceptorDstu3Test.java | 1 - .../ResourceValidatorDstu2_1Test.java | 1 - .../ResourceValidatorDstu3Test.java | 1 - .../Dstu2ResourceValidatorDstu2Test.java | 5 - .../karaf/dstu21/JsonParserDstu2_1Test.java | 15 +- .../karaf/dstu21/XmlParserDstu2_1Test.java | 21 +- .../JsonParserHl7OrgDstu2Test.java | 7 - .../dstu2hl7org/XmlParserHl7OrgDstu2Test.java | 7 - .../karaf/dstu3/Dstu3JsonParserTest.java | 15 +- .../karaf/dstu3/Dstu3XmlParserTest.java | 22 +- .../ResourceValidatorDstu3FeatureTest.java | 1 - .../karaf/r4/R4JsonParserTest.java | 2 - .../integration/karaf/r4/R4XmlParserTest.java | 2 - 94 files changed, 474 insertions(+), 1356 deletions(-) delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java create mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/GoldenResourceMatchingAssert.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsLinkedTo.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleLinkedTo.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleMatchWith.java delete mode 100644 hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsSameGoldenResourceAs.java delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/HasGetterOrSetterForAllJsonFields.java delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogbackCaptureTestExtension.java delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogbackEventMatcher.java delete mode 100644 hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/StaticLogbackCaptureTestExtension.java diff --git a/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml b/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml index cca82964712..cd9a3b53818 100644 --- a/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml +++ b/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml @@ -23,9 +23,6 @@ - - - diff --git a/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml b/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml index 4512d375391..c74e8b7e01c 100644 --- a/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml +++ b/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml @@ -35,8 +35,8 @@ - - + + diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ElasticTest.java b/hapi-fhir-jpaserver-elastic-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ElasticTest.java index 60f939631fb..da3ec84cbc2 100644 --- a/hapi-fhir-jpaserver-elastic-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ElasticTest.java +++ b/hapi-fhir-jpaserver-elastic-test-utilities/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ElasticTest.java @@ -9,9 +9,8 @@ import ca.uhn.fhir.test.utilities.docker.RequiresDocker; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.AbstractIterableAssert; import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Coding; @@ -33,6 +32,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Objects; @@ -91,9 +91,8 @@ public class ResourceProviderR4ElasticTest extends BaseResourceProviderR4Test { ourLog.info("testAutocompleteDirectionExisting {}", text); assertNotNull(valueSet); List expansions = valueSet.getExpansion().getContains(); - // TODO CHECKSTYLE KHS -// assertThat(expansions, hasItem(valueSetExpansionMatching(mean_blood_pressure))); -// assertThat(expansions).doesNotContain(valueSetExpansionMatching(blood_count)); + ValueSetExpansionIterableAssert.assertThat(expansions).hasExpansionWithCoding(mean_blood_pressure); + ValueSetExpansionIterableAssert.assertThat(expansions).doesNotHaveExpansionWithCoding(blood_count); } } @@ -110,19 +109,51 @@ public class ResourceProviderR4ElasticTest extends BaseResourceProviderR4Test { myObservationDao.create(observation, mySrd).getId().toUnqualifiedVersionless(); } - public static Matcher valueSetExpansionMatching(IBaseCoding theTarget) { - return new TypeSafeDiagnosingMatcher() { - @Override - public void describeTo(Description description) { - description.appendText("ValueSetExpansionContainsComponent matching ").appendValue(theTarget.getSystem() + "|" + theTarget.getCode()); - } + public static class ValueSetExpansionAssert extends AbstractAssert { - @Override - protected boolean matchesSafely(ValueSet.ValueSetExpansionContainsComponent theItem, Description mismatchDescription) { - return Objects.equals(theItem.getSystem(), theTarget.getSystem()) && - Objects.equals(theItem.getCode(), theTarget.getCode()); + protected ValueSetExpansionAssert(ValueSet.ValueSetExpansionContainsComponent valueSetExpansionContainsComponent) { + super(valueSetExpansionContainsComponent, ValueSetExpansionAssert.class); + } + } + + public static class ValueSetExpansionIterableAssert extends AbstractIterableAssert, ValueSet.ValueSetExpansionContainsComponent, ValueSetExpansionAssert> { + protected ValueSetExpansionIterableAssert(Collection actual) { + super(actual, ValueSetExpansionIterableAssert.class); + } + + @Override + protected ValueSetExpansionAssert toAssert(ValueSet.ValueSetExpansionContainsComponent value, String description) { + return new ValueSetExpansionAssert(value).as(description); + } + + public static ValueSetExpansionIterableAssert assertThat(Collection actual) { + return new ValueSetExpansionIterableAssert(actual); + } + + @Override + protected ValueSetExpansionIterableAssert newAbstractIterableAssert(Iterable iterable) { + return new ValueSetExpansionIterableAssert((Collection) iterable); + } + + public ValueSetExpansionIterableAssert hasExpansionWithCoding(IBaseCoding theCoding) { + String otherSystem = theCoding.getSystem(); + String otherCode = theCoding.getCode(); + boolean hasMatchingExpansion = actual.stream().anyMatch(item -> Objects.equals(item.getSystem(), otherSystem) && Objects.equals(item.getCode(), otherCode)); + if (!hasMatchingExpansion) { + failWithMessage("Expansion list should contain an expansion with system " + otherSystem + " and code " + otherCode); } - }; + return this; + } + + public ValueSetExpansionIterableAssert doesNotHaveExpansionWithCoding(IBaseCoding theCoding) { + String otherSystem = theCoding.getSystem(); + String otherCode = theCoding.getCode(); + boolean hasMatchingExpansion = actual.stream().anyMatch(expansion -> Objects.equals(expansion.getCode(), otherCode) && Objects.equals(expansion.getSystem(), otherSystem)); + if (hasMatchingExpansion) { + failWithMessage("Expected not to find a matching expansion, but we found one!"); + } + return this; + } } @Test diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java index 325313eaca1..07f0f62fd7f 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/BaseMdmR4Test.java @@ -12,12 +12,7 @@ import ca.uhn.fhir.jpa.mdm.config.MdmSubmitterConfig; import ca.uhn.fhir.jpa.mdm.config.TestMdmConfigR4; import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; import ca.uhn.fhir.jpa.mdm.helper.MdmLinkHelper; -import ca.uhn.fhir.jpa.mdm.matcher.IsLinkedTo; -import ca.uhn.fhir.jpa.mdm.matcher.IsMatchedToAGoldenResource; -import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleDuplicateOf; -import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleLinkedTo; -import ca.uhn.fhir.jpa.mdm.matcher.IsPossibleMatchWith; -import ca.uhn.fhir.jpa.mdm.matcher.IsSameGoldenResourceAs; +import ca.uhn.fhir.jpa.mdm.matcher.GoldenResourceMatchingAssert; import ca.uhn.fhir.jpa.mdm.svc.MdmMatchLinkSvc; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.dao.JpaPid; @@ -45,8 +40,6 @@ import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; -import org.hamcrest.Description; -import org.hamcrest.Matcher; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.*; @@ -159,6 +152,9 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { myMdmLinkDaoSvc.save(theMdmLink); } + protected GoldenResourceMatchingAssert mdmAssertThat(IAnyResource theResource) { + return GoldenResourceMatchingAssert.assertThat(theResource, myIdHelperService, myMdmLinkDaoSvc); + } @Nonnull protected Patient createGoldenPatient() { return createPatient(new Patient(), true, false); @@ -504,54 +500,6 @@ abstract public class BaseMdmR4Test extends BaseJpaR4Test { return thePractitioner; } - private Matcher wrapMatcherInTransaction(Supplier> theFunction) { - return new Matcher() { - @Override - public boolean matches(Object actual) { - return runInTransaction(() -> theFunction.get().matches(actual)); - } - - @Override - public void describeMismatch(Object actual, Description mismatchDescription) { - runInTransaction(() -> theFunction.get().describeMismatch(actual, mismatchDescription)); - } - - @Override - public void _dont_implement_Matcher___instead_extend_BaseMatcher_() { - - } - - @Override - public void describeTo(Description description) { - runInTransaction(() -> theFunction.get().describeTo(description)); - } - }; - } - - protected Matcher sameGoldenResourceAs(IAnyResource... theBaseResource) { - return wrapMatcherInTransaction(() -> IsSameGoldenResourceAs.sameGoldenResourceAs(myIdHelperService, myMdmLinkDaoSvc, theBaseResource)); - } - - protected Matcher linkedTo(IAnyResource... theBaseResource) { - return wrapMatcherInTransaction(() -> IsLinkedTo.linkedTo(myIdHelperService, myMdmLinkDaoSvc, theBaseResource)); - } - - protected Matcher possibleLinkedTo(IAnyResource... theBaseResource) { - return wrapMatcherInTransaction(() -> IsPossibleLinkedTo.possibleLinkedTo(myIdHelperService, myMdmLinkDaoSvc, theBaseResource)); - } - - protected Matcher possibleMatchWith(IAnyResource... theBaseResource) { - return wrapMatcherInTransaction(() -> IsPossibleMatchWith.possibleMatchWith(myIdHelperService, myMdmLinkDaoSvc, theBaseResource)); - } - - protected Matcher possibleDuplicateOf(IAnyResource... theBaseResource) { - return wrapMatcherInTransaction(() -> IsPossibleDuplicateOf.possibleDuplicateOf(myIdHelperService, myMdmLinkDaoSvc, theBaseResource)); - } - - protected Matcher matchedToAGoldenResource() { - return wrapMatcherInTransaction(() -> IsMatchedToAGoldenResource.matchedToAGoldenResource(myIdHelperService, myMdmLinkDaoSvc)); - } - protected Patient getOnlyGoldenPatient() { List resources = getAllGoldenPatients(); assertEquals(1, resources.size()); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java deleted file mode 100644 index 8c19146eb45..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/BaseGoldenResourceMatcher.java +++ /dev/null @@ -1,82 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.interceptor.model.RequestPartitionId; -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.mdm.api.IMdmLink; -import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; -import ca.uhn.fhir.mdm.util.MdmResourceUtil; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import jakarta.annotation.Nullable; -import org.hamcrest.TypeSafeMatcher; -import org.hl7.fhir.instance.model.api.IAnyResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -public abstract class BaseGoldenResourceMatcher extends TypeSafeMatcher { - - private static final Logger ourLog = LoggerFactory.getLogger(BaseGoldenResourceMatcher.class); - - protected IIdHelperService myIdHelperService; - protected MdmLinkDaoSvc myMdmLinkDaoSvc; - protected Collection myBaseResources; - protected String myTargetType; - - protected BaseGoldenResourceMatcher(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - myIdHelperService = theIdHelperService; - myMdmLinkDaoSvc = theMdmLinkDaoSvc; - myBaseResources = Arrays.stream(theBaseResource).collect(Collectors.toList()); - } - - @Nullable - protected IResourcePersistentId getMatchedResourcePidFromResource(IAnyResource theResource) { - IResourcePersistentId retval; - - boolean isGoldenRecord = MdmResourceUtil.isMdmManaged(theResource); - if (isGoldenRecord) { - return myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theResource); - } - IMdmLink matchLink = getMatchedMdmLink(theResource); - - if (matchLink == null) { - return null; - } else { - retval = matchLink.getGoldenResourcePersistenceId(); - myTargetType = matchLink.getMdmSourceType(); - } - return retval; - } - - protected List getPossibleMatchedGoldenResourcePidsFromTarget(IAnyResource theBaseResource) { - return getMdmLinksForTarget(theBaseResource, MdmMatchResultEnum.POSSIBLE_MATCH) - .stream() - .map(IMdmLink::getGoldenResourcePersistenceId).collect(Collectors.toList()); - } - - protected IMdmLink getMatchedMdmLink(IAnyResource thePatientOrPractitionerResource) { - List mdmLinks = getMdmLinksForTarget(thePatientOrPractitionerResource, MdmMatchResultEnum.MATCH); - if (mdmLinks.size() == 0) { - return null; - } else if (mdmLinks.size() == 1) { - return mdmLinks.get(0); - } else { - throw new IllegalStateException("Its illegal to have more than 1 match for a given target! we found " + mdmLinks.size() + " for resource with id: " + thePatientOrPractitionerResource.getIdElement().toUnqualifiedVersionless()); - } - } - - protected List getMdmLinksForTarget(IAnyResource theTargetResource, MdmMatchResultEnum theMatchResult) { - IResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theTargetResource); - List matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(pidOrNull, theMatchResult); - if (!matchLinkForTarget.isEmpty()) { - return matchLinkForTarget; - } else { - return new ArrayList<>(); - } - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/GoldenResourceMatchingAssert.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/GoldenResourceMatchingAssert.java new file mode 100644 index 00000000000..4cc664d3099 --- /dev/null +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/GoldenResourceMatchingAssert.java @@ -0,0 +1,215 @@ +package ca.uhn.fhir.jpa.mdm.matcher; + +import ca.uhn.fhir.interceptor.model.RequestPartitionId; +import ca.uhn.fhir.jpa.api.svc.IIdHelperService; +import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; +import ca.uhn.fhir.mdm.api.IMdmLink; +import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; +import ca.uhn.fhir.mdm.util.MdmResourceUtil; +import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; +import jakarta.annotation.Nullable; +import org.assertj.core.api.AbstractAssert; +import org.hl7.fhir.instance.model.api.IAnyResource; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Assertion class for asserting matching of golden resources. + */ +public class GoldenResourceMatchingAssert extends AbstractAssert { + + private IResourcePersistentId actualGoldenResourcePid; + private IResourcePersistentId actualSourceResourcePid; + private IIdHelperService myIdHelperService; + private MdmLinkDaoSvc myMdmLinkDaoSvc; + + protected GoldenResourceMatchingAssert(IAnyResource actual, IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) { + super(actual, GoldenResourceMatchingAssert.class); + myIdHelperService = theIdHelperService; + myMdmLinkDaoSvc = theMdmLinkDaoSvc; + actualGoldenResourcePid = getGoldenResourcePid(actual); + actualSourceResourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), actual); + } + + public static GoldenResourceMatchingAssert assertThat(IAnyResource actual, IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) { + return new GoldenResourceMatchingAssert(actual, theIdHelperService, theMdmLinkDaoSvc); + } + + // Method to compare with another resource + public GoldenResourceMatchingAssert is_MATCH_to(IAnyResource other) { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(other); + if (!actualGoldenResourcePid.equals(otherGoldenPid)) { + failWithActualExpectedAndMessage(actualGoldenResourcePid, otherGoldenPid, "Did not match golden resource pids!"); + } + return this; + } + + public GoldenResourceMatchingAssert is_not_MATCH_to(IAnyResource other) { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(other); + if (actualGoldenResourcePid != null && actualGoldenResourcePid.equals(otherGoldenPid)) { + failWithActualExpectedAndMessage(actualGoldenResourcePid, otherGoldenPid, "Matched when it should not have!"); + } + return this; + } + + + + public GoldenResourceMatchingAssert is_NO_MATCH_to(IAnyResource other) { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(other); + if (actualGoldenResourcePid != null && actualGoldenResourcePid.equals(otherGoldenPid)) { + failWithActualExpectedAndMessage(actualGoldenResourcePid, otherGoldenPid, "Both resources are linked to the same Golden pid!"); + } + return this; + } + + public GoldenResourceMatchingAssert is_POSSIBLE_MATCH_to(IAnyResource other) { + boolean possibleMatch = hasPossibleMatchWith(other); + + if (!possibleMatch) { + failWithMessage("No POSSIBLE_MATCH between these two resources."); + } + + return this; + } + + private boolean hasPossibleMatchWith(IAnyResource other) { + IResourcePersistentId otherSourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), other); + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(other); + + //Check for direct matches in either direction. + // A POSSIBLE_MATCH -> B + if (actualGoldenResourcePid != null) { + Optional directForwardLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(actualGoldenResourcePid, otherSourcePid, MdmMatchResultEnum.POSSIBLE_MATCH); + if (directForwardLink.isPresent()) { + return true; + } + } + // B -> POSSIBLE_MATCH -> A + if (otherGoldenPid != null) { + Optional directBackwardLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(otherGoldenPid, actualSourceResourcePid, MdmMatchResultEnum.POSSIBLE_MATCH); + if (directBackwardLink.isPresent()) { + return true; + } + } + + // Check for indirect possible matches, e.g. + // A -> POSSIBLE_MATCH -> B + // C -> POSSIBLE_MATCH -> B + // this implies + // A -> POSSIBLE_MATCH ->C + + boolean possibleMatch = false; + Set goldenPids = new HashSet<>(); + List possibleLinksForOther = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(otherSourcePid, MdmMatchResultEnum.POSSIBLE_MATCH); + Set otherPossibles = possibleLinksForOther.stream().map(IMdmLink::getGoldenResourcePersistenceId).collect(Collectors.toSet()); + goldenPids.addAll(otherPossibles); + + +// Compare and inflate with all possible matches from the actual. If we hit a collision, we know that the implies POSSIBLE_MATCH exists. + List possibleLinksForActual = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(actualSourceResourcePid, MdmMatchResultEnum.POSSIBLE_MATCH); + Set actualPossiblePids = possibleLinksForActual.stream().map(IMdmLink::getGoldenResourcePersistenceId).collect(Collectors.toSet()); + possibleMatch = isPossibleMatch(actualPossiblePids, goldenPids, possibleMatch); + return possibleMatch; + } + + private static boolean isPossibleMatch(Set matchedPids, Set goldenPids, boolean possibleMatch) { + for (IResourcePersistentId pid : matchedPids) { + if (goldenPids.contains(pid)) { + return true; + } else { + goldenPids.add(pid); + } + } + return false; + } + + public boolean possibleDuplicateLinkExistsBetween(IResourcePersistentId goldenPid1, IResourcePersistentId goldenPid2) { + Optional possibleForwardsLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenPid1, goldenPid2, MdmMatchResultEnum.POSSIBLE_DUPLICATE); + Optional possibleBackwardsLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(goldenPid2, goldenPid1, MdmMatchResultEnum.POSSIBLE_DUPLICATE); + return possibleBackwardsLink.isPresent() || possibleForwardsLink.isPresent(); + } + + public GoldenResourceMatchingAssert is_POSSIBLE_DUPLICATE_to(IAnyResource other) { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(other); + if (actualGoldenResourcePid == null || otherGoldenPid == null) { + failWithMessage("For a POSSIBLE_DUPLICATE, both resources must have a MATCH. This is not the case for these resources."); + } + boolean possibleDuplicateExists = possibleDuplicateLinkExistsBetween(actualGoldenResourcePid, otherGoldenPid); + if (!possibleDuplicateExists) { + failWithActualExpectedAndMessage("No POSSIBLE_DUPLICATE found between " + actualGoldenResourcePid + " and " + otherGoldenPid, + "POSSIBLE_DUPLICATE found between " + actualGoldenResourcePid + " and " + otherGoldenPid, + "No POSSIBLE_DUPLICATE links were found between golden resources"); + } + return this; + } + + + @Nullable + protected IResourcePersistentId getGoldenResourcePid(IAnyResource theResource) { + IResourcePersistentId retval; + + boolean isGoldenRecord = MdmResourceUtil.isMdmManaged(theResource); + if (isGoldenRecord) { + return myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theResource); + } + IMdmLink matchLink = getMatchedMdmLink(theResource); + + if (matchLink == null) { + return null; + } else { + retval = matchLink.getGoldenResourcePersistenceId(); + } + return retval; + } + + protected IMdmLink getMatchedMdmLink(IAnyResource thePatientOrPractitionerResource) { + List mdmLinks = getMdmLinksForTarget(thePatientOrPractitionerResource, MdmMatchResultEnum.MATCH); + if (mdmLinks.size() == 0) { + return null; + } else if (mdmLinks.size() == 1) { + return mdmLinks.get(0); + } else { + throw new IllegalStateException("Its illegal to have more than 1 match for a given target! we found " + mdmLinks.size() + " for resource with id: " + thePatientOrPractitionerResource.getIdElement().toUnqualifiedVersionless()); + } + } + + protected List getMdmLinksForTarget(IAnyResource theTargetResource, MdmMatchResultEnum theMatchResult) { + IResourcePersistentId pidOrNull = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theTargetResource); + List matchLinkForTarget = myMdmLinkDaoSvc.getMdmLinksBySourcePidAndMatchResult(pidOrNull, theMatchResult); + if (!matchLinkForTarget.isEmpty()) { + return matchLinkForTarget; + } else { + return new ArrayList<>(); + } + } + + public GoldenResourceMatchingAssert hasGoldenResourceMatch() { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(actual); + if (otherGoldenPid == null) { + failWithMessage("Expected resource to be matched to a golden resource. Found no such matches. "); + } + return this; + } + + public GoldenResourceMatchingAssert doesNotHaveGoldenResourceMatch() { + IResourcePersistentId otherGoldenPid = getGoldenResourcePid(actual); + if (otherGoldenPid != null) { + failWithMessage("Expected resource to have no golden resource match, but it did."); + } + return this; + } + + public GoldenResourceMatchingAssert is_not_POSSIBLE_DUPLICATE_to(IAnyResource other) { + IResourcePersistentId otherGoldenResourcePid = getGoldenResourcePid(other); + boolean possibleDuplicateExists = possibleDuplicateLinkExistsBetween(actualGoldenResourcePid, otherGoldenResourcePid); + if (possibleDuplicateExists) { + failWithMessage("Possible duplicate exists between both resources!"); + } + return this; + } +} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsLinkedTo.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsLinkedTo.java deleted file mode 100644 index 5c1568d11e4..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsLinkedTo.java +++ /dev/null @@ -1,48 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * A Matcher which allows us to check that a target patient/practitioner at a given link level. - * is linked to a set of patients/practitioners via a golden resource. - */ -public class IsLinkedTo extends BaseGoldenResourceMatcher { - - private List baseResourceGoldenResourcePids; - private IResourcePersistentId incomingResourceGoldenResourcePid; - - protected IsLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } - - - @Override - protected boolean matchesSafely(IAnyResource theIncomingResource) { - incomingResourceGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource); - - //OK, lets grab all the golden resource pids of the resources passed in via the constructor. - baseResourceGoldenResourcePids = myBaseResources.stream() - .map(this::getMatchedResourcePidFromResource) - .collect(Collectors.toList()); - - //The resources are linked if all golden resource pids match the incoming golden resource pid. - return baseResourceGoldenResourcePids.stream() - .allMatch(pid -> pid.equals(incomingResourceGoldenResourcePid)); - } - - @Override - public void describeTo(Description theDescription) { - } - - public static Matcher linkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - return new IsLinkedTo(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java deleted file mode 100644 index 916f7119a55..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsMatchedToAGoldenResource.java +++ /dev/null @@ -1,38 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.interceptor.model.RequestPartitionId; -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.mdm.api.IMdmLink; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.Optional; - -public class IsMatchedToAGoldenResource extends TypeSafeMatcher { - - private final IIdHelperService myIdHelperService; - private final MdmLinkDaoSvc myMdmLinkDaoSvc; - - public IsMatchedToAGoldenResource(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) { - myIdHelperService = theIdHelperService; - myMdmLinkDaoSvc = theMdmLinkDaoSvc; - } - - @Override - protected boolean matchesSafely(IAnyResource theIncomingResource) { - Optional matchedLinkForTargetPid = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theIncomingResource)); - return matchedLinkForTargetPid.isPresent(); - } - - @Override - public void describeTo(Description theDescription) { - theDescription.appendText("target was not linked to a Golden Resource."); - } - - public static Matcher matchedToAGoldenResource(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc) { - return new IsMatchedToAGoldenResource(theIdHelperService, theMdmLinkDaoSvc); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java deleted file mode 100644 index ce560cf4c4e..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleDuplicateOf.java +++ /dev/null @@ -1,62 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.mdm.api.IMdmLink; -import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class IsPossibleDuplicateOf extends BaseGoldenResourceMatcher { - - /** - * Matcher with tells us if there is an MdmLink with between these two resources that are considered POSSIBLE DUPLICATE. - * For use only on GoldenResource. - */ - private IResourcePersistentId incomingGoldenResourcePid; - - protected IsPossibleDuplicateOf(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } - - @Override - protected boolean matchesSafely(IAnyResource theIncomingResource) { - incomingGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource); - - List goldenResourcePidsToMatch = myBaseResources.stream() - .map(this::getMatchedResourcePidFromResource) - .collect(Collectors.toList()); - - - //Returns true if there is a POSSIBLE_DUPLICATE between the incoming resource, and all of the resources passed in via the constructor. - return goldenResourcePidsToMatch.stream() - .map(baseResourcePid -> { - Optional duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(baseResourcePid, incomingGoldenResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); - if (!duplicateLink.isPresent()) { - duplicateLink = myMdmLinkDaoSvc.getMdmLinksByGoldenResourcePidSourcePidAndMatchResult(incomingGoldenResourcePid, baseResourcePid, MdmMatchResultEnum.POSSIBLE_DUPLICATE); - } - return duplicateLink; - }).allMatch(Optional::isPresent); - } - - @Override - public void describeTo(Description theDescription) { - theDescription.appendText("Resource was not duplicate of Resource/" + incomingGoldenResourcePid); - } - - @Override - protected void describeMismatchSafely(IAnyResource item, Description mismatchDescription) { - super.describeMismatchSafely(item, mismatchDescription); - mismatchDescription.appendText("No MdmLink With POSSIBLE_DUPLICATE was found"); - } - - public static Matcher possibleDuplicateOf(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - return new IsPossibleDuplicateOf(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleLinkedTo.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleLinkedTo.java deleted file mode 100644 index 226f83b17dd..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleLinkedTo.java +++ /dev/null @@ -1,48 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.interceptor.model.RequestPartitionId; -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * A Matcher which allows us to check that a target resource at a given link level - * is linked to a set of target resources via a golden resource. - */ -public class IsPossibleLinkedTo extends BaseGoldenResourceMatcher { - - private List baseResourceGoldenResourcePids; - private IResourcePersistentId incomingResourceGoldenResourcePid; - - protected IsPossibleLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theTargetResources) { - super(theIdHelperService, theMdmLinkDaoSvc, theTargetResources); - } - - @Override - protected boolean matchesSafely(IAnyResource theGoldenResource) { - incomingResourceGoldenResourcePid = myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), theGoldenResource); - - //OK, lets grab all the golden resource pids of the resources passed in via the constructor. - baseResourceGoldenResourcePids = myBaseResources.stream() - .flatMap(iBaseResource -> getPossibleMatchedGoldenResourcePidsFromTarget(iBaseResource).stream()) - .collect(Collectors.toList()); - - //The resources are linked if all golden resource pids match the incoming golden resource pid. - return baseResourceGoldenResourcePids.stream() - .allMatch(pid -> pid.equals(incomingResourceGoldenResourcePid)); - } - - @Override - public void describeTo(Description theDescription) { - } - - public static Matcher possibleLinkedTo(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - return new IsPossibleLinkedTo(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleMatchWith.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleMatchWith.java deleted file mode 100644 index ecdae0a4f2d..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsPossibleMatchWith.java +++ /dev/null @@ -1,61 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.mdm.api.IMdmLink; -import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * Matcher with tells us if there is an MdmLink with between these two resources that are considered POSSIBLE_MATCH - */ -public class IsPossibleMatchWith extends BaseGoldenResourceMatcher { - - protected IsPossibleMatchWith(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } - - @Override - protected boolean matchesSafely(IAnyResource theIncomingResource) { - List mdmLinks = getMdmLinksForTarget(theIncomingResource, MdmMatchResultEnum.POSSIBLE_MATCH); - - List goldenResourcePidsToMatch = myBaseResources.stream() - .map(this::getMatchedResourcePidFromResource) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - if (goldenResourcePidsToMatch.isEmpty()) { - goldenResourcePidsToMatch = myBaseResources.stream() - .flatMap(iBaseResource -> getPossibleMatchedGoldenResourcePidsFromTarget(iBaseResource).stream()) - .collect(Collectors.toList()); - } - - List mdmLinkGoldenResourcePids = mdmLinks - .stream().map(IMdmLink::getGoldenResourcePersistenceId) - .collect(Collectors.toList()); - - return mdmLinkGoldenResourcePids.containsAll(goldenResourcePidsToMatch); - } - - @Override - public void describeTo(Description theDescription) { - theDescription.appendText(" no link found with POSSIBLE_MATCH to the requested PIDS"); - } - - @Override - protected void describeMismatchSafely(IAnyResource item, Description mismatchDescription) { - super.describeMismatchSafely(item, mismatchDescription); - mismatchDescription.appendText("No MDM Link With POSSIBLE_MATCH was found"); - } - - public static Matcher possibleMatchWith(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - return new IsPossibleMatchWith(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsSameGoldenResourceAs.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsSameGoldenResourceAs.java deleted file mode 100644 index 9493c511af2..00000000000 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/matcher/IsSameGoldenResourceAs.java +++ /dev/null @@ -1,47 +0,0 @@ -package ca.uhn.fhir.jpa.mdm.matcher; - -import ca.uhn.fhir.jpa.api.svc.IIdHelperService; -import ca.uhn.fhir.jpa.mdm.dao.MdmLinkDaoSvc; -import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hl7.fhir.instance.model.api.IAnyResource; - -import java.util.List; -import java.util.stream.Collectors; - -public class IsSameGoldenResourceAs extends BaseGoldenResourceMatcher { - - private List goldenResourcePidsToMatch; - private IResourcePersistentId incomingGoldenResourcePid; - - public IsSameGoldenResourceAs(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - super(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } - - @Override - protected boolean matchesSafely(IAnyResource theIncomingResource) { - incomingGoldenResourcePid = getMatchedResourcePidFromResource(theIncomingResource); - goldenResourcePidsToMatch = myBaseResources.stream().map(this::getMatchedResourcePidFromResource).collect(Collectors.toList()); - boolean allToCheckAreSame = goldenResourcePidsToMatch.stream().allMatch(pid -> pid.equals(goldenResourcePidsToMatch.get(0))); - if (!allToCheckAreSame) { - throw new IllegalStateException("You wanted to do a source resource comparison, but the pool of source resources you submitted for checking don't match! We won't even check the incoming source resource against them."); - } - return goldenResourcePidsToMatch.contains(incomingGoldenResourcePid); - } - - @Override - public void describeTo(Description theDescription) { - theDescription.appendText(String.format(" %s linked to source resource %s/%s", myTargetType, myTargetType, goldenResourcePidsToMatch)); - } - - @Override - protected void describeMismatchSafely(IAnyResource item, Description mismatchDescription) { - super.describeMismatchSafely(item, mismatchDescription); - mismatchDescription.appendText(String.format(" was actually linked to %s/%s", myTargetType, incomingGoldenResourcePid)); - } - - public static Matcher sameGoldenResourceAs(IIdHelperService theIdHelperService, MdmLinkDaoSvc theMdmLinkDaoSvc, IAnyResource... theBaseResource) { - return new IsSameGoldenResourceAs(theIdHelperService, theMdmLinkDaoSvc, theBaseResource); - } -} diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java index d06f383e9d1..9fc1051558b 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/provider/MdmProviderMergeGoldenResourcesR4Test.java @@ -1,9 +1,11 @@ package ca.uhn.fhir.jpa.mdm.provider; +import static org.assertj.core.api.Assertions.assertThat; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.entity.PartitionEntity; +import ca.uhn.fhir.jpa.mdm.matcher.GoldenResourceMatchingAssert; import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.mdm.api.MdmLinkSourceEnum; import ca.uhn.fhir.mdm.api.MdmMatchResultEnum; @@ -20,16 +22,11 @@ import org.junit.jupiter.api.Test; import java.io.IOException; import java.util.List; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.endsWith; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -//TODO GGG Convert this to assertJ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { private Patient myFromGoldenPatient; @@ -88,7 +85,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { assertFalse(MdmResourceUtil.isGoldenRecordRedirected(mergedSourcePatient)); assertEquals(myToGoldenPatient.getIdElement(), mergedSourcePatient.getIdElement()); - assertThat(mergedSourcePatient, is(sameGoldenResourceAs(myToGoldenPatient))); + GoldenResourceMatchingAssert.assertThat(mergedSourcePatient, myIdHelperService, myMdmLinkDaoSvc).is_MATCH_to(myToGoldenPatient); assertEquals(1, getAllRedirectedGoldenPatients().size()); assertEquals(1, getAllGoldenPatients().size()); @@ -99,10 +96,10 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { //TODO GGG eventually this will need to check a redirect... this is a hack which doesnt work // Optional redirect = fromSourcePatient.getIdentifier().stream().filter(theIdentifier -> theIdentifier.getSystem().equals("REDIRECT")).findFirst(); - // assertThat(redirect.get().getValue(), is(equalTo(myToSourcePatient.getIdElement().toUnqualified().getValue()))); + // assertThat(redirect.get().getValue()).isEqualTo(myToSourcePatient.getIdElement().toUnqualified().getValue()); List links = (List) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myToGoldenPatient); - assertThat(links, hasSize(1)); + assertThat(links).hasSize(1); MdmLink link = links.get(0); assertEquals(link.getSourcePid(), myToGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); @@ -131,13 +128,13 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { assertFalse(MdmResourceUtil.isGoldenRecordRedirected(mergedSourcePatient)); assertEquals(toGoldenPatient.getIdElement(), mergedSourcePatient.getIdElement()); - assertThat(mergedSourcePatient, is(sameGoldenResourceAs(toGoldenPatient))); + mdmAssertThat(mergedSourcePatient).is_MATCH_to(toGoldenPatient); assertEquals(1, getAllRedirectedGoldenPatients().size()); // 2 from the set-up and only one from this test should be golden resource assertEquals(3, getAllGoldenPatients().size()); List links = (List) myMdmLinkDaoSvc.findMdmLinksBySourceResource(toGoldenPatient); - assertThat(links, hasSize(1)); + assertThat(links).hasSize(1); MdmLink link = links.get(0); assertEquals(link.getSourcePid(), toGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); @@ -163,7 +160,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { myMdmProvider.mergeGoldenResources(fromGoldenPatientId, toGoldenPatientId, null, myRequestDetails); fail(); } catch (InvalidRequestException e) { - assertThat(e.getMessage(), endsWith("This operation is only available for resources on the same partition.")); + assertThat(e.getMessage()).endsWith("This operation is only available for resources on the same partition."); } } @@ -178,7 +175,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { patient, myRequestDetails); assertEquals(myToGoldenPatient.getIdElement(), mergedSourcePatient.getIdElement()); - assertThat(mergedSourcePatient, is(sameGoldenResourceAs(myToGoldenPatient))); + mdmAssertThat(mergedSourcePatient).is_MATCH_to(myToGoldenPatient); assertEquals(1, getAllRedirectedGoldenPatients().size()); assertEquals(1, getAllGoldenPatients().size()); @@ -187,7 +184,7 @@ public class MdmProviderMergeGoldenResourcesR4Test extends BaseProviderR4Test { assertTrue(MdmResourceUtil.isGoldenRecordRedirected(fromSourcePatient)); List links = (List) myMdmLinkDaoSvc.findMdmLinksBySourceResource(myToGoldenPatient); - assertThat(links, hasSize(1)); + assertThat(links).hasSize(1); MdmLink link = links.get(0); assertEquals(link.getSourcePid(), myToGoldenPatient.getIdElement().toUnqualifiedVersionless().getIdPartAsLong()); diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java index b68f014edaa..1901a9faf5c 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmGoldenResourceMergerSvcTest.java @@ -18,6 +18,7 @@ import ca.uhn.fhir.mdm.model.MdmTransactionContext; import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import ca.uhn.fhir.rest.server.TransactionLogMessages; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.jpa.mdm.matcher.GoldenResourceMatchingAssert; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Address; import org.hl7.fhir.r4.model.DateType; @@ -95,8 +96,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test { Patient mergedGoldenPatient = mergeGoldenPatients(); assertEquals(myToGoldenPatient.getIdElement(), mergedGoldenPatient.getIdElement()); - // TODO CHECKSTYLE KHS restore -// assertThat(mergedGoldenPatient).is(sameGoldenResourceAs(mergedGoldenPatient)); + GoldenResourceMatchingAssert.assertThat(mergedGoldenPatient, myIdHelperService, myMdmLinkDaoSvc).is_MATCH_to(mergedGoldenPatient); assertThat(getAllGoldenPatients()).hasSize(1); assertThat(getAllRedirectedGoldenPatients()).hasSize(1); } @@ -242,8 +242,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test { Patient mergedGoldenPatient = mergeGoldenPatients(); List links = getNonRedirectLinksByGoldenResource(mergedGoldenPatient); assertThat(links).hasSize(1); - // TODO CHECKSTYLE KHS restore -// assertThat(mergedGoldenPatient, possibleLinkedTo(myTargetPatient1)); + GoldenResourceMatchingAssert.assertThat(mergedGoldenPatient, myIdHelperService, myMdmLinkDaoSvc).is_POSSIBLE_MATCH_to(myTargetPatient1); } @Test @@ -253,8 +252,7 @@ public class MdmGoldenResourceMergerSvcTest extends BaseMdmR4Test { Patient mergedSourcePatient = mergeGoldenPatients(); List links = getNonRedirectLinksByGoldenResource(mergedSourcePatient); assertThat(links).hasSize(1); - // TODO CHECKSTYLE KHS restore -// assertThat(mergedSourcePatient, possibleLinkedTo(myTargetPatient1)); + GoldenResourceMatchingAssert.assertThat(mergedSourcePatient, myIdHelperService, myMdmLinkDaoSvc).is_POSSIBLE_MATCH_to(myTargetPatient1); } private Patient mergeGoldenResources(Patient theFrom, Patient theTo) { diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java index 48b492f92aa..11bd7ad6eb2 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcMultipleEidModeTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.mdm.svc; +import static org.assertj.core.api.Assertions.assertThat; import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; @@ -22,12 +23,6 @@ import java.util.stream.Stream; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.MATCH; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.POSSIBLE_DUPLICATE; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.POSSIBLE_MATCH; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.in; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; import static org.slf4j.LoggerFactory.getLogger; @TestPropertySource(properties = { @@ -64,7 +59,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchVector(null, 6L); //We want to make sure the patients were linked to the same GoldenResource. - assertThat(patient, is(sameGoldenResourceAs(janePatient))); + mdmAssertThat(patient).is_MATCH_to(janePatient); Patient sourcePatient = (Patient) getGoldenResourceFromTargetResource(patient); @@ -72,17 +67,17 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { //The collision should have kept the old identifier Identifier firstIdentifier = identifier.get(0); - assertThat(firstIdentifier.getSystem(), is(equalTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM))); - assertThat(firstIdentifier.getValue(), is(equalTo(foundHapiEid))); + assertThat(firstIdentifier.getSystem()).isEqualTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM); + assertThat(firstIdentifier.getValue()).isEqualTo(foundHapiEid); //The collision should have added a new identifier with the external system. Identifier secondIdentifier = identifier.get(1); - assertThat(secondIdentifier.getSystem(), is(equalTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")))); - assertThat(secondIdentifier.getValue(), is(equalTo("12345"))); + assertThat(secondIdentifier.getSystem()).isEqualTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")); + assertThat(secondIdentifier.getValue()).isEqualTo("12345"); Identifier thirdIdentifier = identifier.get(2); - assertThat(thirdIdentifier.getSystem(), is(equalTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")))); - assertThat(thirdIdentifier.getValue(), is(equalTo("67890"))); + assertThat(thirdIdentifier.getSystem()).isEqualTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")); + assertThat(thirdIdentifier.getValue()).isEqualTo("67890"); } @Test @@ -111,14 +106,14 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchScore(1.0, 1.0); assertLinksMatchVector(null, null); - assertThat(patient1, is(sameGoldenResourceAs(patient2))); + mdmAssertThat(patient1).is_MATCH_to(patient2); clearExternalEIDs(patient2); addExternalEID(patient2, "id_6"); //At this point, there should be 5 EIDs on the GoldenResource Patient patientFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2); - assertThat(patientFromTarget.getIdentifier(), hasSize(5)); + assertThat(patientFromTarget.getIdentifier()).hasSize(5); ourLog.info("About to update patient..."); updatePatientAndUpdateLinks(patient2); @@ -128,10 +123,10 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchScore(1.0, 1.0); assertLinksMatchVector(null, null); - assertThat(patient1, is(sameGoldenResourceAs(patient2))); + mdmAssertThat(patient1).is_MATCH_to(patient2); patientFromTarget = (Patient) getGoldenResourceFromTargetResource(patient2); - assertThat(patientFromTarget.getIdentifier(), hasSize(6)); + assertThat(patientFromTarget.getIdentifier()).hasSize(6); } @Test @@ -157,7 +152,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchVector(null, null, null); List possibleDuplicates = (List) myMdmLinkDaoSvc.getPossibleDuplicates(); - assertThat(possibleDuplicates, hasSize(1)); + assertThat(possibleDuplicates).hasSize(1); Patient finalPatient1 = patient1; Patient finalPatient2 = patient2; @@ -167,8 +162,8 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { //The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink. MdmLink mdmLink = possibleDuplicates.get(0); - assertThat(mdmLink.getGoldenResourcePersistenceId(), is(in(duplicatePids))); - assertThat(mdmLink.getSourcePersistenceId(), is(in(duplicatePids))); + assertThat(mdmLink.getGoldenResourcePersistenceId()).isIn(duplicatePids); + assertThat(mdmLink.getSourcePersistenceId()).isIn(duplicatePids); } @Test @@ -204,7 +199,7 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchVector(null, null, null); //Now, Patient 2 and 3 are linked, and the GoldenResource has 2 eids. - assertThat(patient2, is(sameGoldenResourceAs(patient3))); + mdmAssertThat(patient2).is_MATCH_to(patient3); //Now lets change one of the EIDs on the second patient to one that matches our original patient. //This should create a situation in which the incoming EIDs are matched to _two_ different GoldenResources. In this case, we want to @@ -220,12 +215,12 @@ public class MdmMatchLinkSvcMultipleEidModeTest extends BaseMdmR4Test { assertLinksMatchScore(1.0, 1.0, 1.0, 1.0, null); assertLinksMatchVector(null, null, null, null, null); - assertThat(patient2, is(not(matchedToAGoldenResource()))); - assertThat(patient2, is(possibleMatchWith(patient1))); - assertThat(patient2, is(possibleMatchWith(patient3))); + mdmAssertThat(patient2).doesNotHaveGoldenResourceMatch(); + mdmAssertThat(patient2).is_POSSIBLE_MATCH_to(patient1); + mdmAssertThat(patient2).is_POSSIBLE_MATCH_to(patient3); List possibleDuplicates = (List) myMdmLinkDaoSvc.getPossibleDuplicates(); - assertThat(possibleDuplicates, hasSize(1)); - assertThat(patient3, is(possibleDuplicateOf(patient1))); + assertThat(possibleDuplicates).hasSize(1); + mdmAssertThat(patient3).is_POSSIBLE_DUPLICATE_to(patient1); } } diff --git a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java index 57b19c41294..8c4db3c08db 100644 --- a/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java +++ b/hapi-fhir-jpaserver-mdm/src/test/java/ca/uhn/fhir/jpa/mdm/svc/MdmMatchLinkSvcTest.java @@ -1,13 +1,13 @@ package ca.uhn.fhir.jpa.mdm.svc; +import static org.assertj.core.api.Assertions.assertThat; import ca.uhn.fhir.interceptor.model.RequestPartitionId; -import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; -import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; import ca.uhn.fhir.jpa.entity.MdmLink; import ca.uhn.fhir.jpa.mdm.BaseMdmR4Test; import ca.uhn.fhir.jpa.mdm.config.BaseTestMdmConfig; import ca.uhn.fhir.jpa.mdm.config.BlockListConfig; import ca.uhn.fhir.jpa.mdm.helper.testmodels.MDMState; +import ca.uhn.fhir.jpa.mdm.matcher.GoldenResourceMatchingAssert; import ca.uhn.fhir.jpa.model.dao.JpaPid; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.mdm.api.IMdmLink; @@ -59,14 +59,6 @@ import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.MATCH; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.NO_MATCH; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.POSSIBLE_DUPLICATE; import static ca.uhn.fhir.mdm.api.MdmMatchResultEnum.POSSIBLE_MATCH; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.blankOrNullString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.equalToIgnoringCase; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.in; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -183,7 +175,7 @@ public class MdmMatchLinkSvcTest { assertLinkCount(2); - assertThat(patient1, is(not(sameGoldenResourceAs(patient2)))); + mdmAssertThat(patient1).is_not_MATCH_to(patient2); assertLinksMatchResult(MATCH, MATCH); assertLinksCreatedNewResource(true, true); @@ -200,7 +192,7 @@ public class MdmMatchLinkSvcTest { Patient patient2 = createPatientAndUpdateLinks(buildJanePatient()); assertLinkCount(2); - assertThat(patient1, is(sameGoldenResourceAs(patient2))); + mdmAssertThat(patient1).is_MATCH_to(patient2); assertLinksMatchResult(MATCH, MATCH); assertLinksCreatedNewResource(true, false); assertLinksMatchedByEid(false, false); @@ -211,7 +203,7 @@ public class MdmMatchLinkSvcTest { @Test public void testWhenMatchOccursOnGoldenResourceThatHasBeenManuallyNOMATCHedThatItIsBlocked() { Patient originalJane = createPatientAndUpdateLinks(buildJanePatient()); - IAnyResource janeGoldenResource = getGoldenResourceFromTargetResource(originalJane); + Patient janeGoldenResource = getGoldenResourceFromTargetResource(originalJane); //Create a manual NO_MATCH between janeGoldenResource and unmatchedJane. Patient unmatchedJane = createPatient(buildJanePatient()); @@ -220,8 +212,8 @@ public class MdmMatchLinkSvcTest { //rerun MDM rules against unmatchedJane. myMdmMatchLinkSvc.updateMdmLinksForMdmSource(unmatchedJane, createContextForCreate("Patient")); - assertThat(unmatchedJane, is(not(sameGoldenResourceAs(janeGoldenResource)))); - assertThat(unmatchedJane, is(not(linkedTo(originalJane)))); + mdmAssertThat(unmatchedJane).is_not_MATCH_to(janeGoldenResource); + mdmAssertThat(unmatchedJane).is_not_MATCH_to(originalJane); assertLinksMatchResult(MATCH, NO_MATCH, MATCH); assertLinksCreatedNewResource(true, false, true); @@ -244,7 +236,7 @@ public class MdmMatchLinkSvcTest { //Then: The secondary jane should link to the first jane. myMdmMatchLinkSvc.updateMdmLinksForMdmSource(resource, buildUpdateResourceMdmTransactionContext()); - assertThat(secondaryJane, is(sameGoldenResourceAs(jane))); + mdmAssertThat(secondaryJane).is_MATCH_to(goldenJane); } @Test @@ -252,7 +244,7 @@ public class MdmMatchLinkSvcTest { Patient originalJane = createPatientAndUpdateLinks(buildJanePatient()); IBundleProvider search = myPatientDao.search(buildGoldenRecordSearchParameterMap()); - IAnyResource janeGoldenResource = (IAnyResource) search.getResources(0, 1).get(0); + Patient janeGoldenResource = (Patient) search.getResources(0, 1).get(0); Patient unmatchedPatient = createPatient(buildJanePatient()); @@ -264,8 +256,8 @@ public class MdmMatchLinkSvcTest { //should cause a whole new GoldenResource to be created. myMdmMatchLinkSvc.updateMdmLinksForMdmSource(unmatchedPatient, createContextForCreate("Patient")); - assertThat(unmatchedPatient, is(not(sameGoldenResourceAs(janeGoldenResource)))); - assertThat(unmatchedPatient, is(not(linkedTo(originalJane)))); + GoldenResourceMatchingAssert.assertThat(unmatchedPatient, myIdHelperService, myMdmLinkDaoSvc).is_not_MATCH_to(janeGoldenResource); + GoldenResourceMatchingAssert.assertThat(unmatchedPatient, myIdHelperService, myMdmLinkDaoSvc).is_not_MATCH_to(originalJane); assertLinksMatchResult(MATCH, NO_MATCH, MATCH); assertLinksCreatedNewResource(true, false, true); @@ -281,13 +273,13 @@ public class MdmMatchLinkSvcTest { janePatient = createPatientAndUpdateLinks(janePatient); Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(JpaPid.fromId(janePatient.getIdElement().getIdPartAsLong())); - assertThat(mdmLink.isPresent(), is(true)); + assertTrue(mdmLink.isPresent()); Patient patient = getTargetResourceFromMdmLink(mdmLink.get(), "Patient"); List externalEid = myEidHelper.getExternalEid(patient); - assertThat(externalEid.get(0).getSystem(), is(equalTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")))); - assertThat(externalEid.get(0).getValue(), is(equalTo(sampleEID))); + assertThat(externalEid.get(0).getSystem()).isEqualTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")); + assertThat(externalEid.get(0).getValue()).isEqualTo(sampleEID); } @Test @@ -297,8 +289,8 @@ public class MdmMatchLinkSvcTest { Patient targetPatient = getTargetResourceFromMdmLink(mdmLink, "Patient"); Identifier identifierFirstRep = targetPatient.getIdentifierFirstRep(); - assertThat(identifierFirstRep.getSystem(), is(equalTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM))); - assertThat(identifierFirstRep.getValue(), not(blankOrNullString())); + assertThat(identifierFirstRep.getSystem()).isEqualTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM); + assertThat(identifierFirstRep.getValue()).isNotBlank(); } @Test @@ -308,20 +300,20 @@ public class MdmMatchLinkSvcTest { Optional mdmLink = myMdmLinkDaoSvc.getMatchedLinkForSourcePid(JpaPid.fromId(patient.getIdElement().getIdPartAsLong())); Patient read = getTargetResourceFromMdmLink(mdmLink.get(), "Patient"); - assertThat(read.getNameFirstRep().getFamily(), is(equalTo(patient.getNameFirstRep().getFamily()))); - assertThat(read.getNameFirstRep().getGivenAsSingleString(), is(equalTo(patient.getNameFirstRep().getGivenAsSingleString()))); - assertThat(read.getBirthDateElement().toHumanDisplay(), is(equalTo(patient.getBirthDateElement().toHumanDisplay()))); - assertThat(read.getTelecomFirstRep().getValue(), is(equalTo(patient.getTelecomFirstRep().getValue()))); - assertThat(read.getPhoto().size(), is(equalTo(patient.getPhoto().size()))); - assertThat(read.getPhotoFirstRep().getData(), is(equalTo(patient.getPhotoFirstRep().getData()))); - assertThat(read.getGender(), is(equalTo(patient.getGender()))); + assertThat(read.getNameFirstRep().getFamily()).isEqualTo(patient.getNameFirstRep().getFamily()); + assertThat(read.getNameFirstRep().getGivenAsSingleString()).isEqualTo(patient.getNameFirstRep().getGivenAsSingleString()); + assertThat(read.getBirthDateElement().toHumanDisplay()).isEqualTo(patient.getBirthDateElement().toHumanDisplay()); + assertThat(read.getTelecomFirstRep().getValue()).isEqualTo(patient.getTelecomFirstRep().getValue()); + assertThat(read.getPhoto().size()).isEqualTo(patient.getPhoto().size()); + assertThat(read.getPhotoFirstRep().getData()).isEqualTo(patient.getPhotoFirstRep().getData()); + assertThat(read.getGender()).isEqualTo(patient.getGender()); } @Test public void testPatientMatchingAnotherPatientLinksToSameGoldenResource() { Patient janePatient = createPatientAndUpdateLinks(buildJanePatient()); Patient sameJanePatient = createPatientAndUpdateLinks(buildJanePatient()); - assertThat(janePatient, is(sameGoldenResourceAs(sameJanePatient))); + mdmAssertThat(janePatient).is_MATCH_to(sameJanePatient); } @Test @@ -338,7 +330,7 @@ public class MdmMatchLinkSvcTest { createPatientAndUpdateLinks(janePatient); //We want to make sure the patients were linked to the same Golden Resource. - assertThat(patient, is(sameGoldenResourceAs(janePatient))); + mdmAssertThat(patient).is_MATCH_to(janePatient); Patient sourcePatient = getGoldenResourceFromTargetResource(patient); @@ -346,13 +338,13 @@ public class MdmMatchLinkSvcTest { //The collision should have kept the old identifier Identifier firstIdentifier = identifier.get(0); - assertThat(firstIdentifier.getSystem(), is(equalTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM))); - assertThat(firstIdentifier.getValue(), is(equalTo(foundHapiEid))); + assertThat(firstIdentifier.getSystem()).isEqualTo(MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM); + assertThat(firstIdentifier.getValue()).isEqualTo(foundHapiEid); //The collision should have added a new identifier with the external system. Identifier secondIdentifier = identifier.get(1); - assertThat(secondIdentifier.getSystem(), is(equalTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")))); - assertThat(secondIdentifier.getValue(), is(equalTo("12345"))); + assertThat(secondIdentifier.getSystem()).isEqualTo(myMdmSettings.getMdmRules().getEnterpriseEIDSystemForResourceType("Patient")); + assertThat(secondIdentifier.getValue()).isEqualTo("12345"); } @Test @@ -365,7 +357,7 @@ public class MdmMatchLinkSvcTest { patient2 = addExternalEID(patient2, "uniqueid"); createPatientAndUpdateLinks(patient2); - assertThat(patient1, is(sameGoldenResourceAs(patient2))); + mdmAssertThat(patient1).is_MATCH_to(patient2); } @Test @@ -382,7 +374,7 @@ public class MdmMatchLinkSvcTest { addExternalEID(patient2, "id_1"); createPatientAndUpdateLinks(patient2); - assertThat(patient1, is(sameGoldenResourceAs(patient2))); + mdmAssertThat(patient1).is_MATCH_to(patient2); } @Test @@ -395,7 +387,7 @@ public class MdmMatchLinkSvcTest { patient2 = createPatientAndUpdateLinks(patient2); List possibleDuplicates = (List) myMdmLinkDaoSvc.getPossibleDuplicates(); - assertThat(possibleDuplicates, hasSize(1)); + assertThat(possibleDuplicates).hasSize(1); Patient finalPatient1 = patient1; Patient finalPatient2 = patient2; @@ -405,8 +397,8 @@ public class MdmMatchLinkSvcTest { //The two GoldenResources related to the patients should both show up in the only existing POSSIBLE_DUPLICATE MdmLink. MdmLink mdmLink = possibleDuplicates.get(0); - assertThat(mdmLink.getGoldenResourcePersistenceId(), is(in(duplicatePids))); - assertThat(mdmLink.getSourcePersistenceId(), is(in(duplicatePids))); + assertThat(mdmLink.getGoldenResourcePersistenceId()).isIn(duplicatePids); + assertThat(mdmLink.getSourcePersistenceId()).isIn(duplicatePids); } @Test @@ -425,7 +417,7 @@ public class MdmMatchLinkSvcTest { Practitioner janePractitioner = createPractitionerAndUpdateLinks(buildJanePractitioner()); assertLinkCount(2); - assertThat(janePatient, is(not(sameGoldenResourceAs(janePractitioner)))); + mdmAssertThat(janePatient).is_not_MATCH_to(janePractitioner); } @Test @@ -434,7 +426,7 @@ public class MdmMatchLinkSvcTest { Practitioner anotherJanePractitioner = createPractitionerAndUpdateLinks(buildJanePractitioner()); assertLinkCount(2); - assertThat(anotherJanePractitioner, is(sameGoldenResourceAs(janePractitioner))); + mdmAssertThat(anotherJanePractitioner).is_MATCH_to(janePractitioner); } @Test @@ -446,7 +438,7 @@ public class MdmMatchLinkSvcTest { assertLinkCount(0); Patient janePatient = createPatientAndUpdateLinks(buildJanePatient()); assertLinkCount(1); - assertThat(janePatient, is(matchedToAGoldenResource())); + mdmAssertThat(janePatient).hasGoldenResourceMatch(); } @Test @@ -459,11 +451,14 @@ public class MdmMatchLinkSvcTest { Patient janePatient2 = createPatientAndUpdateLinks(buildJanePatient()); assertLinkCount(2); - assertThat(janePatient, is(sameGoldenResourceAs(janePatient2))); + mdmAssertThat(janePatient).is_MATCH_to(janePatient2); + Patient incomingJanePatient = createPatientAndUpdateLinks(buildJanePatient()); - assertThat(incomingJanePatient, is(sameGoldenResourceAs(janePatient, janePatient2))); - assertThat(incomingJanePatient, is(linkedTo(janePatient, janePatient2))); + mdmAssertThat(incomingJanePatient) + .is_MATCH_to(janePatient) + .is_MATCH_to(janePatient2); + } @Test @@ -483,20 +478,22 @@ public class MdmMatchLinkSvcTest { myMdmSurvivorshipService ); myMdmLinkSvc.updateLink(goldenResource, janePatient2, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient")); - assertThat(janePatient, is(not(sameGoldenResourceAs(janePatient2)))); + mdmAssertThat(janePatient).is_not_MATCH_to(janePatient2); //In theory, this will match both GoldenResources! Patient incomingJanePatient = createPatientAndUpdateLinks(buildJanePatient()); //There should now be a single POSSIBLE_DUPLICATE link with - assertThat(janePatient, is(possibleDuplicateOf(janePatient2))); + mdmAssertThat(janePatient).is_POSSIBLE_DUPLICATE_to(janePatient2); //There should now be 2 POSSIBLE_MATCH links with this goldenResource. - assertThat(incomingJanePatient, is(possibleMatchWith(janePatient, janePatient2))); + mdmAssertThat(incomingJanePatient) + .is_POSSIBLE_MATCH_to(janePatient) + .is_POSSIBLE_MATCH_to(janePatient2); //Ensure there is no successful MATCH links for incomingJanePatient Optional matchedLinkForTargetPid = runInTransaction(() -> myMdmLinkDaoSvc.getMatchedLinkForSourcePid(myIdHelperService.getPidOrNull(RequestPartitionId.allPartitions(), incomingJanePatient))); - assertThat(matchedLinkForTargetPid.isPresent(), is(false)); + assertThat(matchedLinkForTargetPid.isPresent()).isEqualTo(false); logAllLinks(); assertLinksMatchResult(MATCH, MATCH, POSSIBLE_MATCH, POSSIBLE_MATCH, POSSIBLE_DUPLICATE); @@ -513,19 +510,19 @@ public class MdmMatchLinkSvcTest { Patient patient = buildJanePatient(); patient.getNameFirstRep().setFamily("familyone"); patient = createPatientAndUpdateLinks(patient); - assertThat(patient, is(sameGoldenResourceAs(patient))); + mdmAssertThat(patient).is_MATCH_to(patient); Patient patient2 = buildJanePatient(); patient2.getNameFirstRep().setFamily("pleasedonotmatchatall"); patient2 = createPatientAndUpdateLinks(patient2); - assertThat(patient2, is(possibleMatchWith(patient))); + mdmAssertThat(patient2).is_POSSIBLE_MATCH_to(patient); Patient patient3 = buildJanePatient(); patient3.getNameFirstRep().setFamily("pleasedonotmatchatall"); patient3 = createPatientAndUpdateLinks(patient3); - assertThat(patient3, is(possibleMatchWith(patient2))); - assertThat(patient3, is(possibleMatchWith(patient))); + mdmAssertThat(patient3).is_POSSIBLE_MATCH_to(patient2); + mdmAssertThat(patient3).is_POSSIBLE_MATCH_to(patient); IBundleProvider bundle = myPatientDao.search(buildGoldenRecordSearchParameterMap()); assertEquals(1, bundle.size()); @@ -549,7 +546,7 @@ public class MdmMatchLinkSvcTest { Patient patient = buildJanePatient(); patient.getNameFirstRep().setFamily("familyone"); patient = createPatientAndUpdateLinks(patient); - assertThat(patient, is(sameGoldenResourceAs(patient))); + mdmAssertThat(patient).is_MATCH_to(patient); Patient patient2 = buildJanePatient(); patient2.getNameFirstRep().setFamily("pleasedonotmatchatall"); @@ -559,9 +556,9 @@ public class MdmMatchLinkSvcTest { patient3.getNameFirstRep().setFamily("familyone"); patient3 = createPatientAndUpdateLinks(patient3); - assertThat(patient2, is(not(sameGoldenResourceAs(patient)))); - assertThat(patient2, is(possibleMatchWith(patient))); - assertThat(patient3, is(sameGoldenResourceAs(patient))); + mdmAssertThat(patient2).is_not_MATCH_to(patient); + mdmAssertThat(patient2).is_POSSIBLE_MATCH_to(patient); + mdmAssertThat(patient3).is_MATCH_to(patient); } @@ -571,15 +568,14 @@ public class MdmMatchLinkSvcTest { Patient patient = buildJanePatient(); patient.getNameFirstRep().setFamily("familyone"); patient = createPatientAndUpdateLinks(patient); - assertThat(patient, is(sameGoldenResourceAs(patient))); + mdmAssertThat(patient).is_MATCH_to(patient); Patient patient2 = buildJanePatient(); patient2.getNameFirstRep().setFamily("pleasedonotmatchatall"); patient2 = createPatientAndUpdateLinks(patient2); - assertThat(patient2, is(not(sameGoldenResourceAs(patient)))); - assertThat(patient2, is(not(linkedTo(patient)))); - assertThat(patient2, is(possibleMatchWith(patient))); + mdmAssertThat(patient2).is_not_MATCH_to(patient); + mdmAssertThat(patient2).is_POSSIBLE_MATCH_to(patient); patient2.getNameFirstRep().setFamily(patient.getNameFirstRep().getFamily()); @@ -587,8 +583,7 @@ public class MdmMatchLinkSvcTest { updatePatientAndUpdateLinks(patient2); // validate - assertThat(patient2, is(linkedTo(patient))); - assertThat(patient2, is(sameGoldenResourceAs(patient))); + mdmAssertThat(patient2).is_MATCH_to(patient); } @Test @@ -606,7 +601,7 @@ public class MdmMatchLinkSvcTest { assertFalse(myEidHelper.getHapiEid(janeGoldenResourcePatient).isEmpty()); // original checks - verifies that EIDs are assigned - assertThat("Resource must not be identical", janePatient != janeGoldenResourcePatient); + assertThat(janePatient != janeGoldenResourcePatient).as("Resource must not be identical").isTrue(); assertFalse(janePatient.getIdentifier().isEmpty()); assertFalse(janeGoldenResourcePatient.getIdentifier().isEmpty()); @@ -629,13 +624,13 @@ public class MdmMatchLinkSvcTest { patient1.setId(janePatient.getId()); Patient janePaulPatient = updatePatientAndUpdateLinks(patient1); - assertThat(janeSourcePatient, is(sameGoldenResourceAs(janePaulPatient))); + mdmAssertThat(janeSourcePatient).is_MATCH_to(janePaulPatient); //Ensure the related GoldenResource was updated with new info. Patient sourcePatientFromTarget = getGoldenResourceFromTargetResource(janePaulPatient); HumanName nameFirstRep = sourcePatientFromTarget.getNameFirstRep(); - assertThat(nameFirstRep.getGivenAsSingleString(), is(equalToIgnoringCase("paul"))); + assertThat(nameFirstRep.getGivenAsSingleString()).isEqualToIgnoringCase("paul"); } @Test @@ -647,7 +642,7 @@ public class MdmMatchLinkSvcTest { paul = createPatientAndUpdateLinks(paul); Patient sourcePatientFromTarget = getGoldenResourceFromTargetResource(paul); - assertThat(sourcePatientFromTarget.getBirthDateElement().getValueAsString(), is(incorrectBirthdate)); + assertThat(sourcePatientFromTarget.getBirthDateElement().getValueAsString()).isEqualTo(incorrectBirthdate); String correctBirthdate = "1990-06-28"; paul.getBirthDateElement().setValueAsString(correctBirthdate); @@ -655,7 +650,7 @@ public class MdmMatchLinkSvcTest { paul = updatePatientAndUpdateLinks(paul); sourcePatientFromTarget = getGoldenResourceFromTargetResource(paul); - assertThat(sourcePatientFromTarget.getBirthDateElement().getValueAsString(), is(equalTo(correctBirthdate))); + assertThat(sourcePatientFromTarget.getBirthDateElement().getValueAsString()).isEqualTo(correctBirthdate); assertLinkCount(1); } @@ -672,8 +667,8 @@ public class MdmMatchLinkSvcTest { addExternalEID(paul, EID_2); updatePatientAndUpdateLinks(paul); - assertThat(originalJaneGolden, is(possibleDuplicateOf(originalPaulGolden))); - assertThat(jane, is(sameGoldenResourceAs(paul))); + mdmAssertThat(originalJaneGolden).is_POSSIBLE_DUPLICATE_to(originalPaulGolden); + mdmAssertThat(jane).is_MATCH_to(paul); } @Test @@ -702,8 +697,8 @@ public class MdmMatchLinkSvcTest { updatePatientAndUpdateLinks(paul); // verify - assertThat(originalJaneGolden, is(not(possibleDuplicateOf(originalPaulGolden)))); - assertThat(jane, is(sameGoldenResourceAs(paul))); + mdmAssertThat(originalJaneGolden).is_not_POSSIBLE_DUPLICATE_to(originalPaulGolden); + mdmAssertThat(jane).is_MATCH_to(paul); } @Test @@ -713,7 +708,7 @@ public class MdmMatchLinkSvcTest { Patient originalPaulGolden = getGoldenResourceFromTargetResource(paul); String oldEid = myEidHelper.getExternalEid(originalPaulGolden).get(0).getValue(); - assertThat(oldEid, is(equalTo(EID_1))); + assertThat(oldEid).isEqualTo(EID_1); clearExternalEIDs(paul); addExternalEID(paul, EID_2); @@ -722,14 +717,14 @@ public class MdmMatchLinkSvcTest { assertNoDuplicates(); Patient newlyFoundPaulPatient = getGoldenResourceFromTargetResource(paul); - assertThat(originalPaulGolden, is(sameGoldenResourceAs(newlyFoundPaulPatient))); + mdmAssertThat(originalPaulGolden).is_MATCH_to(newlyFoundPaulPatient); String newEid = myEidHelper.getExternalEid(newlyFoundPaulPatient).get(0).getValue(); - assertThat(newEid, is(equalTo(EID_2))); + assertThat(newEid).isEqualTo(EID_2); } private void assertNoDuplicates() { List possibleDuplicates = (List) myMdmLinkDaoSvc.getPossibleDuplicates(); - assertThat(possibleDuplicates, hasSize(0)); + assertThat(possibleDuplicates).hasSize(0); } @Test @@ -748,7 +743,7 @@ public class MdmMatchLinkSvcTest { patient3 = createPatientAndUpdateLinks(patient3); //Now, Patient 2 and 3 are linked, and the GoldenResource has 2 eids. - assertThat(patient2, is(sameGoldenResourceAs(patient3))); + mdmAssertThat(patient2).is_MATCH_to(patient3); assertNoDuplicates(); // GoldenResource A -> {P1} // GoldenResource B -> {P2, P3} @@ -761,11 +756,11 @@ public class MdmMatchLinkSvcTest { // GoldenResource B -> {P3} // Possible duplicates A<->B - assertThat(patient2, is(sameGoldenResourceAs(patient1))); + mdmAssertThat(patient2).is_MATCH_to(patient1); List possibleDuplicates = (List) myMdmLinkDaoSvc.getPossibleDuplicates(); - assertThat(possibleDuplicates, hasSize(1)); - assertThat(patient3, is(possibleDuplicateOf(patient1))); + assertThat(possibleDuplicates).hasSize(1); + mdmAssertThat(patient3).is_POSSIBLE_DUPLICATE_to(patient1); } @Test @@ -782,16 +777,16 @@ public class MdmMatchLinkSvcTest { ); myMdmLinkSvc.updateLink(goldenResource, janePatient2, MdmMatchOutcome.NEW_GOLDEN_RESOURCE_MATCH, MdmLinkSourceEnum.AUTO, createContextForCreate("Patient")); - assertThat(janePatient, is(not(sameGoldenResourceAs(janePatient2)))); + mdmAssertThat(janePatient).is_not_MATCH_to(janePatient2); //In theory, this will match both GoldenResources! Patient incomingJanePatient = createPatientAndUpdateLinks(buildJanePatient()); //There should now be a single POSSIBLE_DUPLICATE link with - assertThat(janePatient, is(possibleDuplicateOf(janePatient2))); + mdmAssertThat(janePatient).is_POSSIBLE_DUPLICATE_to(janePatient2); //There should now be 2 POSSIBLE_MATCH links with this goldenResource. - assertThat(incomingJanePatient, is(possibleMatchWith(janePatient, janePatient2))); + mdmAssertThat(incomingJanePatient).is_POSSIBLE_MATCH_to(janePatient).is_POSSIBLE_MATCH_to(janePatient2); // Ensure both links are POSSIBLE_MATCH and both have a score value List janetPatientLinks = runInTransaction(() -> myMdmLinkDaoSvc.findMdmLinksBySourceResource(incomingJanePatient)); diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java index 84266307a3e..ae8b530072a 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2Test.java @@ -78,8 +78,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import org.apache.commons.lang3.RandomStringUtils; -import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterEach; diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java index bcfebae9bac..e0d0af476a6 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java @@ -1868,8 +1868,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest { // assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$")); // assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$")); // - // assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart())); - // assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart())); + // assertThat(o1.getSubject().getReference().getValue()).endsWith("Patient/" + p1.getId().getIdPart()); + // assertThat(o2.getSubject().getReference().getValue()).endsWith("Patient/" + p1.getId().getIdPart()); // // } // diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index 4d9308165f7..2283bab81e0 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -1349,7 +1349,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { // ourLog.info(output); // List ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseBundle(output)); // ourLog.info(ids.toString()); -// assertThat(ids, contains(pId, cId)); +// assertThat(ids).contains(pId, cId); // } finally { // response.close(); // } @@ -1363,7 +1363,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { // ourLog.info(output); // List ids = toIdListUnqualifiedVersionless(myFhirCtx.newXmlParser().parseBundle(output)); // ourLog.info(ids.toString()); -// assertThat(ids, contains(cId, pId, oId)); +// assertThat(ids).contains(cId, pId, oId); // } finally { // response.close(); // } diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java index 6fc58129635..d48de17a9d5 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImplTest.java @@ -30,7 +30,6 @@ import ca.uhn.fhir.rest.server.IPagingProvider; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.system.HapiSystemProperties; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -324,7 +323,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc { ourLog.info("Registering the first search"); new Thread(() -> mySvc.registerSearch(myCallingDao, params, "Patient", new CacheControlDirective(), null, RequestPartitionId.allPartitions())).start(); - await().until(iter::getCountReturned, Matchers.greaterThan(0)); + await().untilAsserted(() -> assertThat(iter.getCountReturned()).isGreaterThan(0)); String searchId = mySvc.getActiveSearchIds().iterator().next(); CountDownLatch completionLatch = new CountDownLatch(1); diff --git a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/subscription/email/EmailSubscriptionDstu2Test.java b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/subscription/email/EmailSubscriptionDstu2Test.java index 07456625ae6..90726afb0c8 100644 --- a/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/subscription/email/EmailSubscriptionDstu2Test.java +++ b/hapi-fhir-jpaserver-test-dstu2/src/test/java/ca/uhn/fhir/jpa/subscription/email/EmailSubscriptionDstu2Test.java @@ -19,7 +19,6 @@ import ca.uhn.fhir.rest.server.mail.MailSvc; import com.icegreen.greenmail.junit5.GreenMailExtension; import com.icegreen.greenmail.util.GreenMailUtil; import com.icegreen.greenmail.util.ServerSetupTest; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -123,11 +122,11 @@ public class EmailSubscriptionDstu2Test extends BaseResourceProviderDstu2Test { Subscription subscription1 = createSubscription(criteria1, payload, "to1@example.com,to2@example.com"); mySubscriptionTestUtil.waitForQueueToDrain(); - await().until(() -> mySubscriptionRegistry.get(subscription1.getIdElement().getIdPart()), Matchers.not(Matchers.nullValue())); + await().untilAsserted(() -> assertThat(mySubscriptionRegistry.get(subscription1.getIdElement().getIdPart())).isNotNull()); mySubscriptionTestUtil.setEmailSender(subscription1.getIdElement(), new EmailSenderImpl(withMailService())); assertThat(Arrays.asList(ourGreenMail.getReceivedMessages())).isEmpty(); - Observation observation1 = sendObservation(code, "SNOMED-CT"); + sendObservation(code, "SNOMED-CT"); assertTrue(ourGreenMail.waitForIncomingEmail(10000, 1)); diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java index 504212ac5d6..38dce826530 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java @@ -66,7 +66,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test { // // map = new SearchParameterMap(); // map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT)); -// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); +// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map))).isEmpty(); // // map = new SearchParameterMap(); // map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT)); diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index e245163576b..72754cb7465 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -1972,7 +1972,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { // ourLog.info(output); // List ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output)); // ourLog.info(ids.toString()); - // assertThat(ids, contains(pId, cId)); + // assertThat(ids).contains(pId, cId); // } finally { // response.close(); // } @@ -1986,7 +1986,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { // ourLog.info(output); // List ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output)); // ourLog.info(ids.toString()); - // assertThat(ids, contains(cId, pId, oId)); + // assertThat(ids).contains(cId, pId, oId); // } finally { // response.close(); // } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/imprt/svc/BulkDataImportR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/imprt/svc/BulkDataImportR4Test.java index bbbb85ea29d..dec666c0c15 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/imprt/svc/BulkDataImportR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/bulk/imprt/svc/BulkDataImportR4Test.java @@ -29,7 +29,6 @@ import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.util.BundleBuilder; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Patient; import org.junit.jupiter.api.AfterEach; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java index 640d2a45398..427b54ad690 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4QueryCountTest.java @@ -49,7 +49,6 @@ import ca.uhn.fhir.test.utilities.server.HashMapResourceProviderExtension; import ca.uhn.fhir.test.utilities.server.RestfulServerExtension; import ca.uhn.fhir.util.BundleBuilder; import jakarta.annotation.Nonnull; -import org.hamcrest.CoreMatchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.BooleanType; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchFtTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchFtTest.java index 8ed933716df..cc2eb123dc5 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchFtTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchFtTest.java @@ -31,8 +31,6 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.not; import static org.hl7.fhir.r4.model.Observation.SP_VALUE_QUANTITY; import static org.junit.jupiter.api.Assertions.fail; @@ -80,7 +78,7 @@ public class FhirResourceDaoR4SearchFtTest extends BaseJpaR4Test { // // map = new SearchParameterMap(); // map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT)); -// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map)), empty()); +// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(map))).isEmpty(); // // map = new SearchParameterMap(); // map.add(Observation.SP_CODE, new TokenParam(null, "blood").setModifier(TokenParamModifier.TEXT)); @@ -148,7 +146,7 @@ public class FhirResourceDaoR4SearchFtTest extends BaseJpaR4Test { // contains doesn't work // map = new SearchParameterMap(); // map.add(Observation.SP_VALUE_STRING, new StringParam("sure").setContains(true)); -// assertThat("contains matches internal fragment", toUnqualifiedVersionlessIdValues(myObservationDao.search(map)), containsInAnyOrder(toValues(id1, id2))); +// assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(map))).as("contains matches internal fragment").containsExactlyInAnyOrder(toValues(id1, id2)); } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java index 75471d9993a..899e2bcde2d 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java @@ -1180,7 +1180,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test { // params = new SearchParameterMap(); // params.setLoadSynchronous(true); // params.add("_has", new HasParam("Observation", "subject", "device.identifier", "urn:system|DEVICEID")); -// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(params)), contains(pid0.getValue())); +// assertThat(toUnqualifiedVersionlessIdValues(myPatientDao.search(params))).contains(pid0.getValue()); // No targets exist params = new SearchParameterMap(); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java index 1e12124a0b6..e03d3725746 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchOptimizedTest.java @@ -71,7 +71,6 @@ import static org.apache.commons.lang3.StringUtils.leftPad; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchSqlTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchSqlTest.java index 410b05fbb22..388bb493592 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchSqlTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchSqlTest.java @@ -9,7 +9,6 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.UriParam; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.SearchParameter; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTagSnapshotTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTagSnapshotTest.java index 6c9616e0720..d4a786b8536 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTagSnapshotTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTagSnapshotTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; import com.google.common.collect.Lists; -import org.hamcrest.Matchers; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Patient; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetMultiVersionTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetMultiVersionTest.java index 8cd8ace52b2..4bf524f41a7 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetMultiVersionTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValueSetMultiVersionTest.java @@ -7,7 +7,6 @@ import ca.uhn.fhir.jpa.entity.TermValueSet; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.test.BaseJpaR4Test; import ca.uhn.fhir.jpa.util.ValueSetTestUtil; -import org.hamcrest.Matchers; import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.ValueSet; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchListTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchListTest.java index 6e0454f5329..3bbaaa76285 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchListTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchListTest.java @@ -62,7 +62,7 @@ public class FhirResourceDaoSearchListTest extends BaseJpaR4Test { for(IIdType patientId: theExpectedPatientIds) { assertThat(ids).contains(patientId); - //assertThat(patientId, contains(ids)); + //assertThat(patientId).contains(ids); } // assert ids equal pid1 and pid2 } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4Test.java index ec213cd74ce..83c2be3a669 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4Test.java @@ -40,7 +40,6 @@ import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder; import ca.uhn.fhir.util.BundleBuilder; import ca.uhn.fhir.util.ClasspathUtil; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.AllergyIntolerance; @@ -4777,8 +4776,8 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest { // assertTrue(o1.getId().getValue(), o1.getId().getIdPart().matches("^[0-9]+$")); // assertTrue(o2.getId().getValue(), o2.getId().getIdPart().matches("^[0-9]+$")); // - // assertThat(o1.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart())); - // assertThat(o2.getSubject().getReference().getValue(), endsWith("Patient/" + p1.getId().getIdPart())); + // assertThat(o1.getSubject().getReference().getValue()).endsWith("Patient/" + p1.getId().getIdPart()); + // assertThat(o2.getSubject().getReference().getValue()).endsWith("Patient/" + p1.getId().getIdPart()); // // } // diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/PartitioningSqlR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/PartitioningSqlR4Test.java index dc25cb69f2e..b1c0a5c9f88 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/PartitioningSqlR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/PartitioningSqlR4Test.java @@ -49,7 +49,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.BundleBuilder; import org.apache.commons.lang3.StringUtils; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Bundle; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/PartitioningInterceptorR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/PartitioningInterceptorR4Test.java index 21296393cde..95256cf8f8a 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/PartitioningInterceptorR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/PartitioningInterceptorR4Test.java @@ -28,7 +28,6 @@ import ca.uhn.fhir.util.HapiExtensions; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.BooleanType; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/ResponseTerminologyTranslationInterceptorTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/ResponseTerminologyTranslationInterceptorTest.java index e60fe8d4fff..31dec792b29 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/ResponseTerminologyTranslationInterceptorTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/ResponseTerminologyTranslationInterceptorTest.java @@ -14,7 +14,6 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseTerminologyTranslationInterce import ca.uhn.fhir.util.Batch2JobDefinitionConstants; import ca.uhn.fhir.util.JsonUtil; import com.google.common.collect.Sets; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Coding; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheSearchR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheSearchR4Test.java index 8a261a8ae1c..85c81eec901 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheSearchR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/JpaPackageCacheSearchR4Test.java @@ -8,7 +8,6 @@ import ca.uhn.fhir.jpa.test.BaseJpaR4Test; import ca.uhn.fhir.test.utilities.ProxyUtil; import ca.uhn.fhir.util.ClasspathUtil; import ca.uhn.fhir.util.JsonUtil; -import org.hamcrest.Matchers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderConcurrencyR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderConcurrencyR4Test.java index bd36b3faa2c..b709757a839 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderConcurrencyR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderConcurrencyR4Test.java @@ -27,11 +27,11 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; @SuppressWarnings("Duplicates") @@ -155,22 +155,20 @@ public class ResourceProviderConcurrencyR4Test extends BaseResourceProviderR4Tes } ourLog.info("About to wait for FAMILY3 to complete"); - await().until(() -> { - ourLog.info("Received names: {}", myReceivedNames); - return myReceivedNames; - }, contains("FAMILY3")); + await().untilAsserted(() -> assertThat(myReceivedNames).contains("FAMILY3")); ourLog.info("Got FAMILY3"); searchBlockingInterceptorFamily1.getLatch().countDown(); ourLog.info("About to wait for FAMILY1 to complete"); - await().until(() -> myReceivedNames, contains("FAMILY3", "FAMILY1", "FAMILY1")); + await().untilAsserted(() -> assertThat(myReceivedNames).containsOnly("FAMILY3", "FAMILY1","FAMILY1")); ourLog.info("Got FAMILY1"); assertEquals(1, searchBlockingInterceptorFamily1.getHits()); } + @Interceptor public static class SearchBlockingInterceptor { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java index b122f229378..e726b1c1046 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java @@ -60,7 +60,6 @@ import static org.apache.commons.lang3.time.DateUtils.MILLIS_PER_SECOND; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; @@ -249,7 +248,7 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes await() .atMost(60, TimeUnit.SECONDS) .pollInterval(1, TimeUnit.SECONDS) - .until(()->{ + .untilAsserted(()-> { Bundle observations = myClient .search() .forResource("Observation") @@ -258,9 +257,8 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes .cacheControl(CacheControlDirective.noCache()) .execute(); ourLog.info("Have {} observations", observations.getEntry().size()); - return observations.getEntry().size(); - }, - equalTo(1)); + assertThat(observations.getEntry()).hasSize(1); + }); } finally { myServer.getRestfulServer().unregisterInterceptor(interceptor); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderMeaningfulOutcomeMessageR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderMeaningfulOutcomeMessageR4Test.java index d874b22b050..b75ff922668 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderMeaningfulOutcomeMessageR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderMeaningfulOutcomeMessageR4Test.java @@ -10,7 +10,6 @@ import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test; import ca.uhn.fhir.model.api.StorageResponseCodeEnum; import ca.uhn.fhir.rest.api.PreferReturnEnum; import ca.uhn.fhir.util.BundleBuilder; -import org.hamcrest.Matcher; import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CodeType; @@ -248,8 +247,7 @@ public class ResourceProviderMeaningfulOutcomeMessageR4Test extends BaseResource .execute(); ourLog.debug("Create {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(output)); OperationOutcome oo = (OperationOutcome) output.getEntry().get(0).getResponse().getOutcome(); - // TODO CHECKSTYLE KHS restore this -// assertThat(oo.getIssueFirstRep().getDiagnostics()).matches("Successfully conditionally created resource \".*\". No existing resources matched URL \"Patient\\?active=true\". Took [0-9]+ms."); + assertThat(oo.getIssueFirstRep().getDiagnostics()).matches("Successfully conditionally created resource \".*\". No existing resources matched URL \"Patient\\?active=true\". Took [0-9]+ms."); assertEquals(StorageResponseCodeEnum.SUCCESSFUL_CREATE_NO_CONDITIONAL_MATCH.name(), oo.getIssueFirstRep().getDetails().getCodingFirstRep().getCode()); assertEquals(StorageResponseCodeEnum.SYSTEM, oo.getIssueFirstRep().getDetails().getCodingFirstRep().getSystem()); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderOnlySomeResourcesProvidedR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderOnlySomeResourcesProvidedR4Test.java index a2d76822a35..e198a2fc8fa 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderOnlySomeResourcesProvidedR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderOnlySomeResourcesProvidedR4Test.java @@ -3,8 +3,6 @@ package ca.uhn.fhir.jpa.provider.r4; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; -import org.hamcrest.CoreMatchers; -import org.hamcrest.Matchers; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Practitioner; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4EverythingTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4EverythingTest.java index 3485d28c075..6968a69b08a 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4EverythingTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4EverythingTest.java @@ -797,7 +797,7 @@ public class ResourceProviderR4EverythingTest extends BaseResourceProviderR4Test // ourLog.info(output); // List ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output)); // ourLog.info(ids.toString()); - // assertThat(ids, contains(pId, cId)); + // assertThat(ids).contains(pId, cId); // } finally { // response.close(); // } @@ -811,7 +811,7 @@ public class ResourceProviderR4EverythingTest extends BaseResourceProviderR4Test // ourLog.info(output); // List ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output)); // ourLog.info(ids.toString()); - // assertThat(ids, contains(cId, pId, oId)); + // assertThat(ids).contains(cId, pId, oId); // } finally { // response.close(); // } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4SearchVariousScenariosTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4SearchVariousScenariosTest.java index 9fcfa54687e..66972ba0de5 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4SearchVariousScenariosTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4SearchVariousScenariosTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.provider.r4; +import static org.assertj.core.api.Assertions.assertThat; import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.rest.api.server.IBundleProvider; @@ -7,7 +8,6 @@ import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -import org.hamcrest.MatcherAssert; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CarePlan; @@ -35,7 +35,6 @@ import org.junit.jupiter.params.provider.ValueSource; import java.util.List; -import static org.hamcrest.Matchers.contains; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -442,7 +441,7 @@ public class ResourceProviderR4SearchVariousScenariosTest extends BaseResourcePr .map(Resource::getIdPart) .toList(); - MatcherAssert.assertThat(theReason, actualIdsInOrder, contains(theExpectedIdsInOrder)); + assertThat(actualIdsInOrder).as(theReason).contains(theExpectedIdsInOrder); } private void runAndAssert(String theQueryString) { diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ServerCapabilityStatementProviderJpaR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ServerCapabilityStatementProviderJpaR4Test.java index e6f7d679304..e1fe8a63758 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ServerCapabilityStatementProviderJpaR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ServerCapabilityStatementProviderJpaR4Test.java @@ -9,7 +9,6 @@ import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; import ca.uhn.fhir.util.ClasspathUtil; import org.apache.commons.lang3.StringUtils; -import org.hamcrest.Matchers; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CapabilityStatement; import org.hl7.fhir.r4.model.Enumerations; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/GiantTransactionPerfTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/GiantTransactionPerfTest.java index 8d62071d4ac..df20dea6542 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/GiantTransactionPerfTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/GiantTransactionPerfTest.java @@ -49,7 +49,6 @@ import ca.uhn.fhir.util.MetaTagSorterAlphabetical; import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.validation.IInstanceValidatorModule; import com.google.common.collect.Lists; -import org.hamcrest.Matchers; import org.hibernate.internal.SessionImpl; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java index 04e7308ed19..83b7e061ed3 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java @@ -24,7 +24,6 @@ import com.google.common.collect.Sets; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.Matchers; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java index 0065bdc5269..bd3503b9bc0 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java @@ -40,7 +40,6 @@ import static ca.uhn.fhir.batch2.jobs.termcodesystem.TermCodeSystemJobConfig.TER import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.fail; diff --git a/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java b/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java index 73598e141d8..f3ad0dbdc64 100644 --- a/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java +++ b/hapi-fhir-jpaserver-test-r4b/src/test/java/ca/uhn/fhir/jpa/provider/r4b/ResourceProviderR4BTest.java @@ -12,7 +12,6 @@ import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4b.model.Bundle; import org.hl7.fhir.r4b.model.Bundle.BundleEntryComponent; diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java index b1065099520..ba047dc73c5 100644 --- a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/ResourceProviderR5Test.java @@ -17,7 +17,6 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/dao/TestDaoSearch.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/dao/TestDaoSearch.java index d94e42d2395..58d52d0a07f 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/dao/TestDaoSearch.java +++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/dao/TestDaoSearch.java @@ -33,8 +33,6 @@ import ca.uhn.fhir.rest.server.IRestfulServerDefaults; import ca.uhn.fhir.rest.server.method.SortParameter; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import jakarta.annotation.Nonnull; -import org.hamcrest.Matcher; -import org.hamcrest.MatcherAssert; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.springframework.beans.factory.annotation.Autowired; @@ -48,11 +46,6 @@ import java.util.stream.Collectors; import static org.apache.commons.lang3.ArrayUtils.EMPTY_STRING_ARRAY; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.everyItem; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.in; -import static org.hamcrest.Matchers.not; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -105,7 +98,7 @@ public class TestDaoSearch { * @param theIds the resource ids to expect. */ public void assertSearchFinds(String theReason, String theQueryUrl, String... theIds) { - assertSearchResultIds(theQueryUrl, theReason, hasItems(theIds)); + assertSearchResultIds(theQueryUrl, theReason, theIds); } public void assertSearchFinds(String theReason, String theQueryUrl, List theIds) { @@ -121,7 +114,7 @@ public class TestDaoSearch { public void assertSearchFinds(String theReason, String theQueryUrl, IIdType... theIds) { String[] bareIds = idTypeToIdParts(theIds); - assertSearchResultIds(theQueryUrl, theReason, hasItems(bareIds)); + assertSearchResultIds(theQueryUrl, theReason, bareIds); } public void assertSearchFindsInOrder(String theReason, String theQueryUrl, String... theIds) { @@ -135,20 +128,17 @@ public class TestDaoSearch { } public void assertSearchFindsOnly(String theReason, String theQueryUrl, String... theIds) { - assertSearchIdsMatch(theReason, theQueryUrl, containsInAnyOrder(theIds)); + assertSearchIdsMatch(theReason, theQueryUrl, theIds); } - public void assertSearchIdsMatch( - String theReason, String theQueryUrl, Matcher> theMatchers) { + public void assertSearchIdsMatch(String theReason, String theQueryUrl, String... theIds) { List ids = searchForIds(theQueryUrl); - - MatcherAssert.assertThat(theReason, ids, theMatchers); + assertThat(ids).as(theReason).containsExactlyInAnyOrder(theIds); } - public void assertSearchResultIds(String theQueryUrl, String theReason, Matcher> matcher) { + public void assertSearchResultIds(String theQueryUrl, String theReason, String... theExpectedIds) { List ids = searchForIds(theQueryUrl); - - MatcherAssert.assertThat(theReason, ids, matcher); + assertThat(ids).as(theReason).contains(theExpectedIds); } /** @@ -159,8 +149,7 @@ public class TestDaoSearch { */ public void assertSearchNotFound(String theReason, String theQueryUrl, IIdType... theIds) { List ids = searchForIds(theQueryUrl); - - MatcherAssert.assertThat(theReason, ids, everyItem(not(in(idTypeToIdParts(theIds))))); + assertThat(ids).as(theReason).doesNotContain(idTypeToIdParts(theIds)); } @Nonnull diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/sched/SchedulerServiceImplTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/sched/SchedulerServiceImplTest.java index 5b76511f721..bcdda9ec4e8 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/sched/SchedulerServiceImplTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/sched/SchedulerServiceImplTest.java @@ -31,8 +31,6 @@ import java.util.concurrent.atomic.AtomicInteger; import static ca.uhn.fhir.util.TestUtil.sleepAtLeast; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.junit.jupiter.api.Assertions.fail; @ContextConfiguration(classes = SchedulerServiceImplTest.TestConfiguration.class) @@ -59,8 +57,7 @@ public class SchedulerServiceImplTest { StopWatch sw = new StopWatch(); mySvc.scheduleLocalJob(100, def); - - await().until(CountingJob.ourCount::get, greaterThan(5)); + await().until(CountingJob.ourCount::get, count -> count > 5); ourLog.info("Fired {} times in {}", CountingJob.ourCount, sw); assertThat(sw.getMillis()).isGreaterThan(500L); @@ -77,8 +74,7 @@ public class SchedulerServiceImplTest { for (int i = 0; i < 20; ++i) { mySvc.triggerLocalJobImmediately(def); } - - await().until(CountingJob.ourCount::get, greaterThan(25)); + await().until(CountingJob.ourCount::get, count -> count > 25); ourLog.info("Fired {} times in {}", CountingJob.ourCount, sw); assertThat(sw.getMillis()).isGreaterThan(500L); @@ -106,7 +102,7 @@ public class SchedulerServiceImplTest { StopWatch sw = new StopWatch(); mySvc.scheduleLocalJob(100, def); - await().until(CountingJob.ourCount::get, greaterThan(5)); + await().until(CountingJob.ourCount::get, count -> count > 5); ourLog.info("Fired {} times in {}", CountingJob.ourCount, sw); assertThat(sw.getMillis()).isGreaterThan(0L); @@ -121,7 +117,7 @@ public class SchedulerServiceImplTest { StopWatch sw = new StopWatch(); mySvc.scheduleLocalJob(100, def); - await().until(CountingJob.ourCount::get, greaterThan(5)); + await().until(CountingJob.ourCount::get, count -> count > 5); ourLog.info("Fired {} times in {}", CountingJob.ourCount, sw); assertThat(sw.getMillis()).isGreaterThan(3000L); @@ -138,7 +134,7 @@ public class SchedulerServiceImplTest { mySvc.triggerLocalJobImmediately(def); mySvc.triggerLocalJobImmediately(def); - await().until(CountingJob.ourCount::get, greaterThan(5)); + await().until(CountingJob.ourCount::get, count -> count > 5); ourLog.info("Fired {} times in {}", CountingJob.ourCount, sw); assertThat(sw.getMillis()).isGreaterThan(3000L); @@ -160,7 +156,7 @@ public class SchedulerServiceImplTest { ourLog.info("Fired {} times", CountingIntervalJob.ourCount); - await().until(() -> CountingIntervalJob.ourCount, greaterThanOrEqualTo(2)); + await().until(() -> CountingIntervalJob.ourCount, count -> count >= 2); assertThat(CountingIntervalJob.ourCount).isLessThan(6); } diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java index 8f1b4c39552..550ed46cd10 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.search.builder.predicate; +import static org.assertj.core.api.Assertions.assertThat; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.interceptor.model.RequestPartitionId; @@ -16,8 +17,6 @@ import com.healthmarketscience.sqlbuilder.InCondition; import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema; import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec; import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -114,7 +113,7 @@ public class ResourceLinkPredicateBuilderTest { when(mockSearchParam.getPathsSplit()).thenReturn(List.of("Patient.given", "Bundle.composition.subject", "Bundle.type")); when(mySearchParamRegistry.getActiveSearchParam(resourceType, paramName)).thenReturn(mockSearchParam); List result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of()); - MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Bundle.composition.subject", "Bundle.type")); + assertThat(result).containsExactlyInAnyOrder("Bundle.composition.subject", "Bundle.type"); } @Test @@ -122,7 +121,7 @@ public class ResourceLinkPredicateBuilderTest { String paramName = "param.name"; String resourceType = "Bundle"; List result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of()); - MatcherAssert.assertThat(result, Matchers.empty()); + assertThat(result).isEmpty(); } @Test @@ -138,7 +137,7 @@ public class ResourceLinkPredicateBuilderTest { when(patientIdentifierSP.getPathsSplit()).thenReturn(List.of("Patient.identifier")); when(mySearchParamRegistry.getActiveSearchParam("Patient", "identifier")).thenReturn(patientIdentifierSP); List result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of()); - MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Observation.subject.identifier")); + assertThat(result).containsExactlyInAnyOrder("Observation.subject.identifier"); } @Test @@ -165,7 +164,7 @@ public class ResourceLinkPredicateBuilderTest { when(mySearchParamRegistry.getActiveSearchParam("Organization", "identifier")).thenReturn(organizationIdentifierSP); List result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Patient", "Organization")); - MatcherAssert.assertThat(result, Matchers.containsInAnyOrder("Observation.subject.managingOrganization.identifier")); + assertThat(result).containsExactlyInAnyOrder("Observation.subject.managingOrganization.identifier"); } @Test @@ -178,6 +177,6 @@ public class ResourceLinkPredicateBuilderTest { when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient")); when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP); List result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Group")); - MatcherAssert.assertThat(result, Matchers.empty()); + assertThat(result).isEmpty(); } } diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java index 1f4c2cfb4fa..e03d8d6c187 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2_1Test.java @@ -18,8 +18,6 @@ import net.sf.json.JSON; import net.sf.json.JSONSerializer; import net.sf.json.JsonConfig; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; import org.hl7.fhir.dstu2016may.model.Address.AddressUse; import org.hl7.fhir.dstu2016may.model.Address.AddressUseEnumFactory; import org.hl7.fhir.dstu2016may.model.AuditEvent; diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu2_1Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu2_1Test.java index 386b9521ee5..def1a706d79 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu2_1Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu2_1Test.java @@ -8,7 +8,6 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.Read; import ca.uhn.fhir.util.TestUtil; -import org.hamcrest.core.StringContains; import org.hl7.fhir.dstu2016may.model.Patient; import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.jupiter.api.AfterAll; diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java index 4911c007268..0a38faed956 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorDstu2Test.java @@ -20,7 +20,6 @@ import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; -import org.hamcrest.core.StringContains; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java index 9504c855469..85fa64620f5 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/JsonParserDstu2Test.java @@ -58,7 +58,6 @@ import net.sf.json.JSON; import net.sf.json.JSONSerializer; import net.sf.json.JsonConfig; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matchers; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientDstu2Test.java index a13caf0a1d0..ea95984432c 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientDstu2Test.java @@ -19,7 +19,6 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; -import org.hamcrest.core.StringContains; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/InterceptorUserDataMapDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/InterceptorUserDataMapDstu2Test.java index fed50282ef6..d1e45bc66ef 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/InterceptorUserDataMapDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/InterceptorUserDataMapDstu2Test.java @@ -46,7 +46,6 @@ import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.contains; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -92,7 +91,15 @@ public class InterceptorUserDataMapDstu2Test { assertEquals(400, status.getStatusLine().getStatusCode()); } - await().until(() -> myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "preProcessOutgoingException", "handleException", "processingCompleted")); + await().untilAsserted(() -> + assertThat(myMapCheckMethods).containsExactly( + "incomingRequestPostProcessed", + "incomingRequestPreHandled", + "preProcessOutgoingException", + "handleException", + "processingCompleted" + ) + ); } @Test @@ -104,7 +111,7 @@ public class InterceptorUserDataMapDstu2Test { String response = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8); assertThat(response).contains("\"id\":\"1\""); - await().until(() -> myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally", "processingCompleted")); + await().untilAsserted(() -> assertThat(myMapCheckMethods).contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally", "processingCompleted")); } } diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorDstu2Test.java index 0f4ec62c36d..3cb17c4a7bf 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/LoggingInterceptorDstu2Test.java @@ -33,7 +33,6 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; -import org.hamcrest.core.StringContains; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu3Test.java index 6cd20433866..d1b7751679c 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ServerUsingOldTypesDstu3Test.java @@ -8,7 +8,6 @@ import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.Read; import ca.uhn.fhir.util.TestUtil; -import org.hamcrest.core.StringContains; import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.jupiter.api.AfterAll; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/ParametersUtilDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/ParametersUtilDstu3Test.java index 4060830ee58..ae9e77c68e6 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/ParametersUtilDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/util/ParametersUtilDstu3Test.java @@ -1,7 +1,6 @@ package ca.uhn.fhir.util; import ca.uhn.fhir.context.FhirContext; -import org.hamcrest.Matchers; import org.hl7.fhir.dstu3.model.Parameters; import org.hl7.fhir.dstu3.model.StringType; import org.junit.jupiter.api.Test; diff --git a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/model/BaseDateTimeTypeDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/model/BaseDateTimeTypeDstu3Test.java index 40f9ddfabf2..7e65c5051a9 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/model/BaseDateTimeTypeDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/model/BaseDateTimeTypeDstu3Test.java @@ -11,7 +11,6 @@ import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.validation.ValidationResult; import org.apache.commons.lang3.time.FastDateFormat; -import org.hamcrest.Matchers; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java index 4ca063c3da7..4356a997a06 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserHl7OrgDstu2Test.java @@ -12,9 +12,6 @@ import ca.uhn.fhir.rest.api.Constants; import net.sf.json.JSON; import net.sf.json.JSONSerializer; import org.apache.commons.io.IOUtils; -import org.hamcrest.core.IsNot; -import org.hamcrest.core.StringContains; -import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu2.model.Address; import org.hl7.fhir.dstu2.model.Address.AddressUse; import org.hl7.fhir.dstu2.model.Address.AddressUseEnumFactory; diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientTest.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientTest.java index d8d740929ca..f04fc4508d3 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientTest.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/rest/client/ETagClientTest.java @@ -15,7 +15,6 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; -import org.hamcrest.core.StringContains; import org.hl7.fhir.dstu2.model.Patient; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorR4Test.java index ac4e9279cd5..113029bca7c 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/narrative/DefaultThymeleafNarrativeGeneratorR4Test.java @@ -3,7 +3,6 @@ package ca.uhn.fhir.narrative; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; -import org.hamcrest.core.StringContains; import org.hl7.fhir.r4.model.CodeableConcept; import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DateTimeType; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ClientR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ClientR4Test.java index 8054edeb85c..a7f3e58a385 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ClientR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ClientR4Test.java @@ -57,8 +57,6 @@ import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; -import org.hamcrest.core.StringContains; -import org.hamcrest.core.StringEndsWith; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Bundle; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ExceptionHandlingTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ExceptionHandlingTest.java index 25564a7959f..09aacc78825 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ExceptionHandlingTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/ExceptionHandlingTest.java @@ -16,7 +16,6 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; -import org.hamcrest.core.StringContains; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Patient; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientR4Test.java index 4d1a9928a91..b0e42ac0a3e 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/GenericClientR4Test.java @@ -48,7 +48,6 @@ import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicStatusLine; -import org.hamcrest.core.StringContains; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/BlockingContentR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/BlockingContentR4Test.java index 6d44e7fac08..fda304ab422 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/BlockingContentR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/BlockingContentR4Test.java @@ -34,7 +34,6 @@ import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.notNullValue; public class BlockingContentR4Test { @@ -94,7 +93,7 @@ public class BlockingContentR4Test { try (CloseableHttpResponse resp = client.execute(post)) { ourLog.info(Arrays.asList(resp.getAllHeaders()).toString().replace(", ", "\n")); ourLog.info(resp.toString()); - await().until(()->myServerException, notNullValue()); + await().until(()->myServerException != null); } assertThat(myServerException.toString()).contains("Idle timeout expired"); diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CapabilityStatementCacheR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CapabilityStatementCacheR4Test.java index d37d2ecd49d..f12a6cbfbb8 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CapabilityStatementCacheR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/CapabilityStatementCacheR4Test.java @@ -19,7 +19,6 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.empty; import static org.junit.jupiter.api.Assertions.assertEquals; public class CapabilityStatementCacheR4Test { @@ -47,7 +46,9 @@ public class CapabilityStatementCacheR4Test { // Shut down the server myServerExtension.stopServer(); - await().until(() -> Thread.getAllStackTraces().keySet().stream().map(t -> t.getName()).filter(t -> t.startsWith(ConformanceMethodBinding.CACHE_THREAD_PREFIX)).sorted().collect(Collectors.toList()), empty()); + await().until(() -> Thread.getAllStackTraces().keySet().stream() + .map(Thread::getName) + .noneMatch(t -> t.startsWith(ConformanceMethodBinding.CACHE_THREAD_PREFIX))); } private static class MyCapabilityStatementProvider extends ServerCapabilityStatementProvider { diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PlainProviderR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PlainProviderR4Test.java index 1c5cb4a7d80..87a108a99e0 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PlainProviderR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PlainProviderR4Test.java @@ -18,8 +18,6 @@ import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.core.IsEqual; -import org.hamcrest.core.StringStartsWith; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.HumanName; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java index 60eb3f68c06..8225005aa42 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/PreferTest.java @@ -75,7 +75,7 @@ public class PreferTest { assertEquals(Constants.STATUS_HTTP_201_CREATED, status.getStatusLine().getStatusCode()); assertThat(responseContent).isNullOrEmpty(); - // assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue(), not(containsString("fhir"))); + // assertThat(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()).doesNotContain("fhir"); assertNull(status.getFirstHeader(Constants.HEADER_CONTENT_TYPE)); assertEquals(ourServer.getBaseUrl() + "/Patient/001/_history/002", status.getFirstHeader("location").getValue()); assertEquals(ourServer.getBaseUrl() + "/Patient/001/_history/002", status.getFirstHeader("content-location").getValue()); diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerInvalidDefinitionR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerInvalidDefinitionR4Test.java index 2909df29815..c2ac742e06c 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerInvalidDefinitionR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/ServerInvalidDefinitionR4Test.java @@ -19,7 +19,6 @@ import ca.uhn.fhir.test.utilities.server.MockServletUtil; import com.google.common.collect.Lists; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; -import org.hamcrest.core.StringContains; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.DateType; import org.hl7.fhir.r4.model.IdType; diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptorTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptorTest.java index 74ba2371a80..d8ea76fe245 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptorTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/ExceptionHandlingInterceptorTest.java @@ -21,7 +21,6 @@ import com.google.common.base.Charsets; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.core.StringContains; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Patient; diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index 365d17d1ba9..e04473e1dcd 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -50,6 +50,7 @@ ${fhir_core_version} + org.slf4j diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/HasGetterOrSetterForAllJsonFields.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/HasGetterOrSetterForAllJsonFields.java deleted file mode 100644 index ece18cc6af5..00000000000 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/HasGetterOrSetterForAllJsonFields.java +++ /dev/null @@ -1,157 +0,0 @@ -/*- - * #%L - * HAPI FHIR Test Utilities - * %% - * Copyright (C) 2014 - 2024 Smile CDR, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package ca.uhn.test.util; - -import ca.uhn.fhir.model.api.IModelJson; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.annotation.Nonnull; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.beans.BeanInfo; -import java.beans.FeatureDescriptor; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.hamcrest.Matchers.hasItems; - -@Deprecated -/** - * @deprecated convert usages to HasGetterOrSetterForAllJsonFieldsAssert - */ -public class HasGetterOrSetterForAllJsonFields extends TypeSafeMatcher> { - private static final Logger ourLog = LoggerFactory.getLogger(HasGetterOrSetterForAllJsonFields.class); - - @Override - public void describeTo(Description description) { - description.appendText("All @JsonProperty annotated fields have getters and setters."); - } - - @Override - protected boolean matchesSafely(Class item) { - List jsonPropertyFields = getJsonPropertyFields(item); - Matcher> matcher = hasItems(jsonPropertyFields.toArray()); - List properties = getProperties(item); - ourLog.info("{}: testing {} @JsonProperty fields", item.getSimpleName(), jsonPropertyFields.size()); - return matcher.matches(properties); - } - - @Nonnull - private List getJsonPropertyFields(Class item) { - List fields = new ArrayList<>(); - - populateFields(fields, item); - - return fields.stream() - .filter(this::isJsonProperty) - .filter(this::isNotCollection) - .filter(this::isNotMap) - .map(Field::getName) - .map(this::stripPrefix) - .map(this::stripUnderscoreSuffix) - .sorted() - .collect(Collectors.toList()); - } - - private boolean isNotCollection(Field theField) { - return !Collection.class.isAssignableFrom(theField.getType()); - } - - private boolean isNotMap(Field theField) { - return !Map.class.isAssignableFrom(theField.getType()); - } - - private boolean isJsonProperty(Field theField) { - if (!theField.isAnnotationPresent(JsonProperty.class)) { - return false; - } - Schema apiModelProperty = theField.getAnnotation(Schema.class); - if (apiModelProperty != null && apiModelProperty.accessMode() == Schema.AccessMode.READ_ONLY) { - return false; - } - return apiModelProperty == null || !apiModelProperty.hidden(); - } - - private String stripPrefix(String theFieldName) { - if (theFieldName.startsWith("my")) { - return theFieldName.substring(2, 3).toLowerCase() + theFieldName.substring(3); - } - return theFieldName; - } - - private String stripUnderscoreSuffix(String theFieldName) { - if (theFieldName.endsWith("_")) { - return theFieldName.substring(0, theFieldName.length() - 1); - } - return theFieldName; - } - - @Override - protected void describeMismatchSafely(Class item, Description mismatchDescription) { - mismatchDescription.appendText(" for class ").appendText(item.getName()).appendText(", "); - List jsonFields = getJsonPropertyFields(item); - Matcher> matcher = hasItems(jsonFields.toArray()); - List properties = getProperties(item); - matcher.describeMismatch(properties, mismatchDescription); - mismatchDescription.appendText("\n All non-collection @JsonProperty fields: " + String.join(", ", jsonFields)); - mismatchDescription.appendText("\n Have get/set methods for: " + String.join(", ", properties)); - } - - private List getProperties(Class item) { - try { - BeanInfo beanInfo = Introspector.getBeanInfo(item); - return Arrays.stream(beanInfo.getPropertyDescriptors()) - .map(FeatureDescriptor::getName) - .filter(name -> !"class".equals(name)) - .map(this::lowerCaseFirstLetter) - .sorted() - .collect(Collectors.toList()); - } catch (IntrospectionException e) { - throw new AssertionError("Unable to introspect " + item.getName(), e); - } - } - - private String lowerCaseFirstLetter(String thePropertyName) { - return thePropertyName.substring(0, 1).toLowerCase() + thePropertyName.substring(1); - } - - private static void populateFields(List theFields, Class theItem) { - theFields.addAll(Arrays.asList(theItem.getDeclaredFields())); - - if (theItem.getSuperclass() != null) { - populateFields(theFields, theItem.getSuperclass()); - } - } - - public static HasGetterOrSetterForAllJsonFields hasGetterOrSetterForAllJsonFields() { - return new HasGetterOrSetterForAllJsonFields(); - } -} diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogEventAssert.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogEventAssert.java index 3e080895124..6dd8bdfce7c 100644 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogEventAssert.java +++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogEventAssert.java @@ -27,7 +27,4 @@ public class LogEventAssert extends AbstractAssert myListAppender = null; - private Level mySavedLevel; - - /** - * - * @param theLogger the log to capture - */ - public LogbackCaptureTestExtension(Logger theLogger) { - myLogger = theLogger; - myLevel = null; - } - - /** - * - * @param theLogger the log to capture - * @param theTestLogLevel the log Level to set on the target logger for the duration of the test - */ - public LogbackCaptureTestExtension(Logger theLogger, Level theTestLogLevel) { - myLogger = theLogger; - myLevel = theTestLogLevel; - } - - /** - * @param theLoggerName the log name to capture - */ - public LogbackCaptureTestExtension(String theLoggerName) { - this((Logger) LoggerFactory.getLogger(theLoggerName)); - } - - /** - * Capture the root logger - all lines. - */ - public LogbackCaptureTestExtension() { - this(org.slf4j.Logger.ROOT_LOGGER_NAME); - } - - public LogbackCaptureTestExtension(String theLoggerName, Level theLevel) { - this((Logger) LoggerFactory.getLogger(theLoggerName), theLevel); - } - - public LogbackCaptureTestExtension(Class theClass) { - this(theClass.getName()); - } - - public LogbackCaptureTestExtension(Class theClass, Level theLevel) { - this(theClass.getName(), theLevel); - } - - public LogbackCaptureTestExtension(org.slf4j.Logger theLogger) { - this((Logger) theLogger); - } - - /** - * Returns a copy to avoid concurrent modification errors. - * @return A copy of the log events so far. - */ - public java.util.List getLogEvents() { - // copy to avoid concurrent mod errors - return new ArrayList<>(myListAppender.list); - } - - /** Clear accumulated log events. */ - public void clearEvents() { - myListAppender.list.clear(); - } - - public ListAppender getAppender() { - return myListAppender; - } - - @Override - public void beforeEach(ExtensionContext context) throws Exception { - setUp(); - } - - /** - * Guts of beforeEach exposed for manual lifecycle. - */ - public void setUp() { - setUp(myLevel); - } - - /** - * Guts of beforeEach exposed for manual lifecycle. - */ - public void setUp(Level theLevel) { - myListAppender = new ListAppender<>(); - myListAppender.start(); - myLogger.addAppender(myListAppender); - if (theLevel != null) { - mySavedLevel = myLogger.getLevel(); - myLogger.setLevel(theLevel); - } - } - - @Override - public void afterEach(ExtensionContext context) throws Exception { - myLogger.detachAppender(myListAppender); - myListAppender.stop(); - if (myLevel != null) { - myLogger.setLevel(mySavedLevel); - } - } - - - public List filterLoggingEventsWithMessageEqualTo(String theMessageText){ - return filterLoggingEventsWithPredicate(loggingEvent -> loggingEvent.getFormattedMessage().equals(theMessageText)); - } - - public List filterLoggingEventsWithMessageContaining(String theMessageText){ - return filterLoggingEventsWithPredicate(loggingEvent -> loggingEvent.getFormattedMessage().contains(theMessageText)); - } - - public List filterLoggingEventsWithPredicate(Predicate theLoggingEventPredicate){ - return getLogEvents() - .stream() - .filter(theLoggingEventPredicate) - .collect(Collectors.toList()); - } - - /** - * Extract the log messages from the logging events. - * @return a copy of the List of log messages - * - */ - @Nonnull - public List getLogMessages() { - return getLogEvents().stream().map(ILoggingEvent::getMessage).collect(Collectors.toList()); - } - - // Hamcrest matcher support - public static Matcher eventWithLevelAndMessageContains(@Nonnull Level theLevel, @Nonnull String thePartialMessage) { - return new LogbackEventMatcher(theLevel, thePartialMessage); - } - - public static Matcher eventWithLevel(@Nonnull Level theLevel) { - return new LogbackEventMatcher(theLevel, null); - } - - public static Matcher eventWithMessageContains(@Nonnull String thePartialMessage) { - return new LogbackEventMatcher(null, thePartialMessage); - } - - public static Matcher eventWithLevelAndMessageAndThrew(@Nonnull Level theLevel, - @Nonnull String thePartialMessage, - @Nonnull String theThrown) - { - return new LogbackEventMatcher(theLevel, thePartialMessage, theThrown); - } - -} diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogbackEventMatcher.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogbackEventMatcher.java deleted file mode 100644 index 44af2e850d1..00000000000 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/LogbackEventMatcher.java +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * #%L - * HAPI FHIR Test Utilities - * %% - * Copyright (C) 2014 - 2024 Smile CDR, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package ca.uhn.test.util; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import org.hamcrest.CustomTypeSafeMatcher; - -import jakarta.annotation.Nonnull; -import jakarta.annotation.Nullable; - -/** - * A Hamcrest matcher for junit assertions. - * Matches on level, partial message, and/or a portion of the message contained by a throwable, if present. - * @deprecated use {@link LogbackEventAssert} - */ -@Deprecated -public class LogbackEventMatcher extends CustomTypeSafeMatcher { - @Nullable - private final Level myLevel; - @Nullable - private final String myLogMessage; - @Nullable - private final String myThrownMessage; - - public LogbackEventMatcher(@Nullable Level theLevel, @Nullable String thePartialString) { - this("log event", theLevel, thePartialString, null); - } - - public LogbackEventMatcher(@Nullable Level theLevel, @Nullable String thePartialString, @Nullable String theThrownMessage) { - this("log event", theLevel, thePartialString, theThrownMessage); - } - - private LogbackEventMatcher(@Nonnull String description, Level theLevel, - String thePartialString, String theThrownMessage) - { - super(makeDescription(description, theLevel, thePartialString, theThrownMessage)); - myLevel = theLevel; - myLogMessage = thePartialString; - myThrownMessage = theThrownMessage; - } - - @Nonnull - private static String makeDescription(String description, Level theLevel, String thePartialString, String theThrownMessage) { - String msg = description; - if (theLevel != null) { - msg = msg + " with level at least " + theLevel; - } - if (thePartialString != null) { - msg = msg + " containing string \"" + thePartialString + "\""; - - } - if (thePartialString != null) { - msg = msg + " and throwable with error message containing string \"" + theThrownMessage + "\""; - - } - return msg; - } - - @Override - protected boolean matchesSafely(ILoggingEvent item) { - return (myLevel == null || item.getLevel().isGreaterOrEqual(myLevel)) && - (myLogMessage == null || item.getFormattedMessage().contains(myLogMessage)) && - (myThrownMessage == null || item.getThrowableProxy() == null || item.getThrowableProxy().getMessage().contains(myThrownMessage)); - } -} diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/StaticLogbackCaptureTestExtension.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/StaticLogbackCaptureTestExtension.java deleted file mode 100644 index d4e356aaa5a..00000000000 --- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/util/StaticLogbackCaptureTestExtension.java +++ /dev/null @@ -1,116 +0,0 @@ -/*- - * #%L - * HAPI FHIR Test Utilities - * %% - * Copyright (C) 2014 - 2024 Smile CDR, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ -package ca.uhn.test.util; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.filter.ThresholdFilter; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.read.ListAppender; -import jakarta.annotation.Nonnull; -import org.junit.jupiter.api.extension.AfterAllCallback; -import org.junit.jupiter.api.extension.BeforeAllCallback; -import org.junit.jupiter.api.extension.ExtensionContext; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static org.slf4j.Logger.ROOT_LOGGER_NAME; - -/** - * This is a static wrapper around LogbackTestExtension for use in IT tests when you need to assert on App - * startup log entries - * @deprecated use {@link StaticLogbackTestExtension} - */ -@Deprecated -public class StaticLogbackCaptureTestExtension implements BeforeAllCallback, AfterAllCallback { - private final LogbackCaptureTestExtension myLogbackCaptureTestExtension; - - public StaticLogbackCaptureTestExtension(LogbackCaptureTestExtension theLogbackCaptureTestExtension) { - myLogbackCaptureTestExtension = theLogbackCaptureTestExtension; - } - - public StaticLogbackCaptureTestExtension() { - myLogbackCaptureTestExtension = new LogbackCaptureTestExtension(); - } - - public static StaticLogbackCaptureTestExtension withThreshold(Level theLevel) { - LogbackCaptureTestExtension logbackCaptureTestExtension = new LogbackCaptureTestExtension(); - logbackCaptureTestExtension.setUp(theLevel); - ThresholdFilter thresholdFilter = new ThresholdFilter(); - thresholdFilter.setLevel(theLevel.levelStr); - logbackCaptureTestExtension.getAppender().addFilter(thresholdFilter); - - return new StaticLogbackCaptureTestExtension(logbackCaptureTestExtension); - } - - @Override - public void beforeAll(ExtensionContext theExtensionContext) throws Exception { - if (myLogbackCaptureTestExtension.getAppender() == null) { - myLogbackCaptureTestExtension.beforeEach(theExtensionContext); - } - } - - @Override - public void afterAll(ExtensionContext theExtensionContext) throws Exception { - myLogbackCaptureTestExtension.afterEach(theExtensionContext); - } - - /** - * Returns a copy to avoid concurrent modification errors. - * @return A copy of the log events so far. - */ - public java.util.List getLogEvents() { - return myLogbackCaptureTestExtension.getLogEvents(); - } - - /** Clear accumulated log events. */ - public void clearEvents() { - myLogbackCaptureTestExtension.clearEvents(); - } - - public ListAppender getAppender() { - return myLogbackCaptureTestExtension.getAppender(); - } - - public List filterLoggingEventsWithMessageEqualTo(String theMessageText){ - return myLogbackCaptureTestExtension.filterLoggingEventsWithMessageEqualTo(theMessageText); - } - - public List filterLoggingEventsWithMessageContaining(String theMessageText){ - return myLogbackCaptureTestExtension.filterLoggingEventsWithMessageContaining(theMessageText); - } - - public List filterLoggingEventsWithPredicate(Predicate theLoggingEventPredicate){ - return myLogbackCaptureTestExtension.filterLoggingEventsWithPredicate(theLoggingEventPredicate); - } - - /** - * Extract the log messages from the logging events. - * @return a copy of the List of log messages - * - */ - @Nonnull - public List getLogMessages() { - return myLogbackCaptureTestExtension.getLogMessages(); - } - -} diff --git a/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java b/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java index b679785f8ef..2d30fbe268e 100644 --- a/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/RequestValidatingInterceptorDstu3Test.java @@ -31,7 +31,6 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; -import org.hamcrest.Matchers; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.IdType; diff --git a/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu3Test.java b/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu3Test.java index f576d8e3af6..2f0199b684a 100644 --- a/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu3Test.java @@ -24,7 +24,6 @@ import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; -import org.hamcrest.Matchers; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.IdType; diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2016may/hapi/validation/ResourceValidatorDstu2_1Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2016may/hapi/validation/ResourceValidatorDstu2_1Test.java index c94f98102f2..1fbb525077e 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2016may/hapi/validation/ResourceValidatorDstu2_1Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu2016may/hapi/validation/ResourceValidatorDstu2_1Test.java @@ -12,7 +12,6 @@ import ca.uhn.fhir.validation.SchemaBaseValidator; import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; import org.apache.commons.io.IOUtils; -import org.hamcrest.core.StringContains; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; import org.hl7.fhir.dstu2016may.model.CodeableConcept; import org.hl7.fhir.dstu2016may.model.Coding; diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java index a2bc7cc9869..6464cd18b05 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java @@ -18,7 +18,6 @@ import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; -import org.hamcrest.core.StringContains; import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport; import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain; import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java index c97af2c13a5..0c099c90deb 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2/Dstu2ResourceValidatorDstu2Test.java @@ -33,9 +33,6 @@ import ca.uhn.fhir.validation.ValidationFailureException; import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.ops4j.pax.exam.Configuration; @@ -47,8 +44,6 @@ import org.ops4j.pax.exam.spi.reactors.PerClass; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_DSTU2; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java index d913746f619..782683dd791 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/JsonParserDstu2_1Test.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.tests.integration.karaf.dstu21; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; @@ -13,8 +14,6 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.LenientErrorHandler; import ca.uhn.fhir.parser.StrictErrorHandler; import com.google.common.collect.Sets; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; import org.hl7.fhir.dstu2016may.model.Conformance; import org.hl7.fhir.dstu2016may.model.PrimitiveType; import org.hl7.fhir.instance.model.api.IIdType; @@ -30,10 +29,6 @@ import org.ops4j.pax.exam.spi.reactors.PerClass; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU2_1; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -668,7 +663,7 @@ public class JsonParserDstu2_1Test { assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); - assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths(), empty()); + assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths()).isEmpty(); org.hl7.fhir.dstu2016may.model.Patient p = new org.hl7.fhir.dstu2016may.model.Patient(); p.setManagingOrganization(new org.hl7.fhir.dstu2016may.model.Reference("http://foo.com/Organization/2/_history/1")); @@ -1033,7 +1028,7 @@ public class JsonParserDstu2_1Test { assertThat(ourCtx.newJsonParser().encodeResourceToString(p)).containsSubsequence("123", "ABC")); assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p)).contains("ABC")); - assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p)).doesNotContain("123"); } @Test @@ -1157,8 +1152,8 @@ public class JsonParserDstu2_1Test { assertEquals("654321", res.getIdentifier().get(0).getValue()); assertEquals(true, res.getActive()); - assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); - assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre()).contains("identifier comment 1", "identifier comment 2"); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre()).contains("use comment 1", "use comment 2"); String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); ourLog.info(encoded); diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java index 077ac70d900..23d84658dc3 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu21/XmlParserDstu2_1Test.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.tests.integration.karaf.dstu21; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -15,10 +16,6 @@ import ca.uhn.fhir.parser.LenientErrorHandler; import ca.uhn.fhir.parser.StrictErrorHandler; import ca.uhn.fhir.rest.api.Constants; import com.google.common.collect.Sets; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; -import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu2016may.model.Address; import org.hl7.fhir.dstu2016may.model.Appointment; import org.hl7.fhir.dstu2016may.model.AuditEvent; @@ -75,10 +72,6 @@ import org.xmlunit.diff.ElementSelectors; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU2_1; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -723,7 +716,7 @@ public class XmlParserDstu2_1Test { //@formatter:on Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); - assertThat(parsed.getMeta().getProfile(), empty()); + assertThat(parsed.getMeta().getProfile()).isEmpty(); List tagList = parsed.getMeta().getTag(); assertEquals(2, tagList.size()); @@ -1673,7 +1666,7 @@ public class XmlParserDstu2_1Test { assertThat(ourCtx.newXmlParser().encodeResourceToString(p)).containsSubsequence("123", "ABC")); assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p)).contains("ABC")); - assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p)).doesNotContain("123"); } @@ -1717,10 +1710,10 @@ public class XmlParserDstu2_1Test { assertEquals("654321", res.getIdentifier().get(0).getValue()); assertEquals(true, res.getActive()); - assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment")); - assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); - assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); - assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment")); + assertThat(res.getIdElement().getFormatCommentsPre()).contains("pre resource comment"); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre()).contains("identifier comment 1", "identifier comment 2"); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre()).contains("use comment 1", "use comment 2"); + assertThat(res.getActiveElement().getFormatCommentsPost()).contains("post resource comment"); String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); ourLog.info(encoded); diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java index f22aae86602..974847ea5e3 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java @@ -12,11 +12,6 @@ import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.Constants; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.hamcrest.core.IsNot; -import org.hamcrest.core.StringContains; -import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu2.model.Address; import org.hl7.fhir.dstu2.model.Address.AddressUse; import org.hl7.fhir.dstu2.model.Address.AddressUseEnumFactory; @@ -65,8 +60,6 @@ import org.xml.sax.SAXException; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java index 0f72daefd67..78e9c1fb10b 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java @@ -17,11 +17,6 @@ import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.Constants; import org.apache.commons.io.IOUtils; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.hamcrest.core.IsNot; -import org.hamcrest.core.StringContains; -import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu2.model.Address; import org.hl7.fhir.dstu2.model.CodeableConcept; import org.hl7.fhir.dstu2.model.Composition; @@ -58,8 +53,6 @@ import org.xmlunit.diff.ElementSelectors; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java index f5ea68fe087..fd62c0da55e 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.tests.integration.karaf.dstu3; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.io.StringReader; import java.math.BigDecimal; @@ -14,8 +15,6 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.LenientErrorHandler; import ca.uhn.fhir.parser.StrictErrorHandler; import com.google.common.collect.Sets; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; import org.hl7.fhir.dstu3.model.AuditEvent; import org.hl7.fhir.dstu3.model.Basic; import org.hl7.fhir.dstu3.model.Binary; @@ -62,10 +61,6 @@ import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3 import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; import static org.apache.commons.lang3.StringUtils.countMatches; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -871,7 +866,7 @@ public class Dstu3JsonParserTest { assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences()); assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences()); - assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths(), empty()); + assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths()).isEmpty(); Patient p = new Patient(); p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1")); @@ -1264,7 +1259,7 @@ public class Dstu3JsonParserTest { assertThat(ourCtx.newJsonParser().encodeResourceToString(p)).containsSubsequence("123", "ABC")); assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p)).contains("ABC")); - assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p)).doesNotContain("123"); } @Test @@ -1430,8 +1425,8 @@ public class Dstu3JsonParserTest { assertEquals("654321", res.getIdentifier().get(0).getValue()); assertEquals(true, res.getActive()); - assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); - assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre()).contains("identifier comment 1", "identifier comment 2"); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre()).contains("use comment 1", "use comment 2"); String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); ourLog.info(encoded); diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java index 8a83f568f7c..6e968755a98 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.tests.integration.karaf.dstu3; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.io.StringReader; import java.nio.charset.StandardCharsets; @@ -20,10 +21,6 @@ import com.google.common.collect.Sets; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; -import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.dstu3.model.Address; import org.hl7.fhir.dstu3.model.AllergyIntolerance; import org.hl7.fhir.dstu3.model.Annotation; @@ -94,11 +91,6 @@ import org.xmlunit.diff.ElementSelectors; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -831,7 +823,7 @@ public class Dstu3XmlParserTest { "")); Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc); - assertThat(parsed.getMeta().getProfile(), empty()); + assertThat(parsed.getMeta().getProfile()).isEmpty(); List tagList = parsed.getMeta().getTag(); assertEquals(2, tagList.size()); @@ -2085,7 +2077,7 @@ public class Dstu3XmlParserTest { assertThat(ourCtx.newXmlParser().encodeResourceToString(p)).containsSubsequence("123", "ABC")); assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p)).contains("ABC")); - assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123"))); + assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p)).doesNotContain("123"); } @Test @@ -2167,10 +2159,10 @@ public class Dstu3XmlParserTest { assertEquals("654321", res.getIdentifier().get(0).getValue()); assertEquals(true, res.getActive()); - assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment")); - assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2")); - assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2")); - assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment")); + assertThat(res.getIdElement().getFormatCommentsPre()).contains("pre resource comment"); + assertThat(res.getIdentifier().get(0).getFormatCommentsPre()).contains("identifier comment 1", "identifier comment 2"); + assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre()).contains("use comment 1", "use comment 2"); + assertThat(res.getActiveElement().getFormatCommentsPost()).contains("post resource comment"); String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); ourLog.info(encoded); diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java index 532a84e14ea..edf76eac0c4 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java @@ -8,7 +8,6 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.StrictErrorHandler; import ca.uhn.fhir.tests.integration.karaf.ValidationConstants; import ca.uhn.fhir.validation.schematron.SchematronBaseValidator; -import org.hamcrest.core.StringContains; import org.hl7.fhir.r5.hapi.validation.FhirInstanceValidator; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java index e02111b439e..ff601ad1fb2 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java @@ -19,8 +19,6 @@ import org.ops4j.pax.exam.spi.reactors.PerClass; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.core.IsNot.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.mockito.ArgumentMatchers.contains; diff --git a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java index d9f893fb0f6..d1a0f53ad75 100644 --- a/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java +++ b/osgi/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java @@ -6,7 +6,6 @@ import java.util.Set; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; import com.google.common.collect.Sets; -import org.hamcrest.core.IsNot; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Patient; import org.junit.jupiter.api.Test; @@ -20,7 +19,6 @@ import org.ops4j.pax.exam.spi.reactors.PerClass; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF; import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP; -import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; From 472984ac65cbf3e9076652cd9dabccf66e1655a9 Mon Sep 17 00:00:00 2001 From: Martha Mitran Date: Tue, 18 Jun 2024 14:57:04 -0700 Subject: [PATCH 04/19] Document pointcut to use to modify request parameters (#6019) * Document pointcut to use to modify request parameters. Add a test to exemplify. * Add another alternate pointcut to use --- .../ca/uhn/fhir/interceptor/api/Pointcut.java | 17 ++++---- .../provider/r4/ResourceProviderR4Test.java | 43 +++++++++++++++++-- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java index 016512e537d..cac6a1725a6 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java @@ -321,9 +321,12 @@ public enum Pointcut implements IPointcut { * This hook is invoked before an incoming request is processed. Note that this method is called * after the server has begun preparing the response to the incoming client request. * As such, it is not able to supply a response to the incoming request in the way that - * SERVER_INCOMING_REQUEST_PRE_PROCESSED and - * {@link #SERVER_INCOMING_REQUEST_POST_PROCESSED} - * are. + * SERVER_INCOMING_REQUEST_PRE_PROCESSED and {@link #SERVER_INCOMING_REQUEST_POST_PROCESSED} are. + * At this point the request has already been passed to the handler so any changes + * (e.g. adding parameters) will not be considered. + * If you'd like to modify request parameters before they are passed to the handler, + * use {@link Pointcut#SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED} or {@link Pointcut#SERVER_INCOMING_REQUEST_POST_PROCESSED}. + * If you are attempting to modify a search before it occurs, use {@link Pointcut#STORAGE_PRESEARCH_REGISTERED}. *

* Hooks may accept the following parameters: *