Updates to validator for CDS Hooks support
This commit is contained in:
parent
c053f08a13
commit
41950eeb0a
|
@ -54,6 +54,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
|
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
|
||||||
|
@ -172,6 +173,22 @@ import org.hl7.fhir.utilities.xml.SchematronWriter.Section;
|
||||||
*/
|
*/
|
||||||
public class ProfileUtilities extends TranslatingUtilities {
|
public class ProfileUtilities extends TranslatingUtilities {
|
||||||
|
|
||||||
|
public static class SourcedChildDefinitions {
|
||||||
|
private StructureDefinition source;
|
||||||
|
private List<ElementDefinition> list;
|
||||||
|
public SourcedChildDefinitions(StructureDefinition source, List<ElementDefinition> list) {
|
||||||
|
super();
|
||||||
|
this.source = source;
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
public StructureDefinition getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
public List<ElementDefinition> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ElementDefinitionResolution {
|
public class ElementDefinitionResolution {
|
||||||
|
|
||||||
private StructureDefinition source;
|
private StructureDefinition source;
|
||||||
|
@ -355,7 +372,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private XVerExtensionManager xver;
|
private XVerExtensionManager xver;
|
||||||
private boolean wantFixDifferentialFirstElementType;
|
private boolean wantFixDifferentialFirstElementType;
|
||||||
private Set<String> masterSourceFileNames;
|
private Set<String> masterSourceFileNames;
|
||||||
private Map<ElementDefinition, List<ElementDefinition>> childMapCache = new HashMap<>();
|
private Map<ElementDefinition, SourcedChildDefinitions> childMapCache = new HashMap<>();
|
||||||
private List<String> keyRows = new ArrayList<>();
|
private List<String> keyRows = new ArrayList<>();
|
||||||
|
|
||||||
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
|
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
|
||||||
|
@ -433,10 +450,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
String getLinkForUrl(String corePath, String s);
|
String getLinkForUrl(String corePath, String s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ElementDefinition> getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
public SourcedChildDefinitions getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
||||||
if (childMapCache .containsKey(element)) {
|
if (childMapCache.containsKey(element)) {
|
||||||
return childMapCache.get(element);
|
return childMapCache.get(element);
|
||||||
}
|
}
|
||||||
|
StructureDefinition src = profile;
|
||||||
if (element.getContentReference() != null) {
|
if (element.getContentReference() != null) {
|
||||||
List<ElementDefinition> list = null;
|
List<ElementDefinition> list = null;
|
||||||
String id = null;
|
String id = null;
|
||||||
|
@ -451,6 +469,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (sd == null) {
|
if (sd == null) {
|
||||||
throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'");
|
throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'");
|
||||||
}
|
}
|
||||||
|
src = sd;
|
||||||
list = sd.getSnapshot().getElement();
|
list = sd.getSnapshot().getElement();
|
||||||
id = ref.substring(ref.indexOf("#")+1);
|
id = ref.substring(ref.indexOf("#")+1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -476,8 +495,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
childMapCache.put(element, res);
|
SourcedChildDefinitions result = new SourcedChildDefinitions(src, res);
|
||||||
return res;
|
childMapCache.put(element, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4229,7 +4249,10 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE);
|
row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE);
|
||||||
} else if (hasDef && isDataType(element.getType().get(0).getWorkingCode())) {
|
} else if (hasDef && isDataType(element.getType().get(0).getWorkingCode())) {
|
||||||
row.setIcon("icon_datatype.gif", HierarchicalTableGenerator.TEXT_ICON_DATATYPE);
|
row.setIcon("icon_datatype.gif", HierarchicalTableGenerator.TEXT_ICON_DATATYPE);
|
||||||
} else if (hasDef && Utilities.existsInList(element.getType().get(0).getWorkingCode(), "Element", "BackboneElement")) {
|
} else if (hasDef && element.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) {
|
||||||
|
row.setIcon("icon-object-box.png", HierarchicalTableGenerator.TEXT_ICON_OBJECT_BOX);
|
||||||
|
keyRows.add(element.getId()+"."+ToolingExtensions.readStringExtension(element, ToolingExtensions.EXT_JSON_PROP_KEY));
|
||||||
|
} else if (hasDef && Utilities.existsInList(element.getType().get(0).getWorkingCode(), "Base", "Element", "BackboneElement")) {
|
||||||
row.setIcon("icon_element.gif", HierarchicalTableGenerator.TEXT_ICON_ELEMENT);
|
row.setIcon("icon_element.gif", HierarchicalTableGenerator.TEXT_ICON_ELEMENT);
|
||||||
} else {
|
} else {
|
||||||
row.setIcon("icon_resource.png", HierarchicalTableGenerator.TEXT_ICON_RESOURCE);
|
row.setIcon("icon_resource.png", HierarchicalTableGenerator.TEXT_ICON_RESOURCE);
|
||||||
|
@ -4877,6 +4900,19 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
c.getPieces().add(piece);
|
c.getPieces().add(piece);
|
||||||
c.getPieces().add(gen.new Piece(null, " is prefixed to the value before validation", null));
|
c.getPieces().add(gen.new Piece(null, " is prefixed to the value before validation", null));
|
||||||
}
|
}
|
||||||
|
if (definition.hasExtension(ToolingExtensions.EXT_ID_EXPECTATION)) {
|
||||||
|
String ide = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_ID_EXPECTATION);
|
||||||
|
if (ide.equals("optional")) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
c.getPieces().add(gen.new Piece(null, "Id may or not be present (this is the default for elements but not resources)", null));
|
||||||
|
} else if (ide.equals("required")) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
c.getPieces().add(gen.new Piece(null, "Id is required to be present (this is the default for resources but not elements)", null));
|
||||||
|
} else if (ide.equals("required")) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
c.getPieces().add(gen.new Piece(null, "An ID is not allowed in this context", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) {
|
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) {
|
||||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
|
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
|
||||||
|
@ -4894,6 +4930,24 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace")+": ", null).addStyle("font-weight:bold"));
|
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace")+": ", null).addStyle("font-weight:bold"));
|
||||||
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
|
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
|
||||||
}
|
}
|
||||||
|
if (definition.hasExtension(ToolingExtensions.EXT_JSON_EMPTY)) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY);
|
||||||
|
if ("present".equals(code)) {
|
||||||
|
c.getPieces().add(gen.new Piece(null, "This element is present as a JSON Array even when there are no items in the instance", null));
|
||||||
|
} else {
|
||||||
|
c.getPieces().add(gen.new Piece(null, "This element may be present as a JSON Array even when there are no items in the instance", null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_NULLABLE)) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
c.getPieces().add(gen.new Piece(null, "This object can be represented as null in the JSON structure (which counts as 'present' for cardinality purposes)", null));
|
||||||
|
}
|
||||||
|
if (definition.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) {
|
||||||
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY);
|
||||||
|
c.getPieces().add(gen.new Piece(null, "Represented as a single JSON Object with named properties using the value of the "+code+" child as the key", null));
|
||||||
|
}
|
||||||
if (definition.hasExtension(ToolingExtensions.EXT_TYPE_SPEC)) {
|
if (definition.hasExtension(ToolingExtensions.EXT_TYPE_SPEC)) {
|
||||||
for (Extension e : definition.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_SPEC)) {
|
for (Extension e : definition.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_SPEC)) {
|
||||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||||
|
@ -6268,8 +6322,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private org.hl7.fhir.r5.elementmodel.Element generateExample(StructureDefinition profile, ExampleValueAccessor accessor) throws FHIRException {
|
private org.hl7.fhir.r5.elementmodel.Element generateExample(StructureDefinition profile, ExampleValueAccessor accessor) throws FHIRException {
|
||||||
ElementDefinition ed = profile.getSnapshot().getElementFirstRep();
|
ElementDefinition ed = profile.getSnapshot().getElementFirstRep();
|
||||||
org.hl7.fhir.r5.elementmodel.Element r = new org.hl7.fhir.r5.elementmodel.Element(ed.getPath(), new Property(context, ed, profile));
|
org.hl7.fhir.r5.elementmodel.Element r = new org.hl7.fhir.r5.elementmodel.Element(ed.getPath(), new Property(context, ed, profile));
|
||||||
List<ElementDefinition> children = getChildMap(profile, ed);
|
SourcedChildDefinitions children = getChildMap(profile, ed);
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children.getList()) {
|
||||||
if (child.getPath().endsWith(".id")) {
|
if (child.getPath().endsWith(".id")) {
|
||||||
org.hl7.fhir.r5.elementmodel.Element id = new org.hl7.fhir.r5.elementmodel.Element("id", new Property(context, child, profile));
|
org.hl7.fhir.r5.elementmodel.Element id = new org.hl7.fhir.r5.elementmodel.Element("id", new Property(context, child, profile));
|
||||||
id.setValue(profile.getId()+accessor.getId());
|
id.setValue(profile.getId()+accessor.getId());
|
||||||
|
@ -6290,8 +6344,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
} else {
|
} else {
|
||||||
org.hl7.fhir.r5.elementmodel.Element res = new org.hl7.fhir.r5.elementmodel.Element(tail(ed.getPath()), new Property(context, ed, profile));
|
org.hl7.fhir.r5.elementmodel.Element res = new org.hl7.fhir.r5.elementmodel.Element(tail(ed.getPath()), new Property(context, ed, profile));
|
||||||
boolean hasValue = false;
|
boolean hasValue = false;
|
||||||
List<ElementDefinition> children = getChildMap(profile, ed);
|
SourcedChildDefinitions children = getChildMap(profile, ed);
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children.getList()) {
|
||||||
if (!child.hasContentReference()) {
|
if (!child.hasContentReference()) {
|
||||||
org.hl7.fhir.r5.elementmodel.Element e = createExampleElement(profile, child, accessor);
|
org.hl7.fhir.r5.elementmodel.Element e = createExampleElement(profile, child, accessor);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.hl7.fhir.r5.elementmodel;
|
package org.hl7.fhir.r5.elementmodel;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
@ -75,7 +77,7 @@ public class Element extends Base {
|
||||||
|
|
||||||
|
|
||||||
public enum SpecialElement {
|
public enum SpecialElement {
|
||||||
CONTAINED, BUNDLE_ENTRY, BUNDLE_OUTCOME, PARAMETER;
|
CONTAINED, BUNDLE_ENTRY, BUNDLE_OUTCOME, PARAMETER, LOGICAL;
|
||||||
|
|
||||||
public static SpecialElement fromProperty(Property property) {
|
public static SpecialElement fromProperty(Property property) {
|
||||||
if (property.getStructure().getType().equals("Parameters"))
|
if (property.getStructure().getType().equals("Parameters"))
|
||||||
|
@ -87,7 +89,7 @@ public class Element extends Base {
|
||||||
if (property.getName().equals("contained"))
|
if (property.getName().equals("contained"))
|
||||||
return CONTAINED;
|
return CONTAINED;
|
||||||
if (property.getStructure().getKind() == StructureDefinitionKind.LOGICAL)
|
if (property.getStructure().getKind() == StructureDefinitionKind.LOGICAL)
|
||||||
return CONTAINED;
|
return LOGICAL;
|
||||||
throw new FHIRException("Unknown resource containing a native resource: "+property.getDefinition().getId());
|
throw new FHIRException("Unknown resource containing a native resource: "+property.getDefinition().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +99,7 @@ public class Element extends Base {
|
||||||
case BUNDLE_OUTCOME: return "outcome";
|
case BUNDLE_OUTCOME: return "outcome";
|
||||||
case CONTAINED: return "contained";
|
case CONTAINED: return "contained";
|
||||||
case PARAMETER: return "parameter";
|
case PARAMETER: return "parameter";
|
||||||
|
case LOGICAL: return "logical";
|
||||||
default: return "??";
|
default: return "??";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,6 +127,7 @@ public class Element extends Base {
|
||||||
private Map<String, List<Element>> childMap;
|
private Map<String, List<Element>> childMap;
|
||||||
private int descendentCount;
|
private int descendentCount;
|
||||||
private int instanceId;
|
private int instanceId;
|
||||||
|
private boolean isNull;
|
||||||
|
|
||||||
public Element(String name) {
|
public Element(String name) {
|
||||||
super();
|
super();
|
||||||
|
@ -211,7 +215,15 @@ public class Element extends Base {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasValue() {
|
public boolean isNull() {
|
||||||
|
return isNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNull(boolean isNull) {
|
||||||
|
this.isNull = isNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasValue() {
|
||||||
return value != null;
|
return value != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,6 +1139,65 @@ public class Element extends Base {
|
||||||
public void setInstanceId(int instanceId) {
|
public void setInstanceId(int instanceId) {
|
||||||
this.instanceId = instanceId;
|
this.instanceId = instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void printToOutput() {
|
||||||
|
printToOutput(System.out, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printToOutput(PrintStream out, String indent) {
|
||||||
|
String s = indent+name +(index == -1 ? "" : "["+index+"]") +(special != null ? "$"+special.toHuman(): "")+ (type!= null || explicitType != null ? " : "+type+(explicitType != null ? "/'"+explicitType+"'" : "") : "");
|
||||||
|
if (isNull) {
|
||||||
|
s = s + " = (null)";
|
||||||
|
} else if (value != null) {
|
||||||
|
s = s + " = '"+value+"'";
|
||||||
|
} else if (xhtml != null) {
|
||||||
|
s = s + " = (xhtml)";
|
||||||
|
}
|
||||||
|
if (property != null) {
|
||||||
|
s = s +" {"+property.summary();
|
||||||
|
if (elementProperty != null) {
|
||||||
|
s = s +" -> "+elementProperty.summary();
|
||||||
|
}
|
||||||
|
s = s + "}";
|
||||||
|
}
|
||||||
|
if (line > 0) {
|
||||||
|
s = s + " (l"+line+":c"+col+")";
|
||||||
|
}
|
||||||
|
out.println(s);
|
||||||
|
if (children != null) {
|
||||||
|
for (Element child : children) {
|
||||||
|
child.printToOutput(out, indent+" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String msgCounts() {
|
||||||
|
int e = 0;
|
||||||
|
int w = 0;
|
||||||
|
int h = 0;
|
||||||
|
for (ValidationMessage msg : messages) {
|
||||||
|
switch (msg.getLevel()) {
|
||||||
|
case ERROR:
|
||||||
|
e++;
|
||||||
|
break;
|
||||||
|
case FATAL:
|
||||||
|
e++;
|
||||||
|
break;
|
||||||
|
case INFORMATION:
|
||||||
|
h++;
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
w++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "e:"+e+",w:"+w+",h:"+h;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -57,6 +57,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||||
import org.hl7.fhir.r5.model.Extension;
|
import org.hl7.fhir.r5.model.Extension;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||||
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.utilities.StringPair;
|
import org.hl7.fhir.utilities.StringPair;
|
||||||
import org.hl7.fhir.utilities.TextFile;
|
import org.hl7.fhir.utilities.TextFile;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
@ -240,7 +241,11 @@ public class JsonParser extends ParserBase {
|
||||||
if (property.isList() && !property.isJsonKeyArray() && (e instanceof JsonArray)) {
|
if (property.isList() && !property.isJsonKeyArray() && (e instanceof JsonArray)) {
|
||||||
JsonArray arr = (JsonArray) e;
|
JsonArray arr = (JsonArray) e;
|
||||||
if (arr.size() == 0) {
|
if (arr.size() == 0) {
|
||||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
|
if (property.canBeEmpty()) {
|
||||||
|
// nothing
|
||||||
|
} else {
|
||||||
|
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (JsonElement am : arr) {
|
for (JsonElement am : arr) {
|
||||||
|
@ -288,7 +293,7 @@ public class JsonParser extends ParserBase {
|
||||||
String fpathV = fpathArr+"."+propV.getName();
|
String fpathV = fpathArr+"."+propV.getName();
|
||||||
if (propV.isPrimitive(propV.getType(null))) {
|
if (propV.isPrimitive(propV.getType(null))) {
|
||||||
parseChildPrimitiveInstance(n, propV, propV.getName(), npathV, fpathV, pv.getValue(), null);
|
parseChildPrimitiveInstance(n, propV, propV.getName(), npathV, fpathV, pv.getValue(), null);
|
||||||
} else if (pv.getValue() instanceof JsonObject) {
|
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
|
||||||
parseChildComplexInstance(npathV, fpathV, n, propV, propV.getName(), pv.getValue());
|
parseChildComplexInstance(npathV, fpathV, n, propV, propV.getName(), pv.getValue());
|
||||||
} else {
|
} else {
|
||||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
|
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
|
||||||
|
@ -354,12 +359,22 @@ public class JsonParser extends ParserBase {
|
||||||
n.setPath(fpath);
|
n.setPath(fpath);
|
||||||
checkObject(child, npath);
|
checkObject(child, npath);
|
||||||
element.getChildren().add(n);
|
element.getChildren().add(n);
|
||||||
if (property.isResource())
|
if (property.isResource()) {
|
||||||
parseResource(npath, child, n, property);
|
parseResource(npath, child, n, property);
|
||||||
else
|
} else {
|
||||||
parseChildren(npath, child, n, false);
|
parseChildren(npath, child, n, false);
|
||||||
} else
|
}
|
||||||
|
} else if (property.isNullable() && e instanceof JsonNull) {
|
||||||
|
// we create an element marked as a null element so we know something was present
|
||||||
|
JsonNull child = (JsonNull) e;
|
||||||
|
Element n = new Element(name, property).markLocation(line(child), col(child));
|
||||||
|
n.setPath(fpath);
|
||||||
|
element.getChildren().add(n);
|
||||||
|
n.setNull(true);
|
||||||
|
// nothing to do, it's ok, but we treat it like it doesn't exist
|
||||||
|
} else {
|
||||||
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR);
|
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String describe(JsonElement e) {
|
private String describe(JsonElement e) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement;
|
import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement;
|
||||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||||
|
@ -93,8 +94,8 @@ public class ObjectConverter {
|
||||||
if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE)
|
if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE)
|
||||||
res.setValue(((PrimitiveType) base).asStringValue());
|
res.setValue(((PrimitiveType) base).asStringValue());
|
||||||
|
|
||||||
List<ElementDefinition> children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
|
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children.getList()) {
|
||||||
String n = tail(child.getPath());
|
String n = tail(child.getPath());
|
||||||
if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {
|
if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {
|
||||||
Base[] values = base.getProperty(n.hashCode(), n, false);
|
Base[] values = base.getProperty(n.hashCode(), n, false);
|
||||||
|
|
|
@ -39,6 +39,7 @@ import java.util.Map;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.formats.FormatUtilities;
|
import org.hl7.fhir.r5.formats.FormatUtilities;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
|
@ -229,8 +230,10 @@ public class Property {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isResource() {
|
public boolean isResource() {
|
||||||
if (definition.getType().size() > 0)
|
if (definition.getType().size() > 0) {
|
||||||
return definition.getType().size() == 1 && ("Resource".equals(definition.getType().get(0).getCode()) || "DomainResource".equals(definition.getType().get(0).getCode()));
|
String tc = definition.getType().get(0).getCode();
|
||||||
|
return definition.getType().size() == 1 && (("Resource".equals(tc) || "DomainResource".equals(tc)) || Utilities.existsInList(tc, context.getResourceNames()));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE);
|
return !definition.getPath().contains(".") && (structure.getKind() == StructureDefinitionKind.RESOURCE);
|
||||||
}
|
}
|
||||||
|
@ -300,9 +303,9 @@ public class Property {
|
||||||
protected List<Property> getChildProperties(String elementName, String statedType) throws FHIRException {
|
protected List<Property> getChildProperties(String elementName, String statedType) throws FHIRException {
|
||||||
ElementDefinition ed = definition;
|
ElementDefinition ed = definition;
|
||||||
StructureDefinition sd = structure;
|
StructureDefinition sd = structure;
|
||||||
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed);
|
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed);
|
||||||
String url = null;
|
String url = null;
|
||||||
if (children.isEmpty() || isElementWithOnlyExtension(ed, children)) {
|
if (children.getList().isEmpty() || isElementWithOnlyExtension(ed, children.getList())) {
|
||||||
// ok, find the right definitions
|
// ok, find the right definitions
|
||||||
String t = null;
|
String t = null;
|
||||||
if (ed.getType().size() == 1)
|
if (ed.getType().size() == 1)
|
||||||
|
@ -369,7 +372,7 @@ public class Property {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Property> properties = new ArrayList<Property>();
|
List<Property> properties = new ArrayList<Property>();
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children.getList()) {
|
||||||
properties.add(new Property(context, child, sd, this.profileUtilities));
|
properties.add(new Property(context, child, sd, this.profileUtilities));
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
|
@ -378,8 +381,8 @@ public class Property {
|
||||||
protected List<Property> getChildProperties(TypeDetails type) throws DefinitionException {
|
protected List<Property> getChildProperties(TypeDetails type) throws DefinitionException {
|
||||||
ElementDefinition ed = definition;
|
ElementDefinition ed = definition;
|
||||||
StructureDefinition sd = structure;
|
StructureDefinition sd = structure;
|
||||||
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed);
|
SourcedChildDefinitions children = profileUtilities.getChildMap(sd, ed);
|
||||||
if (children.isEmpty()) {
|
if (children.getList().isEmpty()) {
|
||||||
// ok, find the right definitions
|
// ok, find the right definitions
|
||||||
String t = null;
|
String t = null;
|
||||||
if (ed.getType().size() == 1)
|
if (ed.getType().size() == 1)
|
||||||
|
@ -408,7 +411,7 @@ public class Property {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Property> properties = new ArrayList<Property>();
|
List<Property> properties = new ArrayList<Property>();
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children.getList()) {
|
||||||
properties.add(new Property(context, child, sd, this.profileUtilities));
|
properties.add(new Property(context, child, sd, this.profileUtilities));
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
|
@ -510,4 +513,23 @@ public class Property {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
return ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_NULLABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String summary() {
|
||||||
|
return structure.getUrl()+"#"+definition.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean canBeEmpty() {
|
||||||
|
if (definition.hasExtension(ToolingExtensions.EXT_JSON_EMPTY)) {
|
||||||
|
return !"absent".equals(ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY));
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.exceptions.PathEngineException;
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
|
||||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
|
@ -5767,10 +5768,10 @@ public class FHIRPathEngine {
|
||||||
if (expr.getName().equals("$this")) {
|
if (expr.getName().equals("$this")) {
|
||||||
focus = element;
|
focus = element;
|
||||||
} else {
|
} else {
|
||||||
List<ElementDefinition> childDefinitions;
|
SourcedChildDefinitions childDefinitions;
|
||||||
childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
||||||
// if that's empty, get the children of the type
|
// if that's empty, get the children of the type
|
||||||
if (childDefinitions.isEmpty()) {
|
if (childDefinitions.getList().isEmpty()) {
|
||||||
|
|
||||||
sd = fetchStructureByType(element, expr);
|
sd = fetchStructureByType(element, expr);
|
||||||
if (sd == null) {
|
if (sd == null) {
|
||||||
|
@ -5778,7 +5779,7 @@ public class FHIRPathEngine {
|
||||||
}
|
}
|
||||||
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
|
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
|
||||||
}
|
}
|
||||||
for (ElementDefinition t : childDefinitions) {
|
for (ElementDefinition t : childDefinitions.getList()) {
|
||||||
if (tailMatches(t, expr.getName()) && !t.hasSlicing()) { // GG: slicing is a problem here. This is for an exetnsion with a fixed value (type slicing)
|
if (tailMatches(t, expr.getName()) && !t.hasSlicing()) { // GG: slicing is a problem here. This is for an exetnsion with a fixed value (type slicing)
|
||||||
focus = new TypedElementDefinition(t);
|
focus = new TypedElementDefinition(t);
|
||||||
break;
|
break;
|
||||||
|
@ -5806,8 +5807,8 @@ public class FHIRPathEngine {
|
||||||
focus = new TypedElementDefinition(sd.getSnapshot().getElementFirstRep());
|
focus = new TypedElementDefinition(sd.getSnapshot().getElementFirstRep());
|
||||||
} else if ("extension".equals(expr.getName())) {
|
} else if ("extension".equals(expr.getName())) {
|
||||||
String targetUrl = expr.getParameters().get(0).getConstant().primitiveValue();
|
String targetUrl = expr.getParameters().get(0).getConstant().primitiveValue();
|
||||||
List<ElementDefinition> childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(sd, element.getElement());
|
||||||
for (ElementDefinition t : childDefinitions) {
|
for (ElementDefinition t : childDefinitions.getList()) {
|
||||||
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
|
if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
|
||||||
System.out.println("t: "+t.getId());
|
System.out.println("t: "+t.getId());
|
||||||
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
|
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
|
||||||
|
@ -5816,7 +5817,7 @@ public class FHIRPathEngine {
|
||||||
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition());
|
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition());
|
||||||
}
|
}
|
||||||
if (exsd != null && exsd.getUrl().equals(targetUrl)) {
|
if (exsd != null && exsd.getUrl().equals(targetUrl)) {
|
||||||
if (profileUtilities.getChildMap(sd, t).isEmpty()) {
|
if (profileUtilities.getChildMap(sd, t).getList().isEmpty()) {
|
||||||
sd = exsd;
|
sd = exsd;
|
||||||
}
|
}
|
||||||
focus = new TypedElementDefinition(t);
|
focus = new TypedElementDefinition(t);
|
||||||
|
|
|
@ -216,9 +216,11 @@ public class ToolingExtensions {
|
||||||
public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding";
|
public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding";
|
||||||
public static final String EXT_JSON_PROP_KEY = "http://hl7.org/fhir/tools/StructureDefinition/json-property-key";
|
public static final String EXT_JSON_PROP_KEY = "http://hl7.org/fhir/tools/StructureDefinition/json-property-key";
|
||||||
public static final String EXT_JSON_EMPTY = "http://hl7.org/fhir/tools/StructureDefinition/json-empty-behavior";
|
public static final String EXT_JSON_EMPTY = "http://hl7.org/fhir/tools/StructureDefinition/json-empty-behavior";
|
||||||
|
public static final String EXT_JSON_NULLABLE = "http://hl7.org/fhir/tools/StructureDefinition/json-nullable";
|
||||||
public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix";
|
public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix";
|
||||||
public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format";
|
public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format";
|
||||||
|
public static final String EXT_ID_EXPECTATION = "http://hl7.org/fhir/tools/StructureDefinition/id-expectation";
|
||||||
|
|
||||||
|
|
||||||
// unregistered? - don't know what these are used for
|
// unregistered? - don't know what these are used for
|
||||||
public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix";
|
public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix";
|
||||||
|
@ -230,7 +232,7 @@ public class ToolingExtensions {
|
||||||
public static final String EXT_MAPPING_CARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-cardinality";
|
public static final String EXT_MAPPING_CARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-cardinality";
|
||||||
public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type";
|
public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type";
|
||||||
public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality";
|
public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality";
|
||||||
|
|
||||||
// specific extension helpers
|
// specific extension helpers
|
||||||
|
|
||||||
public static Extension makeIssueSource(Source source) {
|
public static Extension makeIssueSource(Source source) {
|
||||||
|
@ -482,6 +484,8 @@ public class ToolingExtensions {
|
||||||
return false;
|
return false;
|
||||||
if (!(ex.getValue() instanceof BooleanType))
|
if (!(ex.getValue() instanceof BooleanType))
|
||||||
return false;
|
return false;
|
||||||
|
if (!(ex.getValue().hasPrimitiveValue()))
|
||||||
|
return false;
|
||||||
return ((BooleanType) ex.getValue()).getValue();
|
return ((BooleanType) ex.getValue()).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2516,7 +2516,7 @@ public class StructureMapUtilities {
|
||||||
|
|
||||||
private void addChildMappings(StringBuilder b, String id, String indent, StructureDefinition sd, ElementDefinition ed, boolean inner) throws DefinitionException {
|
private void addChildMappings(StringBuilder b, String id, String indent, StructureDefinition sd, ElementDefinition ed, boolean inner) throws DefinitionException {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed);
|
List<ElementDefinition> children = profileUtilities.getChildMap(sd, ed).getList();
|
||||||
for (ElementDefinition child : children) {
|
for (ElementDefinition child : children) {
|
||||||
if (first && inner) {
|
if (first && inner) {
|
||||||
b.append(" then {\r\n");
|
b.append(" then {\r\n");
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
package org.hl7.fhir.r5.utils.validation.constants;
|
package org.hl7.fhir.r5.utils.validation.constants;
|
||||||
|
|
||||||
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
|
||||||
public enum IdStatus {
|
public enum IdStatus {
|
||||||
OPTIONAL,
|
OPTIONAL,
|
||||||
REQUIRED,
|
REQUIRED,
|
||||||
PROHIBITED
|
PROHIBITED;
|
||||||
|
|
||||||
|
public static IdStatus fromCode(String v) {
|
||||||
|
if (v == null || Utilities.noString(v)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
v = v.toLowerCase();
|
||||||
|
if (v.equals("optional")) {
|
||||||
|
return OPTIONAL;
|
||||||
|
} else if (v.equals("required")) {
|
||||||
|
return REQUIRED;
|
||||||
|
} else if (v.equals("prohibited")) {
|
||||||
|
return PROHIBITED;
|
||||||
|
} else {
|
||||||
|
throw new FHIRException("Unkonwn Id Status code '"+v+"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class I18nConstants {
|
||||||
public static final String DUPLICATE_ID = "DUPLICATE_ID";
|
public static final String DUPLICATE_ID = "DUPLICATE_ID";
|
||||||
public static final String DUPLICATE_RESOURCE_ = "Duplicate_Resource_";
|
public static final String DUPLICATE_RESOURCE_ = "Duplicate_Resource_";
|
||||||
public static final String DUPLICATE_RESOURCE_VERSION = "DUPLICATE_RESOURCE_VERSION";
|
public static final String DUPLICATE_RESOURCE_VERSION = "DUPLICATE_RESOURCE_VERSION";
|
||||||
|
public static final String ELEMENT_CANNOT_BE_NULL = "ELEMENT_CANNOT_BE_NULL";
|
||||||
public static final String ELEMENT_ID__NULL__ON_ = "element_id__null__on_";
|
public static final String ELEMENT_ID__NULL__ON_ = "element_id__null__on_";
|
||||||
public static final String ELEMENT_MUST_HAVE_SOME_CONTENT = "Element_must_have_some_content";
|
public static final String ELEMENT_MUST_HAVE_SOME_CONTENT = "Element_must_have_some_content";
|
||||||
public static final String ELEMENT__NULL_ = "element__null_";
|
public static final String ELEMENT__NULL_ = "element__null_";
|
||||||
|
|
|
@ -437,8 +437,10 @@ public class JsonTrackingParser {
|
||||||
else
|
else
|
||||||
throw lexer.error("Unexpected content at start of JSON: "+lexer.getType().toString());
|
throw lexer.error("Unexpected content at start of JSON: "+lexer.getType().toString());
|
||||||
|
|
||||||
parseProperty();
|
if (lexer.getType() != TokenType.Close) {
|
||||||
readObject(result, true);
|
parseProperty();
|
||||||
|
readObject(result, true);
|
||||||
|
}
|
||||||
if (map != null)
|
if (map != null)
|
||||||
map.put(result, loc);
|
map.put(result, loc);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -748,5 +748,6 @@ TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML = The markdown contains content that appea
|
||||||
TYPE_SPECIFIER_ILLEGAL_TYPE = The Type specifier {1} specified an illegal type {0}
|
TYPE_SPECIFIER_ILLEGAL_TYPE = The Type specifier {1} specified an illegal type {0}
|
||||||
TYPE_SPECIFIER_ABSTRACT_TYPE = The Type specifier {1} specified an abstract type {0}
|
TYPE_SPECIFIER_ABSTRACT_TYPE = The Type specifier {1} specified an abstract type {0}
|
||||||
TYPE_SPECIFIER_NM_ILLEGAL_TYPE = No Type specifier matched, and the underlying type {0} is not valid
|
TYPE_SPECIFIER_NM_ILLEGAL_TYPE = No Type specifier matched, and the underlying type {0} is not valid
|
||||||
TYPE_SPECIFIER_NM_ABSTRACT_TYPE = = No Type specifier matched, and the underlying type {0} is not abstract
|
TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract
|
||||||
|
ELEMENT_CANNOT_BE_NULL = The element is not allowed to be 'null'
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.PathEngineException;
|
import org.hl7.fhir.exceptions.PathEngineException;
|
||||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
|
||||||
import org.hl7.fhir.r5.context.ContextUtilities;
|
import org.hl7.fhir.r5.context.ContextUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||||
|
@ -249,6 +250,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
private static final String EXECUTION_ID = "validator.execution.id";
|
private static final String EXECUTION_ID = "validator.execution.id";
|
||||||
private static final String HTML_FRAGMENT_REGEX = "[a-zA-Z]\\w*(((\\s+)(\\S)*)*)";
|
private static final String HTML_FRAGMENT_REGEX = "[a-zA-Z]\\w*(((\\s+)(\\S)*)*)";
|
||||||
private static final boolean STACK_TRACE = false;
|
private static final boolean STACK_TRACE = false;
|
||||||
|
private static final boolean DEBUG_ELEMENT = false;
|
||||||
|
|
||||||
private class ValidatorHostServices implements IEvaluationContext {
|
private class ValidatorHostServices implements IEvaluationContext {
|
||||||
|
|
||||||
|
@ -863,6 +865,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
errors.removeAll(messagesToRemove);
|
errors.removeAll(messagesToRemove);
|
||||||
timeTracker.overall(t);
|
timeTracker.overall(t);
|
||||||
|
if (DEBUG_ELEMENT) {
|
||||||
|
element.printToOutput();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3622,8 +3627,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
long t = System.nanoTime();
|
long t = System.nanoTime();
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
||||||
timeTracker.sd(t);
|
timeTracker.sd(t);
|
||||||
if (sd != null && (sd.getType().equals(type) || sd.getUrl().equals(type)) && sd.hasSnapshot())
|
if (sd != null && (sd.getType().equals(type) || sd.getUrl().equals(type)) && sd.hasSnapshot()) {
|
||||||
return sd;
|
return sd;
|
||||||
|
}
|
||||||
|
if (sd.getAbstract()) {
|
||||||
|
StructureDefinition sdt = context.fetchTypeDefinition(type);
|
||||||
|
StructureDefinition tt = sdt;
|
||||||
|
while (tt != null) {
|
||||||
|
if (tt.getBaseDefinition().equals(sd.getUrl())) {
|
||||||
|
return sdt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -4854,49 +4871,56 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
ElementDefinition child, ElementDefinition context, Element resource,
|
ElementDefinition child, ElementDefinition context, Element resource,
|
||||||
Element element, NodeStack stack, IdStatus idstatus, StructureDefinition parentProfile, PercentageTracker pct) throws FHIRException {
|
Element element, NodeStack stack, IdStatus idstatus, StructureDefinition parentProfile, PercentageTracker pct) throws FHIRException {
|
||||||
|
|
||||||
SpecialElement special = element.getSpecial();
|
if (element.isNull()) {
|
||||||
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), ToolingExtensions.readBooleanExtension(child, ToolingExtensions.EXT_JSON_NULLABLE),
|
||||||
ContainedReferenceValidationPolicy containedValidationPolicy = getPolicyAdvisor() == null ?
|
I18nConstants.ELEMENT_CANNOT_BE_NULL)) {
|
||||||
ContainedReferenceValidationPolicy.CHECK_VALID : getPolicyAdvisor().policyForContained(this,
|
// nothing else to validate?
|
||||||
hostContext, context.fhirType(), context.getId(), special, path, parentProfile.getUrl());
|
|
||||||
|
|
||||||
if (containedValidationPolicy.ignore()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String resourceName = element.getType();
|
|
||||||
TypeRefComponent typeForResource = null;
|
|
||||||
CommaSeparatedStringBuilder bt = new CommaSeparatedStringBuilder();
|
|
||||||
|
|
||||||
// Iterate through all possible types
|
|
||||||
for (TypeRefComponent type : child.getType()) {
|
|
||||||
bt.append(type.getCode());
|
|
||||||
if (type.getCode().equals("Resource") || type.getCode().equals(resourceName) ) {
|
|
||||||
typeForResource = type;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
stack.qualifyPath(".ofType("+resourceName+")");
|
} else {
|
||||||
|
SpecialElement special = element.getSpecial();
|
||||||
|
|
||||||
if (typeForResource == null) {
|
ContainedReferenceValidationPolicy containedValidationPolicy = getPolicyAdvisor() == null ?
|
||||||
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
ContainedReferenceValidationPolicy.CHECK_VALID : getPolicyAdvisor().policyForContained(this,
|
||||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName, bt.toString());
|
hostContext, context.fhirType(), context.getId(), special, path, parentProfile.getUrl());
|
||||||
} else if (isValidResourceType(resourceName, typeForResource)) {
|
|
||||||
if (containedValidationPolicy.checkValid()) {
|
if (containedValidationPolicy.ignore()) {
|
||||||
// special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise
|
return;
|
||||||
ValidatorHostContext hc = null;
|
}
|
||||||
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
|
|
||||||
resource = element;
|
String resourceName = element.getType();
|
||||||
assert Utilities.existsInList(hostContext.getRootResource().fhirType(), "Bundle", "Parameters") : "Resource is "+hostContext.getRootResource().fhirType()+", expected Bundle or Parameters";
|
TypeRefComponent typeForResource = null;
|
||||||
hc = hostContext.forEntry(element, hostContext.getRootResource()); // root becomes the grouping resource (should be either bundle or parameters)
|
CommaSeparatedStringBuilder bt = new CommaSeparatedStringBuilder();
|
||||||
} else {
|
|
||||||
hc = hostContext.forContained(element);
|
// Iterate through all possible types
|
||||||
|
for (TypeRefComponent type : child.getType()) {
|
||||||
|
bt.append(type.getCode());
|
||||||
|
if (type.getCode().equals("Resource") || type.getCode().equals(resourceName) ) {
|
||||||
|
typeForResource = type;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stack.resetIds();
|
stack.qualifyPath(".ofType("+resourceName+")");
|
||||||
if (special != null) {
|
|
||||||
switch (special) {
|
if (typeForResource == null) {
|
||||||
|
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
|
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName, bt.toString());
|
||||||
|
} else if (isValidResourceType(resourceName, typeForResource)) {
|
||||||
|
if (containedValidationPolicy.checkValid()) {
|
||||||
|
// special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise
|
||||||
|
ValidatorHostContext hc = null;
|
||||||
|
if (special == SpecialElement.BUNDLE_ENTRY || special == SpecialElement.BUNDLE_OUTCOME || special == SpecialElement.PARAMETER) {
|
||||||
|
resource = element;
|
||||||
|
assert Utilities.existsInList(hostContext.getResource().fhirType(), "Bundle", "Parameters") : "Containing Resource is "+hostContext.getResource().fhirType()+", expected Bundle or Parameters at "+stack.getLiteralPath();
|
||||||
|
hc = hostContext.forEntry(element, hostContext.getResource()); // root becomes the grouping resource (should be either bundle or parameters)
|
||||||
|
} else {
|
||||||
|
hc = hostContext.forContained(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.resetIds();
|
||||||
|
if (special != null) {
|
||||||
|
switch (special) {
|
||||||
case BUNDLE_ENTRY:
|
case BUNDLE_ENTRY:
|
||||||
case BUNDLE_OUTCOME:
|
case BUNDLE_OUTCOME:
|
||||||
case PARAMETER:
|
case PARAMETER:
|
||||||
|
@ -4908,51 +4932,52 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (typeForResource.getProfile().size() == 1) {
|
if (typeForResource.getProfile().size() == 1) {
|
||||||
long t = System.nanoTime();
|
long t = System.nanoTime();
|
||||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue());
|
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue());
|
||||||
timeTracker.sd(t);
|
timeTracker.sd(t);
|
||||||
trackUsage(profile, hostContext, element);
|
trackUsage(profile, hostContext, element);
|
||||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_EXPL, special.toHuman(), resourceName, typeForResource.getProfile().get(0).asStringValue())) {
|
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_EXPL, special.toHuman(), resourceName, typeForResource.getProfile().get(0).asStringValue())) {
|
||||||
validateResource(hc, errors, resource, element, profile, idstatus, stack, pct);
|
validateResource(hc, errors, resource, element, profile, idstatus, stack, pct);
|
||||||
|
}
|
||||||
|
} else if (typeForResource.getProfile().isEmpty()) {
|
||||||
|
long t = System.nanoTime();
|
||||||
|
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class,
|
||||||
|
"http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
||||||
|
timeTracker.sd(t);
|
||||||
|
trackUsage(profile, hostContext, element);
|
||||||
|
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
|
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_TYPE, special == null ? "??" : special.toHuman(), resourceName)) {
|
||||||
|
validateResource(hc, errors, resource, element, profile, idstatus, stack, pct);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
for (CanonicalType u : typeForResource.getProfile()) {
|
||||||
|
b.append(u.asStringValue());
|
||||||
|
}
|
||||||
|
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
|
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, special.toHuman(), typeForResource.getCode(), b.toString());
|
||||||
}
|
}
|
||||||
} else if (typeForResource.getProfile().isEmpty()) {
|
|
||||||
long t = System.nanoTime();
|
|
||||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class,
|
|
||||||
"http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
|
||||||
timeTracker.sd(t);
|
|
||||||
trackUsage(profile, hostContext, element);
|
|
||||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
|
||||||
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_TYPE, special == null ? "??" : special.toHuman(), resourceName)) {
|
|
||||||
validateResource(hc, errors, resource, element, profile, idstatus, stack, pct);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
|
||||||
for (CanonicalType u : typeForResource.getProfile()) {
|
|
||||||
b.append(u.asStringValue());
|
|
||||||
}
|
|
||||||
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
|
|
||||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, special.toHuman(), typeForResource.getCode(), b.toString());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
List<String> types = new ArrayList<>();
|
|
||||||
for (UriType u : typeForResource.getProfile()) {
|
|
||||||
StructureDefinition sd = this.context.fetchResource(StructureDefinition.class, u.getValue());
|
|
||||||
if (sd != null && !types.contains(sd.getType())) {
|
|
||||||
types.add(sd.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (types.size() == 1) {
|
|
||||||
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
|
||||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE2, resourceName, types.get(0));
|
|
||||||
} else {
|
} else {
|
||||||
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
List<String> types = new ArrayList<>();
|
||||||
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE3, resourceName, types);
|
for (UriType u : typeForResource.getProfile()) {
|
||||||
|
StructureDefinition sd = this.context.fetchResource(StructureDefinition.class, u.getValue());
|
||||||
|
if (sd != null && !types.contains(sd.getType())) {
|
||||||
|
types.add(sd.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (types.size() == 1) {
|
||||||
|
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
|
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE2, resourceName, types.get(0));
|
||||||
|
} else {
|
||||||
|
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(),
|
||||||
|
false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE3, resourceName, types);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5019,8 +5044,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the list of direct defined children, including slices
|
// get the list of direct defined children, including slices
|
||||||
List<ElementDefinition> childDefinitions = profileUtilities.getChildMap(profile, definition);
|
SourcedChildDefinitions childDefinitions = profileUtilities.getChildMap(profile, definition);
|
||||||
if (childDefinitions.isEmpty()) {
|
if (childDefinitions.getList().isEmpty()) {
|
||||||
if (actualType == null)
|
if (actualType == null)
|
||||||
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
||||||
childDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
childDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
||||||
|
@ -5028,7 +5053,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
// this only happens when the profile constrains the abstract children but leaves th choice open.
|
// this only happens when the profile constrains the abstract children but leaves th choice open.
|
||||||
if (actualType == null)
|
if (actualType == null)
|
||||||
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
return; // there'll be an error elsewhere in this case, and we're going to stop.
|
||||||
List<ElementDefinition> typeChildDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
SourcedChildDefinitions typeChildDefinitions = getActualTypeChildren(hostContext, element, actualType);
|
||||||
// what were going to do is merge them - the type is not allowed to constrain things that the child definitions already do (well, if it does, it'll be ignored)
|
// what were going to do is merge them - the type is not allowed to constrain things that the child definitions already do (well, if it does, it'll be ignored)
|
||||||
childDefinitions = mergeChildLists(childDefinitions, typeChildDefinitions, definition.getPath(), actualType);
|
childDefinitions = mergeChildLists(childDefinitions, typeChildDefinitions, definition.getPath(), actualType);
|
||||||
}
|
}
|
||||||
|
@ -5045,27 +5070,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ElementDefinition> mergeChildLists(List<ElementDefinition> source, List<ElementDefinition> additional, String masterPath, String typePath) {
|
private SourcedChildDefinitions mergeChildLists(SourcedChildDefinitions source, SourcedChildDefinitions additional, String masterPath, String typePath) {
|
||||||
List<ElementDefinition> res = new ArrayList<>();
|
SourcedChildDefinitions res = new SourcedChildDefinitions(additional.getSource(), new ArrayList<>());
|
||||||
res.addAll(source);
|
res.getList().addAll(source.getList());
|
||||||
for (ElementDefinition ed : additional) {
|
for (ElementDefinition ed : additional.getList()) {
|
||||||
boolean inMaster = false;
|
boolean inMaster = false;
|
||||||
for (ElementDefinition t : source) {
|
for (ElementDefinition t : source.getList()) {
|
||||||
String tp = masterPath + ed.getPath().substring(typePath.length());
|
String tp = masterPath + ed.getPath().substring(typePath.length());
|
||||||
if (t.getPath().equals(tp)) {
|
if (t.getPath().equals(tp)) {
|
||||||
inMaster = true;
|
inMaster = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!inMaster) {
|
if (!inMaster) {
|
||||||
res.add(ed);
|
res.getList().add(ed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: the element definition in context might assign a constrained profile for the type?
|
// todo: the element definition in context might assign a constrained profile for the type?
|
||||||
public List<ElementDefinition> getActualTypeChildren(ValidatorHostContext hostContext, Element element, String actualType) {
|
public SourcedChildDefinitions getActualTypeChildren(ValidatorHostContext hostContext, Element element, String actualType) {
|
||||||
List<ElementDefinition> childDefinitions;
|
SourcedChildDefinitions childDefinitions;
|
||||||
StructureDefinition dt = null;
|
StructureDefinition dt = null;
|
||||||
if (isAbsolute(actualType))
|
if (isAbsolute(actualType))
|
||||||
dt = this.context.fetchResource(StructureDefinition.class, actualType);
|
dt = this.context.fetchResource(StructureDefinition.class, actualType);
|
||||||
|
@ -5120,16 +5145,23 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
&& !"BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode())) {
|
&& !"BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode())) {
|
||||||
type = checkDefn.getType().get(0).getWorkingCode();
|
type = checkDefn.getType().get(0).getWorkingCode();
|
||||||
String stype = ei.getElement().fhirType();
|
String stype = ei.getElement().fhirType();
|
||||||
if (checkDefn.isChoice() && !stype.equals(type)) {
|
if (!stype.equals(type)) {
|
||||||
if (extensionUrl != null && !isAbsolute(extensionUrl)) {
|
if (checkDefn.isChoice()) {
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
if (extensionUrl != null && !isAbsolute(extensionUrl)) {
|
||||||
} else if (!isAbstractType(type) && !"Extension".equals(profile.getType())) {
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type), I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
} else if (!isAbstractType(type) && !"Extension".equals(profile.getType())) {
|
||||||
}
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type), I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
||||||
} else if (!isAbstractType(type)) {
|
}
|
||||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type) ||
|
} else if (!isAbstractType(type)) {
|
||||||
|
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type) ||
|
||||||
(Utilities.existsInList(type, "string", "id") && Utilities.existsInList(stype, "string", "id")), // work around a r4 problem with id/string
|
(Utilities.existsInList(type, "string", "id") && Utilities.existsInList(stype, "string", "id")), // work around a r4 problem with id/string
|
||||||
I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
I18nConstants.EXTENSION_PROF_TYPE, profile.getUrl(), type, stype);
|
||||||
|
} else if (!isResource(type)) {
|
||||||
|
// System.out.println("update type "+type+" to "+stype+"?");
|
||||||
|
type = stype;
|
||||||
|
} else {
|
||||||
|
// this will be sorted out in contains ... System.out.println("update type "+type+" to "+stype+"?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Excluding reference is a kludge to get around versioning issues
|
// Excluding reference is a kludge to get around versioning issues
|
||||||
|
@ -5200,9 +5232,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NodeStack localStack = stack.push(ei.getElement(), "*".equals(ei.getDefinition().getBase().getMax()) && ei.count == -1 ? 0 : ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
|
NodeStack localStack = stack.push(ei.getElement(), "*".equals(ei.getDefinition().getBase().getMax()) && ei.count == -1 ? 0 : ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
|
||||||
if (debug) {
|
if (debug) {
|
||||||
System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl()+time());
|
System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getUrl()+time());
|
||||||
}
|
}
|
||||||
String localStackLiteralPath = localStack.getLiteralPath();
|
String localStackLiteralPath = localStack.getLiteralPath();
|
||||||
String eiPath = ei.getPath();
|
String eiPath = ei.getPath();
|
||||||
if (!eiPath.equals(localStackLiteralPath)) {
|
if (!eiPath.equals(localStackLiteralPath)) {
|
||||||
|
@ -5450,9 +5482,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkCardinalities(List<ValidationMessage> errors, StructureDefinition profile, Element element, NodeStack stack,
|
public void checkCardinalities(List<ValidationMessage> errors, StructureDefinition profile, Element element, NodeStack stack,
|
||||||
List<ElementDefinition> childDefinitions, List<ElementInfo> children, List<String> problematicPaths) throws DefinitionException {
|
SourcedChildDefinitions childDefinitions, List<ElementInfo> children, List<String> problematicPaths) throws DefinitionException {
|
||||||
// 3. report any definitions that have a cardinality problem
|
// 3. report any definitions that have a cardinality problem
|
||||||
for (ElementDefinition ed : childDefinitions) {
|
for (ElementDefinition ed : childDefinitions.getList()) {
|
||||||
if (ed.getRepresentation().isEmpty()) { // ignore xml attributes
|
if (ed.getRepresentation().isEmpty()) { // ignore xml attributes
|
||||||
int count = 0;
|
int count = 0;
|
||||||
List<ElementDefinition> slices = null;
|
List<ElementDefinition> slices = null;
|
||||||
|
@ -5490,7 +5522,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> assignChildren(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, Element resource,
|
public List<String> assignChildren(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, Element resource,
|
||||||
NodeStack stack, List<ElementDefinition> childDefinitions, List<ElementInfo> children) throws DefinitionException {
|
NodeStack stack, SourcedChildDefinitions childDefinitions, List<ElementInfo> children) throws DefinitionException {
|
||||||
// 2. assign children to a definition
|
// 2. assign children to a definition
|
||||||
// for each definition, for each child, check whether it belongs in the slice
|
// for each definition, for each child, check whether it belongs in the slice
|
||||||
ElementDefinition slicer = null;
|
ElementDefinition slicer = null;
|
||||||
|
@ -5498,8 +5530,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
List<String> problematicPaths = new ArrayList<String>();
|
List<String> problematicPaths = new ArrayList<String>();
|
||||||
String slicingPath = null;
|
String slicingPath = null;
|
||||||
int sliceOffset = 0;
|
int sliceOffset = 0;
|
||||||
for (int i = 0; i < childDefinitions.size(); i++) {
|
for (int i = 0; i < childDefinitions.getList().size(); i++) {
|
||||||
ElementDefinition ed = childDefinitions.get(i);
|
ElementDefinition ed = childDefinitions.getList().get(i);
|
||||||
boolean childUnsupportedSlicing = false;
|
boolean childUnsupportedSlicing = false;
|
||||||
boolean process = true;
|
boolean process = true;
|
||||||
if (ed.hasSlicing() && !ed.getSlicing().getOrdered()) {
|
if (ed.hasSlicing() && !ed.getSlicing().getOrdered()) {
|
||||||
|
@ -5553,7 +5585,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Don't raise this if we're in an abstract profile, like Resource
|
// Don't raise this if we're in an abstract profile, like Resource
|
||||||
if (!profile.getAbstract()) {
|
if (!childDefinitions.getSource().getAbstract()) {
|
||||||
rule(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.getPath(), (ei.definition != null), I18nConstants.VALIDATION_VAL_PROFILE_NOTALLOWED, profile.getUrl());
|
rule(errors, IssueType.NOTSUPPORTED, ei.line(), ei.col(), ei.getPath(), (ei.definition != null), I18nConstants.VALIDATION_VAL_PROFILE_NOTALLOWED, profile.getUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5674,7 +5706,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
}
|
}
|
||||||
|
|
||||||
private IdStatus idStatusForEntry(Element ep, ElementInfo ei) {
|
private IdStatus idStatusForEntry(Element ep, ElementInfo ei) {
|
||||||
if (isBundleEntry(ei.getPath())) {
|
if (ei.getDefinition().hasExtension(ToolingExtensions.EXT_ID_EXPECTATION)) {
|
||||||
|
return IdStatus.fromCode(ToolingExtensions.readStringExtension(ei.getDefinition(),ToolingExtensions.EXT_ID_EXPECTATION));
|
||||||
|
} else if (isBundleEntry(ei.getPath())) {
|
||||||
Element req = ep.getNamedChild("request");
|
Element req = ep.getNamedChild("request");
|
||||||
Element resp = ep.getNamedChild("response");
|
Element resp = ep.getNamedChild("response");
|
||||||
Element fullUrl = ep.getNamedChild(FULL_URL);
|
Element fullUrl = ep.getNamedChild(FULL_URL);
|
||||||
|
|
|
@ -126,8 +126,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
private JsonObject content;
|
private JsonObject content;
|
||||||
private String version;
|
private String version;
|
||||||
private String name;
|
private String name;
|
||||||
private static StringBuilder logB = new StringBuilder();
|
|
||||||
|
|
||||||
private static Map<String, ValidationEngine> ve = new HashMap<>();
|
private static Map<String, ValidationEngine> ve = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,7 +144,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
CacheVerificationLogger logger = new CacheVerificationLogger();
|
CacheVerificationLogger logger = new CacheVerificationLogger();
|
||||||
long setup = System.nanoTime();
|
long setup = System.nanoTime();
|
||||||
|
|
||||||
logOutputToFile("---- " + name + " ---------------------------------------------------------------- ("+System.getProperty("java.vm.name")+")");
|
logOutput("---- " + name + " ---------------------------------------------------------------- ("+System.getProperty("java.vm.name")+")");
|
||||||
logOutput("** Core: ");
|
logOutput("** Core: ");
|
||||||
String txLog = null;
|
String txLog = null;
|
||||||
if (content.has("txLog")) {
|
if (content.has("txLog")) {
|
||||||
|
@ -220,7 +219,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
if (content.has("packages")) {
|
if (content.has("packages")) {
|
||||||
for (JsonElement e : content.getAsJsonArray("packages")) {
|
for (JsonElement e : content.getAsJsonArray("packages")) {
|
||||||
String n = e.getAsString();
|
String n = e.getAsString();
|
||||||
logOutputToFile("load package "+n);
|
logOutput("load package "+n);
|
||||||
InputStream cnt = n.endsWith(".tgz") ? TestingUtilities.loadTestResourceStream("validator", n) : null;
|
InputStream cnt = n.endsWith(".tgz") ? TestingUtilities.loadTestResourceStream("validator", n) : null;
|
||||||
if (cnt != null) {
|
if (cnt != null) {
|
||||||
igLoader.loadPackage(NpmPackage.fromPackage(cnt), true);
|
igLoader.loadPackage(NpmPackage.fromPackage(cnt), true);
|
||||||
|
@ -237,7 +236,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
String filename = e.getAsString();
|
String filename = e.getAsString();
|
||||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||||
CanonicalResource mr = (CanonicalResource) loadResource(filename, contents);
|
CanonicalResource mr = (CanonicalResource) loadResource(filename, contents);
|
||||||
logOutputToFile("load resource "+mr.getUrl());
|
logOutput("load resource "+mr.getUrl());
|
||||||
val.getContext().cacheResource(mr);
|
val.getContext().cacheResource(mr);
|
||||||
if (mr instanceof ImplementationGuide) {
|
if (mr instanceof ImplementationGuide) {
|
||||||
val.getImplementationGuides().add((ImplementationGuide) mr);
|
val.getImplementationGuides().add((ImplementationGuide) mr);
|
||||||
|
@ -253,7 +252,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
String filename = je.getAsString();
|
String filename = je.getAsString();
|
||||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||||
StructureDefinition sd = loadProfile(filename, contents, messages, val.isDebug(), val.getContext());
|
StructureDefinition sd = loadProfile(filename, contents, messages, val.isDebug(), val.getContext());
|
||||||
logOutputToFile("load resource "+sd.getUrl());
|
logOutput("load resource "+sd.getUrl());
|
||||||
val.getContext().cacheResource(sd);
|
val.getContext().cacheResource(sd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +288,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
JsonObject profile = content.getAsJsonObject("profile");
|
JsonObject profile = content.getAsJsonObject("profile");
|
||||||
if (profile.has("packages")) {
|
if (profile.has("packages")) {
|
||||||
for (JsonElement e : profile.getAsJsonArray("packages")) {
|
for (JsonElement e : profile.getAsJsonArray("packages")) {
|
||||||
logOutputToFile("load package "+e.getAsString());
|
logOutput("load package "+e.getAsString());
|
||||||
igLoader.loadIg(vCurr.getIgs(), vCurr.getBinaries(), e.getAsString(), true);
|
igLoader.loadIg(vCurr.getIgs(), vCurr.getBinaries(), e.getAsString(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +300,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
String filename = e.getAsString();
|
String filename = e.getAsString();
|
||||||
String contents = TestingUtilities.loadTestResource("validator", filename);
|
String contents = TestingUtilities.loadTestResource("validator", filename);
|
||||||
CanonicalResource mr = (CanonicalResource) loadResource(filename, contents);
|
CanonicalResource mr = (CanonicalResource) loadResource(filename, contents);
|
||||||
logOutputToFile("load resource "+mr.getUrl());
|
logOutput("load resource "+mr.getUrl());
|
||||||
val.getContext().cacheResource(mr);
|
val.getContext().cacheResource(mr);
|
||||||
if (mr instanceof ImplementationGuide) {
|
if (mr instanceof ImplementationGuide) {
|
||||||
val.getImplementationGuides().add((ImplementationGuide) mr);
|
val.getImplementationGuides().add((ImplementationGuide) mr);
|
||||||
|
@ -317,7 +316,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
logOutput("Name: " + name + " - profile : " + profile.get("source").getAsString());
|
logOutput("Name: " + name + " - profile : " + profile.get("source").getAsString());
|
||||||
version = content.has("version") ? content.get("version").getAsString() : version;
|
version = content.has("version") ? content.get("version").getAsString() : version;
|
||||||
sd = loadProfile(filename, contents, messages, val.isDebug(), val.getContext());
|
sd = loadProfile(filename, contents, messages, val.isDebug(), val.getContext());
|
||||||
logOutputToFile("load resource "+sd.getUrl());
|
logOutput("load resource "+sd.getUrl());
|
||||||
val.getContext().cacheResource(sd);
|
val.getContext().cacheResource(sd);
|
||||||
}
|
}
|
||||||
val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false);
|
val.setAssumeValidRestReferences(profile.has("assumeValidRestReferences") ? profile.get("assumeValidRestReferences").getAsBoolean() : false);
|
||||||
|
@ -338,13 +337,13 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
if (mr instanceof StructureDefinition) {
|
if (mr instanceof StructureDefinition) {
|
||||||
new ContextUtilities(val.getContext()).generateSnapshot((StructureDefinition) mr, true);
|
new ContextUtilities(val.getContext()).generateSnapshot((StructureDefinition) mr, true);
|
||||||
}
|
}
|
||||||
logOutputToFile("load resource "+mr.getUrl());
|
logOutput("load resource "+mr.getUrl());
|
||||||
val.getContext().cacheResource(mr);
|
val.getContext().cacheResource(mr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (logical.has("packages")) {
|
if (logical.has("packages")) {
|
||||||
for (JsonElement e : logical.getAsJsonArray("packages")) {
|
for (JsonElement e : logical.getAsJsonArray("packages")) {
|
||||||
logOutputToFile("load package "+e.getAsString());
|
logOutput("load package "+e.getAsString());
|
||||||
igLoader.loadIg(vCurr.getIgs(), vCurr.getBinaries(), e.getAsString(), true);
|
igLoader.loadIg(vCurr.getIgs(), vCurr.getBinaries(), e.getAsString(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,13 +556,6 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
||||||
System.out.println(msg);
|
System.out.println(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logOutputToFile(String msg) throws IOException {
|
|
||||||
System.out.println(msg);
|
|
||||||
logB .append(msg);
|
|
||||||
logB.append("\r\n");
|
|
||||||
TextFile.stringToFile(logB.toString(), Utilities.path("[tmp]", "validation-test-log.txt"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private OperationOutcomeIssueComponent findMatchingIssue(OperationOutcome oo, OperationOutcomeIssueComponent iss) {
|
private OperationOutcomeIssueComponent findMatchingIssue(OperationOutcome oo, OperationOutcomeIssueComponent iss) {
|
||||||
for (OperationOutcomeIssueComponent t : oo.getIssue()) {
|
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()
|
if (t.getExpression().get(0).getValue().equals(iss.getExpression().get(0).getValue()) && t.getCode() == iss.getCode() && t.getSeverity() == iss.getSeverity()
|
||||||
|
|
|
@ -2039,3 +2039,12 @@ v: {
|
||||||
"error" : "The code \"[%payloadFormat%]\" is not valid in the system urn:ietf:bcp:13; The code provided (urn:ietf:bcp:13#[%payloadFormat%]) is not valid in the value set 'Mime Types' (from http://tx.fhir.org/r4)"
|
"error" : "The code \"[%payloadFormat%]\" is not valid in the system urn:ietf:bcp:13; The code provided (urn:ietf:bcp:13#[%payloadFormat%]) is not valid in the value set 'Mime Types' (from http://tx.fhir.org/r4)"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"code" : "h"
|
||||||
|
}, "url": "http://hl7.org/fhir/ValueSet/units-of-time", "version": "4.0.1", "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"true", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "小时",
|
||||||
|
"code" : "h",
|
||||||
|
"system" : "http://unitsofmeasure.org"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1966,3 +1966,14 @@ v: {
|
||||||
"system" : "http://loinc.org"
|
"system" : "http://loinc.org"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://loinc.org",
|
||||||
|
"code" : "80764-4",
|
||||||
|
"display" : "Pain medicine Plan of care note"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Pain medicine Plan of care note",
|
||||||
|
"code" : "80764-4",
|
||||||
|
"system" : "http://loinc.org"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -9,3 +9,104 @@ v: {
|
||||||
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1010603",
|
||||||
|
"display" : "Suboxone 2 MG / 0.5 MG Sublingual Film"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film [Suboxone]",
|
||||||
|
"code" : "1010603",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1049502",
|
||||||
|
"display" : "12 HR Oxycodone Hydrochloride 10 MG Extended Release Oral Tablet"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet",
|
||||||
|
"code" : "1049502",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1010600",
|
||||||
|
"display" : "Buprenorphine 2 MG / Naloxone 0.5 MG Oral Strip"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film",
|
||||||
|
"code" : "1010600",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"severity" : "warning",
|
||||||
|
"error" : "The display \"Buprenorphine 2 MG / Naloxone 0.5 MG Oral Strip\" is not a valid display for the code {http://www.nlm.nih.gov/research/umls/rxnorm}1010600 - should be one of ['buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film', 'buprenorphine 2 MG / naloxone 0.5 MG Buccal Film', 'buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film', 'buprenorphine HCl 2 MG / naloxone HCl 0.5 MG Sublingual Film'] (from http://tx.fhir.org/r4)"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "197696",
|
||||||
|
"display" : "72 HR Fentanyl 0.075 MG/HR Transdermal System"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "72 HR fentanyl 0.075 MG/HR Transdermal System",
|
||||||
|
"code" : "197696",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "892495",
|
||||||
|
"display" : "Morphine Sulfate 10 MG [Kadian]"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "morphine sulfate 10 MG [Kadian]",
|
||||||
|
"code" : "892495",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1049502",
|
||||||
|
"display" : "oxyCODONE HCl 10 MG 12HR Extended Release Oral Tablet"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "12 HR oxycodone hydrochloride 10 MG Extended Release Oral Tablet",
|
||||||
|
"code" : "1049502",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "836397",
|
||||||
|
"display" : "Acetaminophen 325 MG / tramadol hydrochloride 37.5 MG Oral Tablet [Ultracet]"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "acetaminophen 325 MG / tramadol hydrochloride 37.5 MG Oral Tablet [Ultracet]",
|
||||||
|
"code" : "836397",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1298088",
|
||||||
|
"display" : "Flurazepam Hydrochloride 15 MG Oral Capsule"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "flurazepam hydrochloride 15 MG Oral Capsule",
|
||||||
|
"code" : "1298088",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
|
||||||
|
"code" : "1010600",
|
||||||
|
"display" : "buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "buprenorphine 2 MG / naloxone 0.5 MG Sublingual Film",
|
||||||
|
"code" : "1010600",
|
||||||
|
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -2002,3 +2002,57 @@ v: {
|
||||||
"system" : "http://snomed.info/sct"
|
"system" : "http://snomed.info/sct"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://snomed.info/sct",
|
||||||
|
"code" : "310627008",
|
||||||
|
"display" : "Urine drug screening (procedure)"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Urine drug screening",
|
||||||
|
"code" : "310627008",
|
||||||
|
"system" : "http://snomed.info/sct"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://snomed.info/sct",
|
||||||
|
"code" : "1049502",
|
||||||
|
"display" : "12 HR Oxycodone Hydrochloride 10 MG Extended Release Oral Tablet"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"severity" : "error",
|
||||||
|
"error" : "Unable to find code 1049502 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20220731); The code \"1049502\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#1049502) 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" : "82423001",
|
||||||
|
"display" : "Chronic pain"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Chronic pain",
|
||||||
|
"code" : "82423001",
|
||||||
|
"system" : "http://snomed.info/sct"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://snomed.info/sct",
|
||||||
|
"code" : "454281000124100",
|
||||||
|
"display" : "Assessment of risk for opioid abuse (procedure)"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"severity" : "error",
|
||||||
|
"error" : "Unable to find code 454281000124100 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20220731); The code \"454281000124100\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#454281000124100) 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",
|
||||||
|
"version" : "http://snomed.info/sct/731000124108",
|
||||||
|
"code" : "454281000124100",
|
||||||
|
"display" : "Assessment of risk for opioid abuse (procedure)"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "Assessment of risk for opioid abuse (procedure)",
|
||||||
|
"code" : "454281000124100",
|
||||||
|
"system" : "http://snomed.info/sct"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -205,3 +205,23 @@ v: {
|
||||||
"error" : "The code provided (http://unitsofmeasure.org#m) is not valid (from http://tx.fhir.org/r4)"
|
"error" : "The code provided (http://unitsofmeasure.org#m) is not valid (from http://tx.fhir.org/r4)"
|
||||||
}
|
}
|
||||||
-------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://unitsofmeasure.org",
|
||||||
|
"code" : "{patch}"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "{patch}",
|
||||||
|
"code" : "{patch}",
|
||||||
|
"system" : "http://unitsofmeasure.org"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
{"code" : {
|
||||||
|
"system" : "http://unitsofmeasure.org",
|
||||||
|
"code" : "{capsule}"
|
||||||
|
}, "valueSet" :null, "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}####
|
||||||
|
v: {
|
||||||
|
"display" : "{capsule}",
|
||||||
|
"code" : "{capsule}",
|
||||||
|
"system" : "http://unitsofmeasure.org"
|
||||||
|
}
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue