From aa9a984075d8ab5bbb41c714544885f0acbfa25b Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 3 Sep 2019 18:44:52 -0400 Subject: [PATCH 01/16] Don't trust stored total when determining whether or not to expand. --- .../java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index cdba0d04b2d..e1cc30878b3 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -518,7 +518,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, theExpansionComponent.addParameter().setName("offset").setValue(new IntegerType(theOffset)); theExpansionComponent.addParameter().setName("count").setValue(new IntegerType(theCount)); - if (theCount == 0 || total == 0) { + if (theCount == 0) { return; } From ea19b46f60f92a4b619674089037f00275c98d09 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 3 Sep 2019 20:36:16 -0400 Subject: [PATCH 02/16] Added an indexed order column to TermValueSetConcept for improved fetching. --- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 2 +- .../jpa/dao/data/ITermValueSetConceptDao.java | 2 +- .../fhir/jpa/entity/TermValueSetConcept.java | 20 +++++++- .../TermValueSetConceptDesignation.java | 8 ++++ .../jpa/term/ValueSetConceptAccumulator.java | 1 + .../jpa/term/TerminologySvcImplR4Test.java | 48 ++++++++++++------- .../tasks/HapiFhirJpaMigrationTasks.java | 9 ++++ 7 files changed, 71 insertions(+), 19 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index a3e93390c8e..a50c382d95a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -149,7 +149,7 @@ public class DaoConfig { /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code false}! */ - private boolean myPreExpandValueSetsExperimental = false; + private boolean myPreExpandValueSetsExperimental = true; private boolean myFilterParameterEnabled = false; private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java index 3f0f8a9e2a3..09a59729ff9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java @@ -40,7 +40,7 @@ public interface ITermValueSetConceptDao extends JpaRepository findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval") diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java index 4827e756d89..85ebf24a0ef 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java @@ -40,7 +40,8 @@ import static org.apache.commons.lang3.StringUtils.length; * bork up migration tasks. */ @Table(name = "TRM_VALUESET_CONCEPT", uniqueConstraints = { - @UniqueConstraint(name = "IDX_VS_CONCEPT_CS_CD", columnNames = {"VALUESET_PID", "SYSTEM_URL", "CODEVAL"}) + @UniqueConstraint(name = "IDX_VS_CONCEPT_CS_CD", columnNames = {"VALUESET_PID", "SYSTEM_URL", "CODEVAL"}), + @UniqueConstraint(name = "IDX_VS_CONCEPT_ORDER", columnNames = {"VALUESET_PID", "VALUESET_ORDER"}) }) @Entity() public class TermValueSetConcept implements Serializable { @@ -56,6 +57,12 @@ public class TermValueSetConcept implements Serializable { @JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID")) private TermValueSet myValueSet; + @Column(name = "VALUESET_PID", insertable = false, updatable = false, nullable = false) + private Long myValueSetPid; + + @Column(name = "VALUESET_ORDER", nullable = false) + private int myOrder; + @Transient private String myValueSetUrl; @@ -87,6 +94,15 @@ public class TermValueSetConcept implements Serializable { return this; } + public int getOrder() { + return myOrder; + } + + public TermValueSetConcept setOrder(int theOrder) { + myOrder = theOrder; + return this; + } + public String getValueSetUrl() { if (myValueSetUrl == null) { myValueSetUrl = getValueSet().getUrl(); @@ -173,6 +189,8 @@ public class TermValueSetConcept implements Serializable { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) + .append("myValueSetPid", myValueSetPid) + .append("myOrder", myOrder) .append("myValueSetUrl", this.getValueSetUrl()) .append("myValueSetName", this.getValueSetName()) .append("mySystem", mySystem) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java index e3aa0c5196a..87e5ef2e8ec 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java @@ -52,10 +52,16 @@ public class TermValueSetConceptDesignation implements Serializable { @JoinColumn(name = "VALUESET_CONCEPT_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_CONCEPT_PID")) private TermValueSetConcept myConcept; + @Column(name = "VALUESET_CONCEPT_PID", insertable = false, updatable = false, nullable = false) + private Long myConceptPid; + @ManyToOne() @JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VSCD_VS_PID")) private TermValueSet myValueSet; + @Column(name = "VALUESET_PID", insertable = false, updatable = false, nullable = false) + private Long myValueSetPid; + @Transient private String myValueSetUrl; @@ -202,7 +208,9 @@ public class TermValueSetConceptDesignation implements Serializable { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) .append(myConcept != null ? ("myConcept - id=" + myConcept.getId()) : ("myConcept=(null)")) + .append("myConceptPid", myConceptPid) .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) + .append("myValueSetPid", myValueSetPid) .append("myValueSetUrl", this.getValueSetUrl()) .append("myValueSetName", this.getValueSetName()) .append("myLanguage", myLanguage) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java index 24f41232fbe..5c7fd8911f4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java @@ -97,6 +97,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { TermValueSetConcept concept = new TermValueSetConcept(); concept.setValueSet(myTermValueSet); + concept.setOrder(myConceptsSaved); concept.setSystem(theSystem); concept.setCode(theCode); if (isNotBlank(theDisplay)) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java index 599912cd965..de3e466a968 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java @@ -2097,11 +2097,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(TermValueSetPreExpansionStatusEnum.EXPANDED, termValueSet.getExpansionStatus()); TermValueSetConcept concept = termValueSet.getConcepts().get(0); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8450-9", concept.getCode()); assertEquals("Systolic blood pressure--expiration", concept.getDisplay()); assertEquals(2, concept.getDesignations().size()); + assertEquals(0, concept.getOrder()); TermValueSetConceptDesignation designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2118,20 +2119,22 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systoliskt blodtryck - utgång", designation.getValue()); concept = termValueSet.getConcepts().get(1); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("11378-7", concept.getCode()); assertEquals("Systolic blood pressure at First encounter", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(1, concept.getOrder()); // ... concept = termValueSet.getConcepts().get(22); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); + assertEquals(22, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2141,11 +2144,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); concept = termValueSet.getConcepts().get(23); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(23, concept.getOrder()); }); } @@ -2195,11 +2199,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(TermValueSetPreExpansionStatusEnum.EXPANDED, termValueSet.getExpansionStatus()); TermValueSetConcept concept = termValueSet.getConcepts().get(0); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8450-9", concept.getCode()); assertEquals("Systolic blood pressure--expiration", concept.getDisplay()); assertEquals(2, concept.getDesignations().size()); + assertEquals(0, concept.getOrder()); TermValueSetConceptDesignation designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2216,20 +2221,22 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systoliskt blodtryck - utgång", designation.getValue()); concept = termValueSet.getConcepts().get(1); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("11378-7", concept.getCode()); assertEquals("Systolic blood pressure at First encounter", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(1, concept.getOrder()); // ... concept = termValueSet.getConcepts().get(22); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); + assertEquals(22, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2239,11 +2246,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); concept = termValueSet.getConcepts().get(23); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(23, concept.getOrder()); }); } @@ -2293,11 +2301,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(TermValueSetPreExpansionStatusEnum.EXPANDED, termValueSet.getExpansionStatus()); TermValueSetConcept concept = termValueSet.getConcepts().get(0); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8450-9", concept.getCode()); assertEquals("Systolic blood pressure--expiration", concept.getDisplay()); assertEquals(2, concept.getDesignations().size()); + assertEquals(0, concept.getOrder()); TermValueSetConceptDesignation designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2314,20 +2323,22 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systoliskt blodtryck - utgång", designation.getValue()); concept = termValueSet.getConcepts().get(1); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("11378-7", concept.getCode()); assertEquals("Systolic blood pressure at First encounter", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(1, concept.getOrder()); // ... concept = termValueSet.getConcepts().get(22 - 2); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); + assertEquals(22, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2337,11 +2348,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); concept = termValueSet.getConcepts().get(23 - 2); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(23, concept.getOrder()); }); } @@ -2391,11 +2403,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(TermValueSetPreExpansionStatusEnum.EXPANDED, termValueSet.getExpansionStatus()); TermValueSetConcept concept = termValueSet.getConcepts().get(0); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8450-9", concept.getCode()); assertEquals("Systolic blood pressure--expiration", concept.getDisplay()); assertEquals(2, concept.getDesignations().size()); + assertEquals(0, concept.getOrder()); TermValueSetConceptDesignation designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2412,20 +2425,22 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systoliskt blodtryck - utgång", designation.getValue()); concept = termValueSet.getConcepts().get(1); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("11378-7", concept.getCode()); assertEquals("Systolic blood pressure at First encounter", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(1, concept.getOrder()); // ... concept = termValueSet.getConcepts().get(22 - 2); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); + assertEquals(22, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2435,11 +2450,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); concept = termValueSet.getConcepts().get(23 - 2); - ourLog.info("Code:\n" + concept.toString()); + ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); + assertEquals(23, concept.getOrder()); }); } diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index 5574be04e90..b21e03dcba3 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -93,6 +93,15 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { Builder.BuilderWithTableName termValueSetTable = version.onTable("TRM_VALUESET"); termValueSetTable.addColumn("TOTAL_CONCEPTS").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG); termValueSetTable.addColumn("TOTAL_CONCEPT_DESIGNATIONS").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG); + + // TermValueSetConcept + version.startSectionWithMessage("Processing table: TRM_VALUESET_CONCEPT"); + Builder.BuilderWithTableName termValueSetConceptTable = version.onTable("TRM_VALUESET_CONCEPT"); + termValueSetConceptTable.addColumn("VALUESET_ORDER").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.INT); + termValueSetConceptTable + .addIndex("IDX_VS_CONCEPT_ORDER") + .unique(true) + .withColumns("VALUESET_PID", "VALUESET_ORDER"); } protected void init400() { From b00b1d2278eee4160ff5b0a656ab10d39fbd5bfd Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 3 Sep 2019 20:36:54 -0400 Subject: [PATCH 03/16] Toggle pre-expansion config. --- .../src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index a50c382d95a..a3e93390c8e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -149,7 +149,7 @@ public class DaoConfig { /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code false}! */ - private boolean myPreExpandValueSetsExperimental = true; + private boolean myPreExpandValueSetsExperimental = false; private boolean myFilterParameterEnabled = false; private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; /** From 91cfecd25759e0911819ed923e68d484d60740e8 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Thu, 5 Sep 2019 11:43:31 -0400 Subject: [PATCH 04/16] Incremental progress on large ValueSet expansion. --- .../ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java | 8 ++++---- .../jpa/dao/data/ITermValueSetConceptDesignationDao.java | 4 ++-- .../java/ca/uhn/fhir/jpa/dao/data/ITermValueSetDao.java | 5 ----- .../ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 4 ++-- .../ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java | 4 ++-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java index 09a59729ff9..37d236fa484 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java @@ -33,17 +33,17 @@ import java.util.Optional; public interface ITermValueSetConceptDao extends JpaRepository { - @Query("SELECT COUNT(*) FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid") + @Query("SELECT COUNT(*) FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid") Integer countByTermValueSetId(@Param("pid") Long theValueSetId); - @Query("DELETE FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid") + @Query("DELETE FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid") @Modifying void deleteByTermValueSetId(@Param("pid") Long theValueSetId); - @Query("SELECT vsc from TermValueSetConcept vsc LEFT OUTER JOIN FETCH vsc.myDesignations WHERE vsc.myValueSet.myId = :pid ORDER BY vsc.myOrder ASC") + @Query("SELECT vsc from TermValueSetConcept vsc LEFT OUTER JOIN FETCH vsc.myDesignations WHERE vsc.myValueSetPid = :pid ORDER BY vsc.myOrder ASC") Slice findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); - @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myId = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval") + @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval") Optional findByTermValueSetIdSystemAndCode(@Param("pid") Long theValueSetId, @Param("system_url") String theSystem, @Param("codeval") String theCode); @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSet.myResourcePid = :resource_pid AND vsc.myCode = :codeval") diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDesignationDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDesignationDao.java index 1792b8496e0..6144cb652e5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDesignationDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDesignationDao.java @@ -30,10 +30,10 @@ import org.springframework.data.repository.query.Param; public interface ITermValueSetConceptDesignationDao extends JpaRepository { - @Query("SELECT COUNT(vscd) FROM TermValueSetConceptDesignation vscd WHERE vscd.myValueSet.myId = :pid") + @Query("SELECT COUNT(vscd) FROM TermValueSetConceptDesignation vscd WHERE vscd.myValueSetPid = :pid") Integer countByTermValueSetId(@Param("pid") Long theValueSetId); - @Query("DELETE FROM TermValueSetConceptDesignation vscd WHERE vscd.myValueSet.myId = :pid") + @Query("DELETE FROM TermValueSetConceptDesignation vscd WHERE vscd.myValueSetPid = :pid") @Modifying void deleteByTermValueSetId(@Param("pid") Long theValueSetId); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetDao.java index 86053789288..50406e1d2ef 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetDao.java @@ -25,7 +25,6 @@ import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -33,10 +32,6 @@ import java.util.Optional; public interface ITermValueSetDao extends JpaRepository { - @Query("DELETE FROM TermValueSet vs WHERE vs.myId = :pid") - @Modifying - void deleteByTermValueSetId(@Param("pid") Long theId); - @Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid") Optional findByResourcePid(@Param("resource_pid") Long theResourcePid); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index e1cc30878b3..10c0581765c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -392,7 +392,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.info("Deleting existing TermValueSet[{}] and its children...", existingTermValueSet.getId()); myValueSetConceptDesignationDao.deleteByTermValueSetId(existingTermValueSet.getId()); myValueSetConceptDao.deleteByTermValueSetId(existingTermValueSet.getId()); - myValueSetDao.deleteByTermValueSetId(existingTermValueSet.getId()); + myValueSetDao.deleteById(existingTermValueSet.getId()); ourLog.info("Done deleting existing TermValueSet[{}] and its children.", existingTermValueSet.getId()); } } @@ -578,7 +578,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private void logDesignationsExpanded(TermValueSet theValueSet, TermValueSetConcept theConcept, int theDesignationsExpanded) { if (theDesignationsExpanded > 0) { - ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl()); + ourLog.debug("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl()); } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java index de3e466a968..972fa9eda81 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java @@ -658,7 +658,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(0, myTermValueSetConceptDesignationDao.countByTermValueSetId(termValueSetId).intValue()); myTermValueSetConceptDao.deleteByTermValueSetId(termValueSetId); assertEquals(0, myTermValueSetConceptDao.countByTermValueSetId(termValueSetId).intValue()); - myTermValueSetDao.deleteByTermValueSetId(termValueSetId); + myTermValueSetDao.deleteById(termValueSetId); assertFalse(myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).isPresent()); } }); @@ -695,7 +695,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals(0, myTermValueSetConceptDesignationDao.countByTermValueSetId(termValueSetId).intValue()); myTermValueSetConceptDao.deleteByTermValueSetId(termValueSetId); assertEquals(0, myTermValueSetConceptDao.countByTermValueSetId(termValueSetId).intValue()); - myTermValueSetDao.deleteByTermValueSetId(termValueSetId); + myTermValueSetDao.deleteById(termValueSetId); assertFalse(myTermValueSetDao.findByResourcePid(myExtensionalVsIdOnResourceTable).isPresent()); } }); From 6fa9658b24ba6f2030f66e4cb9bc2385ff9ea5f0 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Thu, 5 Sep 2019 15:54:45 -0400 Subject: [PATCH 05/16] Incremental progress on large ValueSet expansion. --- .../uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 10 +++++----- .../uhn/fhir/jpa/term/ValueSetConceptAccumulator.java | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index 10c0581765c..9e7a901e31f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -1750,7 +1750,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, } catch (FHIRException fe) { throw new InternalErrorException(fe); } - myConceptMapDao.save(termConceptMap); + termConceptMap = myConceptMapDao.save(termConceptMap); int codesSaved = 0; if (theConceptMap.hasGroup()) { @@ -1793,7 +1793,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, termConceptMapGroupElementTarget.setEquivalence(elementTarget.getEquivalence()); myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget); - if (codesSaved++ % 250 == 0) { + if (++codesSaved % 250 == 0) { ourLog.info("Have saved {} codes in ConceptMap", codesSaved); myConceptMapGroupElementTargetDao.flush(); } @@ -1815,7 +1815,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, throw new UnprocessableEntityException(msg); } - ourLog.info("Done storing TermConceptMap."); + ourLog.info("Done storing TermConceptMap[{}]", termConceptMap.getId()); } @Scheduled(fixedDelay = 600000) // 10 minutes. @@ -1932,7 +1932,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, Optional optionalExistingTermValueSetByUrl = myValueSetDao.findByUrl(url); if (!optionalExistingTermValueSetByUrl.isPresent()) { - myValueSetDao.save(termValueSet); + termValueSet = myValueSetDao.save(termValueSet); } else { TermValueSet existingTermValueSet = optionalExistingTermValueSetByUrl.get(); @@ -1946,7 +1946,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, throw new UnprocessableEntityException(msg); } - ourLog.info("Done storing TermValueSet."); + ourLog.info("Done storing TermValueSet[{}]", termValueSet.getId()); } @Override diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java index 5c7fd8911f4..f4299d4be9b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java @@ -106,7 +106,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { myValueSetConceptDao.save(concept); myValueSetDao.save(myTermValueSet.incrementTotalConcepts()); - if (myConceptsSaved++ % 250 == 0) { // TODO: DM 2019-08-23 - This message never appears in the log. Fix it! + if (++myConceptsSaved % 250 == 0) { ourLog.info("Have pre-expanded {} concepts in ValueSet[{}]", myConceptsSaved, myTermValueSet.getUrl()); } @@ -131,8 +131,8 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { myValueSetConceptDesignationDao.save(designation); myValueSetDao.save(myTermValueSet.incrementTotalConceptDesignations()); - if (myDesignationsSaved++ % 250 == 0) { // TODO: DM 2019-08-23 - This message never appears in the log. Fix it! - ourLog.info("Have pre-expanded {} designations for Concept[{}|{}] in ValueSet[{}]", myDesignationsSaved, theConcept.getSystem(), theConcept.getCode(), myTermValueSet.getUrl()); + if (++myDesignationsSaved % 250 == 0) { + ourLog.debug("Have pre-expanded {} designations for Concept[{}|{}] in ValueSet[{}]", myDesignationsSaved, theConcept.getSystem(), theConcept.getCode(), myTermValueSet.getUrl()); } return designation; From 0cabc0392ffc039dd0ab770dd0ede9a289eb2978 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Fri, 6 Sep 2019 14:57:34 -0400 Subject: [PATCH 06/16] Incremental progress on large ValueSet expansion. --- .../src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 2 +- .../ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java | 6 +++++- .../ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 7 ++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index a3e93390c8e..4e40f1f67bd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -149,7 +149,7 @@ public class DaoConfig { /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code false}! */ - private boolean myPreExpandValueSetsExperimental = false; + private boolean myPreExpandValueSetsExperimental = true; // FIXME: DM 2019-09-03 - Return to false. private boolean myFilterParameterEnabled = false; private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java index 37d236fa484..202947e833f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java @@ -40,7 +40,11 @@ public interface ITermValueSetConceptDao extends JpaRepository findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); + + @Query("SELECT vsc from TermValueSetConcept vsc LEFT OUTER JOIN FETCH vsc.myDesignations WHERE vsc.myValueSetPid = :pid ORDER BY vsc.myOrder") Slice findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval") diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index 9e7a901e31f..9c8a9440436 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -541,6 +541,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, containsComponent.setDisplay(concept.getDisplay()); // TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to make this optional. + // FIXME: DM 2019-09-05 - Let's try removing the pre-fetch and the code in BaseHapiTerminologySvcImpl that handles designations so we can compare the processing time. 2/2 expandDesignations(theTermValueSet, concept, containsComponent); if (++conceptsExpanded % 250 == 0) { @@ -553,6 +554,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private void logConceptsExpanded(TermValueSet theTermValueSet, int theConceptsExpanded) { if (theConceptsExpanded > 0) { + // FIXME: DM 2019-09-05 - Account for in progress vs. total. ourLog.info("Have expanded {} concepts in ValueSet[{}]", theConceptsExpanded, theTermValueSet.getUrl()); } } @@ -578,7 +580,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private void logDesignationsExpanded(TermValueSet theValueSet, TermValueSetConcept theConcept, int theDesignationsExpanded) { if (theDesignationsExpanded > 0) { - ourLog.debug("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl()); + // FIXME: DM 2019-09-05 - Account for in progress vs. total. + // FIXME: DM 2019-09-06 - Change to debug. + ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl()); } } @@ -1818,6 +1822,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.info("Done storing TermConceptMap[{}]", termConceptMap.getId()); } + // FIXME: DM 2019-09-05 - Return to 600000 @Scheduled(fixedDelay = 600000) // 10 minutes. @Override public synchronized void preExpandDeferredValueSetsToTerminologyTables() { From 6ec991cd39275ceba1cbbaae767ad7845ec26c0c Mon Sep 17 00:00:00 2001 From: James Agnew Date: Fri, 6 Sep 2019 16:29:09 -0400 Subject: [PATCH 07/16] Finally this is fast! --- .../dao/data/ITermValueSetConceptViewDao.java | 38 +++++ .../ca/uhn/fhir/jpa/entity/TermValueSet.java | 4 +- .../fhir/jpa/entity/TermValueSetConcept.java | 30 ++-- .../TermValueSetConceptDesignation.java | 32 +++-- .../jpa/entity/TermValueSetConceptView.java | 133 ++++++++++++++++++ .../jpa/term/BaseHapiTerminologySvcImpl.java | 76 ++++++---- 6 files changed, 255 insertions(+), 58 deletions(-) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java new file mode 100644 index 00000000000..323fd286228 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java @@ -0,0 +1,38 @@ +package ca.uhn.fhir.jpa.dao.data; + +import ca.uhn.fhir.jpa.entity.ResourceSearchView; +import ca.uhn.fhir.jpa.entity.TermValueSetConceptView; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Collection; +import java.util.List; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2019 University Health Network + * %% + * 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% + */ + +public interface ITermValueSetConceptViewDao extends JpaRepository { + + @Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptOrder >= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder") + List findConceptsByValueSetPid(@Param("from") int theOffset, @Param("to") int theToIndex, @Param("pid") Long thePid); + +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java index 3a694227906..8fd89ada6d5 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java @@ -196,9 +196,7 @@ public class TermValueSet implements Serializable { @Override public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getUrl()) - .toHashCode(); + return getUrl().hashCode(); } @Override diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java index 85ebf24a0ef..52bb91878de 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java @@ -53,7 +53,7 @@ public class TermValueSetConcept implements Serializable { @Column(name = "PID") private Long myId; - @ManyToOne() + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID")) private TermValueSet myValueSet; @@ -78,9 +78,12 @@ public class TermValueSetConcept implements Serializable { @Column(name = "DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH) private String myDisplay; - @OneToMany(mappedBy = "myConcept") + @OneToMany(mappedBy = "myConcept", fetch = FetchType.LAZY) private List myDesignations; + @Transient + private transient Integer myHashCode; + public Long getId() { return myId; } @@ -169,7 +172,7 @@ public class TermValueSetConcept implements Serializable { TermValueSetConcept that = (TermValueSetConcept) theO; return new EqualsBuilder() - .append(getValueSetUrl(), that.getValueSetUrl()) + .append(myValueSetPid, that.myValueSetPid) .append(getSystem(), that.getSystem()) .append(getCode(), that.getCode()) .isEquals(); @@ -177,26 +180,29 @@ public class TermValueSetConcept implements Serializable { @Override public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getValueSetUrl()) - .append(getSystem()) - .append(getCode()) - .toHashCode(); + if (myHashCode == null) { + myHashCode = new HashCodeBuilder(17, 37) + .append(myValueSetPid) + .append(getSystem()) + .append(getCode()) + .toHashCode(); + } + return myHashCode; } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) - .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) +// .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) .append("myValueSetPid", myValueSetPid) .append("myOrder", myOrder) - .append("myValueSetUrl", this.getValueSetUrl()) - .append("myValueSetName", this.getValueSetName()) +// .append("myValueSetUrl", this.getValueSetUrl()) +// .append("myValueSetName", this.getValueSetName()) .append("mySystem", mySystem) .append("myCode", myCode) .append("myDisplay", myDisplay) - .append(myDesignations != null ? ("myDesignations - size=" + myDesignations.size()) : ("myDesignations=(null)")) +// .append(myDesignations != null ? ("myDesignations - size=" + myDesignations.size()) : ("myDesignations=(null)")) .toString(); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java index 87e5ef2e8ec..2ec11b143b1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java @@ -48,14 +48,14 @@ public class TermValueSetConceptDesignation implements Serializable { @Column(name = "PID") private Long myId; - @ManyToOne() + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "VALUESET_CONCEPT_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_CONCEPT_PID")) private TermValueSetConcept myConcept; @Column(name = "VALUESET_CONCEPT_PID", insertable = false, updatable = false, nullable = false) private Long myConceptPid; - @ManyToOne() + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VSCD_VS_PID")) private TermValueSet myValueSet; @@ -83,6 +83,9 @@ public class TermValueSetConceptDesignation implements Serializable { @Column(name = "VAL", nullable = false, length = MAX_LENGTH) private String myValue; + @Transient + private transient Integer myHashCode; + public Long getId() { return myId; } @@ -194,25 +197,28 @@ public class TermValueSetConceptDesignation implements Serializable { @Override public int hashCode() { - return new HashCodeBuilder(17, 37) - .append(getLanguage()) - .append(getUseSystem()) - .append(getUseCode()) - .append(getUseDisplay()) - .append(getValue()) - .toHashCode(); + if (myHashCode == null) { + myHashCode = new HashCodeBuilder(17, 37) + .append(getLanguage()) + .append(getUseSystem()) + .append(getUseCode()) + .append(getUseDisplay()) + .append(getValue()) + .toHashCode(); + } + return myHashCode; } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) - .append(myConcept != null ? ("myConcept - id=" + myConcept.getId()) : ("myConcept=(null)")) +// .append(myConcept != null ? ("myConcept - id=" + myConcept.getId()) : ("myConcept=(null)")) .append("myConceptPid", myConceptPid) - .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) +// .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) .append("myValueSetPid", myValueSetPid) - .append("myValueSetUrl", this.getValueSetUrl()) - .append("myValueSetName", this.getValueSetName()) +// .append("myValueSetUrl", this.getValueSetUrl()) +// .append("myValueSetName", this.getValueSetName()) .append("myLanguage", myLanguage) .append("myUseSystem", myUseSystem) .append("myUseCode", myUseCode) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java new file mode 100644 index 00000000000..5e9a13b23e5 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java @@ -0,0 +1,133 @@ +package ca.uhn.fhir.jpa.entity; + +/* + * #%L + * HAPI FHIR JPA Server + * %% + * Copyright (C) 2014 - 2019 University Health Network + * %% + * 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% + */ + +import org.hibernate.annotations.Immutable; +import org.hibernate.annotations.Subselect; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; + +@Entity +@Immutable +@Subselect("select " + + " CONCAT(vsc.PID, ' ', cd.PID) as PID," + + " vsc.PID as CONCEPT_PID, " + + " cd.PID as DESIG_PID, " + + " vsc.CODEVAL as CONCEPT_CODE, " + + " vsc.DISPLAY as CONCEPT_DISPLAY, " + + " vsc.VALUESET_ORDER as CONCEPT_ORDER, " + + " vsc.SYSTEM_URL as CONCEPT_SYSTEM_URL, " + + " vsc.VALUESET_PID as CONCEPT_VS_PID, " + +// " cd.VALUESET_CONCEPT_PID as VALUESET2_35_1_, " + + " cd.LANG as DESIG_LANG, " + + " cd.USE_CODE as DESIG_USE_CODE, " + + " cd.USE_DISPLAY as DESIG_USE_DISPLAY, " + + " cd.USE_SYSTEM as DESIG_USE_SYSTEM, " + + " cd.VAL as DESIG_VAL " + + " from TRM_VALUESET_CONCEPT vsc " + + " left outer join TRM_VALUESET_C_DESIGNATION cd on vsc.PID=cd.VALUESET_CONCEPT_PID " +// + +// " order by vsc.VALUESET_ORDER" +) +public class TermValueSetConceptView implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @Column(name="PID") + private String myPid; + @Column(name = "CONCEPT_PID") + private Long myConceptPid; + @Column(name = "DESIG_PID") + private Long myDesigPid; + @Column(name = "CONCEPT_CODE") + private String myConceptCode; + @Column(name = "CONCEPT_DISPLAY") + private String myConceptDisplay; + @Column(name = "CONCEPT_ORDER") + private int myConceptOrder; + @Column(name = "CONCEPT_SYSTEM_URL") + private String myConceptSystemUrl; + @Column(name = "CONCEPT_VS_PID") + private Long myConceptValueSetPid; + @Column(name = "DESIG_LANG") + private String myDesigLang; + @Column(name = "DESIG_USE_CODE") + private String myDesigUseCode; + @Column(name = "DESIG_USE_DISPLAY") + private String myDesigUseDisplay; + @Column(name = "DESIG_USE_SYSTEM") + private String myDesigUseSystem; + @Column(name = "DESIG_VAL") + private String myDesigVal; + + + public Long getConceptPid() { + return myConceptPid; + } + + public Long getDesigPid() { + return myDesigPid; + } + + public String getConceptCode() { + return myConceptCode; + } + + public String getConceptDisplay() { + return myConceptDisplay; + } + + public int getConceptOrder() { + return myConceptOrder; + } + + public String getConceptSystemUrl() { + return myConceptSystemUrl; + } + + public Long getConceptValueSetPid() { + return myConceptValueSetPid; + } + + public String getDesigLang() { + return myDesigLang; + } + + public String getDesigUseCode() { + return myDesigUseCode; + } + + public String getDesigUseDisplay() { + return myDesigUseDisplay; + } + + public String getDesigUseSystem() { + return myDesigUseSystem; + } + + public String getDesigVal() { + return myDesigVal; + } +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index 9c8a9440436..a2f27e09200 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -68,6 +68,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.scheduling.annotation.Scheduled; @@ -159,6 +160,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private IFulltextSearchSvc myFulltextSearchSvc; @Autowired private PlatformTransactionManager myTxManager; + @Autowired + private ITermValueSetConceptViewDao myTermValueSetConceptViewDao; private void addCodeIfNotAlreadyAdded(IValueSetConceptAccumulator theValueSetCodeAccumulator, Set theAddedCodes, TermConcept theConcept, boolean theAdd, AtomicInteger theCodeCounter) { String codeSystem = theConcept.getCodeSystemVersion().getCodeSystem().getCodeSystemUri(); @@ -528,21 +531,53 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private void expandConcepts(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) { int conceptsExpanded = 0; int toIndex = theOffset + theCount; - Slice slice = myValueSetConceptDao.findByTermValueSetIdAndPreFetchDesignations(SearchCoordinatorSvcImpl.toPage(theOffset, toIndex), theTermValueSet.getId()); - if (!slice.hasContent()) { + +// Slice slice = myValueSetConceptDao.findByTermValueSetIdAndPreFetchDesignations(SearchCoordinatorSvcImpl.toPage(theOffset, toIndex), theTermValueSet.getId()); + Pageable page = SearchCoordinatorSvcImpl.toPage(theOffset, toIndex); + Collection slice = myTermValueSetConceptViewDao.findConceptsByValueSetPid(theOffset, toIndex, theTermValueSet.getId()); + + if (slice.isEmpty()) { logConceptsExpanded(theTermValueSet, conceptsExpanded); return; } - for (TermValueSetConcept concept : slice.getContent()) { - ValueSet.ValueSetExpansionContainsComponent containsComponent = theExpansionComponent.addContains(); - containsComponent.setSystem(concept.getSystem()); - containsComponent.setCode(concept.getCode()); - containsComponent.setDisplay(concept.getDisplay()); + Map pidToConcept = new HashMap<>(); + + int designationsExpanded = 0; + for (TermValueSetConceptView concept : slice) { + + Long conceptPid = concept.getConceptPid(); + ValueSet.ValueSetExpansionContainsComponent containsComponent; + + if (!pidToConcept.containsKey(conceptPid)) { + containsComponent = theExpansionComponent.addContains(); + containsComponent.setSystem(concept.getConceptSystemUrl()); + containsComponent.setCode(concept.getConceptCode()); + containsComponent.setDisplay(concept.getConceptDisplay()); + pidToConcept.put(conceptPid, containsComponent); + } else { + containsComponent = pidToConcept.get(conceptPid); + } + + if (concept.getDesigPid() != null) { + ValueSet.ConceptReferenceDesignationComponent designationComponent = containsComponent.addDesignation(); + designationComponent.setLanguage(concept.getDesigLang()); + designationComponent.setUse(new Coding( + concept.getDesigUseSystem(), + concept.getDesigUseCode(), + concept.getDesigUseDisplay())); + designationComponent.setValue(concept.getDesigVal()); + + if (++designationsExpanded % 250 == 0) { + logDesignationsExpanded(theTermValueSet, designationsExpanded); + } + + logDesignationsExpanded(theTermValueSet, designationsExpanded); + } // TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to make this optional. // FIXME: DM 2019-09-05 - Let's try removing the pre-fetch and the code in BaseHapiTerminologySvcImpl that handles designations so we can compare the processing time. 2/2 - expandDesignations(theTermValueSet, concept, containsComponent); +// expandDesignations(theTermValueSet, concept, containsComponent); if (++conceptsExpanded % 250 == 0) { logConceptsExpanded(theTermValueSet, conceptsExpanded); @@ -559,30 +594,11 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, } } - private void expandDesignations(TermValueSet theValueSet, TermValueSetConcept theConcept, ValueSet.ValueSetExpansionContainsComponent theContainsComponent) { - int designationsExpanded = 0; - for (TermValueSetConceptDesignation designation : theConcept.getDesignations()) { - ValueSet.ConceptReferenceDesignationComponent designationComponent = theContainsComponent.addDesignation(); - designationComponent.setLanguage(designation.getLanguage()); - designationComponent.setUse(new Coding( - designation.getUseSystem(), - designation.getUseCode(), - designation.getUseDisplay())); - designationComponent.setValue(designation.getValue()); - - if (++designationsExpanded % 250 == 0) { - logDesignationsExpanded(theValueSet, theConcept, designationsExpanded); - } - } - - logDesignationsExpanded(theValueSet, theConcept, designationsExpanded); - } - - private void logDesignationsExpanded(TermValueSet theValueSet, TermValueSetConcept theConcept, int theDesignationsExpanded) { + private void logDesignationsExpanded(TermValueSet theValueSet, int theDesignationsExpanded) { if (theDesignationsExpanded > 0) { // FIXME: DM 2019-09-05 - Account for in progress vs. total. // FIXME: DM 2019-09-06 - Change to debug. - ourLog.info("Have expanded {} designations for Concept[{}|{}] in ValueSet[{}]", theDesignationsExpanded, theConcept.getSystem(), theConcept.getCode(), theValueSet.getUrl()); + ourLog.info("Have expanded {} designations in ValueSet[{}]", theDesignationsExpanded, theValueSet.getUrl()); } } @@ -972,7 +988,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, if (theCoding.hasSystem() && theCoding.hasCode()) { concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, theCoding.getSystem(), theCoding.getCode())); } - } else if (theCodeableConcept != null){ + } else if (theCodeableConcept != null) { for (Coding coding : theCodeableConcept.getCoding()) { if (coding.hasSystem() && coding.hasCode()) { concepts.addAll(findByValueSetResourcePidSystemAndCode(valueSetResourcePid, coding.getSystem(), coding.getCode())); From 4fc0ad6f0a6db22cfda8fc16ac4010058a959594 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Fri, 6 Sep 2019 17:56:56 -0400 Subject: [PATCH 08/16] Cleanup following paired programming with JA. --- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 2 +- .../jpa/dao/data/ITermValueSetConceptDao.java | 9 -- .../dao/data/ITermValueSetConceptViewDao.java | 5 +- .../ca/uhn/fhir/jpa/entity/TermValueSet.java | 11 +- .../fhir/jpa/entity/TermValueSetConcept.java | 8 +- .../TermValueSetConceptDesignation.java | 8 +- .../jpa/entity/TermValueSetConceptView.java | 121 +++++++++--------- .../jpa/term/BaseHapiTerminologySvcImpl.java | 67 ++++------ 8 files changed, 107 insertions(+), 124 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 4e40f1f67bd..996949bb7c3 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -149,7 +149,7 @@ public class DaoConfig { /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code false}! */ - private boolean myPreExpandValueSetsExperimental = true; // FIXME: DM 2019-09-03 - Return to false. + private boolean myPreExpandValueSetsExperimental = true; // FIXME: DM 2019-09-03 - Return to false before merging into master. private boolean myFilterParameterEnabled = false; private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java index 202947e833f..37fe6e45fb0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java @@ -21,8 +21,6 @@ package ca.uhn.fhir.jpa.dao.data; */ import ca.uhn.fhir.jpa.entity.TermValueSetConcept; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -40,13 +38,6 @@ public interface ITermValueSetConceptDao extends JpaRepository findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); - - @Query("SELECT vsc from TermValueSetConcept vsc LEFT OUTER JOIN FETCH vsc.myDesignations WHERE vsc.myValueSetPid = :pid ORDER BY vsc.myOrder") - Slice findByTermValueSetIdAndPreFetchDesignations(Pageable thePage, @Param("pid") Long theValueSetId); - @Query("SELECT vsc FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid AND vsc.mySystem = :system_url AND vsc.myCode = :codeval") Optional findByTermValueSetIdSystemAndCode(@Param("pid") Long theValueSetId, @Param("system_url") String theSystem, @Param("codeval") String theCode); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java index 323fd286228..ee7ec6b300b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptViewDao.java @@ -1,13 +1,10 @@ package ca.uhn.fhir.jpa.dao.data; -import ca.uhn.fhir.jpa.entity.ResourceSearchView; import ca.uhn.fhir.jpa.entity.TermValueSetConceptView; -import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import java.util.Collection; import java.util.List; /* @@ -33,6 +30,6 @@ import java.util.List; public interface ITermValueSetConceptViewDao extends JpaRepository { @Query("SELECT v FROM TermValueSetConceptView v WHERE v.myConceptValueSetPid = :pid AND v.myConceptOrder >= :from AND v.myConceptOrder < :to ORDER BY v.myConceptOrder") - List findConceptsByValueSetPid(@Param("from") int theOffset, @Param("to") int theToIndex, @Param("pid") Long thePid); + List findByTermValueSetId(@Param("from") int theFrom, @Param("to") int theTo, @Param("pid") Long theValueSetId); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java index 8fd89ada6d5..34cf7546e54 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSet.java @@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.entity; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.util.ValidateUtil; 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.hibernate.annotations.ColumnDefault; @@ -67,7 +66,7 @@ public class TermValueSet implements Serializable { @Column(name = "VSNAME", nullable = true, length = MAX_NAME_LENGTH) private String myName; - @OneToMany(mappedBy = "myValueSet") + @OneToMany(mappedBy = "myValueSet", fetch = FetchType.LAZY) private List myConcepts; @Column(name = "TOTAL_CONCEPTS", nullable = false) @@ -82,6 +81,9 @@ public class TermValueSet implements Serializable { @Column(name = "EXPANSION_STATUS", nullable = false, length = MAX_EXPANSION_STATUS_LENGTH) private TermValueSetPreExpansionStatusEnum myExpansionStatus; + @Transient + private transient Integer myHashCode; + public TermValueSet() { super(); myExpansionStatus = TermValueSetPreExpansionStatusEnum.NOT_EXPANDED; @@ -196,7 +198,10 @@ public class TermValueSet implements Serializable { @Override public int hashCode() { - return getUrl().hashCode(); + if (myHashCode == null) { + myHashCode = getUrl().hashCode(); + } + return myHashCode; } @Override diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java index 52bb91878de..e219439239f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConcept.java @@ -194,15 +194,15 @@ public class TermValueSetConcept implements Serializable { public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) -// .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) + .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) .append("myValueSetPid", myValueSetPid) .append("myOrder", myOrder) -// .append("myValueSetUrl", this.getValueSetUrl()) -// .append("myValueSetName", this.getValueSetName()) + .append("myValueSetUrl", this.getValueSetUrl()) + .append("myValueSetName", this.getValueSetName()) .append("mySystem", mySystem) .append("myCode", myCode) .append("myDisplay", myDisplay) -// .append(myDesignations != null ? ("myDesignations - size=" + myDesignations.size()) : ("myDesignations=(null)")) + .append(myDesignations != null ? ("myDesignations - size=" + myDesignations.size()) : ("myDesignations=(null)")) .toString(); } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java index 2ec11b143b1..f418c76172f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptDesignation.java @@ -213,12 +213,12 @@ public class TermValueSetConceptDesignation implements Serializable { public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("myId", myId) -// .append(myConcept != null ? ("myConcept - id=" + myConcept.getId()) : ("myConcept=(null)")) + .append(myConcept != null ? ("myConcept - id=" + myConcept.getId()) : ("myConcept=(null)")) .append("myConceptPid", myConceptPid) -// .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) + .append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)")) .append("myValueSetPid", myValueSetPid) -// .append("myValueSetUrl", this.getValueSetUrl()) -// .append("myValueSetName", this.getValueSetName()) + .append("myValueSetUrl", this.getValueSetUrl()) + .append("myValueSetName", this.getValueSetName()) .append("myLanguage", myLanguage) .append("myUseSystem", myUseSystem) .append("myUseCode", myUseCode) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java index 5e9a13b23e5..df7fe29f2e8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java @@ -30,25 +30,22 @@ import java.io.Serializable; @Entity @Immutable -@Subselect("select " + - " CONCAT(vsc.PID, ' ', cd.PID) as PID," + - " vsc.PID as CONCEPT_PID, " + - " cd.PID as DESIG_PID, " + - " vsc.CODEVAL as CONCEPT_CODE, " + - " vsc.DISPLAY as CONCEPT_DISPLAY, " + - " vsc.VALUESET_ORDER as CONCEPT_ORDER, " + - " vsc.SYSTEM_URL as CONCEPT_SYSTEM_URL, " + - " vsc.VALUESET_PID as CONCEPT_VS_PID, " + -// " cd.VALUESET_CONCEPT_PID as VALUESET2_35_1_, " + - " cd.LANG as DESIG_LANG, " + - " cd.USE_CODE as DESIG_USE_CODE, " + - " cd.USE_DISPLAY as DESIG_USE_DISPLAY, " + - " cd.USE_SYSTEM as DESIG_USE_SYSTEM, " + - " cd.VAL as DESIG_VAL " + - " from TRM_VALUESET_CONCEPT vsc " + - " left outer join TRM_VALUESET_C_DESIGNATION cd on vsc.PID=cd.VALUESET_CONCEPT_PID " -// + -// " order by vsc.VALUESET_ORDER" +@Subselect( + "SELECT CONCAT(vsc.PID, ' ', vscd.PID) AS PID, " + + " vsc.PID AS CONCEPT_PID, " + + " vsc.VALUESET_PID AS CONCEPT_VALUESET_PID, " + + " vsc.VALUESET_ORDER AS CONCEPT_VALUESET_ORDER, " + + " vsc.SYSTEM_URL AS CONCEPT_SYSTEM_URL, " + + " vsc.CODEVAL AS CONCEPT_CODEVAL, " + + " vsc.DISPLAY AS CONCEPT_DISPLAY, " + + " vscd.PID AS DESIGNATION_PID, " + + " vscd.LANG AS DESIGNATION_LANG, " + + " vscd.USE_SYSTEM AS DESIGNATION_USE_SYSTEM, " + + " vscd.USE_CODE AS DESIGNATION_USE_CODE, " + + " vscd.USE_DISPLAY AS DESIGNATION_USE_DISPLAY, " + + " vscd.VAL AS DESIGNATION_VAL " + + "FROM TRM_VALUESET_CONCEPT vsc " + + " LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID" ) public class TermValueSetConceptView implements Serializable { @@ -57,38 +54,50 @@ public class TermValueSetConceptView implements Serializable { @Id @Column(name="PID") private String myPid; + @Column(name = "CONCEPT_PID") private Long myConceptPid; - @Column(name = "DESIG_PID") - private Long myDesigPid; - @Column(name = "CONCEPT_CODE") - private String myConceptCode; - @Column(name = "CONCEPT_DISPLAY") - private String myConceptDisplay; - @Column(name = "CONCEPT_ORDER") + + @Column(name = "CONCEPT_VALUESET_PID") + private Long myConceptValueSetPid; + + @Column(name = "CONCEPT_VALUESET_ORDER") private int myConceptOrder; + @Column(name = "CONCEPT_SYSTEM_URL") private String myConceptSystemUrl; - @Column(name = "CONCEPT_VS_PID") - private Long myConceptValueSetPid; - @Column(name = "DESIG_LANG") - private String myDesigLang; - @Column(name = "DESIG_USE_CODE") - private String myDesigUseCode; - @Column(name = "DESIG_USE_DISPLAY") - private String myDesigUseDisplay; - @Column(name = "DESIG_USE_SYSTEM") - private String myDesigUseSystem; - @Column(name = "DESIG_VAL") - private String myDesigVal; + + @Column(name = "CONCEPT_CODEVAL") + private String myConceptCode; + + @Column(name = "CONCEPT_DISPLAY") + private String myConceptDisplay; + + @Column(name = "DESIGNATION_PID") + private Long myDesignationPid; + + @Column(name = "DESIGNATION_LANG") + private String myDesignationLang; + + @Column(name = "DESIGNATION_USE_SYSTEM") + private String myDesignationUseSystem; + + @Column(name = "DESIGNATION_USE_CODE") + private String myDesignationUseCode; + + @Column(name = "DESIGNATION_USE_DISPLAY") + private String myDesignationUseDisplay; + + @Column(name = "DESIGNATION_VAL") + private String myDesignationVal; public Long getConceptPid() { return myConceptPid; } - public Long getDesigPid() { - return myDesigPid; + public String getConceptSystemUrl() { + return myConceptSystemUrl; } public String getConceptCode() { @@ -99,35 +108,27 @@ public class TermValueSetConceptView implements Serializable { return myConceptDisplay; } - public int getConceptOrder() { - return myConceptOrder; + public Long getDesignationPid() { + return myDesignationPid; } - public String getConceptSystemUrl() { - return myConceptSystemUrl; + public String getDesignationLang() { + return myDesignationLang; } - public Long getConceptValueSetPid() { - return myConceptValueSetPid; + public String getDesignationUseSystem() { + return myDesignationUseSystem; } - public String getDesigLang() { - return myDesigLang; + public String getDesignationUseCode() { + return myDesignationUseCode; } - public String getDesigUseCode() { - return myDesigUseCode; + public String getDesignationUseDisplay() { + return myDesignationUseDisplay; } - public String getDesigUseDisplay() { - return myDesigUseDisplay; - } - - public String getDesigUseSystem() { - return myDesigUseSystem; - } - - public String getDesigVal() { - return myDesigVal; + public String getDesignationVal() { + return myDesignationVal; } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index a2f27e09200..a149226868d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -28,7 +28,6 @@ import ca.uhn.fhir.jpa.dao.data.*; import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.model.entity.ResourceTable; -import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.util.ScrollableResultsIterator; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; @@ -68,7 +67,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.scheduling.annotation.Scheduled; @@ -530,75 +528,64 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, private void expandConcepts(ValueSet.ValueSetExpansionComponent theExpansionComponent, TermValueSet theTermValueSet, int theOffset, int theCount) { int conceptsExpanded = 0; + int designationsExpanded = 0; int toIndex = theOffset + theCount; + Collection conceptViews = myTermValueSetConceptViewDao.findByTermValueSetId(theOffset, toIndex, theTermValueSet.getId()); -// Slice slice = myValueSetConceptDao.findByTermValueSetIdAndPreFetchDesignations(SearchCoordinatorSvcImpl.toPage(theOffset, toIndex), theTermValueSet.getId()); - Pageable page = SearchCoordinatorSvcImpl.toPage(theOffset, toIndex); - Collection slice = myTermValueSetConceptViewDao.findConceptsByValueSetPid(theOffset, toIndex, theTermValueSet.getId()); - - if (slice.isEmpty()) { - logConceptsExpanded(theTermValueSet, conceptsExpanded); + if (conceptViews.isEmpty()) { + logConceptsExpanded("No concepts to expand. ", theTermValueSet, conceptsExpanded); return; } Map pidToConcept = new HashMap<>(); + for (TermValueSetConceptView conceptView : conceptViews) { - int designationsExpanded = 0; - for (TermValueSetConceptView concept : slice) { - - Long conceptPid = concept.getConceptPid(); + Long conceptPid = conceptView.getConceptPid(); ValueSet.ValueSetExpansionContainsComponent containsComponent; if (!pidToConcept.containsKey(conceptPid)) { containsComponent = theExpansionComponent.addContains(); - containsComponent.setSystem(concept.getConceptSystemUrl()); - containsComponent.setCode(concept.getConceptCode()); - containsComponent.setDisplay(concept.getConceptDisplay()); + containsComponent.setSystem(conceptView.getConceptSystemUrl()); + containsComponent.setCode(conceptView.getConceptCode()); + containsComponent.setDisplay(conceptView.getConceptDisplay()); pidToConcept.put(conceptPid, containsComponent); } else { containsComponent = pidToConcept.get(conceptPid); } - if (concept.getDesigPid() != null) { + // TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to designations optional. + if (conceptView.getDesignationPid() != null) { ValueSet.ConceptReferenceDesignationComponent designationComponent = containsComponent.addDesignation(); - designationComponent.setLanguage(concept.getDesigLang()); + designationComponent.setLanguage(conceptView.getDesignationLang()); designationComponent.setUse(new Coding( - concept.getDesigUseSystem(), - concept.getDesigUseCode(), - concept.getDesigUseDisplay())); - designationComponent.setValue(concept.getDesigVal()); + conceptView.getDesignationUseSystem(), + conceptView.getDesignationUseCode(), + conceptView.getDesignationUseDisplay())); + designationComponent.setValue(conceptView.getDesignationVal()); if (++designationsExpanded % 250 == 0) { - logDesignationsExpanded(theTermValueSet, designationsExpanded); + logDesignationsExpanded("Expansion of designations in progress. ", theTermValueSet, designationsExpanded); } - - logDesignationsExpanded(theTermValueSet, designationsExpanded); } - // TODO: DM 2019-08-17 - Implement includeDesignations parameter for $expand operation to make this optional. - // FIXME: DM 2019-09-05 - Let's try removing the pre-fetch and the code in BaseHapiTerminologySvcImpl that handles designations so we can compare the processing time. 2/2 -// expandDesignations(theTermValueSet, concept, containsComponent); - if (++conceptsExpanded % 250 == 0) { - logConceptsExpanded(theTermValueSet, conceptsExpanded); + logConceptsExpanded("Expansion of concepts in progress. ", theTermValueSet, conceptsExpanded); } } - logConceptsExpanded(theTermValueSet, conceptsExpanded); + logDesignationsExpanded("Finished expanding designations. ", theTermValueSet, designationsExpanded); + logConceptsExpanded("Finished expanding concepts. ", theTermValueSet, conceptsExpanded); } - private void logConceptsExpanded(TermValueSet theTermValueSet, int theConceptsExpanded) { + private void logConceptsExpanded(String thePrefix, TermValueSet theTermValueSet, int theConceptsExpanded) { if (theConceptsExpanded > 0) { - // FIXME: DM 2019-09-05 - Account for in progress vs. total. - ourLog.info("Have expanded {} concepts in ValueSet[{}]", theConceptsExpanded, theTermValueSet.getUrl()); + ourLog.info("{}Have expanded {} concepts in ValueSet[{}]", thePrefix, theConceptsExpanded, theTermValueSet.getUrl()); } } - private void logDesignationsExpanded(TermValueSet theValueSet, int theDesignationsExpanded) { + private void logDesignationsExpanded(String thePrefix, TermValueSet theTermValueSet, int theDesignationsExpanded) { if (theDesignationsExpanded > 0) { - // FIXME: DM 2019-09-05 - Account for in progress vs. total. - // FIXME: DM 2019-09-06 - Change to debug. - ourLog.info("Have expanded {} designations in ValueSet[{}]", theDesignationsExpanded, theValueSet.getUrl()); + ourLog.info("{}Have expanded {} designations in ValueSet[{}]", thePrefix, theDesignationsExpanded, theTermValueSet.getUrl()); } } @@ -646,6 +633,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, } } + // FIXME: DM 2019-09-06 - After handling excludes, we need to adjust TermValueSetConcept.myOrder to account for any gaps. + ourLog.info("Done working with {} in {}ms", valueSetInfo, sw.getMillis()); } @@ -1838,8 +1827,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.info("Done storing TermConceptMap[{}]", termConceptMap.getId()); } - // FIXME: DM 2019-09-05 - Return to 600000 - @Scheduled(fixedDelay = 600000) // 10 minutes. + // FIXME: DM 2019-09-05 - Return to 600000 before merging into master. + @Scheduled(fixedDelay = 6000) // 10 minutes. @Override public synchronized void preExpandDeferredValueSetsToTerminologyTables() { if (isNotSafeToPreExpandValueSets()) { From c82c3a093f3e3fd54a5208a496e4b339a6c48abd Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 9 Sep 2019 15:24:37 -0400 Subject: [PATCH 09/16] Removing gaps from concept order when pre-expanding ValueSets. --- .../jpa/dao/data/ITermValueSetConceptDao.java | 7 +++++ .../jpa/term/BaseHapiTerminologySvcImpl.java | 12 ++++---- .../jpa/term/ValueSetConceptAccumulator.java | 29 +++++++++++++++++-- .../jpa/term/TerminologySvcImplR4Test.java | 16 +++++----- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java index 37fe6e45fb0..4cb025ae4aa 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/data/ITermValueSetConceptDao.java @@ -46,4 +46,11 @@ public interface ITermValueSetConceptDao extends JpaRepository findByValueSetResourcePidSystemAndCode(@Param("resource_pid") Long theValueSetId, @Param("system_url") String theSystem, @Param("codeval") String theCode); + + @Query("SELECT vsc.myId FROM TermValueSetConcept vsc WHERE vsc.myValueSetPid = :pid ORDER BY vsc.myId") + List findIdsByTermValueSetId(@Param("pid") Long theValueSetId); + + @Query("UPDATE TermValueSetConcept vsc SET vsc.myOrder = :order WHERE vsc.myId = :pid") + @Modifying + void updateOrderById(@Param("pid") Long theId, @Param("order") int theOrder); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index a149226868d..0887a04f6bd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -607,10 +607,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.debug("Handling includes"); for (ValueSet.ConceptSetComponent include : theValueSetToExpand.getCompose().getInclude()) { for (int i = 0; ; i++) { - int finalI = i; + int queryIndex = i; Boolean shouldContinue = myTxTemplate.execute(t -> { boolean add = true; - return expandValueSetHandleIncludeOrExclude(theValueSetCodeAccumulator, addedCodes, include, add, theCodeCounter, finalI); + return expandValueSetHandleIncludeOrExclude(theValueSetCodeAccumulator, addedCodes, include, add, theCodeCounter, queryIndex); }); if (!shouldContinue) { break; @@ -622,10 +622,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.debug("Handling excludes"); for (ValueSet.ConceptSetComponent exclude : theValueSetToExpand.getCompose().getExclude()) { for (int i = 0; ; i++) { - int finalI = i; + int queryIndex = i; Boolean shouldContinue = myTxTemplate.execute(t -> { boolean add = false; - return expandValueSetHandleIncludeOrExclude(theValueSetCodeAccumulator, addedCodes, exclude, add, theCodeCounter, finalI); + return expandValueSetHandleIncludeOrExclude(theValueSetCodeAccumulator, addedCodes, exclude, add, theCodeCounter, queryIndex); }); if (!shouldContinue) { break; @@ -633,7 +633,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, } } - // FIXME: DM 2019-09-06 - After handling excludes, we need to adjust TermValueSetConcept.myOrder to account for any gaps. + if (theValueSetCodeAccumulator instanceof ValueSetConceptAccumulator) { + myTxTemplate.execute(t -> ((ValueSetConceptAccumulator) theValueSetCodeAccumulator).removeGapsFromConceptOrder()); + } ourLog.info("Done working with {} in {}ms", valueSetInfo, sw.getMillis()); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java index f4299d4be9b..0cbb6ff4e69 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java @@ -31,6 +31,7 @@ import ca.uhn.fhir.util.ValidateUtil; import javax.annotation.Nonnull; import java.util.Collection; +import java.util.List; import java.util.Optional; import static org.apache.commons.lang3.StringUtils.*; @@ -44,6 +45,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { private ITermValueSetConceptDesignationDao myValueSetConceptDesignationDao; private int myConceptsSaved; private int myDesignationsSaved; + private int myConceptsExcluded; public ValueSetConceptAccumulator(@Nonnull TermValueSet theTermValueSet, @Nonnull ITermValueSetDao theValueSetDao, @Nonnull ITermValueSetConceptDao theValueSetConceptDao, @Nonnull ITermValueSetConceptDesignationDao theValueSetConceptDesignationDao) { myTermValueSet = theTermValueSet; @@ -52,6 +54,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { myValueSetConceptDesignationDao = theValueSetConceptDesignationDao; myConceptsSaved = 0; myDesignationsSaved = 0; + myConceptsExcluded = 0; } @Override @@ -88,6 +91,10 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { myTermValueSet.decrementTotalConcepts(); myValueSetDao.save(myTermValueSet); ourLog.info("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl()); + + if (++myConceptsExcluded % 250 == 0) { + ourLog.info("Have excluded {} concepts from ValueSet[{}]", myConceptsExcluded, myTermValueSet.getUrl()); + } } } @@ -138,7 +145,23 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { return designation; } - // TODO: DM 2019-07-16 - We need TermValueSetConceptProperty, similar to TermConceptProperty. - // TODO: DM 2019-07-16 - We should also populate TermValueSetConceptProperty entities here. - // TODO: DM 2019-07-30 - Expansions don't include the properties themselves; they are needed to facilitate filters and parameterized expansions. + public Boolean removeGapsFromConceptOrder() { + if (myConceptsExcluded <= 0) { + return false; + } + + ourLog.info("Removing gaps from concept order for ValueSet[{}]", myTermValueSet.getUrl()); + int order = 0; + List conceptIds = myValueSetConceptDao.findIdsByTermValueSetId(myTermValueSet.getId()); + for (Long conceptId : conceptIds) { + myValueSetConceptDao.updateOrderById(conceptId, order++); + } + ourLog.info("Have remove gaps from concept order for {} concepts in ValueSet[{}]", conceptIds.size(), myTermValueSet.getUrl()); + + return true; + } + + // TODO: DM 2019-07-16 - We may need TermValueSetConceptProperty, similar to TermConceptProperty. + // TODO: DM 2019-07-16 - If so, we should also populate TermValueSetConceptProperty entities here. + // TODO: DM 2019-07-30 - Expansions don't include the properties themselves; they may be needed to facilitate filters and parameterized expansions. } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java index 972fa9eda81..e108f2b8457 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java @@ -2332,13 +2332,13 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { // ... - concept = termValueSet.getConcepts().get(22 - 2); + concept = termValueSet.getConcepts().get(20); ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); - assertEquals(22, concept.getOrder()); + assertEquals(20, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2347,13 +2347,13 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Synonym", designation.getUseDisplay()); assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); - concept = termValueSet.getConcepts().get(23 - 2); + concept = termValueSet.getConcepts().get(21); ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); - assertEquals(23, concept.getOrder()); + assertEquals(21, concept.getOrder()); }); } @@ -2434,13 +2434,13 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { // ... - concept = termValueSet.getConcepts().get(22 - 2); + concept = termValueSet.getConcepts().get(20); ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8491-3", concept.getCode()); assertEquals("Systolic blood pressure 1 hour minimum", concept.getDisplay()); assertEquals(1, concept.getDesignations().size()); - assertEquals(22, concept.getOrder()); + assertEquals(20, concept.getOrder()); designation = concept.getDesignations().get(0); assertEquals("nl", designation.getLanguage()); @@ -2449,13 +2449,13 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Synonym", designation.getUseDisplay()); assertEquals("Systolische bloeddruk minimaal 1 uur", designation.getValue()); - concept = termValueSet.getConcepts().get(23 - 2); + concept = termValueSet.getConcepts().get(21); ourLog.info("Concept:\n" + concept.toString()); assertEquals("http://acme.org", concept.getSystem()); assertEquals("8492-1", concept.getCode()); assertEquals("Systolic blood pressure 8 hour minimum", concept.getDisplay()); assertEquals(0, concept.getDesignations().size()); - assertEquals(23, concept.getOrder()); + assertEquals(21, concept.getOrder()); }); } From 19676a01b728ba983e04338ec699d400080699d3 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 9 Sep 2019 17:24:01 -0400 Subject: [PATCH 10/16] Incremental progress on large ValueSet expansion with URL parameter. --- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 6 +- .../fhir/jpa/term/HapiTerminologySvcR4.java | 2 +- .../jpa/term/ValueSetConceptAccumulator.java | 2 +- .../r4/ResourceProviderR4ValueSetTest.java | 245 +++++++++++++++--- 4 files changed, 218 insertions(+), 37 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 996949bb7c3..32a8f556bb9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -146,12 +146,12 @@ public class DaoConfig { private boolean myEnableInMemorySubscriptionMatching = true; private boolean myEnforceReferenceTargetTypes = true; private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC; + private boolean myFilterParameterEnabled = false; + private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code false}! */ - private boolean myPreExpandValueSetsExperimental = true; // FIXME: DM 2019-09-03 - Return to false before merging into master. - private boolean myFilterParameterEnabled = false; - private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID; + private boolean myPreExpandValueSetsExperimental = false; /** * EXPERIMENTAL - Do not use in production! Do not change default of {@code 0}! */ diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java index a7e3d60e8e7..e9498856f14 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java @@ -121,7 +121,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements } @Override - public List expandValueSet(String theValueSet) { + public List expandValueSet(String theValueSet) {//FIXME: DM COWABUNGA ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { return Collections.emptyList(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java index 0cbb6ff4e69..55a8d2e5b8f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/ValueSetConceptAccumulator.java @@ -156,7 +156,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator { for (Long conceptId : conceptIds) { myValueSetConceptDao.updateOrderById(conceptId, order++); } - ourLog.info("Have remove gaps from concept order for {} concepts in ValueSet[{}]", conceptIds.size(), myTermValueSet.getUrl()); + ourLog.info("Have removed gaps from concept order for {} concepts in ValueSet[{}]", conceptIds.size(), myTermValueSet.getUrl()); return true; } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java index 7a69fd83b55..e29ae2a327b 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.provider.r4; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; @@ -24,10 +25,13 @@ import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r4.model.ValueSet.FilterOperator; +import org.hl7.fhir.r4.model.codesystems.HttpVerb; +import org.junit.After; import org.junit.AfterClass; -import org.junit.Before; import org.junit.Test; -import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -40,18 +44,86 @@ import static org.junit.Assert.*; public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4ValueSetTest.class); + private IIdType myExtensionalCsId; private IIdType myExtensionalVsId; private IIdType myLocalValueSetId; + private Long myExtensionalCsIdOnResourceTable; + private Long myExtensionalVsIdOnResourceTable; private ValueSet myLocalVs; - @Before - @Transactional - public void before02() throws IOException { - CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); - myCodeSystemDao.create(cs, mySrd); +// @Before +// @Transactional +// public void before02() throws IOException { +// CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); +// myCodeSystemDao.create(cs, mySrd); +// +// ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); +// myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); +// } - ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); - myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); + private void loadAndPersistCodeSystemAndValueSet(HttpVerb theVerb) throws IOException { + loadAndPersistCodeSystem(theVerb); + loadAndPersistValueSet(theVerb); + } + + private void loadAndPersistCodeSystem(HttpVerb theVerb) throws IOException { + CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); + codeSystem.setId("CodeSystem/cs"); + persistCodeSystem(codeSystem, theVerb); + } + + private void persistCodeSystem(CodeSystem theCodeSystem, HttpVerb theVerb) { + switch (theVerb) { + case POST: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + case PUT: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalCsId = myCodeSystemDao.update(theCodeSystem, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + default: + throw new IllegalArgumentException("HTTP verb is not supported: " + theVerb); + } + myExtensionalCsIdOnResourceTable = myCodeSystemDao.readEntity(myExtensionalCsId, null).getId(); + } + + private void loadAndPersistValueSet(HttpVerb theVerb) throws IOException { + ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); + valueSet.setId("ValueSet/vs"); + persistValueSet(valueSet, theVerb); + } + + private void persistValueSet(ValueSet theValueSet, HttpVerb theVerb) { + switch (theVerb) { + case POST: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalVsId = myValueSetDao.create(theValueSet, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + case PUT: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalVsId = myValueSetDao.update(theValueSet, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + default: + throw new IllegalArgumentException("HTTP verb is not supported: " + theVerb); + } + myExtensionalVsIdOnResourceTable = myValueSetDao.readEntity(myExtensionalVsId, null).getId(); } private CodeSystem createExternalCs() { @@ -128,8 +200,9 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testExpandById() { - //@formatter:off + public void testExpandById() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -137,7 +210,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -158,9 +230,42 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testExpandByIdWithFilter() { + public void testExpandByIdWithPreExpansion() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + Parameters respParam = ourClient + .operation() + .onInstance(myExtensionalVsId) + .named("expand") + .withNoParameters(Parameters.class) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + assertThat(resp, containsString("")); + + } + + @Test + public void testExpandByIdWithFilter() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -168,7 +273,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withParameter(Parameters.class, "filter", new StringType("first")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -178,12 +282,64 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testExpandByUrl() { + public void testExpandByIdWithFilterWithPreExpansion() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + Parameters respParam = ourClient + .operation() + .onInstance(myExtensionalVsId) + .named("expand") + .withParameter(Parameters.class, "filter", new StringType("first")) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, containsString("")); + assertThat(resp, not(containsString(""))); + + } + + @Test + public void testExpandByUrl() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("expand") - .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) +// .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) //FIXME: DM + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, stringContainsInOrder( + "", + "")); + + } + + @Test + public void testExpandByUrlWithPreExpansion() throws Exception {//FIXME: DM + myDaoConfig.setPreExpandValueSetsExperimental(true); + + ourLog.info("DIEDERIK - before loading CD and VS"); + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + ourLog.info("DIEDERIK - after loading CD and VS; before pre-expansion"); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + ourLog.info("DIEDERIK - after pre-expansion"); + + Parameters respParam = ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + // .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) //FIXME: DM + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); @@ -197,6 +353,8 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { @Test public void testExpandByValueSet() throws IOException { + loadAndPersistCodeSystem(HttpVerb.POST); + ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); Parameters respParam = ourClient @@ -215,13 +373,36 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } + @Test + public void testExpandByValueSetWithPreExpansion() throws IOException { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystem(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); + + Parameters respParam = ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "valueSet", toExpand) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, stringContainsInOrder( + "", + "")); + + } @Test public void testExpandInlineVsAgainstBuiltInCs() { createLocalVsPointingAtBuiltInCodeSystem(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -229,7 +410,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withParameter(Parameters.class, "valueSet", myLocalVs) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -243,7 +423,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { assertNotNull(myLocalVs); myLocalVs.setId(""); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -251,7 +430,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withParameter(Parameters.class, "valueSet", myLocalVs) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -263,7 +441,9 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testExpandInvalidParams() throws IOException { + public void testExpandInvalidParams() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + try { ourClient .operation() @@ -334,7 +514,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { createLocalVsPointingAtBuiltInCodeSystem(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myLocalValueSetId) @@ -342,7 +521,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -355,7 +533,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { createExternalCsAndLocalVs(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myLocalValueSetId) @@ -363,7 +540,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -401,7 +577,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { createExternalCsAndLocalVsWithUnknownCode(); assertNotNull(myLocalValueSetId); - //@formatter:off try { ourClient .operation() @@ -412,7 +587,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: Invalid filter criteria - code does not exist: {http://example.com/my_code_system}childFOOOOOOO", e.getMessage()); } - //@formatter:on } /** @@ -438,8 +612,9 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testValidateCodeOperationByCodeAndSystemInstance() { - //@formatter:off + public void testValidateCodeOperationByCodeAndSystemInstance() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -498,8 +673,9 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testValidateCodeOperationByCodeAndSystemType() { - //@formatter:off + public void testValidateCodeOperationByCodeAndSystemType() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -585,6 +761,11 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } + @After + public void afterResetPreExpansionDefault() { + myDaoConfig.setPreExpandValueSetsExperimental(new DaoConfig().isPreExpandValueSetsExperimental()); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); From 2052df315297201940a7db140b1f03019c6fb291 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Mon, 9 Sep 2019 18:01:41 -0400 Subject: [PATCH 11/16] Error with a 404 on invalid valueset --- .../ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 7 ++++++- .../java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java | 2 +- .../java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java | 2 +- .../java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index 0887a04f6bd..fe562f4298c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -32,9 +32,11 @@ import ca.uhn.fhir.jpa.util.ScrollableResultsIterator; import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.ObjectUtil; import ca.uhn.fhir.util.StopWatch; +import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.ValidateUtil; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; @@ -487,7 +489,6 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, if (!optionalTermValueSet.isPresent()) { ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory expansion without parameters. Will schedule this ValueSet for pre-expansion. {}", getValueSetInfo(theValueSetToExpand)); - myDeferredValueSets.add(theValueSetToExpand); return expandValueSet(theValueSetToExpand); // In-memory expansion. } @@ -2366,6 +2367,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, return retVal; } + protected void throwInvalidValueSet(String theValueSet) { + throw new ResourceNotFoundException("Unknown ValueSet: " + UrlUtil.escapeUrlParam(theValueSet)); + } + private static void extractLinksFromConceptAndChildren(TermConcept theConcept, List theLinks) { theLinks.addAll(theConcept.getParents()); for (TermConceptParentChildLink child : theConcept.getChildren()) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java index 0070469c00f..e50a2fecb7c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java @@ -212,7 +212,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen public List expandValueSet(String theValueSet) { ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { - return Collections.emptyList(); + super.throwInvalidValueSet(theValueSet); } org.hl7.fhir.r4.model.ValueSet valueSetToExpandR4; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java index e9498856f14..e0845156c09 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java @@ -124,7 +124,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements public List expandValueSet(String theValueSet) {//FIXME: DM COWABUNGA ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { - return Collections.emptyList(); + super.throwInvalidValueSet(theValueSet); } return expandValueSetAndReturnVersionIndependentConcepts(vs); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java index ede8dc78120..a23d7120fa4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java @@ -133,7 +133,7 @@ public class HapiTerminologySvcR5 extends BaseHapiTerminologySvcImpl implements public List expandValueSet(String theValueSet) { ValueSet valueSetR5 = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (valueSetR5 == null) { - return Collections.emptyList(); + super.throwInvalidValueSet(theValueSet); } return expandValueSetAndReturnVersionIndependentConcepts(org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSetR5)); From 7e76c1893f50d470fa049b3d1b0c569ccf059cfa Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 9 Sep 2019 18:41:00 -0400 Subject: [PATCH 12/16] Fixed bug for large ValueSet expansion with URL parameter; return 404 for unknown ValueSets. --- .../jpa/term/BaseHapiTerminologySvcImpl.java | 5 +- .../r4/ResourceProviderR4ValueSetTest.java | 49 ++++++++++++++++--- .../jpa/term/TerminologySvcImplR4Test.java | 9 +--- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index fe562f4298c..ea2ee08dd6e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -488,7 +488,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, } if (!optionalTermValueSet.isPresent()) { - ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory expansion without parameters. Will schedule this ValueSet for pre-expansion. {}", getValueSetInfo(theValueSetToExpand)); + ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory expansion without parameters. {}", getValueSetInfo(theValueSetToExpand)); return expandValueSet(theValueSetToExpand); // In-memory expansion. } @@ -947,8 +947,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, Optional optionalTermValueSet = myValueSetDao.findByResourcePid(valueSetResourcePid); if (!optionalTermValueSet.isPresent()) { - ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory code validation. Will schedule this ValueSet for pre-expansion. {}", getValueSetInfo(theValueSet)); - myDeferredValueSets.add(theValueSet); + ourLog.warn("ValueSet is not present in terminology tables. Will perform in-memory code validation. {}", getValueSetInfo(theValueSet)); return false; } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java index e29ae2a327b..207e54474d2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java @@ -9,6 +9,7 @@ import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; @@ -311,8 +312,7 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { .operation() .onType(ValueSet.class) .named("expand") -// .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) //FIXME: DM - .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); @@ -325,21 +325,34 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } @Test - public void testExpandByUrlWithPreExpansion() throws Exception {//FIXME: DM + public void testExpandByUrlWithBogusUrl() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + + try { + ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .execute(); + } catch (ResourceNotFoundException e) { + assertEquals(404, e.getStatusCode()); + assertEquals("HTTP 404 Not Found: Unknown ValueSet: http%3A%2F%2Fwww.healthintersections.com.au%2Ffhir%2FValueSet%2Fbogus", e.getMessage()); + } + } + + @Test + public void testExpandByUrlWithPreExpansion() throws Exception { myDaoConfig.setPreExpandValueSetsExperimental(true); - ourLog.info("DIEDERIK - before loading CD and VS"); loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - ourLog.info("DIEDERIK - after loading CD and VS; before pre-expansion"); myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); - ourLog.info("DIEDERIK - after pre-expansion"); Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("expand") - // .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) //FIXME: DM - .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); @@ -351,6 +364,26 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { } + @Test + public void testExpandByUrlWithPreExpansionAndBogusUrl() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + try { + Parameters respParam = ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .execute(); + } catch (ResourceNotFoundException e) { + assertEquals(404, e.getStatusCode()); + assertEquals("HTTP 404 Not Found: Unknown ValueSet: http%3A%2F%2Fwww.healthintersections.com.au%2Ffhir%2FValueSet%2Fbogus", e.getMessage()); + } + } + @Test public void testExpandByValueSet() throws IOException { loadAndPersistCodeSystem(HttpVerb.POST); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java index e108f2b8457..a4613d1efb3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java @@ -885,19 +885,12 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test { assertEquals("Systolic blood pressure 8 hour minimum", containsComponent.getDisplay()); assertFalse(containsComponent.hasDesignation()); - myTermSvc.saveDeferred(); - myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); - expandedValueSet = myTermSvc.expandValueSet(valueSet, myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), myDaoConfig.getPreExpandValueSetsDefaultCountExperimental()); ourLog.info("Expanded ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expandedValueSet)); assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getTotal()); assertEquals(myDaoConfig.getPreExpandValueSetsDefaultOffsetExperimental(), expandedValueSet.getExpansion().getOffset()); - assertEquals(2, expandedValueSet.getExpansion().getParameter().size()); - assertEquals("offset", expandedValueSet.getExpansion().getParameter().get(0).getName()); - assertEquals(0, expandedValueSet.getExpansion().getParameter().get(0).getValueIntegerType().getValue().intValue()); - assertEquals("count", expandedValueSet.getExpansion().getParameter().get(1).getName()); - assertEquals(1000, expandedValueSet.getExpansion().getParameter().get(1).getValueIntegerType().getValue().intValue()); + assertEquals(0, expandedValueSet.getExpansion().getParameter().size()); assertEquals(codeSystem.getConcept().size(), expandedValueSet.getExpansion().getContains().size()); From dbe5a36f26910495d76f799701b28d762b8e5ebb Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Mon, 9 Sep 2019 18:44:25 -0400 Subject: [PATCH 13/16] Reset schedule for pre-expansions. Ready for review. --- .../java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java | 3 +-- .../main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index ea2ee08dd6e..b08eb880834 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -1829,8 +1829,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ourLog.info("Done storing TermConceptMap[{}]", termConceptMap.getId()); } - // FIXME: DM 2019-09-05 - Return to 600000 before merging into master. - @Scheduled(fixedDelay = 6000) // 10 minutes. + @Scheduled(fixedDelay = 600000) // 10 minutes. @Override public synchronized void preExpandDeferredValueSetsToTerminologyTables() { if (isNotSafeToPreExpandValueSets()) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java index e0845156c09..a5648798df3 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java @@ -121,7 +121,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements } @Override - public List expandValueSet(String theValueSet) {//FIXME: DM COWABUNGA + public List expandValueSet(String theValueSet) { ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { super.throwInvalidValueSet(theValueSet); From 57d4cc23ee802c73183cc267b6c40910adb92953 Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 10 Sep 2019 11:56:07 -0400 Subject: [PATCH 14/16] More bug-hunting. DSTU3 was missing a null check. --- .../dstu3/FhirResourceDaoValueSetDstu3.java | 9 +- .../jpa/dao/r4/FhirResourceDaoValueSetR4.java | 1 + .../jpa/dao/r5/FhirResourceDaoValueSetR5.java | 1 + .../jpa/term/HapiTerminologySvcDstu3.java | 1 + .../fhir/jpa/term/HapiTerminologySvcR4.java | 1 + .../fhir/jpa/term/HapiTerminologySvcR5.java | 1 + .../ResourceProviderDstu3ValueSetTest.java | 236 ++++++++++++++++-- .../r4/ResourceProviderR4ValueSetTest.java | 10 - 8 files changed, 226 insertions(+), 34 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java index 4a816fdc40f..c57ac0da775 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoValueSetDstu3.java @@ -93,12 +93,12 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 boolean allSystemsAreSuppportedByTerminologyService = true; for (ConceptSetComponent next : theSource.getCompose().getInclude()) { - if (!myTerminologySvc.supportsSystem(next.getSystem())) { + if (!isBlank(next.getSystem()) && !myTerminologySvc.supportsSystem(next.getSystem())) { allSystemsAreSuppportedByTerminologyService = false; } } for (ConceptSetComponent next : theSource.getCompose().getExclude()) { - if (!myTerminologySvc.supportsSystem(next.getSystem())) { + if (!isBlank(next.getSystem()) && !myTerminologySvc.supportsSystem(next.getSystem())) { allSystemsAreSuppportedByTerminologyService = false; } } @@ -125,12 +125,12 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 boolean allSystemsAreSuppportedByTerminologyService = true; for (ConceptSetComponent next : theSource.getCompose().getInclude()) { - if (!myTerminologySvc.supportsSystem(next.getSystem())) { + if (!isBlank(next.getSystem()) && !myTerminologySvc.supportsSystem(next.getSystem())) { allSystemsAreSuppportedByTerminologyService = false; } } for (ConceptSetComponent next : theSource.getCompose().getExclude()) { - if (!myTerminologySvc.supportsSystem(next.getSystem())) { + if (!isBlank(next.getSystem()) && !myTerminologySvc.supportsSystem(next.getSystem())) { allSystemsAreSuppportedByTerminologyService = false; } } @@ -160,6 +160,7 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3 } ValueSet source = new ValueSet(); + source.setUrl(theUri); source.getCompose().addInclude().addValueSet(theUri); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java index cb20e868505..41d2183f81f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoValueSetR4.java @@ -156,6 +156,7 @@ public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4 imple } ValueSet source = new ValueSet(); + source.setUrl(theUri); source.getCompose().addInclude().addValueSet(theUri); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java index d97e625f948..3113aeb9530 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r5/FhirResourceDaoValueSetR5.java @@ -162,6 +162,7 @@ public class FhirResourceDaoValueSetR5 extends FhirResourceDaoR5 imple } ValueSet source = new ValueSet(); + source.setUrl(theUri); source.getCompose().addInclude().addValueSet(theUri); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java index e50a2fecb7c..b265ba26f39 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java @@ -210,6 +210,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen @Override public List expandValueSet(String theValueSet) { + // TODO: DM 2019-09-10 - This is problematic because an incorrect URL that matches ValueSet.id will not be found in the terminology tables but will yield a ValueSet here. Depending on the ValueSet, the expansion may time-out. ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { super.throwInvalidValueSet(theValueSet); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java index a5648798df3..06378a6cd10 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java @@ -122,6 +122,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvcImpl implements @Override public List expandValueSet(String theValueSet) { + // TODO: DM 2019-09-10 - This is problematic because an incorrect URL that matches ValueSet.id will not be found in the terminology tables but will yield a ValueSet here. Depending on the ValueSet, the expansion may time-out. ValueSet vs = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (vs == null) { super.throwInvalidValueSet(theValueSet); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java index a23d7120fa4..457094eee71 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR5.java @@ -131,6 +131,7 @@ public class HapiTerminologySvcR5 extends BaseHapiTerminologySvcImpl implements @Override public List expandValueSet(String theValueSet) { + // TODO: DM 2019-09-10 - This is problematic because an incorrect URL that matches ValueSet.id will not be found in the terminology tables but will yield a ValueSet here. Depending on the ValueSet, the expansion may time-out. ValueSet valueSetR5 = myValidationSupport.fetchResource(myContext, ValueSet.class, theValueSet); if (valueSetR5 == null) { super.throwInvalidValueSet(theValueSet); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java index c789f0a82b9..d681b3d1778 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java @@ -1,14 +1,16 @@ package ca.uhn.fhir.jpa.provider.dstu3; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4TerminologyTest; -import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; +import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.UrlUtil; @@ -25,11 +27,14 @@ import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator; +import org.hl7.fhir.dstu3.model.codesystems.HttpVerb; import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; import org.junit.AfterClass; -import org.junit.Before; import org.junit.Test; -import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; +import org.springframework.transaction.support.TransactionTemplate; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -43,18 +48,86 @@ import static org.junit.Assert.*; public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3Test { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3ValueSetTest.class); + private IIdType myExtensionalCsId; private IIdType myExtensionalVsId; private IIdType myLocalValueSetId; + private Long myExtensionalCsIdOnResourceTable; + private Long myExtensionalVsIdOnResourceTable; private ValueSet myLocalVs; - @Before - @Transactional - public void before02() throws IOException { - CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); - myCodeSystemDao.create(cs, mySrd); +// @Before +// @Transactional +// public void before02() throws IOException { +// CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); +// myCodeSystemDao.create(cs, mySrd); +// +// ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); +// myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); +// } - ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); - myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); + private void loadAndPersistCodeSystemAndValueSet(HttpVerb theVerb) throws IOException { + loadAndPersistCodeSystem(theVerb); + loadAndPersistValueSet(theVerb); + } + + private void loadAndPersistCodeSystem(HttpVerb theVerb) throws IOException { + CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); + codeSystem.setId("CodeSystem/cs"); + persistCodeSystem(codeSystem, theVerb); + } + + private void persistCodeSystem(CodeSystem theCodeSystem, HttpVerb theVerb) { + switch (theVerb) { + case POST: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + case PUT: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalCsId = myCodeSystemDao.update(theCodeSystem, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + default: + throw new IllegalArgumentException("HTTP verb is not supported: " + theVerb); + } + myExtensionalCsIdOnResourceTable = myCodeSystemDao.readEntity(myExtensionalCsId, null).getId(); + } + + private void loadAndPersistValueSet(HttpVerb theVerb) throws IOException { + ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); + valueSet.setId("ValueSet/vs"); + persistValueSet(valueSet, theVerb); + } + + private void persistValueSet(ValueSet theValueSet, HttpVerb theVerb) { + switch (theVerb) { + case POST: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalVsId = myValueSetDao.create(theValueSet, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + case PUT: + new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() { + @Override + protected void doInTransactionWithoutResult(TransactionStatus theStatus) { + myExtensionalVsId = myValueSetDao.update(theValueSet, mySrd).getId().toUnqualifiedVersionless(); + } + }); + break; + default: + throw new IllegalArgumentException("HTTP verb is not supported: " + theVerb); + } + myExtensionalVsIdOnResourceTable = myValueSetDao.readEntity(myExtensionalVsId, null).getId(); } private CodeSystem createExternalCs() { @@ -169,7 +242,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 @Test - public void testExpandValueSetPropertySearchWithRegexExcludeUsingOr() { + public void testExpandValueSetPropertySearchWithRegexExcludeUsingOr() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + createLoincSystemWithSomeCodes(); List codes; @@ -207,7 +282,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 @Test - public void testExpandValueSetPropertySearchWithRegexExcludeNoFilter() { + public void testExpandValueSetPropertySearchWithRegexExcludeNoFilter() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + createLoincSystemWithSomeCodes(); List codes; @@ -233,7 +310,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 @Test - public void testExpandById() { + public void testExpandById() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + //@formatter:off Parameters respParam = ourClient .operation() @@ -263,7 +342,41 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } @Test - public void testExpandByIdWithFilter() { + public void testExpandByIdWithPreExpansion() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + Parameters respParam = ourClient + .operation() + .onInstance(myExtensionalVsId) + .named("expand") + .withNoParameters(Parameters.class) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + assertThat(resp, Matchers.containsString("")); + + } + + @Test + public void testExpandByIdWithFilter() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); //@formatter:off Parameters respParam = ourClient @@ -290,7 +403,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 * https://groups.google.com/d/msgid/hapi-fhir/CAN2Cfy8kW%2BAOkgC6VjPsU3gRCpExCNZBmJdi-k5R_TWeyWH4tA%40mail.gmail.com?utm_medium=email&utm_source=footer */ @Test - public void testExpandByIdentifier() { + public void testExpandByIdentifier() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -308,7 +423,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } @Test - public void testExpandByUrl() { + public void testExpandByUrl() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -325,8 +442,70 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } + @Test + public void testExpandByUrlWithBogusUrl() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + + try { + ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .execute(); + } catch (ResourceNotFoundException e) { + assertEquals(404, e.getStatusCode()); + assertEquals("HTTP 404 Not Found: Unknown ValueSet: http%3A%2F%2Fwww.healthintersections.com.au%2Ffhir%2FValueSet%2Fbogus", e.getMessage()); + } + } + + @Test + public void testExpandByUrlWithPreExpansion() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + Parameters respParam = ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) + .execute(); + ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); + + String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); + ourLog.info(resp); + assertThat(resp, Matchers.stringContainsInOrder( + "", + "")); + + } + + @Test + public void testExpandByUrlWithPreExpansionAndBogusUrl() throws Exception { + myDaoConfig.setPreExpandValueSetsExperimental(true); + + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + myTermSvc.preExpandDeferredValueSetsToTerminologyTables(); + + try { + Parameters respParam = ourClient + .operation() + .onType(ValueSet.class) + .named("expand") + .withParameter(Parameters.class, "url", new UriType("http://www.healthintersections.com.au/fhir/ValueSet/bogus")) + .execute(); + } catch (ResourceNotFoundException e) { + assertEquals(404, e.getStatusCode()); + assertEquals("HTTP 404 Not Found: Unknown ValueSet: http%3A%2F%2Fwww.healthintersections.com.au%2Ffhir%2FValueSet%2Fbogus", e.getMessage()); + } + } + @Test public void testExpandByValueSet() throws IOException { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); //@formatter:off @@ -397,6 +576,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 @Test public void testExpandInvalidParams() throws IOException { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + try { ourClient .operation() @@ -576,7 +757,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } @Test - public void testValidateCodeOperationByCodeAndSystemInstance() { + public void testValidateCodeOperationByCodeAndSystemInstance() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + //@formatter:off Parameters respParam = ourClient .operation() @@ -595,6 +778,8 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 @Test public void testValidateCodeOperationByCodeAndSystemInstanceOnInstance() throws IOException { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + createLocalCsAndVs(); createLocalVsWithIncludeConcept(); @@ -617,7 +802,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } @Test - public void testValidateCodeOperationByCodeAndSystemType() { + public void testValidateCodeOperationByCodeAndSystemType() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + //@formatter:off Parameters respParam = ourClient .operation() @@ -638,7 +825,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 * Technically this is the wrong param name */ @Test - public void testValiedateCodeAgainstBuiltInSystem() { + public void testValiedateCodeAgainstBuiltInSystem() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -666,7 +855,9 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 * Technically this is the right param name */ @Test - public void testValiedateCodeAgainstBuiltInSystemByUrl() { + public void testValiedateCodeAgainstBuiltInSystemByUrl() throws Exception { + loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); + Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -690,6 +881,11 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 assertEquals("Burn", ((StringType) respParam.getParameter().get(2).getValue()).getValue()); } + @After + public void afterResetPreExpansionDefault() { + myDaoConfig.setPreExpandValueSetsExperimental(new DaoConfig().isPreExpandValueSetsExperimental()); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java index 207e54474d2..bceb5f6c365 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4ValueSetTest.java @@ -52,16 +52,6 @@ public class ResourceProviderR4ValueSetTest extends BaseResourceProviderR4Test { private Long myExtensionalVsIdOnResourceTable; private ValueSet myLocalVs; -// @Before -// @Transactional -// public void before02() throws IOException { -// CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); -// myCodeSystemDao.create(cs, mySrd); -// -// ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); -// myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); -// } - private void loadAndPersistCodeSystemAndValueSet(HttpVerb theVerb) throws IOException { loadAndPersistCodeSystem(theVerb); loadAndPersistValueSet(theVerb); From d4feb5d0b102968206125310e8d1e0e932d7c4cf Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 10 Sep 2019 14:21:42 -0400 Subject: [PATCH 15/16] Final cleanup before review. --- .../ResourceProviderDstu3ValueSetTest.java | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java index d681b3d1778..e5785c809e2 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3ValueSetTest.java @@ -55,16 +55,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 private Long myExtensionalVsIdOnResourceTable; private ValueSet myLocalVs; -// @Before -// @Transactional -// public void before02() throws IOException { -// CodeSystem cs = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml"); -// myCodeSystemDao.create(cs, mySrd); -// -// ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); -// myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); -// } - private void loadAndPersistCodeSystemAndValueSet(HttpVerb theVerb) throws IOException { loadAndPersistCodeSystem(theVerb); loadAndPersistValueSet(theVerb); @@ -151,7 +141,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } private void createLocalCsAndVs() { - //@formatter:off CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setContent(CodeSystemContentMode.COMPLETE); @@ -165,7 +154,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .addConcept().setCode("B").setDisplay("Code B") .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA")) .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB")); - //@formatter:on myCodeSystemDao.create(codeSystem, mySrd); createLocalVs(codeSystem); @@ -313,7 +301,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 public void testExpandById() throws Exception { loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -321,7 +308,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -378,7 +364,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 public void testExpandByIdWithFilter() throws Exception { loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -386,7 +371,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "filter", new StringType("first")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -508,7 +492,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml"); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -516,15 +499,12 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "valueSet", toExpand) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); - //@formatter:off assertThat(resp, Matchers.stringContainsInOrder( "", "")); - //@formatter:on } @@ -533,7 +513,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 createLocalVsPointingAtBuiltInCodeSystem(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -541,7 +520,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "valueSet", myLocalVs) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -555,7 +533,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 assertNotNull(myLocalVs); myLocalVs.setId(""); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -563,7 +540,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "valueSet", myLocalVs) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -648,7 +624,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 createLocalVsPointingAtBuiltInCodeSystem(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myLocalValueSetId) @@ -656,7 +631,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -669,7 +643,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 createExternalCsAndLocalVs(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myLocalValueSetId) @@ -677,7 +650,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -693,7 +665,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 createExternalCsAndLocalVs(); assertNotNull(myLocalValueSetId); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -701,7 +672,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "identifier", new UriType(URL_MY_VALUE_SET)) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); @@ -717,7 +687,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 createExternalCsAndLocalVsWithUnknownCode(); assertNotNull(myLocalValueSetId); - //@formatter:off try { ourClient .operation() @@ -728,7 +697,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: Invalid filter criteria - code does not exist: {http://example.com/my_code_system}childFOOOOOOO", e.getMessage()); } - //@formatter:on } /** @@ -760,7 +728,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 public void testValidateCodeOperationByCodeAndSystemInstance() throws Exception { loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) @@ -768,7 +735,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "code", new CodeType("8495-4")) .andParameter("system", new UriType("http://acme.org")) .execute(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); @@ -805,7 +771,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 public void testValidateCodeOperationByCodeAndSystemType() throws Exception { loadAndPersistCodeSystemAndValueSet(HttpVerb.POST); - //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) @@ -813,7 +778,6 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3 .withParameter(Parameters.class, "code", new CodeType("8450-9")) .andParameter("system", new UriType("http://acme.org")) .execute(); - //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); From 65e029458ca7e626242aee093f2d38fad70eb65d Mon Sep 17 00:00:00 2001 From: Diederik Muylwyk Date: Tue, 10 Sep 2019 17:50:49 -0400 Subject: [PATCH 16/16] Test fixes. --- .../jpa/entity/TermValueSetConceptView.java | 21 ++++++++-------- .../jpa/term/BaseHapiTerminologySvcImpl.java | 8 +++--- .../FhirResourceDaoDstu3TerminologyTest.java | 16 +++++++----- .../r4/FhirResourceDaoR4TerminologyTest.java | 25 ++++++++++++------- .../fhir/jpa/provider/r4/ExpungeR4Test.java | 14 +++-------- 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java index df7fe29f2e8..de921c27f49 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermValueSetConceptView.java @@ -48,11 +48,12 @@ import java.io.Serializable; " LEFT OUTER JOIN TRM_VALUESET_C_DESIGNATION vscd ON vsc.PID = vscd.VALUESET_CONCEPT_PID" ) public class TermValueSetConceptView implements Serializable { - private static final long serialVersionUID = 1L; + private static final int MAX_LENGTH = 500; + @Id - @Column(name="PID") + @Column(name="PID", length = MAX_LENGTH) private String myPid; @Column(name = "CONCEPT_PID") @@ -64,31 +65,31 @@ public class TermValueSetConceptView implements Serializable { @Column(name = "CONCEPT_VALUESET_ORDER") private int myConceptOrder; - @Column(name = "CONCEPT_SYSTEM_URL") + @Column(name = "CONCEPT_SYSTEM_URL", length = TermCodeSystem.MAX_URL_LENGTH) private String myConceptSystemUrl; - @Column(name = "CONCEPT_CODEVAL") + @Column(name = "CONCEPT_CODEVAL", length = TermConcept.MAX_CODE_LENGTH) private String myConceptCode; - @Column(name = "CONCEPT_DISPLAY") + @Column(name = "CONCEPT_DISPLAY", length = TermConcept.MAX_DESC_LENGTH) private String myConceptDisplay; @Column(name = "DESIGNATION_PID") private Long myDesignationPid; - @Column(name = "DESIGNATION_LANG") + @Column(name = "DESIGNATION_LANG", length = TermValueSetConceptDesignation.MAX_LENGTH) private String myDesignationLang; - @Column(name = "DESIGNATION_USE_SYSTEM") + @Column(name = "DESIGNATION_USE_SYSTEM", length = TermValueSetConceptDesignation.MAX_LENGTH) private String myDesignationUseSystem; - @Column(name = "DESIGNATION_USE_CODE") + @Column(name = "DESIGNATION_USE_CODE", length = TermValueSetConceptDesignation.MAX_LENGTH) private String myDesignationUseCode; - @Column(name = "DESIGNATION_USE_DISPLAY") + @Column(name = "DESIGNATION_USE_DISPLAY", length = TermValueSetConceptDesignation.MAX_LENGTH) private String myDesignationUseDisplay; - @Column(name = "DESIGNATION_VAL") + @Column(name = "DESIGNATION_VAL", length = TermValueSetConceptDesignation.MAX_LENGTH) private String myDesignationVal; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java index 341b977e812..8ea73872735 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java @@ -578,15 +578,15 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, logConceptsExpanded("Finished expanding concepts. ", theTermValueSet, conceptsExpanded); } - private void logConceptsExpanded(String thePrefix, TermValueSet theTermValueSet, int theConceptsExpanded) { + private void logConceptsExpanded(String theLogDescriptionPrefix, TermValueSet theTermValueSet, int theConceptsExpanded) { if (theConceptsExpanded > 0) { - ourLog.info("{}Have expanded {} concepts in ValueSet[{}]", thePrefix, theConceptsExpanded, theTermValueSet.getUrl()); + ourLog.info("{}Have expanded {} concepts in ValueSet[{}]", theLogDescriptionPrefix, theConceptsExpanded, theTermValueSet.getUrl()); } } - private void logDesignationsExpanded(String thePrefix, TermValueSet theTermValueSet, int theDesignationsExpanded) { + private void logDesignationsExpanded(String theLogDescriptionPrefix, TermValueSet theTermValueSet, int theDesignationsExpanded) { if (theDesignationsExpanded > 0) { - ourLog.info("{}Have expanded {} designations in ValueSet[{}]", thePrefix, theDesignationsExpanded, theTermValueSet.getUrl()); + ourLog.info("{}Have expanded {} designations in ValueSet[{}]", theLogDescriptionPrefix, theDesignationsExpanded, theTermValueSet.getUrl()); } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java index de223cbb46c..74e611b3df1 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java @@ -13,6 +13,7 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.validation.FhirValidator; @@ -801,8 +802,8 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { try { params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); - } catch (InvalidRequestException e) { - assertEquals("Unable to find imported value set http://example.com/my_value_set", e.getMessage()); + } catch (ResourceNotFoundException e) { + assertEquals("Unknown ValueSet: http%3A%2F%2Fexample.com%2Fmy_value_set", e.getMessage()); } } @@ -1117,10 +1118,13 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { valueSet.setUrl(URL_MY_VALUE_SET); myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless(); - params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); - params.add(Observation.SP_STATUS, new TokenParam(null, "final")); - assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); + try { + params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); + params.add(Observation.SP_STATUS, new TokenParam(null, "final")); + } catch (ResourceNotFoundException e) { + assertEquals("Unknown ValueSet: http%3A%2F%2Fexample.com%2Fmy_value_set", e.getMessage()); + } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java index fe666c008a4..d4d327347c7 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4TerminologyTest.java @@ -13,6 +13,7 @@ import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.validation.FhirValidator; @@ -1168,9 +1169,12 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/audit-event-type").setModifier(TokenParamModifier.IN)); assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), containsInAnyOrder(idIn1.getValue(), idIn2.getValue())); - params = new SearchParameterMap(); - params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/v3-PurposeOfUse").setModifier(TokenParamModifier.IN)); - assertThat(toUnqualifiedVersionlessIdValues(myAuditEventDao.search(params)), empty()); + try { + params = new SearchParameterMap(); + params.add(AuditEvent.SP_TYPE, new TokenParam(null, "http://hl7.org/fhir/ValueSet/v3-PurposeOfUse").setModifier(TokenParamModifier.IN)); + } catch (ResourceNotFoundException e) { + assertEquals("Unknown ValueSet: http%3A%2F%2Fhl7.org%2Ffhir%2FValueSet%2Fv3-PurposeOfUse", e.getMessage()); + } } @Test @@ -1203,8 +1207,8 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { try { params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); - } catch (InvalidRequestException e) { - assertEquals("Unable to find imported value set http://example.com/my_value_set", e.getMessage()); + } catch (ResourceNotFoundException e) { + assertEquals("Unknown ValueSet: http%3A%2F%2Fexample.com%2Fmy_value_set", e.getMessage()); } } @@ -1234,10 +1238,13 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test { valueSet.setUrl(URL_MY_VALUE_SET); myValueSetDao.update(valueSet, mySrd).getId().toUnqualifiedVersionless(); - params = new SearchParameterMap(); - params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); - params.add(Observation.SP_STATUS, new TokenParam(null, "final")); - assertThat(toUnqualifiedVersionlessIdValues(myObservationDao.search(params)), empty()); + try { + params = new SearchParameterMap(); + params.add(Observation.SP_CODE, new TokenParam(null, URL_MY_VALUE_SET).setModifier(TokenParamModifier.IN)); + params.add(Observation.SP_STATUS, new TokenParam(null, "final")); + } catch (ResourceNotFoundException e) { + assertEquals("Unknown ValueSet: http%3A%2F%2Fnon_existant_VS", e.getMessage()); + } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java index 182b39366d5..66ad4b49b82 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java @@ -347,22 +347,16 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { public void testExpungeEverythingWhereResourceInSearchResults() { createStandardPatients(); - runInTransaction(() -> { - await().until(()->mySearchEntityDao.count() == 0); - await().until(()->mySearchResultDao.count() == 0); - }); + await().until(()-> runInTransaction(() -> mySearchEntityDao.count() == 0)); + await().until(()-> runInTransaction(() -> mySearchResultDao.count() == 0)); PersistedJpaSearchFirstPageBundleProvider search = (PersistedJpaSearchFirstPageBundleProvider) myPatientDao.search(new SearchParameterMap()); assertEquals(PersistedJpaSearchFirstPageBundleProvider.class, search.getClass()); assertEquals(2, search.size().intValue()); assertEquals(2, search.getResources(0, 2).size()); - runInTransaction(() -> { - await().until(()->mySearchEntityDao.count() == 1); - await().until(()->mySearchResultDao.count() == 2); - ourLog.info("Search results: {}", mySearchResultDao.findAll().toString()); - assertEquals(mySearchResultDao.findAll().toString(), 2, mySearchResultDao.count()); - }); + await().until(()-> runInTransaction(() -> mySearchEntityDao.count() == 1)); + await().until(()-> runInTransaction(() -> mySearchResultDao.count() == 2)); mySystemDao.expunge(new ExpungeOptions() .setExpungeEverything(true), null);