Skip to content

Commit

Permalink
Fix #209 - _revinclude results from JPA server should have a Bundle.e…
Browse files Browse the repository at this point in the history
…ntry.search.mode of "include" and not "match". Thanks to Josh Mandel for reporting!
  • Loading branch information
jamesagnew committed Aug 24, 2015
1 parent 1137602 commit 60339d6
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 55 deletions.
Expand Up @@ -526,7 +526,7 @@ public TagList parseTagList(String theString) {
@SuppressWarnings("cast")
protected List<? extends IBase> preProcessValues(BaseRuntimeChildDefinition metaChildUncast, List<? extends IBase> theValues) {
if (myContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2_HL7ORG)) {
if (shouldAddSubsettedTag()) {
if (shouldAddSubsettedTag() && metaChildUncast.getValidChildNames().contains("meta")) {
BaseRuntimeElementDefinition<?> childByName = metaChildUncast.getChildByName("meta");
if (childByName instanceof BaseRuntimeElementCompositeDefinition<?>) {
BaseRuntimeElementCompositeDefinition<?> metaChildUncast1 = (BaseRuntimeElementCompositeDefinition<?>) childByName;
Expand Down
Expand Up @@ -1446,7 +1446,7 @@ public IBundleProvider history(Long theId, Date theSince) {
return retVal;
}

private void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResource> theResourceListToPopulate, BundleEntrySearchModeEnum theBundleEntryStatus) {
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResource> theResourceListToPopulate, Set<Long> theRevIncludedPids) {
if (theIncludePids.isEmpty()) {
return;
}
Expand All @@ -1472,15 +1472,19 @@ private void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResou
continue;
}

ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(resource, theBundleEntryStatus);
if (theRevIncludedPids.contains(next.getId())) {
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(resource, BundleEntrySearchModeEnum.INCLUDE);
} else {
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(resource, BundleEntrySearchModeEnum.MATCH);
}

theResourceListToPopulate.set(index, resource);
}
}

protected void loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes) {
private Set<Long> loadReverseIncludes(List<Long> theMatches, Set<Include> theRevIncludes) {
if (theMatches.size() == 0) {
return;
return Collections.emptySet();
}

HashSet<Long> pidsToInclude = new HashSet<Long>();
Expand Down Expand Up @@ -1528,6 +1532,7 @@ protected void loadReverseIncludes(List<Long> theMatches, Set<Include> theRevInc
}

theMatches.addAll(pidsToInclude);
return pidsToInclude;
}

@Override
Expand Down Expand Up @@ -1890,8 +1895,11 @@ public IBundleProvider search(final SearchParameterMap theParams) {
}

// Load _revinclude resources
final Set<Long> revIncludedPids;
if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) {
loadReverseIncludes(pids, theParams.getRevIncludes());
revIncludedPids = loadReverseIncludes(pids, theParams.getRevIncludes());
} else {
revIncludedPids = Collections.emptySet();
}

IBundleProvider retVal = new IBundleProvider() {
Expand All @@ -1910,8 +1918,8 @@ public List<IBaseResource> doInTransaction(TransactionStatus theStatus) {

// Execute the query and make sure we return distinct results
List<IBaseResource> retVal = new ArrayList<IBaseResource>();
loadResourcesByPid(pidsSubList, retVal, BundleEntrySearchModeEnum.MATCH);

loadResourcesByPid(pidsSubList, retVal, revIncludedPids);
/*
* Load _include resources - Note that _revincludes are handled differently than _include ones, as
* they are counted towards the total count and paged, so they are loaded outside the bundle provider
Expand Down
Expand Up @@ -69,6 +69,7 @@
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
Expand Down Expand Up @@ -1304,10 +1305,13 @@ public void testReverseIncludes() {
map.setRevIncludes(Collections.singleton(Patient.INCLUDE_ORGANIZATION));
IBundleProvider resultsP = ourOrganizationDao.search(map);
assertEquals(2, resultsP.size());

List<IBaseResource> results = resultsP.getResources(0, resultsP.size());
assertEquals(2, results.size());
assertEquals(Organization.class, results.get(0).getClass());
assertEquals(BundleEntrySearchModeEnum.MATCH, ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get((IResource) results.get(0)));
assertEquals(Patient.class, results.get(1).getClass());
assertEquals(BundleEntrySearchModeEnum.INCLUDE, ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get((IResource) results.get(1)));
}

@Test
Expand Down
Expand Up @@ -214,7 +214,7 @@ public void validate(List<ValidationMessage> errors, JsonObject object) throws E
}
@Override
public void validate(List<ValidationMessage> errors, Element element, String profile) throws Exception {
StructureDefinition p = context.getProfiles().get(profile);
StructureDefinition p = context.getProfile(profile);
if (p == null)
throw new Exception("StructureDefinition '"+profile+"' not found");
validateResource(errors, new DOMWrapperElement(element), p, requiresResourceId, null);
Expand All @@ -231,7 +231,7 @@ public void validate(List<ValidationMessage> errors, JsonObject object, Structur

@Override
public void validate(List<ValidationMessage> errors, JsonObject object, String profile) throws Exception {
StructureDefinition p = context.getProfiles().get(profile);
StructureDefinition p = context.getProfile(profile);
if (p == null)
throw new Exception("StructureDefinition '"+profile+"' not found");
validateResource(errors, new JsonWrapperElement(object), p, requiresResourceId, null);
Expand All @@ -245,7 +245,7 @@ public void validate(List<ValidationMessage> errors, Document document) throws E
@Override
public void validate(List<ValidationMessage> errors, Document document, String profile) throws Exception {
checkForProcessingInstruction(errors, document);
StructureDefinition p = context.getProfiles().get(profile);
StructureDefinition p = context.getProfile(profile);
if (p == null)
throw new Exception("StructureDefinition '"+profile+"' not found");
validateResource(errors, new DOMWrapperElement(document.getDocumentElement()), p, requiresResourceId, null);
Expand Down Expand Up @@ -833,7 +833,7 @@ private void validateResource(List<ValidationMessage> errors, WrapperElement ele
if (ok) {
String resourceName = element.getResourceType();
if (profile == null) {
profile = context.getProfiles().get("http://hl7.org/fhir/StructureDefinition/"+resourceName);
profile = context.getProfile("http://hl7.org/fhir/StructureDefinition/"+resourceName);
ok = rule(errors, IssueType.INVALID, element.line(), element.col(), stack.addToLiteralPath(resourceName), profile != null, "No profile found for resource type '"+resourceName+"'");
} else {
String type = profile.hasConstrainedType() ? profile.getConstrainedType() : profile.getName();
Expand Down Expand Up @@ -891,7 +891,7 @@ private void checkDeclaredProfiles(List<ValidationMessage> errors, WrapperElemen
String ref = profile.getAttribute("value");
String p = stack.addToLiteralPath("meta", "profile", ":"+Integer.toString(i));
if (rule(errors, IssueType.INVALID, element.line(), element.col(), p, !Utilities.noString(ref), "StructureDefinition reference invalid")) {
StructureDefinition pr = context.getProfiles().get(ref);
StructureDefinition pr = context.getProfile(ref);
if (warning(errors, IssueType.INVALID, element.line(), element.col(), p, pr != null, "StructureDefinition reference could not be resolved")) {
if (rule(errors, IssueType.STRUCTURE, element.line(), element.col(), p, pr.hasSnapshot(), "StructureDefinition has no snapshot - validation is against the snapshot, so it must be provided")) {
validateElement(errors, pr, pr.getSnapshot().getElement().get(0), null, null, element, element.getName(), stack);
Expand Down Expand Up @@ -1008,7 +1008,7 @@ private WrapperElement resolveInBundle(List<WrapperElement> entries, String ref,
}

private StructureDefinition getProfileForType(String type) throws Exception {
return context.getProfiles().get("http://hl7.org/fhir/StructureDefinition/"+type);
return context.getProfile("http://hl7.org/fhir/StructureDefinition/"+type);
}

private void validateObservation(List<ValidationMessage> errors, WrapperElement element, NodeStack stack) {
Expand Down Expand Up @@ -1267,7 +1267,7 @@ private ElementDefinition resolveNameReference(StructureDefinitionSnapshotCompon

private ElementDefinition resolveType(String type) {
String url = "http://hl7.org/fhir/StructureDefinition/"+type;
StructureDefinition sd = context.getProfiles().get(url);
StructureDefinition sd = context.getProfile(url);
if (sd == null || !sd.hasSnapshot())
return null;
else
Expand Down Expand Up @@ -1422,7 +1422,7 @@ private String tryParse(String ref) {
}

private String checkResourceType(String type) {
if (context.getProfiles().containsKey("http://hl7.org/fhir/StructureDefinition/"+type))
if (context.getProfile("http://hl7.org/fhir/StructureDefinition/"+type) != null)
return type;
else
return null;
Expand Down Expand Up @@ -1451,7 +1451,7 @@ private StructureDefinition resolveProfile(StructureDefinition profile, String p
return null;
}
else
return context.getProfiles().get(pr);
return context.getProfile(pr);
}

private StructureDefinition checkExtension(List<ValidationMessage> errors, String path, WrapperElement element, ElementDefinition def, StructureDefinition profile, NodeStack stack) throws Exception {
Expand Down Expand Up @@ -1493,7 +1493,7 @@ private boolean allowUnknownExtension(String url) {
}

private boolean isKnownType(String code) {
return context.getProfiles().get(code.toLowerCase()) != null;
return context.getProfile(code.toLowerCase()) != null;
}

private ElementDefinition getElementByPath(StructureDefinition definition, String path) {
Expand Down Expand Up @@ -1613,7 +1613,7 @@ private String tail(String path) {
private void validateContains(List<ValidationMessage> errors, String path, ElementDefinition child, ElementDefinition context, WrapperElement element, NodeStack stack, boolean needsId) throws Exception {
WrapperElement e = element.isXml() ? element.getFirstChild() : element;
String resourceName = e.getResourceType();
StructureDefinition profile = this.context.getProfiles().get("http://hl7.org/fhir/StructureDefinition/"+resourceName);
StructureDefinition profile = this.context.getProfile("http://hl7.org/fhir/StructureDefinition/"+resourceName);
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.addToLiteralPath(resourceName), profile != null, "No profile found for contained resource of type '"+resourceName+"'"))
validateResource(errors, e, profile, needsId, stack);
}
Expand Down
Expand Up @@ -14,74 +14,62 @@
public class FhirInstanceValidatorTest {

private static FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorTest.class);

private FhirValidator val;

@Before
public void before() {
val = ourCtx.newValidator();
val.setValidateAgainstStandardSchema(false);
val.setValidateAgainstStandardSchematron(false);
val.registerValidatorModule(new FhirInstanceValidator());
}

@Test
public void testValidateJsonResource() {
String input = "{"
+ "\"resourceType\":\"Patient\","
+ "\"id\":\"123\""
+ "}";

String input = "{" + "\"resourceType\":\"Patient\"," + "\"id\":\"123\"" + "}";

ValidationResult output = val.validateWithResult(input);
assertEquals(output.toString(), 0, output.getMessages().size());
}

@Test
public void testValidateJsonResourceBadAttributes() {
String input = "{"
+ "\"resourceType\":\"Patient\","
+ "\"id\":\"123\","
+ "\"foo\":\"123\""
+ "}";


String input = "{" + "\"resourceType\":\"Patient\"," + "\"id\":\"123\"," + "\"foo\":\"123\"" + "}";

ValidationResult output = val.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
}

@Test
public void testValidateResourceWithReference() {
QuestionnaireResponse resp = new QuestionnaireResponse();
resp.setStatus(QuestionnaireResponseStatus.COMPLETED);
resp.getQuestionnaire().setReference("Questionnaire/1234");

ValidationResult output = val.validateWithResult(resp);
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output.toOperationOutcome()));
// TODO: get this working
// assertEquals(output.toString(), 0, output.getMessages().size());
}

@Test
public void testValidateXmlResource() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\">"
+ "<id value=\"123\"/>"
+ "</Patient>";

String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "</Patient>";

ValidationResult output = val.validateWithResult(input);
assertEquals(output.toString(), 0, output.getMessages().size());
}


@Test
public void testValidateXmlResourceBadAttributes() {
String input = "<Patient xmlns=\"http://hl7.org/fhir\">"
+ "<id value=\"123\"/>"
+ "<foo value=\"222\"/>"
+ "</Patient>";

String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "<foo value=\"222\"/>" + "</Patient>";

ValidationResult output = val.validateWithResult(input);
assertEquals(output.toString(), 1, output.getMessages().size());
assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
}



@Test
public void testValidateResourceWithReference() {
QuestionnaireResponse resp = new QuestionnaireResponse();
resp.setStatus(QuestionnaireResponseStatus.COMPLETED);
resp.getQuestionnaire().setReference("Questionnaire/1234");

ValidationResult output = val.validateWithResult(resp);
assertEquals(output.toString(), 0, output.getMessages().size());
}

}
4 changes: 4 additions & 0 deletions src/changes/changes.xml
Expand Up @@ -100,6 +100,10 @@
HAPI-FHIR now has support for _summary and _elements parameters, in server, client,
and JPA server.
</action>
<action type="fix" fix="209">
_revinclude results from JPA server should have a Bundle.entry.search.mode of
"include" and not "match". Thanks to Josh Mandel for reporting!
</action>
</release>
<release version="1.1" date="2015-07-13">
<action type="add">
Expand Down

0 comments on commit 60339d6

Please sign in to comment.