Fix #344 - make getResourceDefinition(String) and getElementDefnition(String) case insensitive
This commit is contained in:
parent
c48a5224b4
commit
3fce4cb087
|
@ -27,10 +27,8 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.text.WordUtils;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
@ -185,9 +183,12 @@ public class FhirContext {
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||||
* for extending the core library.
|
* for extending the core library.
|
||||||
|
* <p>
|
||||||
|
* Note that this method is case insensitive!
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public BaseRuntimeElementDefinition<?> getElementDefinition(String theElementName) {
|
public BaseRuntimeElementDefinition<?> getElementDefinition(String theElementName) {
|
||||||
return myNameToElementDefinition.get(theElementName);
|
return myNameToElementDefinition.get(theElementName.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For unit tests only */
|
/** For unit tests only */
|
||||||
|
@ -275,23 +276,15 @@ public class FhirContext {
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed
|
||||||
* for extending the core library.
|
* for extending the core library.
|
||||||
|
* <p>
|
||||||
|
* Note that this method is case insensitive!
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public RuntimeResourceDefinition getResourceDefinition(String theResourceName) {
|
public RuntimeResourceDefinition getResourceDefinition(String theResourceName) {
|
||||||
Validate.notBlank(theResourceName, "theResourceName must not be blank");
|
Validate.notBlank(theResourceName, "theResourceName must not be blank");
|
||||||
|
|
||||||
String resourceName = theResourceName;
|
String resourceName = theResourceName.toLowerCase();
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: this is a bit of a hack, really we should have a translation table based on a property file or
|
|
||||||
* something so that we can detect names like diagnosticreport
|
|
||||||
*/
|
|
||||||
if (Character.isLowerCase(resourceName.charAt(0))) {
|
|
||||||
resourceName = WordUtils.capitalize(resourceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Validate.notBlank(resourceName, "Resource name must not be blank");
|
|
||||||
|
|
||||||
RuntimeResourceDefinition retVal = myNameToResourceDefinition.get(resourceName);
|
RuntimeResourceDefinition retVal = myNameToResourceDefinition.get(resourceName);
|
||||||
|
|
||||||
if (retVal == null) {
|
if (retVal == null) {
|
||||||
|
|
|
@ -319,7 +319,7 @@ class ModelScanner {
|
||||||
resourceDef = new RuntimeCompositeDatatypeDefinition(theDatatypeDefinition, theClass, isStandardType(theClass));
|
resourceDef = new RuntimeCompositeDatatypeDefinition(theDatatypeDefinition, theClass, isStandardType(theClass));
|
||||||
}
|
}
|
||||||
myClassToElementDefinitions.put(theClass, resourceDef);
|
myClassToElementDefinitions.put(theClass, resourceDef);
|
||||||
myNameToElementDefinitions.put(resourceDef.getName(), resourceDef);
|
myNameToElementDefinitions.put(resourceDef.getName().toLowerCase(), resourceDef);
|
||||||
scanCompositeElementForChildren(theClass, resourceDef);
|
scanCompositeElementForChildren(theClass, resourceDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +709,7 @@ class ModelScanner {
|
||||||
myClassToElementDefinitions.put(theClass, resourceDef);
|
myClassToElementDefinitions.put(theClass, resourceDef);
|
||||||
if (primaryNameProvider) {
|
if (primaryNameProvider) {
|
||||||
if (resourceDef.getStructureVersion() == myVersion) {
|
if (resourceDef.getStructureVersion() == myVersion) {
|
||||||
myNameToResourceDefinitions.put(resourceName, resourceDef);
|
myNameToResourceDefinitions.put(resourceName.toLowerCase(), resourceDef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scanCompositeElementForChildren(theClass, resourceDef);
|
scanCompositeElementForChildren(theClass, resourceDef);
|
||||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.parser;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
|
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
|
||||||
|
|
||||||
|
@ -2090,6 +2091,9 @@ class ParserState<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
|
RuntimeResourceDefinition def = (RuntimeResourceDefinition) definition;
|
||||||
|
if (!definition.getName().equals(theLocalPart) && definition.getName().equalsIgnoreCase(theLocalPart)) {
|
||||||
|
throw new DataFormatException("Unknown resource type '" + theLocalPart + "': Resource names are case sensitive, found similar name: '" + definition.getName() + "'");
|
||||||
|
}
|
||||||
myInstance = def.newInstance();
|
myInstance = def.newInstance();
|
||||||
|
|
||||||
String resourceName = def.getName();
|
String resourceName = def.getName();
|
||||||
|
|
|
@ -4,6 +4,8 @@ import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
|
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -23,6 +25,27 @@ public class FhirContextDstu3Test {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #344
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetElementDefinitionCaseInsensitive() {
|
||||||
|
assertEquals(Reference.class, ourCtx.getElementDefinition("reference").getImplementingClass());
|
||||||
|
assertEquals(Reference.class, ourCtx.getElementDefinition("Reference").getImplementingClass());
|
||||||
|
assertEquals(Reference.class, ourCtx.getElementDefinition("REFerence").getImplementingClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #344
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetResourceDefinitionCaseInsensitive() {
|
||||||
|
assertEquals(Patient.class, ourCtx.getResourceDefinition("patient").getImplementingClass());
|
||||||
|
assertEquals(Patient.class, ourCtx.getResourceDefinition("Patient").getImplementingClass());
|
||||||
|
assertEquals(Patient.class, ourCtx.getResourceDefinition("PATient").getImplementingClass());
|
||||||
|
assertEquals(StructureDefinition.class, ourCtx.getResourceDefinition("structuredefinition").getImplementingClass());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCustomTypeDoesntBecomeDefault() {
|
public void testCustomTypeDoesntBecomeDefault() {
|
||||||
FhirContext ctx = FhirContext.forDstu3();
|
FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
|
|
@ -57,6 +57,8 @@ import org.hl7.fhir.dstu3.model.PrimitiveType;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity;
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
|
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
|
||||||
import org.hl7.fhir.dstu3.model.Reference;
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
|
import org.hl7.fhir.dstu3.model.SampledData;
|
||||||
|
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.Type;
|
import org.hl7.fhir.dstu3.model.Type;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
|
@ -86,6 +88,41 @@ public class JsonParserDstu3Test {
|
||||||
ourCtx.setNarrativeGenerator(null);
|
ourCtx.setNarrativeGenerator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #344
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParserIsCaseSensitive() {
|
||||||
|
Observation obs = new Observation();
|
||||||
|
SampledData data = new SampledData();
|
||||||
|
data.setData("1 2 3");
|
||||||
|
data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L));
|
||||||
|
data.setPeriod(1000L);
|
||||||
|
obs.setValue(data);
|
||||||
|
|
||||||
|
IParser p = ourCtx.newJsonParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler());
|
||||||
|
String encoded = p.encodeResourceToString(obs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
p.parseResource(encoded);
|
||||||
|
|
||||||
|
try {
|
||||||
|
p.parseResource(encoded.replace("Observation", "observation"));
|
||||||
|
fail();
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
assertEquals("Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
p.parseResource(encoded.replace("valueSampledData", "valueSampleddata"));
|
||||||
|
fail();
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
assertEquals("Unknown element 'valueSampleddata' found during parse", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseExtensions() throws Exception {
|
public void testEncodeAndParseExtensions() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ import org.hl7.fhir.dstu3.model.PrimitiveType;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity;
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
import org.hl7.fhir.dstu3.model.Reference;
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
import org.hl7.fhir.dstu3.model.Resource;
|
import org.hl7.fhir.dstu3.model.Resource;
|
||||||
|
import org.hl7.fhir.dstu3.model.SampledData;
|
||||||
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
|
@ -114,27 +115,10 @@ public class XmlParserDstu3Test {
|
||||||
ourCtx.setNarrativeGenerator(null);
|
ourCtx.setNarrativeGenerator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* See #347
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testEncodeAndParseMedicationOrder() {
|
|
||||||
MedicationOrder mo = new MedicationOrder();
|
|
||||||
mo.getDateWrittenElement().setValueAsString("2015-10-05");
|
|
||||||
|
|
||||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(mo);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
|
|
||||||
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, encoded);
|
|
||||||
assertEquals("2015-10-05", mo.getDateWrittenElement().getValueAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBundleWithBinary() {
|
public void testBundleWithBinary() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
String bundle = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
String bundle = "<Bundle xmlns=\"http://hl7.org/fhir\">\n" +
|
||||||
" <meta/>\n" +
|
|
||||||
" <base value=\"http://localhost:52788\"/>\n" +
|
" <base value=\"http://localhost:52788\"/>\n" +
|
||||||
" <total value=\"1\"/>\n" +
|
" <total value=\"1\"/>\n" +
|
||||||
" <link>\n" +
|
" <link>\n" +
|
||||||
|
@ -184,6 +168,8 @@ public class XmlParserDstu3Test {
|
||||||
assertEquals("ORG", o.getName());
|
assertEquals("ORG", o.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDuration() {
|
public void testDuration() {
|
||||||
Encounter enc = new Encounter();
|
Encounter enc = new Encounter();
|
||||||
|
@ -463,6 +449,21 @@ public class XmlParserDstu3Test {
|
||||||
assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode());
|
assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #347
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEncodeAndParseMedicationOrder() {
|
||||||
|
MedicationOrder mo = new MedicationOrder();
|
||||||
|
mo.getDateWrittenElement().setValueAsString("2015-10-05");
|
||||||
|
|
||||||
|
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(mo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, encoded);
|
||||||
|
assertEquals("2015-10-05", mo.getDateWrittenElement().getValueAsString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseMetaProfileAndTags() {
|
public void testEncodeAndParseMetaProfileAndTags() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -1213,8 +1214,6 @@ public class XmlParserDstu3Test {
|
||||||
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://hello.world\"><valueString value=\"Hello World\"/></extension></Patient>", xml);
|
assertEquals("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://hello.world\"><valueString value=\"Hello World\"/></extension></Patient>", xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() {
|
public void testEncodeReferenceUsingUnqualifiedResourceWorksCorrectly() {
|
||||||
|
|
||||||
|
@ -1252,6 +1251,8 @@ public class XmlParserDstu3Test {
|
||||||
assertThat(str, containsString("<reference value=\"Observation/phitcc_obs_bp_dia\"/>"));
|
assertThat(str, containsString("<reference value=\"Observation/phitcc_obs_bp_dia\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeSummary() {
|
public void testEncodeSummary() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -2559,6 +2560,39 @@ public class XmlParserDstu3Test {
|
||||||
assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType());
|
assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #344
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testParserIsCaseSensitive() {
|
||||||
|
Observation obs = new Observation();
|
||||||
|
SampledData data = new SampledData();
|
||||||
|
data.setData("1 2 3");
|
||||||
|
data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L));
|
||||||
|
data.setPeriod(1000L);
|
||||||
|
obs.setValue(data);
|
||||||
|
|
||||||
|
IParser p = ourCtx.newXmlParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler());
|
||||||
|
String encoded = p.encodeResourceToString(obs);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
p.parseResource(encoded);
|
||||||
|
|
||||||
|
try {
|
||||||
|
p.parseResource(encoded.replace("Observation", "observation"));
|
||||||
|
fail();
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
assertEquals("DataFormatException at [[row,col {unknown-source}]: [1,1]]: Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
p.parseResource(encoded.replace("valueSampledData", "valueSampleddata"));
|
||||||
|
fail();
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Unknown element 'valueSampleddata' found during parse", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #339
|
* See #339
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue