Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core into IGRenderingChanges
# Conflicts: # org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/AdditionalBindingsRenderer.java
This commit is contained in:
commit
a59cfbe513
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.hl7.fhir.convertors.misc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -28,10 +29,10 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
public static void main(String[] args) throws FHIRException, IOException, ParseException, URISyntaxException {
|
||||
VSACImporter self = new VSACImporter();
|
||||
self.process(args[0], args[1], args[2]);
|
||||
self.process(args[0], args[1], args[2], "true".equals(args[3]));
|
||||
}
|
||||
|
||||
private void process(String source, String dest, String apiKey) throws FHIRException, IOException, URISyntaxException {
|
||||
private void process(String source, String dest, String apiKey, boolean onlyNew) throws FHIRException, IOException, URISyntaxException {
|
||||
CSVReader csv = new CSVReader(new FileInputStream(source));
|
||||
csv.readHeaders();
|
||||
Map<String, String> errs = new HashMap<>();
|
||||
|
@ -39,23 +40,25 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
FHIRToolingClient fhirToolingClient = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir", "fhir/vsac");
|
||||
fhirToolingClient.setUsername("apikey");
|
||||
fhirToolingClient.setPassword(apiKey);
|
||||
fhirToolingClient.setTimeout(30000);
|
||||
fhirToolingClient.setTimeout(120000);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (csv.line()) {
|
||||
String oid = csv.cell("OID");
|
||||
try {
|
||||
ValueSet vs = fhirToolingClient.read(ValueSet.class, oid);
|
||||
try {
|
||||
ValueSet vse = fhirToolingClient.expandValueset(vs.getUrl(), null);
|
||||
vs.setExpansion(vse.getExpansion());
|
||||
j++;
|
||||
} catch (Exception e) {
|
||||
errs.put(oid, "Expansion: " +e.getMessage());
|
||||
System.out.println(e.getMessage());
|
||||
if (!onlyNew || !(new File(Utilities.path(dest, "ValueSet-" + oid + ".json")).exists())) {
|
||||
ValueSet vs = fhirToolingClient.read(ValueSet.class, oid);
|
||||
try {
|
||||
ValueSet vse = fhirToolingClient.expandValueset(vs.getUrl(), null);
|
||||
vs.setExpansion(vse.getExpansion());
|
||||
j++;
|
||||
} catch (Exception e) {
|
||||
errs.put(oid, "Expansion: " +e.getMessage());
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
}
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
i++;
|
||||
if (i % 100 == 0) {
|
||||
System.out.println(":"+i+" ("+j+")");
|
||||
|
|
|
@ -93,4 +93,9 @@ public boolean hasCoding(String system, String code) {
|
|||
public void addCoding(String system, String code, String display) {
|
||||
getCoding().add(new Coding(system, code, display));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return hasCoding() ? getCoding().toString() : "["+getText()+"]";
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@Override
|
||||
public String toString() {
|
||||
if (getExpression().size() == 1) {
|
||||
return getExpression().get(0)+" "+getDiagnostics()+" "+getSeverity().toCode()+"/"+getCode().toCode()+": "+getDetails().getText();
|
||||
} else {
|
||||
return getExpression()+" "+getDiagnostics()+" "+getSeverity().toCode()+"/"+getCode().toCode()+": "+getDetails().getText();
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -342,7 +342,7 @@ public class DataRenderer extends Renderer {
|
|||
return true;
|
||||
}
|
||||
if (Utilities.existsInList(t,
|
||||
"ActivityDefinition", "CapabilityStatement", "CapabilityStatement2", "ChargeItemDefinition", "Citation", "CodeSystem",
|
||||
"ActivityDefinition", "CapabilityStatement", "ChargeItemDefinition", "Citation", "CodeSystem",
|
||||
"CompartmentDefinition", "ConceptMap", "ConditionDefinition", "EventDefinition", "Evidence", "EvidenceReport", "EvidenceVariable",
|
||||
"ExampleScenario", "GraphDefinition", "ImplementationGuide", "Library", "Measure", "MessageDefinition", "NamingSystem", "PlanDefinition"
|
||||
))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ public class AdditionalBindingsRenderer {
|
|||
private String purpose;
|
||||
private String valueSet;
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private UsageContext usage;
|
||||
private boolean any = false;
|
||||
private boolean isUnchanged = false;
|
||||
|
@ -52,6 +53,9 @@ public class AdditionalBindingsRenderer {
|
|||
private boolean alreadyMatched() {
|
||||
return matched;
|
||||
}
|
||||
public String getDoco(boolean full) {
|
||||
return full ? doco : docoShort;
|
||||
}
|
||||
public boolean unchanged() {
|
||||
if (!isUnchanged)
|
||||
return false;
|
||||
|
@ -161,6 +165,7 @@ public class AdditionalBindingsRenderer {
|
|||
abr.purpose = ext.getExtensionString("purpose");
|
||||
abr.valueSet = ext.getExtensionString("valueSet");
|
||||
abr.doco = ext.getExtensionString("documentation");
|
||||
abr.docoShort = ext.getExtensionString("shortDoco");
|
||||
abr.usage = (ext.hasExtension("usage")) && ext.getExtensionByUrl("usage").hasValueUsageContext() ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
||||
abr.any = "any".equals(ext.getExtensionString("scope"));
|
||||
abr.isUnchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
||||
|
@ -188,12 +193,12 @@ public class AdditionalBindingsRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
private void render(List<XhtmlNode> children, boolean doDoco) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public void render(List<XhtmlNode> children, boolean fullDoco) throws FHIRFormatError, DefinitionException, IOException {
|
||||
boolean doco = false;
|
||||
boolean usage = false;
|
||||
boolean any = false;
|
||||
for (AdditionalBindingDetail binding : bindings) {
|
||||
doco = doco || (doDoco && (binding.doco != null || (binding.compare!=null && binding.compare.doco!=null)));
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || binding.usage != null || (binding.compare!=null && binding.compare.usage!=null);
|
||||
any = any || binding.any || (binding.compare!=null && binding.compare.any);
|
||||
}
|
||||
|
@ -266,8 +271,8 @@ public class AdditionalBindingsRenderer {
|
|||
}
|
||||
if (doco) {
|
||||
if (binding.doco != null) {
|
||||
String d = md.processMarkdown("Binding.description", binding.doco);
|
||||
String oldD = binding.compare==null ? null : md.processMarkdown("Binding.description.compare", binding.compare.doco);
|
||||
String d = md.processMarkdown("Binding.description", fullDoco ? binding.doco : binding.docoShort);
|
||||
String oldD = binding.compare==null ? null : md.processMarkdown("Binding.description.compare", fullDoco ? binding.compare.doco : binding.compare.docoShort);
|
||||
tr.td().style("font-size: 11px").innerHTML(compareHtml(d, oldD));
|
||||
} else {
|
||||
tr.td().style("font-size: 11px");
|
||||
|
@ -307,7 +312,10 @@ public class AdditionalBindingsRenderer {
|
|||
td.ah(corePath+"extension-elementdefinition-minvalueset.html", "The minimum allowable value set - any conformant system SHALL support all these codes").tx("Min Binding");
|
||||
break;
|
||||
case "conformance" :
|
||||
td.ah(corePath+"terminologies.html#strength", "Validators will check this binding (strength = required)").tx("Validation Criteria");
|
||||
td.ah(corePath+"terminologies.html#strength", "Validators will check this binding (strength = required)").tx("Validation Binding");
|
||||
break;
|
||||
case "candidate" :
|
||||
td.ah(corePath+"terminologies.html#strength", "This is a candidate binding that constraints on this profile may consider (see doco)").tx("Candidate Validation Binding");
|
||||
break;
|
||||
case "current" :
|
||||
td.span(null, "New records are required to use this value set, but legacy records may use other codes").tx("Required");
|
||||
|
@ -336,5 +344,9 @@ public class AdditionalBindingsRenderer {
|
|||
return br;
|
||||
}
|
||||
|
||||
public boolean hasBindings() {
|
||||
return !bindings.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4998,6 +4998,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
b.setDescription(o.getDescription());
|
||||
b.getDescriptionElement().setUserData(DERIVATION_EQUALS, o.getDescriptionElement());
|
||||
}
|
||||
// todo: derivation?
|
||||
b.getExtension().addAll(binding.getExtension());
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.hl7.fhir.r5.context.IWorkerContext;
|
|||
import org.hl7.fhir.r5.formats.FormatUtilities;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
@ -92,10 +93,13 @@ public abstract class ParserBase {
|
|||
public enum ValidationPolicy { NONE, QUICK, EVERYTHING }
|
||||
|
||||
public boolean isPrimitive(String code) {
|
||||
return Utilities.existsInList(code, "boolean", "integer", "integer64", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "xhtml", "url", "canonical");
|
||||
StructureDefinition sd = context.fetchTypeDefinition(code);
|
||||
if (sd != null) {
|
||||
return sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
|
||||
}
|
||||
|
||||
return Utilities.existsInList(code, "boolean", "integer", "integer64", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "uuid", "xhtml", "url", "canonical");
|
||||
|
||||
// StructureDefinition sd = context.fetchTypeDefinition(code);
|
||||
// return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
|
||||
}
|
||||
|
||||
protected IWorkerContext context;
|
||||
|
|
|
@ -155,7 +155,13 @@ public class XmlParser extends ParserBase {
|
|||
doc = builder.parse(stream);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logError(0, 0, "(syntax)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
|
||||
if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) {
|
||||
int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0);
|
||||
int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0);
|
||||
logError(line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL);
|
||||
} else {
|
||||
logError(0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
|
||||
}
|
||||
doc = null;
|
||||
}
|
||||
if (doc != null) {
|
||||
|
@ -168,12 +174,17 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
|
||||
|
||||
private String extractVal(String src, String name) {
|
||||
src = src.substring(src.indexOf(name)+name.length()+1);
|
||||
src = src.substring(0, src.indexOf(";")).trim();
|
||||
return src;
|
||||
}
|
||||
private void checkForProcessingInstruction(Document document) throws FHIRFormatError {
|
||||
if (policy == ValidationPolicy.EVERYTHING && FormatUtilities.FHIR_NS.equals(document.getDocumentElement().getNamespaceURI())) {
|
||||
Node node = document.getFirstChild();
|
||||
while (node != null) {
|
||||
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE)
|
||||
logError(line(document), col(document), "(document)", IssueType.INVALID, context.formatMessage(
|
||||
logError(line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage(
|
||||
I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR);
|
||||
node = node.getNextSibling();
|
||||
}
|
||||
|
@ -181,14 +192,14 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
|
||||
|
||||
private int line(Node node) {
|
||||
private int line(Node node, boolean end) {
|
||||
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
|
||||
return loc == null ? 0 : loc.getStartLine();
|
||||
return loc == null ? 0 : end ? loc.getEndLine() : loc.getStartLine();
|
||||
}
|
||||
|
||||
private int col(Node node) {
|
||||
private int col(Node node, boolean end) {
|
||||
XmlLocationData loc = node == null ? null : (XmlLocationData) node.getUserData(XmlLocationData.LOCATION_DATA_KEY);
|
||||
return loc == null ? 0 : loc.getStartColumn();
|
||||
return loc == null ? 0 : end ? loc.getEndColumn() : loc.getStartColumn();
|
||||
}
|
||||
|
||||
public Element parse(Document doc) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
|
||||
|
@ -202,14 +213,14 @@ public class XmlParser extends ParserBase {
|
|||
String name = element.getLocalName();
|
||||
String path = "/"+pathPrefix(ns)+name;
|
||||
|
||||
StructureDefinition sd = getDefinition(line(element), col(element), (ns == null ? "noNamespace" : ns), name);
|
||||
StructureDefinition sd = getDefinition(line(element, false), col(element, false), (ns == null ? "noNamespace" : ns), name);
|
||||
if (sd == null)
|
||||
return null;
|
||||
|
||||
Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
|
||||
result.setPath(element.getLocalName());
|
||||
checkElement(element, path, result.getProperty());
|
||||
result.markLocation(line(element), col(element));
|
||||
result.markLocation(line(element, false), col(element, false));
|
||||
result.setType(element.getLocalName());
|
||||
parseChildren(path, element, result);
|
||||
result.numberChildren();
|
||||
|
@ -253,14 +264,14 @@ public class XmlParser extends ParserBase {
|
|||
private void checkElement(org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError {
|
||||
if (policy == ValidationPolicy.EVERYTHING) {
|
||||
if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content
|
||||
logError(line(element), col(element), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
|
||||
logError(line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
|
||||
String ns = prop.getXmlNamespace();
|
||||
String elementNs = element.getNamespaceURI();
|
||||
if (elementNs == null) {
|
||||
elementNs = "noNamespace";
|
||||
}
|
||||
if (!elementNs.equals(ns))
|
||||
logError(line(element), col(element), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR);
|
||||
logError(line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,8 +293,8 @@ public class XmlParser extends ParserBase {
|
|||
List<Property> properties = element.getProperty().getChildProperties(element.getName(), XMLUtil.getXsiType(node));
|
||||
|
||||
String text = XMLUtil.getDirectText(node).trim();
|
||||
int line = line(node);
|
||||
int col = col(node);
|
||||
int line = line(node, false);
|
||||
int col = col(node, false);
|
||||
if (!Utilities.noString(text)) {
|
||||
Property property = getTextProp(properties);
|
||||
if (property != null) {
|
||||
|
@ -307,16 +318,19 @@ public class XmlParser extends ParserBase {
|
|||
Node n = node.getFirstChild();
|
||||
while (n != null) {
|
||||
if (n.getNodeType() == Node.TEXT_NODE && !Utilities.noString(n.getTextContent().trim())) {
|
||||
while (n.getNextSibling() != null && n.getNodeType() != Node.ELEMENT_NODE) {
|
||||
n = n.getNextSibling();
|
||||
}
|
||||
Node nt = n;
|
||||
Node nt = n; // try to find the nearest element for a line/col location
|
||||
boolean end = false;
|
||||
while (nt.getPreviousSibling() != null && nt.getNodeType() != Node.ELEMENT_NODE) {
|
||||
nt = nt.getPreviousSibling();
|
||||
end = true;
|
||||
}
|
||||
line = line(nt);
|
||||
col = col(nt);
|
||||
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(text)), IssueSeverity.ERROR);
|
||||
while (nt.getNextSibling() != null && nt.getNodeType() != Node.ELEMENT_NODE) {
|
||||
nt = nt.getNextSibling();
|
||||
end = false;
|
||||
}
|
||||
line = line(nt, end);
|
||||
col = col(nt, end);
|
||||
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(n.getTextContent().trim())), IssueSeverity.ERROR);
|
||||
}
|
||||
n = n.getNextSibling();
|
||||
}
|
||||
|
@ -351,8 +365,9 @@ public class XmlParser extends ParserBase {
|
|||
} else
|
||||
ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content
|
||||
ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so
|
||||
if (!ok)
|
||||
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
|
||||
if (!ok) {
|
||||
logError(line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -376,12 +391,12 @@ public class XmlParser extends ParserBase {
|
|||
xhtml = new CDANarrativeFormat().convert((org.w3c.dom.Element) child);
|
||||
else
|
||||
xhtml = new XhtmlParser().setValidatorMode(true).parseHtmlNode((org.w3c.dom.Element) child);
|
||||
Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child), col(child));
|
||||
Element n = new Element(property.getName(), property, "xhtml", new XhtmlComposer(XhtmlComposer.XML, false).compose(xhtml)).setXhtml(xhtml).markLocation(line(child, false), col(child, false));
|
||||
n.setPath(element.getPath()+"."+property.getName());
|
||||
element.getChildren().add(n);
|
||||
} else {
|
||||
String npath = path+"/"+pathPrefix(child.getNamespaceURI())+child.getLocalName();
|
||||
Element n = new Element(child.getLocalName(), property).markLocation(line(child), col(child));
|
||||
Element n = new Element(child.getLocalName(), property).markLocation(line(child, false), col(child, false));
|
||||
if (property.isList()) {
|
||||
n.setPath(element.getPath()+"."+property.getName()+"["+repeatCount+"]");
|
||||
} else {
|
||||
|
@ -397,7 +412,7 @@ public class XmlParser extends ParserBase {
|
|||
xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype");
|
||||
n.setType(xsiType);
|
||||
} else {
|
||||
logError(line(child), col(child), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR);
|
||||
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR);
|
||||
ok = false;
|
||||
}
|
||||
} else {
|
||||
|
@ -418,11 +433,11 @@ public class XmlParser extends ParserBase {
|
|||
}
|
||||
}
|
||||
} else
|
||||
logError(line(child), col(child), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName()), IssueSeverity.ERROR);
|
||||
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName()), IssueSeverity.ERROR);
|
||||
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
|
||||
logError(line(child), col(child), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
|
||||
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
|
||||
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {
|
||||
logError(line(child), col(child), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR);
|
||||
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR);
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
|
|
|
@ -404,6 +404,11 @@ public boolean hasCoding(String system, String code) {
|
|||
public void addCoding(String system, String code, String display) {
|
||||
getCoding().add(new Coding(system, code, display));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return hasCoding() ? getCoding().toString() : "["+getText()+"]";
|
||||
}
|
||||
|
||||
// end addition
|
||||
|
||||
|
|
|
@ -1299,6 +1299,15 @@ For resource issues, this will be a simple XPath limited to element names, repet
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (getExpression().size() == 1) {
|
||||
return getExpression().get(0)+" "+getDiagnostics()+" "+getSeverity().toCode()+"/"+getCode().toCode()+": "+getDetails().getText();
|
||||
} else {
|
||||
return getExpression()+" "+getDiagnostics()+" "+getSeverity().toCode()+"/"+getCode().toCode()+": "+getDetails().getText();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -79,8 +79,13 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (be.has("fullUrl")) {
|
||||
root.an(makeInternalBundleLink(be.get("fullUrl").primitiveValue()));
|
||||
}
|
||||
if (be.has("resource") && be.getChildByName("resource").getValues().get(0).has("id")) {
|
||||
root.an(be.get("resource").fhirType() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue());
|
||||
if (be.has("resource")) {
|
||||
if (be.getChildByName("resource").getValues().get(0).has("id")) {
|
||||
root.an(be.get("resource").fhirType() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue());
|
||||
} else {
|
||||
String id = makeIdFromBundleEntry(be.get("fullUrl").primitiveValue());
|
||||
root.an(be.get("resource").fhirType() + "_" + id);
|
||||
}
|
||||
}
|
||||
root.hr();
|
||||
if (be.has("fullUrl")) {
|
||||
|
@ -101,6 +106,7 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (xn == null || xn.isEmpty()) {
|
||||
ResourceRenderer rr = RendererFactory.factory(rw, context);
|
||||
try {
|
||||
rr.setRcontext(new ResourceContext(rcontext, rw));
|
||||
xn = rr.render(rw);
|
||||
} catch (Exception e) {
|
||||
xn = new XhtmlNode();
|
||||
|
@ -128,7 +134,7 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (subject.hasNarrative()) {
|
||||
x.addChildren(subject.getNarrative());
|
||||
} else {
|
||||
RendererFactory.factory(subject, context).render(x, subject);
|
||||
RendererFactory.factory(subject, context, new ResourceContext(rcontext, subject)).render(x, subject);
|
||||
}
|
||||
}
|
||||
x.hr();
|
||||
|
@ -204,12 +210,14 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (nx != null && !nx.isEmpty()) {
|
||||
x.addChildren(nx);
|
||||
} else {
|
||||
RendererFactory.factory(subject, context).render(x, subject);
|
||||
RendererFactory.factory(subject, context).setRcontext(new ResourceContext(rcontext, subject)).render(x, subject);
|
||||
}
|
||||
}
|
||||
x.hr();
|
||||
if (!comp.getText().hasDiv()) {
|
||||
ResourceRenderer rr = RendererFactory.factory(comp, getContext()); rr.render(comp);
|
||||
ResourceRenderer rr = RendererFactory.factory(comp, getContext());
|
||||
rr.setRcontext(new ResourceContext(rcontext, comp));
|
||||
rr.render(comp);
|
||||
}
|
||||
if (comp.getText().hasDiv()) {
|
||||
x.addChildren(comp.getText().getDiv());
|
||||
|
@ -292,8 +300,14 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (i > start) {
|
||||
if (be.hasFullUrl())
|
||||
x.an(makeInternalBundleLink(be.getFullUrl()));
|
||||
if (be.hasResource() && be.getResource().hasId())
|
||||
x.an(be.getResource().getResourceType().name() + "_" + be.getResource().getId());
|
||||
if (be.hasResource()) {
|
||||
if (be.getResource().hasId()) {
|
||||
x.an(be.getResource().getResourceType().name() + "_" + be.getResource().getId());
|
||||
} else {
|
||||
String id = makeIdFromBundleEntry(be.getFullUrl());
|
||||
x.an(be.getResource().getResourceType().name() + "_" + id);
|
||||
}
|
||||
}
|
||||
x.hr();
|
||||
if (docMode) {
|
||||
if (be.hasFullUrl() && be.hasResource()) {
|
||||
|
@ -329,6 +343,7 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
if (xn == null || xn.isEmpty()) {
|
||||
ResourceRenderer rr = RendererFactory.factory(be.getResource(), context);
|
||||
try {
|
||||
rr.setRcontext(new ResourceContext(rcontext, be.getResource()));
|
||||
xn = rr.build(be.getResource());
|
||||
} catch (Exception e) {
|
||||
xn = makeExceptionXhtml(e, "generating narrative");
|
||||
|
|
|
@ -341,7 +341,7 @@ public class DataRenderer extends Renderer {
|
|||
return true;
|
||||
}
|
||||
if (Utilities.existsInList(t,
|
||||
"ActivityDefinition", "CapabilityStatement", "CapabilityStatement2", "ChargeItemDefinition", "Citation", "CodeSystem",
|
||||
"ActivityDefinition", "CapabilityStatement", "ChargeItemDefinition", "Citation", "CodeSystem",
|
||||
"CompartmentDefinition", "ConceptMap", "ConditionDefinition", "EventDefinition", "Evidence", "EvidenceReport", "EvidenceVariable",
|
||||
"ExampleScenario", "GraphDefinition", "ImplementationGuide", "Library", "Measure", "MessageDefinition", "NamingSystem", "PlanDefinition"
|
||||
))
|
||||
|
|
|
@ -381,7 +381,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
renderContactPoint(x, c);
|
||||
}
|
||||
} else if (e instanceof UriType) {
|
||||
renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResourceResource() != null ? rcontext.getResourceResource().getId() : null);
|
||||
renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResource() != null ? rcontext.getResource().getId() : null);
|
||||
} else if (e instanceof Timing) {
|
||||
renderTiming(x, (Timing) e);
|
||||
} else if (e instanceof Range) {
|
||||
|
@ -418,6 +418,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
ctxtc.setAddGeneratedNarrativeHeader(false);
|
||||
ctxtc.setContained(true);
|
||||
ResourceRenderer rr = RendererFactory.factory(rw, ctxtc);
|
||||
rr.setRcontext(new ResourceContext(rcontext, rw));
|
||||
rr.render(parent.blockquote(), rw);
|
||||
} else {
|
||||
x.ah(ref).tx("See "+rw.fhirType());
|
||||
|
@ -690,12 +691,12 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
x.para().b().tx("Generated Narrative: "+profile.present()+(showCodeDetails ? " with Details" : ""));
|
||||
}
|
||||
try {
|
||||
generateByProfile(rcontext.getResourceResource(), profile, rcontext.getResourceResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile, profile.getSnapshot().getElement(), rcontext.getResourceResource().getResourceType().toString()), x, rcontext.getResourceResource().getResourceType().toString(), showCodeDetails);
|
||||
generateByProfile(rcontext.getResource(), profile, rcontext.getResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile, profile.getSnapshot().getElement(), rcontext.getResource().getResourceType().toString()), x, rcontext.getResource().getResourceType().toString(), showCodeDetails);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||
}
|
||||
inject(rcontext.getResourceResource(), x, NarrativeStatus.GENERATED);
|
||||
inject((DomainResource) rcontext.getResource(), x, NarrativeStatus.GENERATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,15 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
this.rcontext = rcontext;
|
||||
}
|
||||
|
||||
public ResourceContext getRcontext() {
|
||||
return rcontext;
|
||||
}
|
||||
|
||||
public ResourceRenderer setRcontext(ResourceContext rcontext) {
|
||||
this.rcontext = rcontext;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XhtmlNode build(Resource dr) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||
render(x, dr);
|
||||
|
@ -324,7 +333,11 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
if (rcontext != null) {
|
||||
BundleEntryComponent bundleResource = rcontext.resolve(url);
|
||||
if (bundleResource != null) {
|
||||
String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + bundleResource.getResource().getId();
|
||||
String id = bundleResource.getResource().getId();
|
||||
if (id == null) {
|
||||
id = makeIdFromBundleEntry(bundleResource.getFullUrl());
|
||||
}
|
||||
String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + id;
|
||||
return new ResourceWithReference(bundleUrl, new ResourceWrapperDirect(this.context, bundleResource.getResource()));
|
||||
}
|
||||
org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url, version);
|
||||
|
@ -350,6 +363,16 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
}
|
||||
|
||||
|
||||
protected String makeIdFromBundleEntry(String url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
if (url.startsWith("urn:uuid:")) {
|
||||
return url.substring(9).toLowerCase();
|
||||
}
|
||||
return fullUrlToAnchor(url);
|
||||
}
|
||||
|
||||
private String fullUrlToAnchor(String url) {
|
||||
return url.replace(":", "").replace("/", "_");
|
||||
}
|
||||
|
|
|
@ -299,6 +299,10 @@ public class DirectWrappers {
|
|||
return new PropertyWrapperDirect(context, p);
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -286,6 +286,10 @@ public class ElementWrappers {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Element getElement() {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper {
|
||||
|
|
|
@ -7,15 +7,10 @@ import org.hl7.fhir.r5.model.Parameters;
|
|||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContextType;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class Resolver {
|
||||
|
||||
public enum ResourceContextType {
|
||||
PARAMETERS, BUNDLE
|
||||
}
|
||||
|
||||
public interface IReferenceResolver {
|
||||
ResourceWithReference resolve(RenderingContext context, String url);
|
||||
|
||||
|
@ -24,27 +19,24 @@ public class Resolver {
|
|||
}
|
||||
|
||||
public static class ResourceContext {
|
||||
private ResourceContextType type;
|
||||
private Resource containerResource;
|
||||
private org.hl7.fhir.r5.elementmodel.Element containerElement;
|
||||
private ResourceContext container;
|
||||
|
||||
DomainResource resourceResource;
|
||||
org.hl7.fhir.r5.elementmodel.Element resourceElement;
|
||||
Resource resource;
|
||||
org.hl7.fhir.r5.elementmodel.Element element;
|
||||
|
||||
public ResourceContext(ResourceContextType type, Resource bundle, DomainResource dr) {
|
||||
public ResourceContext(ResourceContext container, Resource dr) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.containerResource = bundle;
|
||||
this.resourceResource = dr;
|
||||
this.container = container;
|
||||
this.resource = dr;
|
||||
}
|
||||
|
||||
public ResourceContext(ResourceContextType type, org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
public ResourceContext(ResourceContext container, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.containerElement = bundle;
|
||||
this.resourceElement = dr;
|
||||
this.container = container;
|
||||
this.element = dr;
|
||||
}
|
||||
|
||||
|
||||
// public ResourceContext(Object bundle, Element doc) {
|
||||
// // TODO Auto-generated constructor stub
|
||||
// }
|
||||
|
@ -54,22 +46,45 @@ public class Resolver {
|
|||
// }
|
||||
|
||||
|
||||
public ResourceContext(ResourceContext container, ResourceWrapper rw) {
|
||||
super();
|
||||
this.container = container;
|
||||
// todo: howto do this better?
|
||||
|
||||
if (rw instanceof DirectWrappers.ResourceWrapperDirect) {
|
||||
this.resource = ((DirectWrappers.ResourceWrapperDirect) rw).getResource();
|
||||
} else if (rw instanceof ElementWrappers.ResourceWrapperMetaElement) {
|
||||
this.element = ((ElementWrappers.ResourceWrapperMetaElement) rw).getElement();
|
||||
} else {
|
||||
throw new Error("Not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceContext getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public void setContainer(ResourceContext container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
// public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||
// return containerElement;
|
||||
// }
|
||||
//
|
||||
public DomainResource getResourceResource() {
|
||||
return resourceResource;
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element getResourceElement() {
|
||||
return resourceElement;
|
||||
public org.hl7.fhir.r5.elementmodel.Element getElement() {
|
||||
return element;
|
||||
}
|
||||
|
||||
public BundleEntryComponent resolve(String value) {
|
||||
if (value.startsWith("#")) {
|
||||
if (resourceResource != null) {
|
||||
for (Resource r : resourceResource.getContained()) {
|
||||
if (resource instanceof DomainResource) {
|
||||
DomainResource dr = (DomainResource) resource;
|
||||
for (Resource r : dr.getContained()) {
|
||||
if (r.getId().equals(value.substring(1))) {
|
||||
BundleEntryComponent be = new BundleEntryComponent();
|
||||
be.setResource(r);
|
||||
|
@ -79,44 +94,45 @@ public class Resolver {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerResource != null) {
|
||||
for (BundleEntryComponent be : ((Bundle) containerResource).getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
|
||||
if (resource instanceof Bundle) {
|
||||
Bundle b = (Bundle) resource;
|
||||
for (BundleEntryComponent be : b.getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
}
|
||||
}
|
||||
|
||||
if (resource instanceof Parameters) {
|
||||
Parameters pp = (Parameters) resource;
|
||||
for (ParametersParameterComponent p : pp.getParameter()) {
|
||||
if (p.getResource() != null && value.equals(p.getResource().fhirType()+"/"+p.getResource().getId())) {
|
||||
BundleEntryComponent be = new BundleEntryComponent();
|
||||
be.setResource(p.getResource());
|
||||
return be;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerResource != null) {
|
||||
for (ParametersParameterComponent p : ((Parameters) containerResource).getParameter()) {
|
||||
if (p.getResource() != null && value.equals(p.getResource().fhirType()+"/"+p.getResource().getId())) {
|
||||
BundleEntryComponent be = new BundleEntryComponent();
|
||||
be.setResource(p.getResource());
|
||||
return be;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return container != null ? container.resolve(value) : null;
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value, String version) {
|
||||
if (value.startsWith("#")) {
|
||||
if (resourceElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element r : resourceElement.getChildrenByName("contained")) {
|
||||
if (element != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element r : element.getChildrenByName("contained")) {
|
||||
if (r.getChildValue("id").equals(value.substring(1)))
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : containerElement.getChildren("entry")) {
|
||||
if (element != null) {
|
||||
if (element.fhirType().equals("Bundle")) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : element.getChildren("entry")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||
if (res != null) {
|
||||
if (value.equals(be.getChildValue("fullUrl"))) {
|
||||
|
@ -132,10 +148,8 @@ public class Resolver {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element p : containerElement.getChildren("parameter")) {
|
||||
if (element.fhirType().equals("Parameters")) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element p : element.getChildren("parameter")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource");
|
||||
if (res != null && value.equals(res.fhirType()+"/"+res.getChildValue("id"))) {
|
||||
if (checkVersion(version, res)) {
|
||||
|
@ -145,7 +159,7 @@ public class Resolver {
|
|||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return container != null ? container.resolveElement(value, version) : null;
|
||||
}
|
||||
|
||||
private boolean checkVersion(String version, org.hl7.fhir.r5.elementmodel.Element res) {
|
||||
|
|
|
@ -11,7 +11,7 @@ public class JurisdictionUtilities {
|
|||
}
|
||||
|
||||
public static String getJurisdictionFromLocale(String s) {
|
||||
if (Utilities.existsInList(s,
|
||||
if (Utilities.existsInList(s.toUpperCase(),
|
||||
"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ",
|
||||
"AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB",
|
||||
"BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM",
|
||||
|
@ -41,7 +41,7 @@ public class JurisdictionUtilities {
|
|||
"UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF",
|
||||
"WS", "YE", "YT", "ZA", "ZM", "ZW"
|
||||
)) {
|
||||
return "urn:iso:std:iso:3166#"+s;
|
||||
return "urn:iso:std:iso:3166#"+s.toUpperCase();
|
||||
} else {
|
||||
switch (s) {
|
||||
case "uv" : return "http://unstats.un.org/unsd/methods/m49/m49.htm#001";
|
||||
|
@ -54,7 +54,7 @@ public class JurisdictionUtilities {
|
|||
}
|
||||
|
||||
public static String displayJurisdiction(String s) {
|
||||
return displayJurisdiction(CodeSystemUtilities.readCoding(s));
|
||||
return displayJurisdiction(CodeSystemUtilities.readCoding(getJurisdictionFromLocale(s)));
|
||||
}
|
||||
|
||||
public static String displayJurisdiction(Coding c) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
|
@ -34,10 +35,24 @@ import java.util.List;
|
|||
|
||||
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ETooCostly;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||
|
||||
public interface ValueSetChecker {
|
||||
|
||||
Boolean codeInValueSet(String system, String code, List<String> warnings) throws ETooCostly, EOperationOutcome, Exception;
|
||||
public static class ValidationProcessInfo {
|
||||
private TerminologyServiceErrorClass err;
|
||||
private List<String> warnings = new ArrayList<>();
|
||||
public TerminologyServiceErrorClass getErr() {
|
||||
return err;
|
||||
}
|
||||
public void setErr(TerminologyServiceErrorClass err) {
|
||||
this.err = err;
|
||||
}
|
||||
public List<String> getWarnings() {
|
||||
return warnings;
|
||||
}
|
||||
}
|
||||
Boolean codeInValueSet(String system, String code, ValidationProcessInfo info) throws ETooCostly, EOperationOutcome, Exception;
|
||||
|
||||
}
|
|
@ -61,6 +61,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetChecker.ValidationProcessInfo;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
|
@ -129,11 +130,11 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
public ValidationResult validateCode(CodeableConcept code) throws FHIRException {
|
||||
// first, we validate the codings themselves
|
||||
List<String> errors = new ArrayList<String>();
|
||||
List<String> warnings = new ArrayList<String>();
|
||||
ValidationProcessInfo info = new ValidationProcessInfo();
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
for (Coding c : code.getCoding()) {
|
||||
if (!c.hasSystem()) {
|
||||
warnings.add(context.formatMessage(I18nConstants.CODING_HAS_NO_SYSTEM__CANNOT_VALIDATE));
|
||||
info.getWarnings().add(context.formatMessage(I18nConstants.CODING_HAS_NO_SYSTEM__CANNOT_VALIDATE));
|
||||
}
|
||||
CodeSystem cs = resolveCodeSystem(c.getSystem());
|
||||
ValidationResult res = null;
|
||||
|
@ -145,7 +146,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
if (!res.isOk()) {
|
||||
errors.add(res.getMessage());
|
||||
} else if (res.getMessage() != null) {
|
||||
warnings.add(res.getMessage());
|
||||
info.getWarnings().add(res.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +154,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
Boolean result = false;
|
||||
for (Coding c : code.getCoding()) {
|
||||
Boolean ok = codeInValueSet(c.getSystem(), c.getCode(), warnings);
|
||||
Boolean ok = codeInValueSet(c.getSystem(), c.getCode(), info);
|
||||
if (ok == null && result == false) {
|
||||
result = null;
|
||||
} else if (ok) {
|
||||
|
@ -162,15 +163,15 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
}
|
||||
if (result == null) {
|
||||
warnings.add(0, context.formatMessage(I18nConstants.UNABLE_TO_CHECK_IF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET_, valueset.getUrl()));
|
||||
info.getWarnings().add(0, context.formatMessage(I18nConstants.UNABLE_TO_CHECK_IF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET_, valueset.getUrl()));
|
||||
} else if (!result) {
|
||||
errors.add(0, context.formatMessage(I18nConstants.NONE_OF_THE_PROVIDED_CODES_ARE_IN_THE_VALUE_SET_, valueset.getUrl()));
|
||||
}
|
||||
}
|
||||
if (errors.size() > 0) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, errors.toString());
|
||||
} else if (warnings.size() > 0) {
|
||||
return new ValidationResult(IssueSeverity.WARNING, warnings.toString());
|
||||
} else if (info.getWarnings().size() > 0) {
|
||||
return new ValidationResult(IssueSeverity.WARNING, info.getWarnings().toString());
|
||||
} else {
|
||||
ConceptDefinitionComponent cd = new ConceptDefinitionComponent(foundCoding.getCode());
|
||||
cd.setDisplay(foundCoding.getDisplay());
|
||||
|
@ -251,19 +252,24 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
inInclude = checkInclude(code);
|
||||
}
|
||||
|
||||
List<String> warnings = new ArrayList<>();
|
||||
ValidationProcessInfo info = new ValidationProcessInfo();
|
||||
|
||||
// then, if we have a value set, we check it's in the value set
|
||||
if (valueset != null && options.getValueSetMode() != ValueSetMode.NO_MEMBERSHIP_CHECK) {
|
||||
if ((res==null || res.isOk())) {
|
||||
Boolean ok = codeInValueSet(system, code.getCode(), warnings);
|
||||
Boolean ok = codeInValueSet(system, code.getCode(), info);
|
||||
if (ok == null || !ok) {
|
||||
if (res == null) {
|
||||
res = new ValidationResult((IssueSeverity) null, null);
|
||||
}
|
||||
if (!inExpansion && !inInclude) {
|
||||
if (warnings != null) {
|
||||
res.setMessage("Not in value set "+valueset.getUrl()+" ("+warnings+")").setSeverity(IssueSeverity.ERROR);
|
||||
if (info.getErr() != null) {
|
||||
res.setErrorClass(info.getErr());
|
||||
}
|
||||
if (ok == null) {
|
||||
res.setMessage("Unable to check whether code is in value set "+valueset.getUrl()+": "+info.getWarnings()).setSeverity(IssueSeverity.WARNING);
|
||||
} else if (!inExpansion && !inInclude) {
|
||||
if (!info.getWarnings().isEmpty()) {
|
||||
res.setMessage("Not in value set "+valueset.getUrl()+": "+info.getWarnings()).setSeverity(IssueSeverity.ERROR);
|
||||
} else {
|
||||
res.setMessage("Not in value set "+valueset.getUrl()).setSeverity(IssueSeverity.ERROR);
|
||||
}
|
||||
|
@ -583,7 +589,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return false;
|
||||
}
|
||||
CodeSystem cs = resolveCodeSystem(vsi.getSystem());
|
||||
if (cs != null) {
|
||||
if (cs != null && cs.getContent() == CodeSystemContentMode.COMPLETE) {
|
||||
|
||||
if (vsi.hasConcept()) {
|
||||
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
||||
|
@ -598,15 +604,15 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
sys.add(vsi.getSystem());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (vsi.hasConcept()) {
|
||||
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
||||
boolean match = cc.getCode().equals(code);
|
||||
if (match) {
|
||||
sys.add(vsi.getSystem());
|
||||
}
|
||||
} else if (vsi.hasConcept()) {
|
||||
for (ConceptReferenceComponent cc : vsi.getConcept()) {
|
||||
boolean match = cc.getCode().equals(code);
|
||||
if (match) {
|
||||
sys.add(vsi.getSystem());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -640,7 +646,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
|
||||
@Override
|
||||
public Boolean codeInValueSet(String system, String code, List<String> warnings) throws FHIRException {
|
||||
public Boolean codeInValueSet(String system, String code, ValidationProcessInfo info) throws FHIRException {
|
||||
if (valueset == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -651,7 +657,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
} else if (valueset.hasCompose()) {
|
||||
int i = 0;
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) {
|
||||
Boolean ok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
Boolean ok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, info);
|
||||
i++;
|
||||
if (ok == null && result == false) {
|
||||
result = null;
|
||||
|
@ -662,7 +668,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
i = valueset.getCompose().getInclude().size();
|
||||
for (ConceptSetComponent vsi : valueset.getCompose().getExclude()) {
|
||||
Boolean nok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, warnings);
|
||||
Boolean nok = inComponent(vsi, i, system, code, valueset.getCompose().getInclude().size() == 1, info);
|
||||
i++;
|
||||
if (nok == null && result == false) {
|
||||
result = null;
|
||||
|
@ -675,7 +681,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return result;
|
||||
}
|
||||
|
||||
private Boolean inComponent(ConceptSetComponent vsi, int vsiIndex, String system, String code, boolean only, List<String> warnings) throws FHIRException {
|
||||
private Boolean inComponent(ConceptSetComponent vsi, int vsiIndex, String system, String code, boolean only, ValidationProcessInfo info) throws FHIRException {
|
||||
boolean ok = true;
|
||||
|
||||
if (vsi.hasValueSet()) {
|
||||
|
@ -721,8 +727,9 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
vs.getCompose().addInclude(vsi);
|
||||
ValidationResult res = context.validateCode(options.noClient(), new Coding(system, code, null), vs);
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
|
||||
if (warnings != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
warnings.add(context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system));
|
||||
if (info != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
info.getWarnings().add(context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system));
|
||||
info.setErr(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4503,7 +4503,18 @@ public class FHIRPathEngine {
|
|||
return makeBoolean(false);
|
||||
}
|
||||
} else if (ns.equals("FHIR")) {
|
||||
return makeBoolean(n.equals(focus.get(0).fhirType()));
|
||||
if (n.equals(focus.get(0).fhirType())) {
|
||||
return makeBoolean(true);
|
||||
} else {
|
||||
StructureDefinition sd = worker.fetchTypeDefinition(focus.get(0).fhirType());
|
||||
while (sd != null) {
|
||||
if (n.equals(sd.getType())) {
|
||||
return makeBoolean(true);
|
||||
}
|
||||
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
}
|
||||
return makeBoolean(false);
|
||||
}
|
||||
} else {
|
||||
return makeBoolean(false);
|
||||
}
|
||||
|
|
|
@ -103,6 +103,9 @@ public class GraphQLSchemaGenerator {
|
|||
if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
|
||||
tl.put(sd.getName(), sd);
|
||||
}
|
||||
if (sd.getKind() == StructureDefinitionKind.RESOURCE && sd.getDerivation() != TypeDerivationRule.CONSTRAINT && sd.getAbstract()) {
|
||||
tl.put(sd.getName(), sd);
|
||||
}
|
||||
}
|
||||
writer.write("# FHIR GraphQL Schema. Version " + version + "\r\n\r\n");
|
||||
writer.write("# FHIR Defined Primitive types\r\n");
|
||||
|
@ -290,16 +293,17 @@ public class GraphQLSchemaGenerator {
|
|||
}
|
||||
|
||||
private void generateType(Map<String, String> existingTypeNames, Writer writer, StructureDefinition sd, EnumSet<FHIROperationType> operations) throws IOException {
|
||||
if (sd.getAbstract()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (operations.contains(FHIROperationType.READ) || operations.contains(FHIROperationType.SEARCH)) {
|
||||
List<StringBuilder> list = new ArrayList<>();
|
||||
StringBuilder b = new StringBuilder();
|
||||
list.add(b);
|
||||
b.append("type ");
|
||||
b.append(sd.getName());
|
||||
StructureDefinition sdp = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
if (sdp != null) {
|
||||
b.append(" implements ");
|
||||
b.append(sdp.getType());
|
||||
}
|
||||
b.append(" {\r\n");
|
||||
ElementDefinition ed = sd.getSnapshot().getElementFirstRep();
|
||||
generateProperties(existingTypeNames, list, b, sd.getName(), sd, ed, "type", "");
|
||||
|
@ -370,7 +374,13 @@ public class GraphQLSchemaGenerator {
|
|||
if (suffix)
|
||||
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
|
||||
b.append(": ");
|
||||
b.append(n);
|
||||
if (!child.getMax().equals("1")) {
|
||||
b.append("[");
|
||||
b.append(n);
|
||||
b.append("]");
|
||||
} else {
|
||||
b.append(n);
|
||||
}
|
||||
if (!child.getPath().endsWith(".id")) {
|
||||
b.append(" _");
|
||||
b.append(tail(child.getPath(), suffix));
|
||||
|
|
|
@ -129,4 +129,33 @@ public class OperationOutcomeUtilities {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public static OperationOutcomeIssueComponent convertToIssueSimple(ValidationMessage message, OperationOutcome op) {
|
||||
OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
|
||||
issue.setUserData("source.vm", message);
|
||||
issue.setCode(convert(message.getType()));
|
||||
|
||||
if (message.getLocation() != null) {
|
||||
// message location has a fhirPath in it. We need to populate the expression
|
||||
issue.addExpression(message.getLocation());
|
||||
}
|
||||
if (message.getLine() >= 0 && message.getCol() >= 0) {
|
||||
issue.setDiagnostics("["+message.getLine()+","+message.getCol()+"]");
|
||||
}
|
||||
issue.setSeverity(convert(message.getLevel()));
|
||||
CodeableConcept c = new CodeableConcept();
|
||||
c.setText(message.getMessage());
|
||||
issue.setDetails(c);
|
||||
return issue;
|
||||
}
|
||||
|
||||
public static OperationOutcome createOutcomeSimple(List<ValidationMessage> messages) {
|
||||
OperationOutcome res = new OperationOutcome();
|
||||
for (ValidationMessage vm : messages) {
|
||||
res.addIssue(convertToIssueSimple(vm, res));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
|
@ -205,6 +205,7 @@ public class ToolingExtensions {
|
|||
public static final String EXT_REND_MD = "http://hl7.org/fhir/StructureDefinition/rendering-markdown";
|
||||
public static final String EXT_CAP_STMT_EXPECT = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation";
|
||||
public static final String EXT_ED_HEIRARCHY = "http://hl7.org/fhir/StructureDefinition/elementdefinition-heirarchy";
|
||||
public static final String EXT_SD_DEPENDENCY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies";
|
||||
|
||||
// in the tooling IG
|
||||
public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding";
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package org.hl7.fhir.utilities;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class FileFormat {
|
||||
|
||||
public static boolean fileEncodingIsUtf8() {
|
||||
return Charset.defaultCharset().equals(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static void checkCharsetAndWarnIfNotUTF8(PrintStream out) {
|
||||
if (fileEncodingIsUtf8()) return;
|
||||
out.println("");
|
||||
out.println("WARNING: Default file encoding is " + Charset.defaultCharset() + " which may cause unexpected results. ");
|
||||
out.println(" To fix this issue, run this program with the parameter '-Dfile.encoding=UTF-8'");
|
||||
out.println(" Future releases may not be able to run at all with encoding " + Charset.defaultCharset());
|
||||
out.println("");
|
||||
}
|
||||
}
|
|
@ -64,11 +64,41 @@ public class MarkDownProcessor {
|
|||
}
|
||||
switch (dialect) {
|
||||
case DARING_FIREBALL : return Processor.process(source);
|
||||
case COMMON_MARK : return processCommonMark(source);
|
||||
case COMMON_MARK : return processCommonMark(preProcess(source));
|
||||
default: throw new Error("Unknown Markdown Dialect: "+dialect.toString()+" at "+context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This deals with a painful problem created by the intersection of previous publishing processes
|
||||
* and the way commonmark specifies that < is handled in content. For control reasons, the FHIR specification does
|
||||
* not allow raw html tags in the markdown
|
||||
*
|
||||
* This check finds any raw <[x] where [x] is any alpha character, and prepends \ to it so that it
|
||||
* renders as a < (e.g. gets escaped in the output HTML)
|
||||
*
|
||||
* This is public to enable testing (not for direct use otherwise)
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
public static String preProcess(String source) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < source.length(); i++) {
|
||||
char last = i > 0 ? source.charAt(i-1) : 0;
|
||||
char current = source.charAt(i);
|
||||
char next = i < source.length() -1 ? source.charAt(i+1) : 0;
|
||||
if (current == '<' && Character.isAlphabetic(next) && last != '\\') {
|
||||
b.append('\\');
|
||||
b.append(current);
|
||||
} else {
|
||||
b.append(current);
|
||||
}
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
|
||||
private String processCommonMark(String source) {
|
||||
Set<Extension> extensions = Collections.singleton(TablesExtension.create());
|
||||
Parser parser = Parser.builder().extensions(extensions).build();
|
||||
|
|
|
@ -1758,4 +1758,12 @@ public class Utilities {
|
|||
return text;
|
||||
}
|
||||
|
||||
public static int parseInt(String value, int def) {
|
||||
if (isInteger(value)) {
|
||||
return Integer.parseInt(value);
|
||||
} else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -487,7 +487,6 @@ public class VersionUtilities {
|
|||
|
||||
res.add("ActivityDefinition");
|
||||
res.add("CapabilityStatement");
|
||||
res.add("CapabilityStatement2");
|
||||
res.add("ChargeItemDefinition");
|
||||
res.add("Citation");
|
||||
res.add("CodeSystem");
|
||||
|
|
|
@ -488,6 +488,7 @@ public class I18nConstants {
|
|||
public static final String TYPE_SPECIFIC_CHECKS_DT_BASE64_VALID = "Type_Specific_Checks_DT_Base64_Valid";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_BOOLEAN_VALUE = "Type_Specific_Checks_DT_Boolean_Value";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_CODE_WS = "Type_Specific_Checks_DT_Code_WS";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML = "TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DATETIME_REASONABLE = "Type_Specific_Checks_DT_DateTime_Reasonable";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DATETIME_REGEX = "Type_Specific_Checks_DT_DateTime_Regex";
|
||||
public static final String TYPE_SPECIFIC_CHECKS_DT_DATETIME_TZ = "Type_Specific_Checks_DT_DateTime_TZ";
|
||||
|
@ -610,6 +611,7 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST = "VALIDATION_VAL_PROFILE_SIGNPOST";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = "VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_META = "VALIDATION_VAL_PROFILE_SIGNPOST_META";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_DEP = "VALIDATION_VAL_PROFILE_SIGNPOST_DEP";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM = "VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM";
|
||||
public static final String VALIDATION_VAL_PROFILE_SLICEORDER = "Validation_VAL_Profile_SliceOrder";
|
||||
public static final String VALIDATION_VAL_PROFILE_OTHER_VERSION = "VALIDATION_VAL_PROFILE_OTHER_VERSION";
|
||||
|
@ -621,6 +623,7 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE = "Validation_VAL_Profile_WrongType";
|
||||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE2 = "Validation_VAL_Profile_WrongType2";
|
||||
public static final String VALIDATION_VAL_UNKNOWN_PROFILE = "Validation_VAL_Unknown_Profile";
|
||||
public static final String VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED = "VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED";
|
||||
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER";
|
||||
|
@ -635,6 +638,10 @@ public class I18nConstants {
|
|||
public static final String CODESYSTEM_SHAREABLE_MISSING_HL7 = "CODESYSTEM_SHAREABLE_MISSING_HL7";
|
||||
public static final String CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7 = "CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7";
|
||||
public static final String CODESYSTEM_SHAREABLE_EXTRA_MISSING = "CODESYSTEM_SHAREABLE_EXTRA_MISSING";
|
||||
public static final String MEASURE_SHAREABLE_MISSING = "MEASURE_SHAREABLE_MISSING";
|
||||
public static final String MEASURE_SHAREABLE_MISSING_HL7 = "MEASURE_SHAREABLE_MISSING_HL7";
|
||||
public static final String MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = "MEASURE_SHAREABLE_EXTRA_MISSING_HL7";
|
||||
public static final String MEASURE_SHAREABLE_EXTRA_MISSING = "MEASURE_SHAREABLE_EXTRA_MISSING";
|
||||
public static final String VALUESET_UNC_SYSTEM_WARNING = "VALUESET_UNC_SYSTEM_WARNING";
|
||||
public static final String VALUESET_UNC_SYSTEM_WARNING_VER = "VALUESET_UNC_SYSTEM_WARNING_VER";
|
||||
public static final String VALUESET_IMPORT_UNION_INTERSECTION = "VALUESET_IMPORT_UNION_INTERSECTION";
|
||||
|
|
|
@ -686,7 +686,7 @@ public class JsonTrackingParser {
|
|||
}
|
||||
|
||||
public static void write(JsonObject json, File file) throws IOException {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
String jcnt = gson.toJson(json);
|
||||
TextFile.stringToFile(jcnt, file);
|
||||
}
|
||||
|
|
|
@ -236,6 +236,7 @@ Validation_VAL_Profile_Unknown = Profile reference ''{0}'' has not been checked
|
|||
VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY = Profile reference ''{0}'' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles
|
||||
VALIDATION_VAL_PROFILE_UNKNOWN_ERROR = Profile reference ''{0}'' has not been checked because it is unknown, and fetching it resulted in the error {1}
|
||||
Validation_VAL_Unknown_Profile = Unknown profile {0}
|
||||
VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED = Profile {1} identifies {2} as a dependency (using the extension http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies), but this profile could not be found
|
||||
XHTML_XHTML_Attribute_Illegal = Illegal attribute name in the XHTML (''{0}'' on ''{1}'')
|
||||
XHTML_XHTML_Element_Illegal = Illegal element name in the XHTML (''{0}'')
|
||||
XHTML_XHTML_NS_InValid = Wrong namespace on the XHTML (''{0}'', should be ''{1}'')
|
||||
|
@ -384,7 +385,7 @@ Error_parsing_JSON_ = Error parsing JSON: {0}
|
|||
Node_type__is_not_allowed = Node type {0} is not allowed
|
||||
CDATA_is_not_allowed = CDATA is not allowed
|
||||
Undefined_element_ = Undefined element ''{0}''
|
||||
Undefined_attribute__on__for_type__properties__ = Undefined attribute ''@{0}'' on {1} for type {2} (properties = {3})
|
||||
Undefined_attribute__on__for_type__properties__ = Undefined attribute ''@{0}'' on {1} for type {2}
|
||||
Text_should_not_be_present = Text should not be present (''{0}'')
|
||||
Wrong_namespace__expected_ = Wrong namespace - expected ''{0}''
|
||||
Element_must_have_some_content = Element must have some content
|
||||
|
@ -536,6 +537,7 @@ VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN = Global Profile reference ''{0}'' from IG
|
|||
VALIDATION_VAL_PROFILE_SIGNPOST_BASE = Validate resource against profile
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST = Validate resource against profile {0}
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_META = Validate resource against profile {0} (per meta)
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_DEP = Validate resource against profile {0} (per http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies in {1})
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM = Validate resource against profile {0} - provided as bundle param
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = Validate resource against profile {0} - a global profile in {1}
|
||||
ERROR_GENERATING_SNAPSHOT = Error generating Snapshot: {0} (this usually arises from a problem in the differential)
|
||||
|
@ -726,7 +728,13 @@ VALUESET_SHAREABLE_MISSING = The ShareableValueSet profile says that the {0} ele
|
|||
VALUESET_SHAREABLE_EXTRA_MISSING = The ShareableValueSet profile recommends that the {0} element is populated, but it is not present. Published value sets SHOULD conform to the ShareableValueSet profile
|
||||
VALUESET_SHAREABLE_MISSING_HL7 = The ShareableValueSet profile says that the {0} element is mandatory, but it is not found. HL7 Published value sets SHALL conform to the ShareableValueSet profile
|
||||
VALUESET_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableValueSet profile recommends that the {0} element is populated, but it is not found. HL7 Published value sets SHALL conform to the ShareableValueSet profile
|
||||
CODESYSTEM_SHAREABLE_MISSING = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not present. Published value sets SHOULD conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_EXTRA_MISSING = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not present. Published value sets SHOULD conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_MISSING_HL7 = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not found. HL7 Published value sets SHALL conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not found. HL7 Published value sets SHALL conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_MISSING = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not present. Published code systems SHOULD conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_EXTRA_MISSING = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not present. Published code systems SHOULD conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_MISSING_HL7 = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not found. HL7 Published code systems SHALL conform to the ShareableCodeSystem profile
|
||||
CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not found. HL7 Published code systems SHALL conform to the ShareableCodeSystem profile
|
||||
MEASURE_SHAREABLE_MISSING = The ShareableMeasure profile says that the {0} element is mandatory, but it is not present. Published measures SHOULD conform to the ShareableMeasure profile
|
||||
MEASURE_SHAREABLE_EXTRA_MISSING = The ShareableMeasure profile recommends that the {0} element is populated, but it is not present. Published measures SHOULD conform to the ShareableMeasure profile
|
||||
MEASURE_SHAREABLE_MISSING_HL7 = The ShareableMeasure profile says that the {0} element is mandatory, but it is not found. HL7 Published measures SHALL conform to the ShareableMeasure profile
|
||||
MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableMeasure profile recommends that the {0} element is populated, but it is not found. HL7 Published measures SHALL conform to the ShareableMeasure profile
|
||||
TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML = The markdown contains content that appears to be an embedded HTML tag starting at ''{0}''. This will (or SHOULD) be escaped by the presentation layer. The content should be checked to confirm that this is the desired behaviour
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.hl7.fhir.utilities;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class FileFormatTest {
|
||||
@Test
|
||||
public void testCurrentFileFormat() throws IOException {
|
||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||
|
||||
FileFormat.checkCharsetAndWarnIfNotUTF8(new PrintStream(bo));
|
||||
|
||||
bo.flush();
|
||||
String allWrittenLines = new String(bo.toByteArray());
|
||||
|
||||
assertAWarningIsGivenWhenNotUTF8(allWrittenLines);
|
||||
}
|
||||
|
||||
private static void assertAWarningIsGivenWhenNotUTF8(String allWrittenLines) {
|
||||
if (Charset.defaultCharset().equals(StandardCharsets.UTF_8)) {
|
||||
assertEquals(0, allWrittenLines.length());
|
||||
} else {
|
||||
assertThat(allWrittenLines, containsString("WARNING"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package org.hl7.fhir.utilities.tests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class MarkdownPreprocessorTesting {
|
||||
|
||||
@Test
|
||||
public void testSimple() throws IOException {
|
||||
assertEquals(MarkDownProcessor.preProcess("1 < 2"), "1 < 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHTML() throws IOException {
|
||||
assertEquals(MarkDownProcessor.preProcess("<type>"), "\\<type>");
|
||||
assertEquals(MarkDownProcessor.preProcess("\\<type>"), "\\<type>");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBorder() throws IOException {
|
||||
assertEquals(MarkDownProcessor.preProcess("<>"), "<>");
|
||||
assertEquals(MarkDownProcessor.preProcess("><"), "><");
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -197,7 +197,7 @@
|
|||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.12.6.1</version>
|
||||
<version>2.14.0-rc1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.hl7.fhir.utilities.npm.ToolsVersion;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||
import org.hl7.fhir.validation.BaseValidator.ValidationControl;
|
||||
import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck;
|
||||
import org.hl7.fhir.validation.cli.services.IPackageInstaller;
|
||||
import org.hl7.fhir.validation.cli.utils.*;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
|
@ -160,6 +161,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
@Getter @Setter private boolean allowExampleUrls;
|
||||
@Getter @Setter private boolean showMessagesFromReferences;
|
||||
@Getter @Setter private boolean doImplicitFHIRPathStringConversion;
|
||||
@Getter @Setter private HtmlInMarkdownCheck htmlInMarkdownCheck;
|
||||
@Getter @Setter private Locale locale;
|
||||
@Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>();
|
||||
@Getter @Setter private List<String> extensionDomains = new ArrayList<>();
|
||||
|
@ -625,6 +627,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
validator.getValidationControl().putAll(validationControl);
|
||||
validator.setQuestionnaireMode(questionnaireMode);
|
||||
validator.setLevel(level);
|
||||
validator.setHtmlInMarkdownCheck(htmlInMarkdownCheck);
|
||||
validator.setNoUnicodeBiDiControlChars(noUnicodeBiDiControlChars);
|
||||
validator.setDoImplicitFHIRPathStringConversion(doImplicitFHIRPathStringConversion);
|
||||
if (format == FhirFormat.SHC) {
|
||||
|
|
|
@ -61,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.utilities.FileFormat;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
@ -154,6 +155,8 @@ public class ValidatorCli {
|
|||
|
||||
CliContext cliContext = Params.loadCliContext(args);
|
||||
|
||||
FileFormat.checkCharsetAndWarnIfNotUTF8(System.out);
|
||||
|
||||
if (shouldDisplayHelpToUser(args)) {
|
||||
Display.displayHelpDetails();
|
||||
} else if (Params.hasParam(args, Params.COMPARE)) {
|
||||
|
|
|
@ -48,6 +48,8 @@ public class CliContext {
|
|||
private boolean wantInvariantsInMessages = false;
|
||||
@JsonProperty("doImplicitFHIRPathStringConversion")
|
||||
private boolean doImplicitFHIRPathStringConversion = false;
|
||||
@JsonProperty("htmlInMarkdownCheck")
|
||||
private HtmlInMarkdownCheck htmlInMarkdownCheck = HtmlInMarkdownCheck.WARNING;
|
||||
|
||||
@JsonProperty("map")
|
||||
private String map = null;
|
||||
|
@ -248,6 +250,16 @@ public class CliContext {
|
|||
this.doImplicitFHIRPathStringConversion = doImplicitFHIRPathStringConversion;
|
||||
}
|
||||
|
||||
@JsonProperty("htmlInMarkdownCheck")
|
||||
public HtmlInMarkdownCheck getHtmlInMarkdownCheck() {
|
||||
return htmlInMarkdownCheck;
|
||||
}
|
||||
|
||||
@JsonProperty("htmlInMarkdownCheck")
|
||||
public void setHtmlInMarkdownCheck(HtmlInMarkdownCheck htmlInMarkdownCheck) {
|
||||
this.htmlInMarkdownCheck = htmlInMarkdownCheck;
|
||||
}
|
||||
|
||||
@JsonProperty("locale")
|
||||
public String getLanguageCode() {
|
||||
return locale;
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package org.hl7.fhir.validation.cli.model;
|
||||
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public enum HtmlInMarkdownCheck {
|
||||
NONE,
|
||||
WARNING,
|
||||
ERROR;
|
||||
|
||||
public static boolean isValidCode(String q) {
|
||||
return fromCode(q) != null;
|
||||
}
|
||||
|
||||
public static HtmlInMarkdownCheck fromCode(String q) {
|
||||
if (Utilities.noString(q)) {
|
||||
return null;
|
||||
}
|
||||
q = q.toLowerCase();
|
||||
if (Utilities.existsInList(q, "n", "none", "ignore", "i")) {
|
||||
return NONE;
|
||||
}
|
||||
if (Utilities.existsInList(q, "w", "warning", "warnings", "warn")) {
|
||||
return WARNING;
|
||||
}
|
||||
if (Utilities.existsInList(q, "e", "error", "errors", "err")) {
|
||||
return ERROR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -372,6 +372,7 @@ public class ValidationService {
|
|||
validator.setAssumeValidRestReferences(cliContext.isAssumeValidRestReferences());
|
||||
validator.setShowMessagesFromReferences(cliContext.isShowMessagesFromReferences());
|
||||
validator.setDoImplicitFHIRPathStringConversion(cliContext.isDoImplicitFHIRPathStringConversion());
|
||||
validator.setHtmlInMarkdownCheck(cliContext.getHtmlInMarkdownCheck());
|
||||
validator.setNoExtensibleBindingMessages(cliContext.isNoExtensibleBindingMessages());
|
||||
validator.setNoUnicodeBiDiControlChars(cliContext.isNoUnicodeBiDiControlChars());
|
||||
validator.setNoInvariantChecks(cliContext.isNoInvariants());
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
|||
import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.cli.model.CliContext;
|
||||
import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
@ -69,7 +70,8 @@ public class Params {
|
|||
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
|
||||
public static final String OUTPUT_STYLE = "-output-style";
|
||||
public static final String DO_IMPLICIT_FHIRPATH_STRING_CONVERSION = "-implicit-fhirpath-string-conversions";
|
||||
private static final Object JURISDICTION = "-jurisdiction";
|
||||
public static final String JURISDICTION = "-jurisdiction";
|
||||
public static final String HTML_IN_MARKDOWN = "-html-in-markdown";
|
||||
|
||||
public static final String RUN_TESTS = "-run-tests";
|
||||
|
||||
|
@ -176,6 +178,17 @@ public class Params {
|
|||
cliContext.setShowMessagesFromReferences(true);
|
||||
} else if (args[i].equals(DO_IMPLICIT_FHIRPATH_STRING_CONVERSION)) {
|
||||
cliContext.setDoImplicitFHIRPathStringConversion(true);
|
||||
} else if (args[i].equals(HTML_IN_MARKDOWN)) {
|
||||
if (i + 1 == args.length)
|
||||
throw new Error("Specified "+HTML_IN_MARKDOWN+" without indicating mode");
|
||||
else {
|
||||
String q = args[++i];
|
||||
if (!HtmlInMarkdownCheck.isValidCode(q)) {
|
||||
throw new Error("Specified "+HTML_IN_MARKDOWN+" with na invalid code - must be ignore, warning, or error");
|
||||
} else {
|
||||
cliContext.setHtmlInMarkdownCheck(HtmlInMarkdownCheck.fromCode(q));
|
||||
}
|
||||
}
|
||||
} else if (args[i].equals(LOCALE)) {
|
||||
if (i + 1 == args.length) {
|
||||
throw new Error("Specified -locale without indicating locale");
|
||||
|
|
|
@ -42,6 +42,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -142,6 +144,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
|
|||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.*;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||
import org.hl7.fhir.utilities.SIDUtilities;
|
||||
import org.hl7.fhir.utilities.SimpleTimeTracker;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
|
@ -159,9 +162,12 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck;
|
||||
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
|
||||
import org.hl7.fhir.validation.cli.utils.ValidationLevel;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator.CanonicalResourceLookupResult;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator.CanonicalTypeSorter;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator.StructureDefinitionSorterByUrl;
|
||||
import org.hl7.fhir.validation.instance.type.BundleValidator;
|
||||
import org.hl7.fhir.validation.instance.type.CodeSystemValidator;
|
||||
import org.hl7.fhir.validation.instance.type.MeasureValidator;
|
||||
|
@ -199,6 +205,25 @@ import com.google.gson.JsonObject;
|
|||
*/
|
||||
|
||||
public class InstanceValidator extends BaseValidator implements IResourceValidator {
|
||||
|
||||
public class StructureDefinitionSorterByUrl implements Comparator<StructureDefinition> {
|
||||
|
||||
@Override
|
||||
public int compare(StructureDefinition o1, StructureDefinition o2) {
|
||||
return o1.getUrl().compareTo(o2.getUrl());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CanonicalTypeSorter implements Comparator<CanonicalType> {
|
||||
|
||||
@Override
|
||||
public int compare(CanonicalType o1, CanonicalType o2) {
|
||||
return o1.getValue().compareTo(o2.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CanonicalResourceLookupResult {
|
||||
|
||||
private CanonicalResource resource;
|
||||
|
@ -387,6 +412,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private boolean noCheckAggregation;
|
||||
private boolean wantCheckSnapshotUnchanged;
|
||||
private boolean noUnicodeBiDiControlChars;
|
||||
private HtmlInMarkdownCheck htmlInMarkdownCheck;
|
||||
|
||||
private List<ImplementationGuide> igs = new ArrayList<>();
|
||||
private List<String> extensionDomains = new ArrayList<String>();
|
||||
|
@ -792,15 +818,31 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
setParents(element);
|
||||
|
||||
long t = System.nanoTime();
|
||||
NodeStack stack = new NodeStack(context, path, element, validationLanguage);
|
||||
if (profiles == null || profiles.isEmpty()) {
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, new NodeStack(context, path, element, validationLanguage).resetIds(), null);
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, stack.resetIds(), null);
|
||||
} else {
|
||||
int i = 0;
|
||||
while (i < profiles.size()) {
|
||||
StructureDefinition sd = profiles.get(i);
|
||||
if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
StructureDefinition dep = context.fetchResource( StructureDefinition.class, ext.getValue().primitiveValue());
|
||||
if (dep == null) {
|
||||
warning(errors, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getUrl());
|
||||
} else if (!profiles.contains(dep)) {
|
||||
profiles.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for (StructureDefinition defn : profiles) {
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, new NodeStack(context, path, element, validationLanguage).resetIds(), null);
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, stack.resetIds(), null);
|
||||
}
|
||||
}
|
||||
if (hintAboutNonMustSupport) {
|
||||
checkElementUsage(errors, element, new NodeStack(context, path, element, validationLanguage));
|
||||
checkElementUsage(errors, element, stack);
|
||||
}
|
||||
errors.removeAll(messagesToRemove);
|
||||
timeTracker.overall(t);
|
||||
|
@ -1191,7 +1233,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
checkBindings(errors, path, element, stack, valueset, nextCoding);
|
||||
}
|
||||
}
|
||||
timeTracker.tx(t, "vc "+DataRenderer.display(context, cc));
|
||||
timeTracker.tx(t, "vc "+cc.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -1666,6 +1708,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(binding.getValueSet(), valueset), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) e.printStackTrace();
|
||||
|
@ -2134,7 +2178,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (!"xhtml".equals(type)) {
|
||||
if (securityChecks) {
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, !containsHtmlTags(e.primitiveValue()), I18nConstants.SECURITY_STRING_CONTENT_ERROR);
|
||||
} else {
|
||||
} else if (!"markdown".equals(type)){
|
||||
hint(errors, IssueType.INVALID, e.line(), e.col(), path, !containsHtmlTags(e.primitiveValue()), I18nConstants.SECURITY_STRING_CONTENT_WARNING);
|
||||
}
|
||||
}
|
||||
|
@ -2318,6 +2362,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
checkPrimitiveBinding(hostContext, errors, path, type, context, e, profile, node);
|
||||
}
|
||||
|
||||
if (type.equals("markdown") && htmlInMarkdownCheck != HtmlInMarkdownCheck.NONE) {
|
||||
String raw = e.primitiveValue();
|
||||
String processed = MarkDownProcessor.preProcess(raw);
|
||||
if (!raw.equals(processed)) {
|
||||
int i = 0;
|
||||
while (i < raw.length() && raw.charAt(1) == processed.charAt(i)) {
|
||||
i++;
|
||||
}
|
||||
warningOrError(htmlInMarkdownCheck == HtmlInMarkdownCheck.ERROR, errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML, raw.subSequence(i, 2));
|
||||
}
|
||||
}
|
||||
if (type.equals("xhtml")) {
|
||||
XhtmlNode xhtml = e.getXhtml();
|
||||
if (xhtml != null) { // if it is null, this is an error already noted in the parsers
|
||||
|
@ -3226,7 +3281,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return true;
|
||||
}
|
||||
|
||||
private String asListByUrl(Collection<StructureDefinition> list) {
|
||||
private String asListByUrl(Collection<StructureDefinition> coll) {
|
||||
List<StructureDefinition> list = new ArrayList<>();
|
||||
list.addAll(coll);
|
||||
Collections.sort(list, new StructureDefinitionSorterByUrl());
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (StructureDefinition sd : list) {
|
||||
b.append(sd.getUrl());
|
||||
|
@ -3234,7 +3292,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
private String asList(Collection<CanonicalType> list) {
|
||||
private String asList(Collection<CanonicalType> coll) {
|
||||
List<CanonicalType> list = new ArrayList<>();
|
||||
list.addAll(coll);
|
||||
Collections.sort(list, new CanonicalTypeSorter());
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (CanonicalType c : list) {
|
||||
b.append(c.getValue());
|
||||
|
@ -3670,7 +3731,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private String getErrorMessage(String message) {
|
||||
return message != null ? " (error message = " + message + ")" : "";
|
||||
return message != null ? " (error message = " + message + ")" : "";
|
||||
}
|
||||
|
||||
public boolean isSuppressLoincSnomedMessages() {
|
||||
|
@ -4474,28 +4535,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else if (!fetcher.fetchesCanonicalResource(this, profile.primitiveValue())) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY, profile.primitiveValue());
|
||||
} else {
|
||||
sd = null;
|
||||
String url = profile.primitiveValue();
|
||||
CanonicalResourceLookupResult cr = crLookups.get(url);
|
||||
if (cr != null) {
|
||||
if (cr.error != null) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, url, cr.error);
|
||||
} else {
|
||||
sd = (StructureDefinition) cr.resource;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sd = (StructureDefinition) fetcher.fetchCanonicalResource(this, url);
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(sd));
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) { e.printStackTrace(); }
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(e.getMessage()));
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage());
|
||||
}
|
||||
if (sd != null) {
|
||||
context.cacheResource(sd);
|
||||
}
|
||||
}
|
||||
sd = lookupProfileReference(errors, element, stack, i, profile, sd);
|
||||
}
|
||||
}
|
||||
if (sd != null) {
|
||||
|
@ -4510,6 +4550,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (pctOwned) {
|
||||
pct.done();
|
||||
}
|
||||
if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
StructureDefinition sdi = context.fetchResource(StructureDefinition.class, ext.getValue().primitiveValue());
|
||||
if (sdi == null) {
|
||||
warning(errors, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getUrl());
|
||||
} else {
|
||||
if (crumbTrails) {
|
||||
element.addMessage(signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_DEP, sdi.getUrl(), sd.getUrl()));
|
||||
}
|
||||
stack.resetIds();
|
||||
if (pctOwned) {
|
||||
pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sdi.getUrl(), logProgress);
|
||||
}
|
||||
startInner(hostContext, errors, resource, element, sdi, stack, false, pct);
|
||||
if (pctOwned) {
|
||||
pct.done();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4540,6 +4601,32 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// System.out.println("start: "+(System.currentTimeMillis()-st)+" ("+resource.fhirType()+")");
|
||||
}
|
||||
|
||||
private StructureDefinition lookupProfileReference(List<ValidationMessage> errors, Element element, NodeStack stack,
|
||||
int i, Element profile, StructureDefinition sd) {
|
||||
String url = profile.primitiveValue();
|
||||
CanonicalResourceLookupResult cr = crLookups.get(url);
|
||||
if (cr != null) {
|
||||
if (cr.error != null) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, url, cr.error);
|
||||
} else {
|
||||
sd = (StructureDefinition) cr.resource;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sd = (StructureDefinition) fetcher.fetchCanonicalResource(this, url);
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(sd));
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) { e.printStackTrace(); }
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(e.getMessage()));
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage());
|
||||
}
|
||||
if (sd != null) {
|
||||
context.cacheResource(sd);
|
||||
}
|
||||
}
|
||||
return sd;
|
||||
}
|
||||
|
||||
// private void plog(String msg) {
|
||||
// long n = System.currentTimeMillis();
|
||||
// String elapsed = Utilities.padLeft(Long.toString(n-start), ' ', 5);
|
||||
|
@ -4638,9 +4725,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else if (element.getType().equals("QuestionnaireResponse")) {
|
||||
new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode, xverManager, jurisdiction).validateQuestionannaireResponse(hostContext, errors, element, stack);
|
||||
} else if (element.getType().equals("Measure")) {
|
||||
new MeasureValidator(context, timeTracker, xverManager, jurisdiction).validateMeasure(hostContext, errors, element, stack);
|
||||
new MeasureValidator(context, timeTracker, xverManager, jurisdiction, this).validateMeasure(hostContext, errors, element, stack);
|
||||
} else if (element.getType().equals("MeasureReport")) {
|
||||
new MeasureValidator(context, timeTracker, xverManager, jurisdiction).validateMeasureReport(hostContext, errors, element, stack);
|
||||
new MeasureValidator(context, timeTracker, xverManager, jurisdiction, this).validateMeasureReport(hostContext, errors, element, stack);
|
||||
} else if (element.getType().equals("CapabilityStatement")) {
|
||||
validateCapabilityStatement(errors, element, stack);
|
||||
} else if (element.getType().equals("CodeSystem")) {
|
||||
|
@ -5677,7 +5764,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
boolean ok;
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ok = fpe.evaluateToBoolean(hostContext, resource, hostContext.getRootResource(), element, n);
|
||||
ok = fpe.evaluateToBoolean(hostContext, resource, hostContext.getRootResource(), element, n);
|
||||
timeTracker.fpe(t);
|
||||
msg = fpe.forLog();
|
||||
} catch (Exception ex) {
|
||||
|
@ -6025,6 +6112,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
this.noUnicodeBiDiControlChars = noUnicodeBiDiControlChars;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public HtmlInMarkdownCheck getHtmlInMarkdownCheck() {
|
||||
return htmlInMarkdownCheck;
|
||||
}
|
||||
|
||||
public void setHtmlInMarkdownCheck(HtmlInMarkdownCheck htmlInMarkdownCheck) {
|
||||
this.htmlInMarkdownCheck = htmlInMarkdownCheck;
|
||||
}
|
||||
|
||||
public Coding getJurisdiction() {
|
||||
return jurisdiction;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,9 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
|
||||
checkShareableCodeSystem(errors, cs, stack);
|
||||
if (!stack.isContained()) {
|
||||
checkShareableCodeSystem(errors, cs, stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,17 +37,20 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
|||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.TimeTracker;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public class MeasureValidator extends BaseValidator {
|
||||
|
||||
public MeasureValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager, Coding jurisdiction) {
|
||||
private InstanceValidator parent;
|
||||
public MeasureValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager, Coding jurisdiction, InstanceValidator parent) {
|
||||
super(context, xverManager);
|
||||
source = Source.InstanceValidator;
|
||||
this.timeTracker = timeTracker;
|
||||
this.jurisdiction = jurisdiction;
|
||||
this.parent = parent;
|
||||
|
||||
}
|
||||
|
||||
|
@ -105,8 +108,41 @@ public class MeasureValidator extends BaseValidator {
|
|||
c++;
|
||||
}
|
||||
}
|
||||
if (!stack.isContained()) {
|
||||
checkShareableMeasure(errors, element, stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkShareableMeasure(List<ValidationMessage> errors, Element cs, NodeStack stack) {
|
||||
if (parent.isForPublication()) {
|
||||
if (isHL7(cs)) {
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "url");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "version");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "title");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING_HL7, "name");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "status");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "experimental");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "description");
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "content");
|
||||
if (!"supplement".equals(cs.getChildValue("content"))) {
|
||||
rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "caseSensitive");
|
||||
}
|
||||
} else {
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING, "url");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING, "version");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING, "title");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING, "name");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING, "status");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING, "experimental");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING, "description");
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.MEASURE_SHAREABLE_MISSING, "content");
|
||||
if (!"supplement".equals(cs.getChildValue("content"))) {
|
||||
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.MEASURE_SHAREABLE_MISSING, "caseSensitive");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void validateMeasureCriteria(ValidatorHostContext hostContext, List<ValidationMessage> errors, MeasureContext mctxt, Element crit, NodeStack nsc) {
|
||||
String mimeType = crit.getChildValue("language");
|
||||
if (!Utilities.noString(mimeType)) { // that would be an error elsewhere
|
||||
|
|
|
@ -115,8 +115,9 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
for (Element snapshot : snapshots) {
|
||||
validateElementList(errors, snapshot, stack.push(snapshot, -1, null, null), true, true, sd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd) {
|
||||
List<Element> elements = elementList.getChildrenByName("element");
|
||||
int cc = 0;
|
||||
|
|
|
@ -61,7 +61,9 @@ public class ValueSetValidator extends BaseValidator {
|
|||
cc++;
|
||||
}
|
||||
}
|
||||
checkShareableValueSet(errors, vs, stack);
|
||||
if (!stack.isContained()) {
|
||||
checkShareableValueSet(errors, vs, stack);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkShareableValueSet(List<ValidationMessage> errors, Element vs, NodeStack stack) {
|
||||
|
|
|
@ -45,6 +45,13 @@ public class FHIRPathExpressionFixer {
|
|||
return ("name.exists() implies name.matches('[A-Z]([A-Za-z0-9_]){0,254}')");
|
||||
}
|
||||
|
||||
// R5 ballot
|
||||
if (expr.equals("url.matches('([^|#])*')")) {
|
||||
return ("$this.matches('([^|#])*')");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// clarification in FHIRPath spec
|
||||
if ("eld-19".equals(key)) {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.hl7.fhir.r5.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.elementmodel.ParserBase.ValidationPolicy;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
public class GeneralTests {
|
||||
|
||||
@Test
|
||||
void testXMLParse() throws IOException {
|
||||
System.out.println(System.getProperty("java.vm.name"));
|
||||
InputStream stream = TestingUtilities.loadTestResourceStream("validator",
|
||||
"xml_v10.xml");
|
||||
org.hl7.fhir.r5.elementmodel.XmlParser xp = new org.hl7.fhir.r5.elementmodel.XmlParser(TestingUtilities.getSharedWorkerContext());
|
||||
xp.setAllowXsiLocation(true);
|
||||
List<ValidationMessage> errorList = new ArrayList<>();
|
||||
xp.setupValidation(ValidationPolicy.EVERYTHING, errorList);
|
||||
try {
|
||||
Object resource = xp.parse(stream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (ValidationMessage message : errorList) {
|
||||
System.out.println(message.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package org.hl7.fhir.validation.tests;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -22,6 +26,8 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
|
|||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
|
@ -31,6 +37,7 @@ import org.hl7.fhir.r5.elementmodel.Element;
|
|||
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.r5.elementmodel.ObjectConverter;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
|
@ -46,6 +53,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
|
||||
import org.hl7.fhir.r5.utils.OperationOutcomeUtilities;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
|
||||
|
@ -56,17 +64,20 @@ import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
|||
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
|
||||
import org.hl7.fhir.utilities.json.JsonTrackingParser;
|
||||
import org.hl7.fhir.utilities.json.JsonUtilities;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.validation.IgLoader;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
@ -82,6 +93,7 @@ import com.google.gson.JsonObject;
|
|||
public class ValidationTests implements IEvaluationContext, IValidatorResourceFetcher, IValidationPolicyAdvisor {
|
||||
|
||||
public final static boolean PRINT_OUTPUT_TO_CONSOLE = true;
|
||||
private static final boolean BUILD_NEW = false;
|
||||
|
||||
@Parameters(name = "{index}: id {0}")
|
||||
public static Iterable<Object[]> data() throws IOException {
|
||||
|
@ -128,7 +140,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
long setup = System.nanoTime();
|
||||
|
||||
this.name = name;
|
||||
System.out.println("---- " + name + " ----------------------------------------------------------------");
|
||||
System.out.println("---- " + name + " ---------------------------------------------------------------- ("+System.getProperty("java.vm.name")+")");
|
||||
System.out.println("** Core: ");
|
||||
String txLog = null;
|
||||
if (content.has("txLog")) {
|
||||
|
@ -254,7 +266,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
if (content.has("security-checks")) {
|
||||
val.setSecurityChecks(content.get("security-checks").getAsBoolean());
|
||||
}
|
||||
|
||||
if (content.has("noHtmlInMarkdown")) {
|
||||
val.setHtmlInMarkdownCheck(HtmlInMarkdownCheck.ERROR);
|
||||
}
|
||||
if (content.has("logical")==false) {
|
||||
val.setAssumeValidRestReferences(content.has("assumeValidRestReferences") ? content.get("assumeValidRestReferences").getAsBoolean() : false);
|
||||
System.out.println(String.format("Start Validating (%d to set up)", (System.nanoTime() - setup) / 1000000));
|
||||
|
@ -333,6 +347,9 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
checkOutcomes(errorsLogical, logical, "logical", name);
|
||||
}
|
||||
logger.verifyHasNoRequests();
|
||||
if (BUILD_NEW) {
|
||||
JsonTrackingParser.write(manifest, new File(Utilities.path("[tmp]", "validator", "manifest.new.json")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -400,57 +417,139 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
}
|
||||
}
|
||||
|
||||
private void checkOutcomes(List<ValidationMessage> errors, JsonObject focus, String profile, String name) {
|
||||
private void checkOutcomes(List<ValidationMessage> errors, JsonObject focus, String profile, String name) throws IOException {
|
||||
JsonObject java = focus.getAsJsonObject("java");
|
||||
int ec = 0;
|
||||
int wc = 0;
|
||||
int hc = 0;
|
||||
List<String> errLocs = new ArrayList<>();
|
||||
for (ValidationMessage vm : errors) {
|
||||
if (vm.getLevel() == IssueSeverity.FATAL || vm.getLevel() == IssueSeverity.ERROR) {
|
||||
ec++;
|
||||
if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
System.out.println(vm.getDisplay());
|
||||
}
|
||||
errLocs.add(vm.getLocation());
|
||||
}
|
||||
if (vm.getLevel() == IssueSeverity.WARNING) {
|
||||
wc++;
|
||||
if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
System.out.println(vm.getDisplay());
|
||||
}
|
||||
}
|
||||
if (vm.getLevel() == IssueSeverity.INFORMATION) {
|
||||
hc++;
|
||||
if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
System.out.println(vm.getDisplay());
|
||||
}
|
||||
OperationOutcome goal = java.has("outcome") ? (OperationOutcome) new JsonParser().parse(java.getAsJsonObject("outcome")) : new OperationOutcome();
|
||||
OperationOutcome actual = OperationOutcomeUtilities.createOutcomeSimple(errors);
|
||||
actual.setText(null);
|
||||
String json = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(actual);
|
||||
|
||||
List<String> fails = new ArrayList<>();
|
||||
|
||||
Map<OperationOutcomeIssueComponent, OperationOutcomeIssueComponent> map = new HashMap<>();
|
||||
for (OperationOutcomeIssueComponent issGoal : goal.getIssue()) {
|
||||
OperationOutcomeIssueComponent issActual = findMatchingIssue(actual, issGoal);
|
||||
if (issActual == null) {
|
||||
fails.add("Expected Issue not found: "+issGoal.toString());
|
||||
} else {
|
||||
map.put(issActual, issGoal);
|
||||
}
|
||||
}
|
||||
if (!TestingUtilities.getSharedWorkerContext(version).isNoTerminologyServer() || !focus.has("tx-dependent")) {
|
||||
Assert.assertEquals("Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("errorCount").getAsInt()) + " errors, but found " + Integer.toString(ec) + ".", java.get("errorCount").getAsInt(), ec);
|
||||
for (OperationOutcomeIssueComponent issActual : actual.getIssue()) {
|
||||
if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
System.out.println(issActual.toString());
|
||||
}
|
||||
OperationOutcomeIssueComponent issGoal = map.get(issActual);
|
||||
if (issGoal == null) {
|
||||
fails.add("Unexpected Issue found: "+issActual.toString());
|
||||
}
|
||||
}
|
||||
if (goal.getIssue().size() != actual.getIssue().size() && fails.isEmpty()) {
|
||||
fails.add("Issue count mismatch (check for duplicate error messages)");
|
||||
}
|
||||
|
||||
if (fails.size() > 0) {
|
||||
for (String s : fails) {
|
||||
System.out.println(s);
|
||||
}
|
||||
System.out.println("");
|
||||
System.out.println("========================================================");
|
||||
System.out.println("");
|
||||
System.out.println(json);
|
||||
System.out.println("");
|
||||
System.out.println("========================================================");
|
||||
System.out.println("");
|
||||
Assertions.fail(fails.toString());
|
||||
}
|
||||
// int ec = 0;
|
||||
// int wc = 0;
|
||||
// int hc = 0;
|
||||
// List<String> errLocs = new ArrayList<>();
|
||||
// for (ValidationMessage vm : errors) {
|
||||
// if (vm.getLevel() == IssueSeverity.FATAL || vm.getLevel() == IssueSeverity.ERROR) {
|
||||
// ec++;
|
||||
// if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
// System.out.println(vm.getDisplay());
|
||||
// }
|
||||
// errLocs.add(vm.getLocation());
|
||||
// }
|
||||
// if (vm.getLevel() == IssueSeverity.WARNING) {
|
||||
// wc++;
|
||||
// if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
// System.out.println(vm.getDisplay());
|
||||
// }
|
||||
// }
|
||||
// if (vm.getLevel() == IssueSeverity.INFORMATION) {
|
||||
// hc++;
|
||||
// if (PRINT_OUTPUT_TO_CONSOLE) {
|
||||
// System.out.println(vm.getDisplay());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!TestingUtilities.getSharedWorkerContext(version).isNoTerminologyServer() || !focus.has("tx-dependent")) {
|
||||
// Assert.assertEquals("Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("errorCount").getAsInt()) + " errors, but found " + Integer.toString(ec) + ".", java.get("errorCount").getAsInt(), ec);
|
||||
// if (java.has("warningCount")) {
|
||||
// Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("warningCount").getAsInt()) + " warnings, but found " + Integer.toString(wc) + ".", java.get("warningCount").getAsInt(), wc);
|
||||
// }
|
||||
// if (java.has("infoCount")) {
|
||||
// Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("infoCount").getAsInt()) + " hints, but found " + Integer.toString(hc) + ".", java.get("infoCount").getAsInt(), hc);
|
||||
// }
|
||||
// }
|
||||
// if (java.has("error-locations")) {
|
||||
// JsonArray el = java.getAsJsonArray("error-locations");
|
||||
// Assert.assertEquals( "locations count is not correct", errLocs.size(), el.size());
|
||||
// for (int i = 0; i < errLocs.size(); i++) {
|
||||
// Assert.assertEquals("Location should be " + el.get(i).getAsString() + ", but was " + errLocs.get(i), errLocs.get(i), el.get(i).getAsString());
|
||||
// }
|
||||
// }
|
||||
if (BUILD_NEW) {
|
||||
if (java.has("output")) {
|
||||
java.remove("output");
|
||||
}
|
||||
if (java.has("error-locations")) {
|
||||
java.remove("error-locations");
|
||||
}
|
||||
if (java.has("warningCount")) {
|
||||
Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("warningCount").getAsInt()) + " warnings, but found " + Integer.toString(wc) + ".", java.get("warningCount").getAsInt(), wc);
|
||||
java.remove("warningCount");
|
||||
}
|
||||
if (java.has("infoCount")) {
|
||||
Assert.assertEquals( "Test " + name + (profile == null ? "" : " profile: "+ profile) + ": Expected " + Integer.toString(java.get("infoCount").getAsInt()) + " hints, but found " + Integer.toString(hc) + ".", java.get("infoCount").getAsInt(), hc);
|
||||
java.remove("infoCount");
|
||||
}
|
||||
if (java.has("errorCount")) {
|
||||
java.remove("errorCount");
|
||||
}
|
||||
if (java.has("outcome")) {
|
||||
java.remove("outcome");
|
||||
}
|
||||
if (actual.hasIssue()) {
|
||||
JsonObject oj = JsonTrackingParser.parse(json, null);
|
||||
java.add("outcome", oj);
|
||||
}
|
||||
}
|
||||
if (java.has("error-locations")) {
|
||||
JsonArray el = java.getAsJsonArray("error-locations");
|
||||
Assert.assertEquals( "locations count is not correct", errLocs.size(), el.size());
|
||||
for (int i = 0; i < errLocs.size(); i++) {
|
||||
Assert.assertEquals("Location should be " + el.get(i).getAsString() + ", but was " + errLocs.get(i), errLocs.get(i), el.get(i).getAsString());
|
||||
}
|
||||
|
||||
private OperationOutcomeIssueComponent findMatchingIssue(OperationOutcome oo, OperationOutcomeIssueComponent iss) {
|
||||
for (OperationOutcomeIssueComponent t : oo.getIssue()) {
|
||||
if (t.getExpression().get(0).getValue().equals(iss.getExpression().get(0).getValue()) && t.getCode() == iss.getCode() && t.getSeverity() == iss.getSeverity()
|
||||
&& (t.hasDiagnostics() ? t.getDiagnostics().equals(iss.getDiagnostics()) : !iss.hasDiagnostics()) && textMatches(t.getDetails().getText(), iss.getDetails().getText())) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
if (focus.has("output")) {
|
||||
focus.remove("output");
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean textMatches(String t1, String t2) {
|
||||
if (t1.endsWith("...")) {
|
||||
t2 = t2.substring(0, t1.length()-3);
|
||||
t1 = t1.substring(0, t1.length()-3);
|
||||
}
|
||||
JsonArray vr = new JsonArray();
|
||||
java.add("output", vr);
|
||||
for (ValidationMessage vm : errors) {
|
||||
vr.add(vm.getDisplay());
|
||||
if (t2.endsWith("...")) {
|
||||
t1 = t1.substring(0, t2.length()-3);
|
||||
t2 = t2.substring(0, t2.length()-3);
|
||||
}
|
||||
t1 = t1.trim();
|
||||
t2 = t2.trim();
|
||||
return t1.equals(t2);
|
||||
}
|
||||
|
||||
private org.hl7.fhir.r4.model.Parameters makeExpProfile() {
|
||||
|
|
|
@ -1843,3 +1843,24 @@ v: {
|
|||
"error" : "Unable to find code 2 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20220731); The code \"2\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#2) is not valid in the value set 'All codes known to the system' (from http://tx.fhir.org/r4)"
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://snomed.info/sct",
|
||||
"code" : "56248011000036107",
|
||||
"display" : "Panadol 500 mg tablet, 50"
|
||||
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||
v: {
|
||||
"severity" : "error",
|
||||
"error" : "Unable to find code 56248011000036107 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20220731); The code \"56248011000036107\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#56248011000036107) is not valid in the value set 'All codes known to the system' (from http://tx.fhir.org/r4)"
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://snomed.info/sct",
|
||||
"code" : "361055000",
|
||||
"display" : "Misuses drugs (finding)"
|
||||
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||
v: {
|
||||
"display" : "Misuses drugs",
|
||||
"code" : "361055000",
|
||||
"system" : "http://snomed.info/sct"
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -14,12 +14,12 @@
|
|||
HAPI FHIR
|
||||
-->
|
||||
<artifactId>org.hl7.fhir.core</artifactId>
|
||||
<version>5.6.68-SNAPSHOT</version>
|
||||
<version>5.6.69-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<hapi_fhir_version>5.4.0</hapi_fhir_version>
|
||||
<validator_test_case_version>1.1.113</validator_test_case_version>
|
||||
<validator_test_case_version>1.1.114-SNAPSHOT</validator_test_case_version>
|
||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
<maven_surefire_version>3.0.0-M5</maven_surefire_version>
|
||||
|
|
Loading…
Reference in New Issue