Work on updating validator

This commit is contained in:
jamesagnew 2015-09-14 08:22:43 -04:00
parent d0bac3d419
commit c96d5efe1f
7 changed files with 181 additions and 46 deletions

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.ArrayList;
/*
@ -27,31 +29,37 @@ import java.util.List;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.validation.IResourceValidator.BestPracticeWarningLevel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome.BaseIssue;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome.Issue;
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.IParserErrorHandler;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.validation.DefaultProfileValidationSupport;
import ca.uhn.fhir.validation.FhirInstanceValidator;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.IValidationSupport;
import ca.uhn.fhir.validation.ValidationResult;
import ca.uhn.fhir.validation.ValidationSupportChain;
public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResourceDao<T> {
@Autowired
@Qualifier("myJpaProfileValidationSupportDstu2")
private IValidationSupport myJpaProfilealidationSupport;
@Override
protected List<Object> getIncludeValues(FhirTerser theTerser, Include theInclude, IBaseResource theResource, RuntimeResourceDefinition theResourceDef) {
List<Object> values;
if ("*".equals(theInclude.getValue())) {
@ -59,7 +67,7 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
values.addAll(theTerser.getAllPopulatedChildElementsOfType(theResource, BaseResourceReferenceDt.class));
} else if (theInclude.getValue().startsWith(theResourceDef.getName() + ":")) {
values = new ArrayList<Object>();
RuntimeSearchParam sp = theResourceDef.getSearchParam(theInclude.getValue().substring(theInclude.getValue().indexOf(':')+1));
RuntimeSearchParam sp = theResourceDef.getSearchParam(theInclude.getValue().substring(theInclude.getValue().indexOf(':') + 1));
for (String nextPath : sp.getPathsSplit()) {
values.addAll(theTerser.getValues(theResource, nextPath));
}
@ -81,45 +89,24 @@ public class FhirResourceDaoDstu2<T extends IResource> extends BaseHapiFhirResou
public MethodOutcome validate(T theResource, IdDt theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource);
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
final OperationOutcome oo = new OperationOutcome();
IParser parser = theEncoding.newParser(getContext());
parser.setParserErrorHandler(new IParserErrorHandler() {
@Override
public void unknownAttribute(IParseLocation theLocation, String theAttributeName) {
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDiagnostics("Unknown attribute found: " + theAttributeName);
}
@Override
public void unknownElement(IParseLocation theLocation, String theElementName) {
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDiagnostics("Unknown element found: " + theElementName);
}
@Override
public void unexpectedRepeatingElement(IParseLocation theLocation, String theElementName) {
oo.addIssue().setSeverity(IssueSeverityEnum.ERROR).setCode(IssueTypeEnum.INVALID_CONTENT).setDiagnostics("Multiple repetitions of non-repeatable element found: " + theElementName);
}
});
FhirValidator validator = getContext().newValidator();
validator.setValidateAgainstStandardSchema(true);
validator.setValidateAgainstStandardSchematron(true);
ValidationResult result = validator.validateWithResult(theResource);
OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
for (BaseIssue next : operationOutcome.getIssue()) {
oo.getIssue().add((Issue) next);
}
// This method returns a MethodOutcome object
MethodOutcome retVal = new MethodOutcome();
oo.addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDiagnostics("Validation succeeded");
retVal.setOperationOutcome(oo);
FhirInstanceValidator val = new FhirInstanceValidator();
val.setBestPracticeWarningLevel(BestPracticeWarningLevel.Warning);
val.setValidationSupport(new ValidationSupportChain(new DefaultProfileValidationSupport(), myJpaProfilealidationSupport));
validator.registerValidatorModule(val);
ValidationResult result;
if (isNotBlank(theRawResource)) {
result = validator.validateWithResult(theRawResource);
} else {
result = validator.validateWithResult(theResource);
}
MethodOutcome retVal = new MethodOutcome();
retVal.setOperationOutcome((OperationOutcome) result.toOperationOutcome());
return retVal;
}
}

View File

@ -0,0 +1,44 @@
package ca.uhn.fhir.jpa.dao;
import org.hl7.fhir.instance.model.ValueSet;
import org.hl7.fhir.instance.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.instance.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.validation.IValidationSupport;
public class JpaProfileValidationSupport implements IValidationSupport {
@Override
public ValueSetExpansionComponent expandValueSet(ConceptSetComponent theInclude) {
// TODO Auto-generated method stub
return null;
}
@Override
public ValueSet fetchCodeSystem(String theSystem) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T extends IBaseResource> T fetchResource(FhirContext theContext, Class<T> theClass, String theUri) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isCodeSystemSupported(String theSystem) {
// TODO Auto-generated method stub
return false;
}
@Override
public CodeValidationResult validateCode(String theCodeSystem, String theCode, String theDisplay) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -1,12 +1,16 @@
package ca.uhn.fhir.jpa.dao;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.util.List;
import java.io.IOException;
import java.io.InputStream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -48,8 +52,10 @@ import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.method.MethodUtil;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
//@formatter:off
@ -102,6 +108,9 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myResourceProvidersDstu2")
protected Object myResourceProviders;
@Autowired
@Qualifier("myStructureDefinitionDaoDstu2")
protected IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
@Autowired
@Qualifier("mySystemDaoDstu2")
protected IFhirSystemDao<Bundle> mySystemDao;
@Autowired
@ -134,6 +143,16 @@ public class BaseJpaDstu2Test extends BaseJpaTest {
// nothing
}
protected <T extends IBaseResource> T loadResourceFromClasspath(Class<T> type, String resourceName) throws IOException {
InputStream stream = FhirResourceDaoDstu2SearchTest.class.getResourceAsStream(resourceName);
if (stream == null) {
fail("Unable to load resource: " + resourceName);
}
String string = IOUtils.toString(stream, "UTF-8");
IParser newJsonParser = MethodUtil.detectEncodingNoDefault(string).newParser(myFhirCtx);
return newJsonParser.parseResource(type, string);
}
public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager) {
TransactionTemplate txTemplate = new TransactionTemplate(theTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);

View File

@ -19,7 +19,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -1342,7 +1341,9 @@ public class FhirResourceDaoDstu2SearchTest extends BaseJpaDstu2Test {
public void testSearchWithUriParam() throws Exception {
String methodName = "testSearchWithUriParam";
ValueSet vs = myFhirCtx.newJsonParser().parseResource(ValueSet.class, IOUtils.toString(FhirResourceDaoDstu2SearchTest.class.getResourceAsStream("/valueset-dstu2.json")));
Class<ValueSet> type = ValueSet.class;
String resourceName = "/valueset-dstu2.json";
ValueSet vs = loadResourceFromClasspath(type, resourceName);
myValueSetDao.update(vs);
IBundleProvider result = myValueSetDao.search(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type"));

View File

@ -0,0 +1,81 @@
package ca.uhn.fhir.jpa.dao;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.ObservationStatusEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
public class FhirResourceDaoDstu2ValidateTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2ValidateTest.class);
@Test
public void testValidateResourceContainingProfileDeclaration() throws Exception {
String methodName = "testValidateResourceContainingProfileDeclaration";
Bundle vss = loadResourceFromClasspath(Bundle.class, "/org/hl7/fhir/instance/model/valueset/valuesets.xml");
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-status"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-category"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-codes"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-methods"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-valueabsentreason"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-interpretation"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "body-site"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "referencerange-meaning"));
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-relationshiptypes"));
StructureDefinition sd = loadResourceFromClasspath(StructureDefinition.class, "/org/hl7/fhir/instance/model/profile/devicemetricobservation.profile.xml");
sd.setId(new IdDt());
sd.setUrl("http://example.com/foo/bar/" + methodName);
myStructureDefinitionDao.create(sd);
Observation input = new Observation();
ResourceMetadataKeyEnum.PROFILES.put(input, Arrays.asList(new IdDt(sd.getUrl())));
input.addIdentifier().setSystem("http://acme").setValue("12345");
input.getEncounter().setReference("http://foo.com/Encounter/9");
input.setStatus(ObservationStatusEnum.FINAL);
input.getCode().addCoding().setSystem("http://loinc.org").setCode("12345");
String encoded = myFhirCtx.newJsonParser().encodeResourceToString(input);
ValidationModeEnum mode = ValidationModeEnum.CREATE;
MethodOutcome outcome = myObservationDao.validate(input, null, encoded, EncodingEnum.JSON, mode, null);
String ooString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.getOperationOutcome());
ourLog.info(ooString);
assertThat(ooString, containsString("Element '/f:Observation.subject': minimum required = 1, but only found 0"));
assertThat(ooString, containsString("Element encounter @ /f:Observation: max allowed = 0, but found 1"));
assertThat(ooString, containsString("Element '/f:Observation.device': minimum required = 1, but only found 0"));
}
private IResource findResourceByIdInBundle(Bundle vss, String name) {
IResource retVal = null;
for (Entry next : vss.getEntry()) {
if (next.getResource().getId().getIdPart().equals(name)) {
retVal = next.getResource();
break;
}
}
if (retVal == null) {
fail("Can't find VS: " + name);
}
return retVal;
}
}

View File

@ -12,7 +12,6 @@ import org.hl7.fhir.instance.model.QuestionnaireResponse;
import org.hl7.fhir.instance.model.ValueSet;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.valuesets.IssueType;
import org.hl7.fhir.instance.utils.WorkerContext;
import org.hl7.fhir.instance.validation.QuestionnaireResponseValidator;
import org.hl7.fhir.instance.validation.ValidationMessage;

View File

@ -44,4 +44,8 @@
#end
#if ( ${versionCapitalized} == 'Dstu2' )
<bean id="myJpaProfileValidationSupportDstu2" class="ca.uhn.fhir.jpa.dao.JpaProfileValidationSupport"/>
#end
</beans>