diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java index 243f91a0557..d8a877fe626 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/elementmodel/XmlParser.java @@ -3,6 +3,9 @@ package org.hl7.fhir.dstu3.elementmodel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import javax.xml.parsers.DocumentBuilder; @@ -290,7 +293,16 @@ public class XmlParser extends ParserBase { } private Property getElementProp(List properties, String nodeName) { - for (Property p : properties) + List propsSortedByLongestFirst = new ArrayList(properties); + // sort properties according to their name longest first, so .requestOrganizationReference comes first before .request[x] + // and therefore the longer property names get evaluated first + Collections.sort(propsSortedByLongestFirst, new Comparator() { + @Override + public int compare(Property o1, Property o2) { + return o2.getName().length() - o1.getName().length(); + } + }); + for (Property p : propsSortedByLongestFirst) if (!p.getDefinition().hasRepresentation(PropertyRepresentation.XMLATTR) && !p.getDefinition().hasRepresentation(PropertyRepresentation.XMLTEXT)) { if (p.getName().equals(nodeName)) return p; diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu3Test.java index 19754d90952..c715195ccf3 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/ValidateDstu3Test.java @@ -1,321 +1,321 @@ -package ca.uhn.fhir.rest.server; - -import static org.hamcrest.Matchers.stringContainsInOrder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.util.concurrent.TimeUnit; - -import org.apache.commons.io.IOUtils; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.hl7.fhir.dstu3.model.CodeType; -import org.hl7.fhir.dstu3.model.IdType; -import org.hl7.fhir.dstu3.model.OperationOutcome; -import org.hl7.fhir.dstu3.model.Organization; -import org.hl7.fhir.dstu3.model.Parameters; -import org.hl7.fhir.dstu3.model.Patient; -import org.hl7.fhir.dstu3.model.StringType; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.annotation.IdParam; -import ca.uhn.fhir.rest.annotation.ResourceParam; -import ca.uhn.fhir.rest.annotation.Validate; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.api.ValidationModeEnum; -import ca.uhn.fhir.util.PortUtil; -import ca.uhn.fhir.util.TestUtil; - -public class ValidateDstu3Test { - private static CloseableHttpClient ourClient; - private static FhirContext ourCtx = FhirContext.forDstu3(); - private static EncodingEnum ourLastEncoding; - private static IdType ourLastId; - private static ValidationModeEnum ourLastMode; - public static Patient ourLastPatient; - private static String ourLastProfile; - private static String ourLastResourceBody; - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu3Test.class); - private static OperationOutcome ourOutcomeToReturn; - private static int ourPort; - - private static Server ourServer; - - @Before() - public void before() { - ourLastResourceBody = null; - ourLastEncoding = null; - ourOutcomeToReturn = null; - ourLastMode = null; - ourLastProfile = null; - } - - @Test - public void testValidate() throws Exception { - - Patient patient = new Patient(); - patient.addIdentifier().setValue("001"); - patient.addIdentifier().setValue("002"); - - Parameters params = new Parameters(); - params.addParameter().setName("resource").setResource(patient); - - HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate"); - httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); - - HttpResponse status = ourClient.execute(httpPost); - String resp = IOUtils.toString(status.getEntity().getContent()); - IOUtils.closeQuietly(status.getEntity().getContent()); - - assertEquals(200, status.getStatusLine().getStatusCode()); - - assertThat(resp, stringContainsInOrder(" getResourceType() { - return Organization.class; - } - - @Validate() - public MethodOutcome validate(@ResourceParam String theResourceBody, @ResourceParam EncodingEnum theEncoding) { - ourLastResourceBody = theResourceBody; - ourLastEncoding = theEncoding; - - return new MethodOutcome(new IdType("001")); - } - - } - - public static class PatientProvider implements IResourceProvider { - - @Override - public Class getResourceType() { - return Patient.class; - } - - @Validate() - public MethodOutcome validatePatient(@ResourceParam Patient thePatient, @IdParam(optional=true) IdType theId, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile) { - - ourLastPatient = thePatient; - ourLastId = theId; - IdType id; - if (thePatient != null) { - id = new IdType(thePatient.getIdentifier().get(0).getValue()); - if (thePatient.getIdElement().isEmpty() == false) { - id = thePatient.getIdElement(); - } - } else { - id = new IdType("1"); - } - ourLastMode = theMode; - ourLastProfile = theProfile; - - MethodOutcome outcome = new MethodOutcome(id.withVersion("002")); - outcome.setOperationOutcome(ourOutcomeToReturn); - return outcome; - } - - } - -} +package ca.uhn.fhir.rest.server; + +import static org.hamcrest.Matchers.stringContainsInOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.hl7.fhir.dstu3.model.CodeType; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.OperationOutcome; +import org.hl7.fhir.dstu3.model.Organization; +import org.hl7.fhir.dstu3.model.Parameters; +import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.StringType; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.annotation.IdParam; +import ca.uhn.fhir.rest.annotation.ResourceParam; +import ca.uhn.fhir.rest.annotation.Validate; +import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.ValidationModeEnum; +import ca.uhn.fhir.util.PortUtil; +import ca.uhn.fhir.util.TestUtil; + +public class ValidateDstu3Test { + private static CloseableHttpClient ourClient; + private static FhirContext ourCtx = FhirContext.forDstu3(); + private static EncodingEnum ourLastEncoding; + private static IdType ourLastId; + private static ValidationModeEnum ourLastMode; + public static Patient ourLastPatient; + private static String ourLastProfile; + private static String ourLastResourceBody; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidateDstu3Test.class); + private static OperationOutcome ourOutcomeToReturn; + private static int ourPort; + + private static Server ourServer; + + @Before() + public void before() { + ourLastResourceBody = null; + ourLastEncoding = null; + ourOutcomeToReturn = null; + ourLastMode = null; + ourLastProfile = null; + } + + @Test + public void testValidate() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier().setValue("001"); + patient.addIdentifier().setValue("002"); + + Parameters params = new Parameters(); + params.addParameter().setName("resource").setResource(patient); + + HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/$validate"); + httpPost.setEntity(new StringEntity(ourCtx.newXmlParser().encodeResourceToString(params), ContentType.create(Constants.CT_FHIR_XML, "UTF-8"))); + + HttpResponse status = ourClient.execute(httpPost); + String resp = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + assertEquals(200, status.getStatusLine().getStatusCode()); + + assertThat(resp, stringContainsInOrder(" getResourceType() { + return Organization.class; + } + + @Validate() + public MethodOutcome validate(@ResourceParam String theResourceBody, @ResourceParam EncodingEnum theEncoding) { + ourLastResourceBody = theResourceBody; + ourLastEncoding = theEncoding; + + return new MethodOutcome(new IdType("001")); + } + + } + + public static class PatientProvider implements IResourceProvider { + + @Override + public Class getResourceType() { + return Patient.class; + } + + @Validate() + public MethodOutcome validatePatient(@ResourceParam Patient thePatient, @IdParam(optional=true) IdType theId, @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile) { + + ourLastPatient = thePatient; + ourLastId = theId; + IdType id; + if (thePatient != null) { + id = new IdType(thePatient.getIdentifier().get(0).getValue()); + if (thePatient.getIdElement().isEmpty() == false) { + id = thePatient.getIdElement(); + } + } else { + id = new IdType("1"); + } + ourLastMode = theMode; + ourLastProfile = theProfile; + + MethodOutcome outcome = new MethodOutcome(id.withVersion("002")); + outcome.setOperationOutcome(ourOutcomeToReturn); + return outcome; + } + + } + +} diff --git a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java index 1f2d8be4073..00e137846e9 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/org/hl7/fhir/dstu3/hapi/validation/ResourceValidatorDstu3Test.java @@ -249,4 +249,27 @@ public class ResourceValidatorDstu3Test { assertThat(messageString, not(containsString("valueResource"))); } + @Test + public void testValidateDifferentPropertyButSameStartsWithPath() throws Exception { + + EnrollmentResponse fhirObj = new EnrollmentResponse(); + Organization org = new Organization(); + org.setId("1"); + fhirObj.setRequestOrganization(new Reference(org)); + String input = ourCtx.newXmlParser().encodeResourceToString(fhirObj); + + FhirValidator validator = ourCtx.newValidator(); + validator.registerValidatorModule(new FhirInstanceValidator()); + + ValidationResult result = validator.validateWithResult(input); + assertEquals(3, result.getMessages().size()); + + fhirObj = new EnrollmentResponse(); + Identifier ident = new Identifier().setSystem("a").setValue("b"); + fhirObj.setRequest(ident); + input = ourCtx.newXmlParser().encodeResourceToString(fhirObj); + + result = validator.validateWithResult(input); + assertEquals(2, result.getMessages().size()); + } }