Creates new methods that return a ValidationResult object instead of throwing an exception which requires catching and inspecting the exception itself. Migrating from the old to the new API should be pretty simple as the method calls match quite closely.
This commit is contained in:
Joseph Athman 2014-10-15 12:26:30 -05:00
parent 2a9d92df7a
commit 2741f1cae5
4 changed files with 240 additions and 57 deletions

View File

@ -20,18 +20,15 @@ package ca.uhn.fhir.validation;
* #L%
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.Validate;
import com.phloc.schematron.ISchematronResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import org.apache.commons.lang3.Validate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Resource validator, which checks resources for compliance against various validation schemes (schemas, schematrons, etc.)
@ -133,25 +130,18 @@ public class FhirValidator {
/**
* Validates a bundle instance, throwing a {@link ValidationFailureException} if the validation fails. This validation includes validation of all resources in the bundle.
*
* @param theResource
* @param theBundle
* The resource to validate
* @throws ValidationFailureException
* If the validation fails
* @deprecated use {@link #validateWithResult(ca.uhn.fhir.model.api.Bundle)} instead
*/
@Deprecated
public void validate(Bundle theBundle) {
Validate.notNull(theBundle, "theBundle must not be null");
ValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
for (IValidator next : myValidators) {
next.validateBundle(ctx);
}
OperationOutcome oo = ctx.getOperationOutcome();
if (oo != null && oo.getIssue().size() > 0) {
throw new ValidationFailureException(oo);
}
ValidationResult validationResult = validateWithResult(theBundle);
if (!validationResult.isSuccessful()) {
throw new ValidationFailureException(validationResult.getOperationOutcome());
}
}
/**
@ -161,21 +151,54 @@ public class FhirValidator {
* The resource to validate
* @throws ValidationFailureException
* If the validation fails
* @deprecated use {@link #validateWithResult(ca.uhn.fhir.model.api.IResource)} instead
*/
@Deprecated
public void validate(IResource theResource) throws ValidationFailureException {
Validate.notNull(theResource, "theResource must not be null");
ValidationResult validationResult = validateWithResult(theResource);
if (!validationResult.isSuccessful()) {
throw new ValidationFailureException(validationResult.getOperationOutcome());
}
}
ValidationContext<IResource> ctx = ValidationContext.forResource(myContext, theResource);
/**
* Validates a bundle instance returning a {@link ca.uhn.fhir.validation.ValidationResult} which contains the results.
* This validation includes validation of all resources in the bundle.
*
* @param theBundle the bundle to validate
* @return the results of validation
* @since 0.7
*/
public ValidationResult validateWithResult(Bundle theBundle) {
Validate.notNull(theBundle, "theBundle must not be null");
for (IValidator next : myValidators) {
next.validateResource(ctx);
}
ValidationContext<Bundle> ctx = ValidationContext.forBundle(myContext, theBundle);
OperationOutcome oo = ctx.getOperationOutcome();
if (oo != null && oo.getIssue().size() > 0) {
throw new ValidationFailureException(oo);
}
for (IValidator next : myValidators) {
next.validateBundle(ctx);
}
}
OperationOutcome oo = ctx.getOperationOutcome();
return ValidationResult.valueOf(oo);
}
/**
* Validates a resource instance returning a {@link ca.uhn.fhir.validation.ValidationResult} which contains the results.
*
* @param theResource the resource to validate
* @return the results of validation
* @since 0.7
*/
public ValidationResult validateWithResult(IResource theResource) {
Validate.notNull(theResource, "theResource must not be null");
ValidationContext<IResource> ctx = ValidationContext.forResource(myContext, theResource);
for (IValidator next : myValidators) {
next.validateResource(ctx);
}
OperationOutcome oo = ctx.getOperationOutcome();
return ValidationResult.valueOf(oo);
}
}

View File

@ -0,0 +1,72 @@
package ca.uhn.fhir.validation;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
/**
* Encapsulates the results of validation
*
* @see ca.uhn.fhir.validation.FhirValidator
* @since 0.7
*/
public class ValidationResult {
private OperationOutcome myOperationOutcome;
private ValidationResult(OperationOutcome myOperationOutcome) {
this.myOperationOutcome = myOperationOutcome;
}
public static ValidationResult valueOf(OperationOutcome myOperationOutcome) {
return new ValidationResult(myOperationOutcome);
}
public OperationOutcome getOperationOutcome() {
return myOperationOutcome;
}
@Override
public String toString() {
return "ValidationResult{" +
"myOperationOutcome=" + myOperationOutcome +
", description='" + toDescription() + '\'' +
'}';
}
private String toDescription() {
StringBuilder b = new StringBuilder(100);
if (myOperationOutcome != null) {
OperationOutcome.Issue issueFirstRep = myOperationOutcome.getIssueFirstRep();
b.append(issueFirstRep.getDetails().getValue());
b.append(" - ");
b.append(issueFirstRep.getLocationFirstRep().getValue());
}
return b.toString();
}
/**
* Was the validation successful
* @return true if the validation was successful
*/
public boolean isSuccessful() {
return myOperationOutcome == null || myOperationOutcome.getIssue().isEmpty();
}
}

View File

@ -1,17 +1,22 @@
package ca.uhn.fhir.validation;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.ContactSystemEnum;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class ResourceValidatorTest {
@ -45,9 +50,7 @@ public class ResourceValidatorTest {
String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("atom-document-large.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(res);
FhirValidator val = ourCtx.newValidator();
val.setValidateAgainstStandardSchema(true);
val.setValidateAgainstStandardSchematron(true);
FhirValidator val = createFhirValidator();
val.validate(b);
@ -64,7 +67,6 @@ public class ResourceValidatorTest {
}
}
@Test
public void testSchematronResourceValidator() throws IOException {
String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("patient-example-dicom.xml"));
@ -74,20 +76,60 @@ public class ResourceValidatorTest {
val.setValidateAgainstStandardSchema(false);
val.setValidateAgainstStandardSchematron(true);
val.validate(p);
ValidationResult validationResult = val.validateWithResult(p);
assertTrue(validationResult.isSuccessful());
p.getTelecomFirstRep().setValue("123-4567");
validationResult = val.validateWithResult(p);
assertFalse(validationResult.isSuccessful());
OperationOutcome operationOutcome = validationResult.getOperationOutcome();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
assertEquals(1, operationOutcome.getIssue().size());
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2: A system is required if a value is provided."));
p.getTelecomFirstRep().setValue("123-4567");
try {
val.validate(p);
fail();
} catch (ValidationFailureException e) {
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
assertEquals(1, e.getOperationOutcome().getIssue().size());
assertThat(e.getOperationOutcome().getIssueFirstRep().getDetails().getValue(), containsString("Inv-2: A system is required if a value is provided."));
}
p.getTelecomFirstRep().setSystem(ContactSystemEnum.EMAIL);
val.validate(p);
validationResult = val.validateWithResult(p);
assertTrue(validationResult.isSuccessful());
}
@Test
public void testSchemaBundleValidatorIsSuccessful() throws IOException {
String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("atom-document-large.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(res);
FhirValidator val = createFhirValidator();
ValidationResult result = val.validateWithResult(b);
assertTrue(result.isSuccessful());
OperationOutcome operationOutcome = result.getOperationOutcome();
assertNotNull(operationOutcome);
assertEquals(0, operationOutcome.getIssue().size());
}
@Test
public void testSchemaBundleValidatorFails() throws IOException {
String res = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("atom-document-large.xml"));
Bundle b = ourCtx.newXmlParser().parseBundle(res);
FhirValidator val = createFhirValidator();
ValidationResult validationResult = val.validateWithResult(b);
assertTrue(validationResult.isSuccessful());
Patient p = (Patient) b.getEntries().get(0).getResource();
p.getTelecomFirstRep().setValue("123-4567");
validationResult = val.validateWithResult(b);
assertFalse(validationResult.isSuccessful());
OperationOutcome operationOutcome = validationResult.getOperationOutcome();
ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome));
assertEquals(1, operationOutcome.getIssue().size());
assertThat(operationOutcome.getIssueFirstRep().getDetails().getValue(), containsString("Inv-2: A system is required if a value is provided."));
}
private FhirValidator createFhirValidator() {
FhirValidator val = ourCtx.newValidator();
val.setValidateAgainstStandardSchema(true);
val.setValidateAgainstStandardSchematron(true);
return val;
}
}

View File

@ -0,0 +1,46 @@
package ca.uhn.fhir.validation;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import org.junit.Test;
import java.util.List;
import java.util.UUID;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class ValidationResultTest {
@Test
public void isSuccessful_IsTrueForNullOperationOutcome() {
ValidationResult result = ValidationResult.valueOf(null);
assertTrue(result.isSuccessful());
}
@Test
public void isSuccessful_IsTrueForNoIssues() {
OperationOutcome operationOutcome = new OperationOutcome();
// make sure a non-null ID doesn't cause the validation result to be a fail
operationOutcome.setId(UUID.randomUUID().toString());
ValidationResult result = ValidationResult.valueOf(operationOutcome);
assertTrue(result.isSuccessful());
}
@Test
public void isSuccessful_FalseForIssues() {
OperationOutcome operationOutcome = new OperationOutcome();
OperationOutcome.Issue issue = operationOutcome.addIssue();
String errorMessage = "There was a validation problem";
issue.setDetails(errorMessage);
ValidationResult result = ValidationResult.valueOf(operationOutcome);
assertFalse(result.isSuccessful());
List<OperationOutcome.Issue> issues = result.getOperationOutcome().getIssue();
assertEquals(1, issues.size());
assertEquals(errorMessage, issues.get(0).getDetails().getValue());
assertThat("ValidationResult#toString should contain the issue description", result.toString(), containsString(errorMessage));
}
}