From 5c08e8fdf81fe0e048d1763e896c5d014f677c91 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 3 Sep 2019 15:05:44 -0400 Subject: [PATCH 1/3] anylist r5 support also added another accessor --- hapi-fhir-jpaserver-model/pom.xml | 5 ++ .../fhir/jpa/model/any/AnyListResource.java | 85 +++++++++++++++++++ .../jpa/model/any/AnyListResourceTest.java | 24 ++++++ .../fhir/r4/hapi/ctx/HapiWorkerContext.java | 5 ++ .../fhir/r5/hapi/ctx/HapiWorkerContext.java | 5 ++ 5 files changed, 124 insertions(+) create mode 100644 hapi-fhir-jpaserver-model/src/test/java/ca/uhn/fhir/jpa/model/any/AnyListResourceTest.java diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 45ab231bec8..8ae1cc7e7f8 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -46,6 +46,11 @@ hapi-fhir-structures-r4 ${project.version} + + ca.uhn.hapi.fhir + hapi-fhir-structures-r5 + ${project.version} + ca.uhn.hapi.fhir hapi-fhir-structures-hl7org-dstu2 diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/any/AnyListResource.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/any/AnyListResource.java index c2636f3d88a..9ba10073f52 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/any/AnyListResource.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/any/AnyListResource.java @@ -43,6 +43,8 @@ public class AnyListResource { return new AnyListResource(new org.hl7.fhir.dstu3.model.ListResource()); case R4: return new AnyListResource(new org.hl7.fhir.r4.model.ListResource()); + case R5: + return new AnyListResource(new org.hl7.fhir.r5.model.ListResource()); default: throw new UnsupportedOperationException(version + " not supported"); } @@ -63,6 +65,11 @@ public class AnyListResource { myListResource = theListResourceR4; } + public AnyListResource(org.hl7.fhir.r5.model.ListResource theListResourceR5) { + myFhirVersion = FhirVersionEnum.R5; + myListResource = theListResourceR5; + } + public static AnyListResource fromResource(IBaseResource theListResource) { if (theListResource instanceof ca.uhn.fhir.model.dstu2.resource.ListResource) { return new AnyListResource((ca.uhn.fhir.model.dstu2.resource.ListResource) theListResource); @@ -70,6 +77,8 @@ public class AnyListResource { return new AnyListResource((org.hl7.fhir.dstu3.model.ListResource) theListResource); } else if (theListResource instanceof org.hl7.fhir.r4.model.ListResource) { return new AnyListResource((org.hl7.fhir.r4.model.ListResource) theListResource); + } else if (theListResource instanceof org.hl7.fhir.r5.model.ListResource) { + return new AnyListResource((org.hl7.fhir.r5.model.ListResource) theListResource); } else { throw new UnsupportedOperationException("Cannot convert " + theListResource.getClass().getName() + " to AnyList"); } @@ -94,6 +103,11 @@ public class AnyListResource { return (org.hl7.fhir.r4.model.ListResource) get(); } + public org.hl7.fhir.r5.model.ListResource getR5() { + Validate.isTrue(myFhirVersion == FhirVersionEnum.R5); + return (org.hl7.fhir.r5.model.ListResource) get(); + } + public FhirVersionEnum getFhirVersion() { return myFhirVersion; } @@ -106,6 +120,9 @@ public class AnyListResource { case R4: getR4().getCode().addCoding().setSystem(theSystem).setCode(theCode); break; + case R5: + getR5().getCode().addCoding().setSystem(theSystem).setCode(theCode); + break; default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -119,6 +136,9 @@ public class AnyListResource { case R4: getR4().getIdentifier().add(new org.hl7.fhir.r4.model.Identifier().setSystem(theSystem).setValue(theValue)); break; + case R5: + getR5().getIdentifier().add(new org.hl7.fhir.r5.model.Identifier().setSystem(theSystem).setValue(theValue)); + break; default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -132,6 +152,9 @@ public class AnyListResource { case R4: getR4().addExtension().setUrl(theUrl).setValue(new org.hl7.fhir.r4.model.StringType(theValue)); break; + case R5: + getR5().addExtension().setUrl(theUrl).setValue(new org.hl7.fhir.r5.model.StringType(theValue)); + break; default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -143,6 +166,8 @@ public class AnyListResource { return getStringExtensionValueOrNullDstu3(theUrl); case R4: return getStringExtensionValueOrNullR4(theUrl); + case R5: + return getStringExtensionValueOrNullR5(theUrl); default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -166,6 +191,15 @@ public class AnyListResource { return targetType.getValue(); } + private String getStringExtensionValueOrNullR5(String theUrl) { + List targetTypes = getR5().getExtensionsByUrl(theUrl); + if (targetTypes.size() < 1) { + return null; + } + org.hl7.fhir.r5.model.StringType targetType = (org.hl7.fhir.r5.model.StringType) targetTypes.get(0).getValue(); + return targetType.getValue(); + } + public void addReference(IBaseReference theReference) { switch (myFhirVersion) { case DSTU3: @@ -174,6 +208,9 @@ public class AnyListResource { case R4: getR4().addEntry().setItem((org.hl7.fhir.r4.model.Reference) theReference); break; + case R5: + getR5().addEntry().setItem((org.hl7.fhir.r5.model.Reference) theReference); + break; default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -187,6 +224,9 @@ public class AnyListResource { case R4: getR4().addEntry().setItem(new org.hl7.fhir.r4.model.Reference(theReferenceId)); break; + case R5: + getR5().addEntry().setItem(new org.hl7.fhir.r5.model.Reference(theReferenceId)); + break; default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -202,6 +242,10 @@ public class AnyListResource { return getR4().getEntry().stream() .map(entry -> entry.getItem().getReference()) .map(reference -> new org.hl7.fhir.r4.model.IdType(reference).toUnqualifiedVersionless().getValue()); + case R5: + return getR5().getEntry().stream() + .map(entry -> entry.getItem().getReference()) + .map(reference -> new org.hl7.fhir.r5.model.IdType(reference).toUnqualifiedVersionless().getValue()); default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -213,6 +257,8 @@ public class AnyListResource { return removeItemDstu3(theReferenceId); case R4: return removeItemR4(theReferenceId); + case R5: + return removeItemR5(theReferenceId); default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } @@ -250,6 +296,22 @@ public class AnyListResource { return removed; } + private boolean removeItemR5(String theReferenceId) { + boolean removed = false; + for (org.hl7.fhir.r5.model.ListResource.ListEntryComponent entry : getR5().getEntry()) { + if (theReferenceId.equals(entry.getItem().getReference()) && !entry.getDeleted()) { + entry.setDeleted(true); + removed = true; + break; + } + } + + if (removed) { + getR5().getEntry().removeIf(entry -> entry.getDeleted()); + } + return removed; + } + public TokenParam getCodeFirstRep() { switch (myFhirVersion) { case DSTU3: @@ -258,17 +320,40 @@ public class AnyListResource { case R4: org.hl7.fhir.r4.model.Coding codingR4 = getR4().getCode().getCodingFirstRep(); return new TokenParam(codingR4.getSystem(), codingR4.getCode()); + case R5: + org.hl7.fhir.r5.model.Coding codingR5 = getR5().getCode().getCodingFirstRep(); + return new TokenParam(codingR5.getSystem(), codingR5.getCode()); default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } } + public TokenParam getIdentifierirstRep() { + switch (myFhirVersion) { + case DSTU3: + org.hl7.fhir.dstu3.model.Identifier identDstu3 = getDstu3().getIdentifierFirstRep(); + return new TokenParam(identDstu3.getSystem(), identDstu3.getValue()); + case R4: + org.hl7.fhir.r4.model.Identifier identR4 = getR4().getIdentifierFirstRep(); + return new TokenParam(identR4.getSystem(), identR4.getValue()); + case R5: + org.hl7.fhir.r5.model.Identifier identR5 = getR5().getIdentifierFirstRep(); + return new TokenParam(identR5.getSystem(), identR5.getValue()); + default: + throw new UnsupportedOperationException(myFhirVersion + " not supported"); + } + } + + + public boolean isEmpty() { switch (myFhirVersion) { case DSTU3: return getDstu3().getEntry().isEmpty(); case R4: return getR4().getEntry().isEmpty(); + case R5: + return getR5().getEntry().isEmpty(); default: throw new UnsupportedOperationException(myFhirVersion + " not supported"); } diff --git a/hapi-fhir-jpaserver-model/src/test/java/ca/uhn/fhir/jpa/model/any/AnyListResourceTest.java b/hapi-fhir-jpaserver-model/src/test/java/ca/uhn/fhir/jpa/model/any/AnyListResourceTest.java new file mode 100644 index 00000000000..46b71084710 --- /dev/null +++ b/hapi-fhir-jpaserver-model/src/test/java/ca/uhn/fhir/jpa/model/any/AnyListResourceTest.java @@ -0,0 +1,24 @@ +package ca.uhn.fhir.jpa.model.any; + +import org.hl7.fhir.r5.model.ListResource; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class AnyListResourceTest { + @Test + public void getCodeFirstRep() { + AnyListResource listResource = AnyListResource.fromResource(new ListResource()); + listResource.addCode("foo", "bar"); + assertEquals("foo", listResource.getCodeFirstRep().getSystem()); + assertEquals("bar", listResource.getCodeFirstRep().getValue()); + } + + @Test + public void getIdentifierFirstRep() { + AnyListResource listResource = AnyListResource.fromResource(new ListResource()); + listResource.addIdentifier("foo", "bar"); + assertEquals("foo", listResource.getIdentifierirstRep().getSystem()); + assertEquals("bar", listResource.getIdentifierirstRep().getValue()); + } +} diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java index bd771e1c766..d2dfd73e5a2 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java @@ -389,6 +389,11 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander throw new UnsupportedOperationException(); } + @Override + public String getLinkForUrl(String theS, String theS1) { + return null; + } + @Override public List getTypeNames() { throw new UnsupportedOperationException(); diff --git a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java index a3ebec0ce7e..b3268072dce 100644 --- a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java +++ b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java @@ -353,6 +353,11 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander throw new UnsupportedOperationException(); } + @Override + public String getLinkForUrl(String theS, String theS1) { + return null; + } + @Override public boolean isNoTerminologyServer() { return false; From e6d866cbf1cd95efb38ff7b38268ac4b751ba0c2 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Tue, 3 Sep 2019 15:14:27 -0400 Subject: [PATCH 2/3] Revert: premature hapiworkercontext changes --- .../java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java | 5 ----- .../java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java | 5 ----- 2 files changed, 10 deletions(-) diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java index d2dfd73e5a2..bd771e1c766 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/HapiWorkerContext.java @@ -389,11 +389,6 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander throw new UnsupportedOperationException(); } - @Override - public String getLinkForUrl(String theS, String theS1) { - return null; - } - @Override public List getTypeNames() { throw new UnsupportedOperationException(); diff --git a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java index b3268072dce..a3ebec0ce7e 100644 --- a/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java +++ b/hapi-fhir-structures-r5/src/main/java/org/hl7/fhir/r5/hapi/ctx/HapiWorkerContext.java @@ -353,11 +353,6 @@ public final class HapiWorkerContext implements IWorkerContext, ValueSetExpander throw new UnsupportedOperationException(); } - @Override - public String getLinkForUrl(String theS, String theS1) { - return null; - } - @Override public boolean isNoTerminologyServer() { return false; From 0a5c52122e7d3cbf2cdc3d1294d6280c8c4ce950 Mon Sep 17 00:00:00 2001 From: Ken Stevens Date: Wed, 4 Sep 2019 08:49:18 -0400 Subject: [PATCH 3/3] added list stresstest --- .../fhir/jpa/stresstest/StressTestR4Test.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java index 15d9764c213..88fc163c44d 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/stresstest/StressTestR4Test.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; +import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor; @@ -31,10 +32,8 @@ import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator; import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.Bundle.BundleType; import org.hl7.fhir.r4.model.Bundle.HTTPVerb; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; +import org.hl7.fhir.r4.model.codesystems.HttpVerb; +import org.junit.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; import org.springframework.test.util.AopTestUtils; @@ -337,6 +336,45 @@ public class StressTestR4Test extends BaseResourceProviderR4Test { assertEquals(1202, resultsAndIncludes.size()); } + @Ignore + @Test + public void testUpdateListWithLargeNumberOfEntries() { + int numPatients = 3000; + + ListResource lr = new ListResource(); + lr.setId(IdType.newRandomUuid()); + + { + Bundle bundle = new Bundle(); + for (int i = 0; i < numPatients; ++i) { + Patient patient = new Patient(); + patient.setId(IdType.newRandomUuid()); + bundle.addEntry().setFullUrl(patient.getId()).setResource(patient).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient"); + lr.addEntry().setItem(new Reference(patient.getId())); + } + bundle.addEntry().setFullUrl(lr.getId()).setResource(lr).getRequest().setMethod(HTTPVerb.POST).setUrl("List"); + + StopWatch sw = new StopWatch(); + ourLog.info("Saving list with {} entries", lr.getEntry().size()); + mySystemDao.transaction(null, bundle); + ourLog.info("Saved {} resources in {}", bundle.getEntry().size(), sw); + } + + { + Bundle bundle = new Bundle(); + + Patient newPatient = new Patient(); + newPatient.setId(IdType.newRandomUuid()); + bundle.addEntry().setFullUrl(newPatient.getId()).setResource(newPatient).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient"); + lr.addEntry().setItem(new Reference(newPatient.getId())); + bundle.addEntry().setFullUrl(lr.getId()).setResource(lr).getRequest().setMethod(HTTPVerb.PUT).setUrl(lr.getIdElement().toUnqualifiedVersionless().getValue()); + + StopWatch sw = new StopWatch(); + ourLog.info("Updating list with {} entries", lr.getEntry().size()); + mySystemDao.transaction(null, bundle); + ourLog.info("Updated {} resources in {}", bundle.getEntry().size(), sw); + } + } @Test public void testMultithreadedSearch() throws Exception {