Issue 5004 make bundleutil also accept name prev for previous links (#5042)
* Add test * Fix * Changelog * Small details to reset build pipe * Reformat * Make definition animal-sniffer (check-android-26-compliance) compliant --------- Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
This commit is contained in:
parent
ce04e897cf
commit
ed04dd2498
|
@ -27,18 +27,22 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.i18n.Msg;
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
import ca.uhn.fhir.rest.api.PatchTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.util.bundle.BundleEntryMutator;
|
import ca.uhn.fhir.util.bundle.BundleEntryMutator;
|
||||||
import ca.uhn.fhir.util.bundle.BundleEntryParts;
|
import ca.uhn.fhir.util.bundle.BundleEntryParts;
|
||||||
import ca.uhn.fhir.util.bundle.EntryListAccumulator;
|
import ca.uhn.fhir.util.bundle.EntryListAccumulator;
|
||||||
import ca.uhn.fhir.util.bundle.ModifiableBundleEntry;
|
import ca.uhn.fhir.util.bundle.ModifiableBundleEntry;
|
||||||
import ca.uhn.fhir.util.bundle.SearchBundleEntryParts;
|
import ca.uhn.fhir.util.bundle.SearchBundleEntryParts;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -51,29 +55,41 @@ import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
import static org.hl7.fhir.instance.model.api.IBaseBundle.LINK_PREV;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch resources from a bundle
|
* Fetch resources from a bundle
|
||||||
*/
|
*/
|
||||||
public class BundleUtil {
|
public class BundleUtil {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BundleUtil.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(BundleUtil.class);
|
||||||
|
|
||||||
|
private static final String PREVIOUS = LINK_PREV;
|
||||||
|
private static final String PREV = "prev";
|
||||||
|
private static final Set<String> previousOrPrev = Sets.newHashSet(PREVIOUS, PREV);
|
||||||
|
|
||||||
|
public static final String DIFFERENT_LINK_ERROR_MSG = "Mismatching 'previous' and 'prev' links exist. 'previous' " +
|
||||||
|
"is: '$PREVIOUS' and 'prev' is: '$PREV'.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns <code>null</code> if the link isn't found or has no value
|
* @return Returns <code>null</code> if the link isn't found or has no value
|
||||||
*/
|
*/
|
||||||
public static String getLinkUrlOfType(FhirContext theContext, IBaseBundle theBundle, String theLinkRelation) {
|
public static String getLinkUrlOfType(FhirContext theContext, IBaseBundle theBundle, String theLinkRelation) {
|
||||||
|
return getLinkUrlOfType(theContext, theBundle, theLinkRelation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLinkUrlOfType(FhirContext theContext, IBaseBundle theBundle, String theLinkRelation, boolean isPreviousCheck) {
|
||||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
||||||
BaseRuntimeChildDefinition entryChild = def.getChildByName("link");
|
BaseRuntimeChildDefinition entryChild = def.getChildByName("link");
|
||||||
List<IBase> links = entryChild.getAccessor().getValues(theBundle);
|
List<IBase> links = entryChild.getAccessor().getValues(theBundle);
|
||||||
for (IBase nextLink : links) {
|
for (IBase nextLink : links) {
|
||||||
|
|
||||||
boolean isRightRel = false;
|
boolean isRightRel = false;
|
||||||
BaseRuntimeElementCompositeDefinition relDef = (BaseRuntimeElementCompositeDefinition) theContext.getElementDefinition(nextLink.getClass());
|
BaseRuntimeElementCompositeDefinition<?> relDef = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(nextLink.getClass());
|
||||||
BaseRuntimeChildDefinition relChild = relDef.getChildByName("relation");
|
BaseRuntimeChildDefinition relChild = relDef.getChildByName("relation");
|
||||||
List<IBase> relValues = relChild.getAccessor().getValues(nextLink);
|
List<IBase> relValues = relChild.getAccessor().getValues(nextLink);
|
||||||
for (IBase next : relValues) {
|
for (IBase next : relValues) {
|
||||||
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) next;
|
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) next;
|
||||||
if (theLinkRelation.equals(nextValue.getValueAsString())) {
|
if (isRelationMatch(theContext, theBundle,theLinkRelation, nextValue.getValueAsString(), isPreviousCheck)) {
|
||||||
isRightRel = true;
|
isRightRel = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +98,7 @@ public class BundleUtil {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseRuntimeElementCompositeDefinition linkDef = (BaseRuntimeElementCompositeDefinition) theContext.getElementDefinition(nextLink.getClass());
|
BaseRuntimeElementCompositeDefinition<?> linkDef = (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(nextLink.getClass());
|
||||||
BaseRuntimeChildDefinition urlChild = linkDef.getChildByName("url");
|
BaseRuntimeChildDefinition urlChild = linkDef.getChildByName("url");
|
||||||
List<IBase> values = urlChild.getAccessor().getValues(nextLink);
|
List<IBase> values = urlChild.getAccessor().getValues(nextLink);
|
||||||
for (IBase nextUrl : values) {
|
for (IBase nextUrl : values) {
|
||||||
|
@ -91,12 +107,40 @@ public class BundleUtil {
|
||||||
return nextValue.getValueAsString();
|
return nextValue.getValueAsString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isRelationMatch(FhirContext theContext, IBaseBundle theBundle, String value, String matching, boolean theIsPreviousCheck) {
|
||||||
|
if ( ! theIsPreviousCheck) {
|
||||||
|
return value.equals(matching);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( previousOrPrev.contains(value) ) {
|
||||||
|
validateUniqueOrMatchingPreviousValues(theContext, theBundle);
|
||||||
|
if ( previousOrPrev.contains(matching) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (value.equals(matching));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validateUniqueOrMatchingPreviousValues(FhirContext theContext, IBaseBundle theBundle) {
|
||||||
|
String previousLink = getLinkNoCheck(theContext, theBundle, PREVIOUS);
|
||||||
|
String prevLink = getLinkNoCheck(theContext, theBundle, PREV);
|
||||||
|
if (prevLink != null && previousLink != null) {
|
||||||
|
if ( ! previousLink.equals(prevLink)) {
|
||||||
|
String msg = DIFFERENT_LINK_ERROR_MSG.replace("$PREVIOUS", previousLink).replace("$PREV", prevLink);
|
||||||
|
throw new InternalErrorException(Msg.code(2368) + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLinkNoCheck(FhirContext theContext, IBaseBundle theBundle, String theLinkRelation) {
|
||||||
|
return getLinkUrlOfType(theContext, theBundle, theLinkRelation, false);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static List<Pair<String, IBaseResource>> getBundleEntryUrlsAndResources(FhirContext theContext, IBaseBundle theBundle) {
|
public static List<Pair<String, IBaseResource>> getBundleEntryUrlsAndResources(FhirContext theContext, IBaseBundle theBundle) {
|
||||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
||||||
|
@ -160,6 +204,7 @@ public class BundleUtil {
|
||||||
BaseRuntimeChildDefinition entryChild = def.getChildByName("total");
|
BaseRuntimeChildDefinition entryChild = def.getChildByName("total");
|
||||||
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
|
List<IBase> entries = entryChild.getAccessor().getValues(theBundle);
|
||||||
if (entries.size() > 0) {
|
if (entries.size() > 0) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
IPrimitiveType<Number> typeElement = (IPrimitiveType<Number>) entries.get(0);
|
IPrimitiveType<Number> typeElement = (IPrimitiveType<Number>) entries.get(0);
|
||||||
if (typeElement != null && typeElement.getValue() != null) {
|
if (typeElement != null && typeElement.getValue() != null) {
|
||||||
return typeElement.getValue().intValue();
|
return typeElement.getValue().intValue();
|
||||||
|
@ -171,6 +216,7 @@ public class BundleUtil {
|
||||||
public static void setTotal(FhirContext theContext, IBaseBundle theBundle, Integer theTotal) {
|
public static void setTotal(FhirContext theContext, IBaseBundle theBundle, Integer theTotal) {
|
||||||
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
RuntimeResourceDefinition def = theContext.getResourceDefinition(theBundle);
|
||||||
BaseRuntimeChildDefinition entryChild = def.getChildByName("total");
|
BaseRuntimeChildDefinition entryChild = def.getChildByName("total");
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
IPrimitiveType<Integer> value = (IPrimitiveType<Integer>) entryChild.getChildByName("total").newInstance();
|
IPrimitiveType<Integer> value = (IPrimitiveType<Integer>) entryChild.getChildByName("total").newInstance();
|
||||||
value.setValue(theTotal);
|
value.setValue(theTotal);
|
||||||
entryChild.getMutator().setValue(theBundle, value);
|
entryChild.getMutator().setValue(theBundle, value);
|
||||||
|
@ -194,11 +240,11 @@ public class BundleUtil {
|
||||||
* 1. Deletes
|
* 1. Deletes
|
||||||
* 2. Creates
|
* 2. Creates
|
||||||
* 3. Updates
|
* 3. Updates
|
||||||
*
|
* <p>
|
||||||
* Furthermore, within these operation types, the entries will be sorted based on the order in which they should be processed
|
* Furthermore, within these operation types, the entries will be sorted based on the order in which they should be processed
|
||||||
* e.g. if you have 2 CREATEs, one for a Patient, and one for an Observation which has this Patient as its Subject,
|
* e.g. if you have 2 CREATEs, one for a Patient, and one for an Observation which has this Patient as its Subject,
|
||||||
* the patient will come first, then the observation.
|
* the patient will come first, then the observation.
|
||||||
*
|
* <p>
|
||||||
* In cases of there being a cyclic dependency (e.g. Organization/1 is partOf Organization/2 and Organization/2 is partOf Organization/1)
|
* In cases of there being a cyclic dependency (e.g. Organization/1 is partOf Organization/2 and Organization/2 is partOf Organization/1)
|
||||||
* this function will throw an IllegalStateException.
|
* this function will throw an IllegalStateException.
|
||||||
*
|
*
|
||||||
|
@ -207,12 +253,11 @@ public class BundleUtil {
|
||||||
*/
|
*/
|
||||||
public static void sortEntriesIntoProcessingOrder(FhirContext theContext, IBaseBundle theBundle) throws IllegalStateException {
|
public static void sortEntriesIntoProcessingOrder(FhirContext theContext, IBaseBundle theBundle) throws IllegalStateException {
|
||||||
Map<BundleEntryParts, IBase> partsToIBaseMap = getPartsToIBaseMap(theContext, theBundle);
|
Map<BundleEntryParts, IBase> partsToIBaseMap = getPartsToIBaseMap(theContext, theBundle);
|
||||||
LinkedHashSet<IBase> retVal = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
//Get all deletions.
|
//Get all deletions.
|
||||||
LinkedHashSet<IBase> deleteParts = sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.DELETE, partsToIBaseMap);
|
LinkedHashSet<IBase> deleteParts = sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.DELETE, partsToIBaseMap);
|
||||||
validatePartsNotNull(deleteParts);
|
validatePartsNotNull(deleteParts);
|
||||||
retVal.addAll(deleteParts);
|
LinkedHashSet<IBase> retVal = new LinkedHashSet<>(deleteParts);
|
||||||
|
|
||||||
//Get all Creations
|
//Get all Creations
|
||||||
LinkedHashSet<IBase> createParts= sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.POST, partsToIBaseMap);
|
LinkedHashSet<IBase> createParts= sortEntriesOfTypeIntoProcessingOrder(theContext, RequestTypeEnum.POST, partsToIBaseMap);
|
||||||
|
@ -408,8 +453,7 @@ public class BundleUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchBundleEntryParts parts = new SearchBundleEntryParts(fullUrl, resource, matchMode);
|
return new SearchBundleEntryParts(fullUrl, resource, matchMode);
|
||||||
return parts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -485,8 +529,7 @@ public class BundleUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BundleEntryParts parts = new BundleEntryParts(fullUrl, requestType, url, resource, conditionalUrl);
|
return new BundleEntryParts(fullUrl, requestType, url, resource, conditionalUrl);
|
||||||
return parts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -540,12 +583,12 @@ public class BundleUtil {
|
||||||
boolean isPatch = false;
|
boolean isPatch = false;
|
||||||
if (thePayloadResource instanceof IBaseBinary) {
|
if (thePayloadResource instanceof IBaseBinary) {
|
||||||
String contentType = ((IBaseBinary) thePayloadResource).getContentType();
|
String contentType = ((IBaseBinary) thePayloadResource).getContentType();
|
||||||
try {
|
try {
|
||||||
PatchTypeEnum.forContentTypeOrThrowInvalidRequestException(theContext, contentType);
|
PatchTypeEnum.forContentTypeOrThrowInvalidRequestException(theContext, contentType);
|
||||||
isPatch = true;
|
isPatch = true;
|
||||||
} catch (InvalidRequestException e) {
|
} catch (InvalidRequestException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isPatch;
|
return isPatch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 5004
|
||||||
|
title: "Previously when requesting `previous` or `prev` link using `BundleUtil.getLinkUrlOfType`, only the literal requested
|
||||||
|
link was returned. Now when requesting either `previous` or `prev` `previous` or `prev` link is returned.
|
||||||
|
If both exist, equality is validated and exception is thrown on failure."
|
|
@ -1,11 +1,14 @@
|
||||||
package ca.uhn.fhir.util.bundle;
|
package ca.uhn.fhir.util.bundle;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.i18n.Msg;
|
||||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.util.BundleBuilder;
|
import ca.uhn.fhir.util.BundleBuilder;
|
||||||
import ca.uhn.fhir.util.BundleUtil;
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
|
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
|
||||||
import org.hl7.fhir.r4.model.Medication;
|
import org.hl7.fhir.r4.model.Medication;
|
||||||
|
@ -16,12 +19,14 @@ import org.hl7.fhir.r4.model.Quantity;
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.hl7.fhir.r4.model.UriType;
|
import org.hl7.fhir.r4.model.UriType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.util.BundleUtil.DIFFERENT_LINK_ERROR_MSG;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
@ -33,39 +38,135 @@ import static org.hl7.fhir.r4.model.Bundle.HTTPVerb.GET;
|
||||||
import static org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST;
|
import static org.hl7.fhir.r4.model.Bundle.HTTPVerb.POST;
|
||||||
import static org.hl7.fhir.r4.model.Bundle.HTTPVerb.PUT;
|
import static org.hl7.fhir.r4.model.Bundle.HTTPVerb.PUT;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class BundleUtilTest {
|
public class BundleUtilTest {
|
||||||
|
|
||||||
private static FhirContext ourCtx = FhirContext.forR4();
|
private static final FhirContext ourCtx = FhirContext.forR4Cached();
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetLink() {
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
b.getLinkOrCreate("prev").setUrl("http://bar");
|
|
||||||
b.getLinkOrCreate("next").setUrl("http://foo");
|
|
||||||
assertEquals("http://foo", BundleUtil.getLinkUrlOfType(ourCtx, b, "next"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Nested
|
||||||
public void testGetLinkDoesntExist() {
|
public class TestGetLinkUrlOfType {
|
||||||
Bundle b = new Bundle();
|
|
||||||
b.getLinkOrCreate("prev").setUrl("http://bar");
|
@Test
|
||||||
assertEquals(null, BundleUtil.getLinkUrlOfType(ourCtx, b, "next"));
|
public void testGetNextExists() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
b.getLinkOrCreate("next").setUrl("http://foo");
|
||||||
|
assertEquals("http://foo", BundleUtil.getLinkUrlOfType(ourCtx, b, "next"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetNextDoesntExist() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
assertNull(BundleUtil.getLinkUrlOfType(ourCtx, b, "next"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
public class TestGetPreviousLink {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrevious_exists_and_no_prev() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, IBaseBundle.LINK_PREV));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrevious_exists_and_prev_also_and_equals() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, IBaseBundle.LINK_PREV));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrevious_exists_and_prev_also_and_different_must_throw() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://foo");
|
||||||
|
InternalErrorException thrown = assertThrows(InternalErrorException.class,
|
||||||
|
() -> BundleUtil.getLinkUrlOfType(ourCtx, b, IBaseBundle.LINK_PREV));
|
||||||
|
|
||||||
|
String expectedExceptionMsg = Msg.code(2368) + DIFFERENT_LINK_ERROR_MSG
|
||||||
|
.replace("$PREVIOUS", "http://bar").replace("$PREV", "http://foo");
|
||||||
|
assertEquals(expectedExceptionMsg, thrown.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrevious_doesnt_exist_neither_prev() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
assertNull(BundleUtil.getLinkUrlOfType(ourCtx, b, IBaseBundle.LINK_PREV));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrevious_doesnt_exist_but_prev_does() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, IBaseBundle.LINK_PREV));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrev_exists_and_no_previous() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, "prev"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrev_exists_and_previous_also_and_equals() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, "prev"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrev_exists_and_previous_also_and_different_must_throw() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
b.getLinkOrCreate("prev").setUrl("http://foo");
|
||||||
|
InternalErrorException thrown = assertThrows(InternalErrorException.class,
|
||||||
|
() -> BundleUtil.getLinkUrlOfType(ourCtx, b, "prev"));
|
||||||
|
|
||||||
|
String expectedExceptionMsg = Msg.code(2368) + DIFFERENT_LINK_ERROR_MSG
|
||||||
|
.replace("$PREVIOUS", "http://bar").replace("$PREV", "http://foo");
|
||||||
|
assertEquals(expectedExceptionMsg, thrown.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrev_doesnt_exist_neither_previous() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
assertNull(BundleUtil.getLinkUrlOfType(ourCtx, b, "prev"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrev_doesnt_exist_but_previous_does() {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://bar");
|
||||||
|
assertEquals("http://bar", BundleUtil.getLinkUrlOfType(ourCtx, b, "prev"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTotal() {
|
public void testGetTotal() {
|
||||||
Bundle b = new Bundle();
|
Bundle b = new Bundle();
|
||||||
b.setTotal(999);
|
b.setTotal(999);
|
||||||
assertEquals(999, BundleUtil.getTotal(ourCtx, b).intValue());
|
Integer total = BundleUtil.getTotal(ourCtx, b);
|
||||||
|
assertNotNull(total);
|
||||||
|
assertEquals(999, total.intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTotalNull() {
|
public void testGetTotalNull() {
|
||||||
Bundle b = new Bundle();
|
Bundle b = new Bundle();
|
||||||
assertEquals(null, BundleUtil.getTotal(ourCtx, b));
|
assertNull(BundleUtil.getTotal(ourCtx, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -148,7 +249,6 @@ public class BundleUtilTest {
|
||||||
|
|
||||||
assertThat(b.getEntry(), hasSize(4));
|
assertThat(b.getEntry(), hasSize(4));
|
||||||
|
|
||||||
List<Bundle.BundleEntryComponent> entry = b.getEntry();
|
|
||||||
int observationIndex = getIndexOfEntryWithId("Observation/O1", b);
|
int observationIndex = getIndexOfEntryWithId("Observation/O1", b);
|
||||||
int patientIndex = getIndexOfEntryWithId("Patient/P1", b);
|
int patientIndex = getIndexOfEntryWithId("Patient/P1", b);
|
||||||
int organizationIndex = getIndexOfEntryWithId("Organization/Org1", b);
|
int organizationIndex = getIndexOfEntryWithId("Organization/Org1", b);
|
||||||
|
@ -182,7 +282,7 @@ public class BundleUtilTest {
|
||||||
try {
|
try {
|
||||||
BundleUtil.sortEntriesIntoProcessingOrder(ourCtx, b);
|
BundleUtil.sortEntriesIntoProcessingOrder(ourCtx, b);
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException e ) {
|
} catch (IllegalStateException ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,71 +374,72 @@ public class BundleUtilTest {
|
||||||
@Test
|
@Test
|
||||||
public void testBundleToSearchBundleEntryParts() {
|
public void testBundleToSearchBundleEntryParts() {
|
||||||
//Given
|
//Given
|
||||||
String bundleString = "{\n" +
|
String bundleString = """
|
||||||
" \"resourceType\": \"Bundle\",\n" +
|
{
|
||||||
" \"id\": \"bd194b7f-ac1e-429a-a206-ee2c470f23b5\",\n" +
|
"resourceType": "Bundle",
|
||||||
" \"meta\": {\n" +
|
"id": "bd194b7f-ac1e-429a-a206-ee2c470f23b5",
|
||||||
" \"lastUpdated\": \"2021-10-18T16:25:55.330-07:00\"\n" +
|
"meta": {
|
||||||
" },\n" +
|
"lastUpdated": "2021-10-18T16:25:55.330-07:00"
|
||||||
" \"type\": \"searchset\",\n" +
|
},
|
||||||
" \"total\": 1,\n" +
|
"type": "searchset",
|
||||||
" \"link\": [\n" +
|
"total": 1,
|
||||||
" {\n" +
|
"link": [
|
||||||
" \"relation\": \"self\",\n" +
|
{
|
||||||
" \"url\": \"http://localhost:8000/Patient?_count=1&_id=pata&_revinclude=Condition%3Asubject%3APatient\"\n" +
|
"relation": "self",
|
||||||
" }\n" +
|
"url": "http://localhost:8000/Patient?_count=1&_id=pata&_revinclude=Condition%3Asubject%3APatient"
|
||||||
" ],\n" +
|
}
|
||||||
" \"entry\": [\n" +
|
],
|
||||||
" {\n" +
|
"entry": [
|
||||||
" \"fullUrl\": \"http://localhost:8000/Patient/pata\",\n" +
|
{
|
||||||
" \"resource\": {\n" +
|
"fullUrl": "http://localhost:8000/Patient/pata",
|
||||||
" \"resourceType\": \"Patient\",\n" +
|
"resource": {
|
||||||
" \"id\": \"pata\",\n" +
|
"resourceType": "Patient",
|
||||||
" \"meta\": {\n" +
|
"id": "pata",
|
||||||
" \"versionId\": \"1\",\n" +
|
"meta": {
|
||||||
" \"lastUpdated\": \"2021-10-18T16:25:48.954-07:00\",\n" +
|
"versionId": "1",
|
||||||
" \"source\": \"#rnEjIucr8LR6Ze3x\"\n" +
|
"lastUpdated": "2021-10-18T16:25:48.954-07:00",
|
||||||
" },\n" +
|
"source": "#rnEjIucr8LR6Ze3x"
|
||||||
" \"name\": [\n" +
|
},
|
||||||
" {\n" +
|
"name": [
|
||||||
" \"family\": \"Simpson\",\n" +
|
{
|
||||||
" \"given\": [\n" +
|
"family": "Simpson",
|
||||||
" \"Homer\",\n" +
|
"given": [
|
||||||
" \"J\"\n" +
|
"Homer",
|
||||||
" ]\n" +
|
"J"
|
||||||
" }\n" +
|
]
|
||||||
" ]\n" +
|
}
|
||||||
" },\n" +
|
]
|
||||||
" \"search\": {\n" +
|
},
|
||||||
" \"mode\": \"match\"\n" +
|
"search": {
|
||||||
" }\n" +
|
"mode": "match"
|
||||||
" },\n" +
|
}
|
||||||
" {\n" +
|
},
|
||||||
" \"fullUrl\": \"http://localhost:8000/Condition/1626\",\n" +
|
{
|
||||||
" \"resource\": {\n" +
|
"fullUrl": "http://localhost:8000/Condition/1626",
|
||||||
" \"resourceType\": \"Condition\",\n" +
|
"resource": {
|
||||||
" \"id\": \"1626\",\n" +
|
"resourceType": "Condition",
|
||||||
" \"meta\": {\n" +
|
"id": "1626",
|
||||||
" \"versionId\": \"1\",\n" +
|
"meta": {
|
||||||
" \"lastUpdated\": \"2021-10-18T16:25:51.672-07:00\",\n" +
|
"versionId": "1",
|
||||||
" \"source\": \"#gSOcGAdA3acaaNq1\"\n" +
|
"lastUpdated": "2021-10-18T16:25:51.672-07:00",
|
||||||
" },\n" +
|
"source": "#gSOcGAdA3acaaNq1"
|
||||||
" \"identifier\": [\n" +
|
},
|
||||||
" {\n" +
|
"identifier": [
|
||||||
" \"system\": \"urn:hssc:musc:conditionid\",\n" +
|
{
|
||||||
" \"value\": \"1064115000.1.5\"\n" +
|
"system": "urn:hssc:musc:conditionid",
|
||||||
" }\n" +
|
"value": "1064115000.1.5"
|
||||||
" ],\n" +
|
}
|
||||||
" \"subject\": {\n" +
|
],
|
||||||
" \"reference\": \"Patient/pata\"\n" +
|
"subject": {
|
||||||
" }\n" +
|
"reference": "Patient/pata"
|
||||||
" },\n" +
|
}
|
||||||
" \"search\": {\n" +
|
},
|
||||||
" \"mode\": \"include\"\n" +
|
"search": {
|
||||||
" }\n" +
|
"mode": "include"
|
||||||
" }\n" +
|
}
|
||||||
" ]\n" +
|
}
|
||||||
"}";
|
]
|
||||||
|
}""";
|
||||||
|
|
||||||
Bundle bundle = ourCtx.newJsonParser().parseResource(Bundle.class, bundleString);
|
Bundle bundle = ourCtx.newJsonParser().parseResource(Bundle.class, bundleString);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue