Fix STU3 validation: find correct extension profile, use custom datatype profile, allow to disable terminology checks
This commit is contained in:
parent
6c47bd4c51
commit
a8e248036e
|
@ -2,6 +2,7 @@ package org.hl7.fhir.dstu3.elementmodel;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
|
||||
import org.hl7.fhir.dstu3.context.IWorkerContext;
|
||||
|
@ -203,7 +204,7 @@ public class Property {
|
|||
ElementDefinition ed = definition;
|
||||
StructureDefinition sd = structure;
|
||||
List<ElementDefinition> children = ProfileUtilities.getChildMap(sd, ed);
|
||||
if (children.isEmpty()) {
|
||||
if (children.isEmpty() || isElementWithOnlyExtension(ed, children)) {
|
||||
// ok, find the right definitions
|
||||
String t = null;
|
||||
if (ed.getType().size() == 1)
|
||||
|
@ -240,7 +241,13 @@ public class Property {
|
|||
}
|
||||
}
|
||||
if (!"xhtml".equals(t)) {
|
||||
sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+t);
|
||||
final String url;
|
||||
if (StringUtils.isNotBlank(ed.getType().get(0).getProfile())) {
|
||||
url = ed.getType().get(0).getProfile();
|
||||
} else {
|
||||
url = "http://hl7.org/fhir/StructureDefinition/" + t;
|
||||
}
|
||||
sd = context.fetchResource(StructureDefinition.class, url);
|
||||
if (sd == null)
|
||||
throw new DefinitionException("Unable to find type '"+t+"' for name '"+elementName+"' on property "+definition.getPath());
|
||||
children = ProfileUtilities.getChildMap(sd, sd.getSnapshot().getElement().get(0));
|
||||
|
@ -340,5 +347,18 @@ public class Property {
|
|||
return context;
|
||||
}
|
||||
|
||||
private boolean isElementWithOnlyExtension(final ElementDefinition ed, final List<ElementDefinition> children) {
|
||||
boolean result = false;
|
||||
if (!ed.getType().isEmpty()) {
|
||||
result = true;
|
||||
for (final ElementDefinition ele : children) {
|
||||
if (!ele.getPath().contains("extension")) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hl7.fhir.dstu3.elementmodel.Element.SpecialElement;
|
|||
import org.hl7.fhir.dstu3.formats.FormatUtilities;
|
||||
import org.hl7.fhir.dstu3.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.dstu3.model.DateTimeType;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition;
|
||||
import org.hl7.fhir.dstu3.model.ElementDefinition.PropertyRepresentation;
|
||||
import org.hl7.fhir.dstu3.model.Enumeration;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
|
@ -45,6 +46,7 @@ import org.w3c.dom.Document;
|
|||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class XmlParser extends ParserBase {
|
||||
private boolean allowXsiLocation;
|
||||
|
@ -250,7 +252,13 @@ public class XmlParser extends ParserBase {
|
|||
Node child = node.getFirstChild();
|
||||
while (child != null) {
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Property property = getElementProp(properties, child.getLocalName());
|
||||
final Property property;
|
||||
if (StringUtils.contains(child.getLocalName(), "extension")) {
|
||||
property = getExtensionProp(properties, child);
|
||||
} else {
|
||||
property = getElementProp(properties, child.getLocalName());
|
||||
}
|
||||
|
||||
if (property != null) {
|
||||
if (!property.isChoice() && "xhtml".equals(property.getType())) {
|
||||
XhtmlNode xhtml = new XhtmlParser().setValidatorMode(true).parseHtmlNode((org.w3c.dom.Element) child);
|
||||
|
@ -293,6 +301,48 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
}
|
||||
|
||||
private Property getExtensionProp(final List<Property> properties, final Node child) {
|
||||
// get the correct property corresponding to the extension
|
||||
Property property = null;
|
||||
final Node extensionNode = child.getAttributes().getNamedItem("url");
|
||||
if (extensionNode != null) {
|
||||
for (final Property prop : properties) {
|
||||
if (prop.getName().contains("extension")) {
|
||||
if (findExtension(prop.getDefinition(), extensionNode.getNodeValue())) {
|
||||
property = prop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (property == null) {
|
||||
property = getElementProp(properties, child.getLocalName());
|
||||
}
|
||||
|
||||
return isDefaultExtensionElement(property) ? null : property;
|
||||
}
|
||||
|
||||
private boolean isDefaultExtensionElement(final Property property) {
|
||||
if (property == null) {
|
||||
return false;
|
||||
}
|
||||
final ElementDefinition ed = property.getDefinition();
|
||||
return StringUtils.contains(ed.getPath(), "extension") && ed.getType().isEmpty() && !ed.getSlicing().isEmpty();
|
||||
}
|
||||
|
||||
private boolean findExtension(final ElementDefinition definition, final String localName) {
|
||||
boolean result = false;
|
||||
if(StringUtils.isNotBlank(localName)) {
|
||||
for (ElementDefinition.TypeRefComponent type:definition.getType()) {
|
||||
if(localName.equals(type.getProfile())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Property getElementProp(List<Property> properties, String nodeName) {
|
||||
List<Property> propsSortedByLongestFirst = new ArrayList<Property>(properties);
|
||||
// sort properties according to their name longest first, so .requestOrganizationReference comes first before .request[x]
|
||||
|
@ -337,15 +387,34 @@ public class XmlParser extends ParserBase {
|
|||
|
||||
private void parseResource(String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
|
||||
org.w3c.dom.Element res = XMLUtil.getFirstChild(container);
|
||||
String name = res.getLocalName();
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+name);
|
||||
final String profile = findProfile(res);
|
||||
final StructureDefinition sd = context.fetchResource(StructureDefinition.class, profile);
|
||||
if (sd == null)
|
||||
throw new FHIRFormatError("Contained resource does not appear to be a FHIR resource (unknown name '"+res.getLocalName()+"')");
|
||||
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
|
||||
parent.setType(name);
|
||||
parent.setType(res.getLocalName());
|
||||
parseChildren(res.getLocalName(), res, parent);
|
||||
}
|
||||
|
||||
private String findProfile(final org.w3c.dom.Element res) {
|
||||
String url = null;
|
||||
for (int i = 0; i < res.getChildNodes().getLength(); i++) {
|
||||
final Node child = res.getChildNodes().item(i);
|
||||
if ("meta".equals(child.getLocalName())) {
|
||||
for (int j = 0; j < child.getChildNodes().getLength(); j++) {
|
||||
final Node subChild = child.getChildNodes().item(j);
|
||||
if ("profile".equals(subChild.getLocalName())) {
|
||||
final Node profileNode = subChild.getAttributes().getNamedItem("value");
|
||||
url = profileNode.getNodeValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return StringUtils.isNotBlank(url) ? url : "http://hl7.org/fhir/StructureDefinition/" + res.getLocalName();
|
||||
}
|
||||
|
||||
private void reapComments(org.w3c.dom.Element element, Element context) {
|
||||
Node node = element.getPreviousSibling();
|
||||
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
|
||||
|
|
|
@ -44,6 +44,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
private DocumentBuilderFactory myDocBuilderFactory;
|
||||
private StructureDefinition myStructureDefintion;
|
||||
private IValidationSupport myValidationSupport;
|
||||
private boolean noTerminologyChecks = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -127,6 +128,21 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
myAnyExtensionsAllowed = theAnyExtensionsAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to {@literal true} (default is false) the valueSet will not be validate
|
||||
*/
|
||||
public boolean isNoTerminologyChecks() {
|
||||
return noTerminologyChecks;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to {@literal true} (default is false) the valueSet will not be validate
|
||||
*/
|
||||
public void setNoTerminologyChecks(final boolean theNoTerminologyChecks) {
|
||||
noTerminologyChecks = theNoTerminologyChecks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the "best practice warning level". When validating, any deviations from best practices will be reported at
|
||||
* this level.
|
||||
|
@ -171,6 +187,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
v.setBestPracticeWarningLevel(getBestPracticeWarningLevel());
|
||||
v.setAnyExtensionsAllowed(isAnyExtensionsAllowed());
|
||||
v.setResourceIdRule(IdStatus.OPTIONAL);
|
||||
v.setNoTerminologyChecks(isNoTerminologyChecks());
|
||||
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.not;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -838,6 +839,13 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(0, all.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNoTerminologyChecks() {
|
||||
assertFalse(myInstanceVal.isNoTerminologyChecks());
|
||||
myInstanceVal.setNoTerminologyChecks(true);
|
||||
assertTrue(myInstanceVal.isNoTerminologyChecks());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidateStructureDefinition() throws IOException {
|
||||
|
|
Loading…
Reference in New Issue