diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java index d48969ae5ca..1d48b6a8fa9 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BundleUtil.java @@ -12,6 +12,8 @@ import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.instance.model.api.*; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.function.Consumer; @@ -170,6 +172,39 @@ public class BundleUtil { return entryListAccumulator.getList(); } + static int WHITE = 1; + static int GRAY = 2; + static int BLACK = 3; + + public static IBaseBundle topologicalSort(FhirContext theContext, IBaseBundle theBundle) { + boolean isPossible = true; + HashMap color = new HashMap(); + HashMap> adjList = new HashMap<>(); + List topologicalOrder = new ArrayList<>(); + + List> prerequisites = new ArrayList<>(); + + List bundleEntryParts = toListOfEntries(theContext, theBundle); + for (BundleEntryParts bundleEntryPart : bundleEntryParts) { + IBaseResource resource = bundleEntryPart.getResource(); + String resourceId = resource.getIdElement().toString(); + if (resourceId == null) { + if (bundleEntryPart.getFullUrl() != null) { + resourceId = bundleEntryPart.getFullUrl(); + } + } + List allResourceReferences = theContext.newTerser().getAllResourceReferences(resource); + String finalResourceId = resourceId; + allResourceReferences + .forEach(refInfo -> { + prerequisites.add(Arrays.asList(finalResourceId, refInfo.getResourceReference().getReferenceElement().getValue())); + }); + + } + System.out.println("zoop!!"); + return null; + } + public static void processEntries(FhirContext theContext, IBaseBundle theBundle, Consumer theProcessor) { RuntimeResourceDefinition bundleDef = theContext.getResourceDefinition(theBundle); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/TransactionHookTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/TransactionHookTest.java index 9b31ae1bce3..57e4ae32ec6 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/TransactionHookTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/TransactionHookTest.java @@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; import ca.uhn.fhir.rest.api.server.storage.DeferredInterceptorBroadcasts; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; +import ca.uhn.fhir.util.BundleUtil; import ca.uhn.test.concurrency.PointcutLatch; import com.google.common.collect.ListMultimap; import org.hl7.fhir.instance.model.api.IBaseResource; @@ -14,7 +15,9 @@ import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DiagnosticReport; import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Quantity; import org.hl7.fhir.r4.model.Reference; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -41,6 +44,7 @@ public class TransactionHookTest extends BaseJpaR4SystemTest { @Autowired private IInterceptorService myInterceptorService; + @BeforeEach public void beforeEach() { myInterceptorService.registerAnonymousInterceptor(Pointcut.STORAGE_TRANSACTION_PROCESSED, myPointcutLatch); @@ -49,6 +53,44 @@ public class TransactionHookTest extends BaseJpaR4SystemTest { myInterceptorService.registerAnonymousInterceptor(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED, myPointcutLatch); } + @Test + public void testTopologicalTransactionSorting() { + + Bundle b = new Bundle(); + Bundle.BundleEntryComponent bundleEntryComponent = b.addEntry(); + final Observation obs1 = new Observation(); + obs1.setStatus(Observation.ObservationStatus.FINAL); + obs1.setSubject(new Reference("Patient/P1")); + obs1.setValue(new Quantity(4)); + obs1.setId("Observation/O1"); + bundleEntryComponent.setResource(obs1); + bundleEntryComponent.getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Observation"); + + bundleEntryComponent = b.addEntry(); + final Observation obs2 = new Observation(); + obs2.setStatus(Observation.ObservationStatus.FINAL); + obs2.setValue(new Quantity(4)); + obs2.setId("Observation/O2"); + bundleEntryComponent.setResource(obs2); + bundleEntryComponent.getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Observation"); + + Bundle.BundleEntryComponent patientComponent = b.addEntry(); + Patient pat1 = new Patient(); + pat1.setId("Patient/P1"); + pat1.setManagingOrganization(new Reference("Organization/Org1")); + patientComponent.setResource(pat1); + patientComponent.getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Patient"); + + Bundle.BundleEntryComponent organizationComponent = b.addEntry(); + Organization org1 = new Organization(); + org1.setId("Organization/Org1"); + organizationComponent.setResource(org1); + organizationComponent.getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Patient"); + + BundleUtil.topologicalSort(myFhirCtx, b); + + } + @Test public void testHookShouldContainParamsForAllCreateUpdateDeleteInvocations() throws InterruptedException {