Fix validation error when Bundle has no type
This commit is contained in:
parent
fddda443a2
commit
78b7188fbc
|
@ -71,10 +71,12 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc {
|
||||||
|
|
||||||
private void deleteSearch(final Long theSearchPid) {
|
private void deleteSearch(final Long theSearchPid) {
|
||||||
Search searchToDelete = mySearchDao.findOne(theSearchPid);
|
Search searchToDelete = mySearchDao.findOne(theSearchPid);
|
||||||
ourLog.info("Deleting search {}/{} - Created[{}] -- Last returned[{}]", searchToDelete.getId(), searchToDelete.getUuid(), searchToDelete.getCreated(), searchToDelete.getSearchLastReturned());
|
if (searchToDelete != null) {
|
||||||
mySearchIncludeDao.deleteForSearch(searchToDelete.getId());
|
ourLog.info("Deleting search {}/{} - Created[{}] -- Last returned[{}]", searchToDelete.getId(), searchToDelete.getUuid(), searchToDelete.getCreated(), searchToDelete.getSearchLastReturned());
|
||||||
mySearchResultDao.deleteForSearch(searchToDelete.getId());
|
mySearchIncludeDao.deleteForSearch(searchToDelete.getId());
|
||||||
mySearchDao.delete(searchToDelete);
|
mySearchResultDao.deleteForSearch(searchToDelete.getId());
|
||||||
|
mySearchDao.delete(searchToDelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -42,7 +42,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
public class SubscriptionsRequireManualActivationInterceptorDstu2 extends ServerOperationInterceptorAdapter {
|
public class SubscriptionsRequireManualActivationInterceptorDstu2 extends ServerOperationInterceptorAdapter {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("mySubscriptionDaoR4")
|
@Qualifier("mySubscriptionDaoDstu2")
|
||||||
private IFhirResourceDao<Subscription> myDao;
|
private IFhirResourceDao<Subscription> myDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,8 +13,8 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
|
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
|
||||||
import org.hl7.fhir.dstu3.context.IWorkerContext;
|
import org.hl7.fhir.dstu3.context.IWorkerContext;
|
||||||
import org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult;
|
import org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult;
|
||||||
|
@ -105,6 +105,7 @@ import org.w3c.dom.Node;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
import ca.uhn.fhir.util.ObjectUtil;
|
import ca.uhn.fhir.util.ObjectUtil;
|
||||||
|
|
||||||
|
@ -292,8 +293,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
source = Source.InstanceValidator;
|
source = Source.InstanceValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isNoInvariantChecks() {
|
public boolean isNoInvariantChecks() {
|
||||||
return noInvariantChecks;
|
return noInvariantChecks;
|
||||||
|
@ -1358,33 +1357,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
checkFixedValue(errors, path + ".denominator", focus.getNamedChild("denominator"), fixed.getDenominator(), "denominator", focus);
|
checkFixedValue(errors, path + ".denominator", focus.getNamedChild("denominator"), fixed.getDenominator(), "denominator", focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Reference readAsReference(Element item) {
|
|
||||||
Reference r = new Reference();
|
|
||||||
r.setDisplay(item.getNamedChildValue("display"));
|
|
||||||
r.setReference(item.getNamedChildValue("reference"));
|
|
||||||
List<Element> identifier = item.getChildrenByName("identifier");
|
|
||||||
if (identifier.isEmpty() == false) {
|
|
||||||
r.setIdentifier(readAsIdentifier(identifier.get(0)));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
private Identifier readAsIdentifier(Element item) {
|
|
||||||
Identifier r = new Identifier();
|
|
||||||
r.setSystem(item.getNamedChildValue("system"));
|
|
||||||
r.setValue(item.getNamedChildValue("value"));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkReference(Object appContext, List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition container, String parentType, NodeStack stack) throws FHIRException, IOException {
|
private void checkReference(Object appContext, List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition container, String parentType, NodeStack stack) throws FHIRException, IOException {
|
||||||
Reference reference = readAsReference(element);
|
String ref = null;
|
||||||
|
try {
|
||||||
String ref = reference.getReference();
|
// Do this inside a try because invalid instances might provide more than one reference.
|
||||||
if (Utilities.noString(ref)) {
|
ref = element.getNamedChildValue("reference");
|
||||||
if (Utilities.noString(reference.getIdentifier().getSystem()) && Utilities.noString(reference.getIdentifier().getValue())) {
|
} catch (Error e) {
|
||||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !Utilities.noString(element.getNamedChildValue("display")), "A Reference without an actual reference or identifier should have a display");
|
|
||||||
}
|
}
|
||||||
return;
|
if (Utilities.noString(ref)) {
|
||||||
}
|
// todo - what should we do in this case?
|
||||||
|
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !Utilities.noString(element.getNamedChildValue("display")), "A Reference without an actual reference should have a display");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Element we = localResolve(ref, stack, errors, path);
|
Element we = localResolve(ref, stack, errors, path);
|
||||||
String refType;
|
String refType;
|
||||||
|
@ -2816,6 +2801,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
List<Element> entries = new ArrayList<Element>();
|
List<Element> entries = new ArrayList<Element>();
|
||||||
bundle.getNamedChildren("entry", entries);
|
bundle.getNamedChildren("entry", entries);
|
||||||
String type = bundle.getNamedChildValue("type");
|
String type = bundle.getNamedChildValue("type");
|
||||||
|
type = StringUtils.defaultString(type);
|
||||||
|
|
||||||
if (entries.size() == 0) {
|
if (entries.size() == 0) {
|
||||||
rule(errors, IssueType.INVALID, stack.getLiteralPath(), !(type.equals("document") || type.equals("message")), "Documents or Messages must contain at least one entry");
|
rule(errors, IssueType.INVALID, stack.getLiteralPath(), !(type.equals("document") || type.equals("message")), "Documents or Messages must contain at least one entry");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -667,9 +667,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
try {
|
try {
|
||||||
if (context.fetchResourceWithException(ValueSet.class, system) != null) {
|
if (context.fetchResourceWithException(ValueSet.class, system) != null) {
|
||||||
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Invalid System URI: "+system+" - cannot use a value set URI as a system");
|
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, false, "Invalid System URI: "+system+" - cannot use a value set URI as a system");
|
||||||
return false;
|
// Lloyd: This error used to prohibit checking for downstream issues, but there are some cases where that checking needs to occur. Please talk to me before changing the code back.
|
||||||
} else
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1445,7 +1445,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
refType = "bundle";
|
refType = "bundle";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReferenceValidationPolicy pol = refType.equals("contained") ? ReferenceValidationPolicy.CHECK_VALID : fetcher == null ? ReferenceValidationPolicy.IGNORE : fetcher.validationPolicy(hostContext.appContext, path, ref);
|
ReferenceValidationPolicy pol = refType.equals("contained") || refType.equals("bundle") ? ReferenceValidationPolicy.CHECK_VALID : fetcher == null ? ReferenceValidationPolicy.IGNORE : fetcher.validationPolicy(hostContext.appContext, path, ref);
|
||||||
|
|
||||||
if (pol.checkExists()) {
|
if (pol.checkExists()) {
|
||||||
if (we == null) {
|
if (we == null) {
|
||||||
|
@ -2783,6 +2783,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
List<Element> entries = new ArrayList<Element>();
|
List<Element> entries = new ArrayList<Element>();
|
||||||
bundle.getNamedChildren("entry", entries);
|
bundle.getNamedChildren("entry", entries);
|
||||||
String type = bundle.getNamedChildValue("type");
|
String type = bundle.getNamedChildValue("type");
|
||||||
|
type = StringUtils.defaultString(type);
|
||||||
|
|
||||||
if (entries.size() == 0) {
|
if (entries.size() == 0) {
|
||||||
rule(errors, IssueType.INVALID, stack.getLiteralPath(), !(type.equals("document") || type.equals("message")), "Documents or Messages must contain at least one entry");
|
rule(errors, IssueType.INVALID, stack.getLiteralPath(), !(type.equals("document") || type.equals("message")), "Documents or Messages must contain at least one entry");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package ca.uhn.fhir.validation;
|
package ca.uhn.fhir.r4.validation;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
@ -17,7 +17,12 @@ import java.io.InputStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||||
|
import ca.uhn.fhir.validation.ValidationResult;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidatorDstu3Test;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.hapi.ctx.*;
|
import org.hl7.fhir.r4.hapi.ctx.*;
|
||||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
|
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||||
|
@ -533,6 +538,16 @@ public class FhirInstanceValidatorR4Test {
|
||||||
assertEquals(output.toString(), 0, output.getMessages().size());
|
assertEquals(output.toString(), 0, output.getMessages().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateBundleWithNoType() throws Exception {
|
||||||
|
String vsContents = IOUtils.toString(FhirInstanceValidatorR4Test.class.getResourceAsStream("/r4/bundle-with-no-type.json"), "UTF-8");
|
||||||
|
|
||||||
|
ValidationResult output = myVal.validateWithResult(vsContents);
|
||||||
|
logResultsAndReturnNonInformationalOnes(output);
|
||||||
|
assertThat(output.getMessages().toString(), containsString("Element 'Bundle.type': minimum required = 1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateRawXmlResourceWithEmptyPrimitive() {
|
public void testValidateRawXmlResourceWithEmptyPrimitive() {
|
||||||
// @formatter:off
|
// @formatter:off
|
|
@ -336,6 +336,15 @@ public class FhirInstanceValidatorDstu3Test {
|
||||||
assertTrue(output.isSuccessful());
|
assertTrue(output.isSuccessful());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateBundleWithNoType() throws Exception {
|
||||||
|
String vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/dstu3/bundle-with-no-type.json"), "UTF-8");
|
||||||
|
|
||||||
|
ValidationResult output = myVal.validateWithResult(vsContents);
|
||||||
|
logResultsAndReturnNonInformationalOnes(output);
|
||||||
|
assertThat(output.getMessages().toString(), containsString("Element 'Bundle.type': minimum required = 1"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #739
|
* See #739
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"resourceType": "Bundle",
|
||||||
|
"entry": [
|
||||||
|
{
|
||||||
|
"fullUrl": "http://localhost:5555/phr/baseDstu3/Person/PERSON1",
|
||||||
|
"resource": {
|
||||||
|
"resourceType": "Person",
|
||||||
|
"id": "PERSON1",
|
||||||
|
"meta": {
|
||||||
|
"versionId": "1",
|
||||||
|
"lastUpdated": "2017-08-17T16:19:40.109+03:00"
|
||||||
|
},
|
||||||
|
"identifier": [
|
||||||
|
{
|
||||||
|
"value": "081181-9984"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"text": "Anna Testi",
|
||||||
|
"family": "Testi",
|
||||||
|
"given": [
|
||||||
|
"Anna"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"family": "asdfas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"telecom": [
|
||||||
|
{
|
||||||
|
"use": "home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": "phone",
|
||||||
|
"value": "(044) 1234567",
|
||||||
|
"use": "work"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gender": "female",
|
||||||
|
"birthDate": "1981-11-08",
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"line": [
|
||||||
|
"Osuuspankkitie 2"
|
||||||
|
],
|
||||||
|
"city": "Helsinki",
|
||||||
|
"postalCode": "00120",
|
||||||
|
"country": "Suomi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Blo-49847020"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"active": true,
|
||||||
|
"link": [
|
||||||
|
{
|
||||||
|
"target": {
|
||||||
|
"reference": "Patient/PATIENT1",
|
||||||
|
"display": "Anna Testi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"url": "Person/PERSON1",
|
||||||
|
"ifMatch": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"resourceType": "Bundle",
|
||||||
|
"entry": [
|
||||||
|
{
|
||||||
|
"fullUrl": "http://localhost:5555/phr/baseDstu3/Person/PERSON1",
|
||||||
|
"resource": {
|
||||||
|
"resourceType": "Person",
|
||||||
|
"id": "PERSON1",
|
||||||
|
"meta": {
|
||||||
|
"versionId": "1",
|
||||||
|
"lastUpdated": "2017-08-17T16:19:40.109+03:00"
|
||||||
|
},
|
||||||
|
"identifier": [
|
||||||
|
{
|
||||||
|
"value": "081181-9984"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"text": "Anna Testi",
|
||||||
|
"family": "Testi",
|
||||||
|
"given": [
|
||||||
|
"Anna"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"family": "asdfas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"telecom": [
|
||||||
|
{
|
||||||
|
"use": "home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": "phone",
|
||||||
|
"value": "(044) 1234567",
|
||||||
|
"use": "work"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gender": "female",
|
||||||
|
"birthDate": "1981-11-08",
|
||||||
|
"address": [
|
||||||
|
{
|
||||||
|
"line": [
|
||||||
|
"Osuuspankkitie 2"
|
||||||
|
],
|
||||||
|
"city": "Helsinki",
|
||||||
|
"postalCode": "00120",
|
||||||
|
"country": "Suomi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"city": "Blo-49847020"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"active": true,
|
||||||
|
"link": [
|
||||||
|
{
|
||||||
|
"target": {
|
||||||
|
"reference": "Patient/PATIENT1",
|
||||||
|
"display": "Anna Testi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"method": "PUT",
|
||||||
|
"url": "Person/PERSON1",
|
||||||
|
"ifMatch": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -55,6 +55,10 @@
|
||||||
the ID of the search, meaning that if a search returns results from the Query
|
the ID of the search, meaning that if a search returns results from the Query
|
||||||
cache, it will reuse the ID of the previously returned Bundle
|
cache, it will reuse the ID of the previously returned Bundle
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Fix a NullPointerException when validating a Bundle (in DSTU3/R4) with no
|
||||||
|
<![CDATA[<code>Bundle.type</code>]]> value
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.0.0" date="2017-09-27">
|
<release version="3.0.0" date="2017-09-27">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue