Merge pull request #1423 from hapifhir/2023-09-gg-shlinks-validation

Add SHLinks validation
This commit is contained in:
Grahame Grieve 2023-09-04 23:03:10 +10:00 committed by GitHub
commit 345b2ac83e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1493 additions and 606 deletions

View File

@ -172,12 +172,20 @@
<version>4.12</version> <version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.30.2</version>
</dependency>
<dependency> <dependency>
<groupId>net.sourceforge.plantuml</groupId> <groupId>net.sourceforge.plantuml</groupId>
<artifactId>plantuml-mit</artifactId> <artifactId>plantuml-mit</artifactId>
<version>1.2023.9</version> <version>1.2023.9</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r5.elementmodel; package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -44,10 +45,14 @@ public class FmlParser extends ParserBase {
} }
@Override @Override
public List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
byte[] content = TextFile.streamToBytes(inStream);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
String text = TextFile.streamToString(stream); String text = TextFile.streamToString(stream);
List<NamedElement> result = new ArrayList<>(); List<NamedElement> result = new ArrayList<>();
result.add(new NamedElement(null, parse(text))); NamedElement ctxt = new NamedElement("focus", "fml", content);
ctxt.setElement(parse(ctxt.getErrors(), text));
result.add(ctxt);
return result; return result;
} }
@ -57,7 +62,7 @@ public class FmlParser extends ParserBase {
throw new Error("Not done yet"); throw new Error("Not done yet");
} }
public Element parse(String text) throws FHIRException { public Element parse(List<ValidationMessage> errors, String text) throws FHIRException {
FHIRLexer lexer = new FHIRLexer(text, "source", true, true); FHIRLexer lexer = new FHIRLexer(text, "source", true, true);
if (lexer.done()) if (lexer.done())
throw lexer.error("Map Input cannot be empty"); throw lexer.error("Map Input cannot be empty");
@ -112,13 +117,13 @@ public class FmlParser extends ParserBase {
if (policy == ValidationPolicy.NONE) { if (policy == ValidationPolicy.NONE) {
throw e; throw e;
} else { } else {
logError("2023-02-24", e.getLocation().getLine(), e.getLocation().getColumn(), "??", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL); logError(errors, "2023-02-24", e.getLocation().getLine(), e.getLocation().getColumn(), "??", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
} }
} catch (Exception e) { } catch (Exception e) {
if (policy == ValidationPolicy.NONE) { if (policy == ValidationPolicy.NONE) {
throw e; throw e;
} else { } else {
logError("2023-02-24", -1, -1, "?", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL); logError(errors, "2023-02-24", -1, -1, "?", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
} }
} }
result.setIgnorePropertyOrder(true); result.setIgnorePropertyOrder(true);

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.r5.elementmodel; package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -50,6 +52,7 @@ import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
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.elementmodel.Element.SpecialElement; import org.hl7.fhir.r5.elementmodel.Element.SpecialElement;
import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonCreator; import org.hl7.fhir.r5.formats.JsonCreator;
import org.hl7.fhir.r5.formats.JsonCreatorCanonical; import org.hl7.fhir.r5.formats.JsonCreatorCanonical;
@ -95,63 +98,66 @@ public class JsonParser extends ParserBase {
this.profileUtilities = new ProfileUtilities(this.context, null, null, new FHIRPathEngine(context)); this.profileUtilities = new ProfileUtilities(this.context, null, null, new FHIRPathEngine(context));
} }
//
public Element parse(String source, String type) throws Exception { // public Element parse(String source, String type) throws Exception {
JsonObject obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true); // JsonObject obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true);
String path = "/"+type; // String path = "/"+type;
StructureDefinition sd = getDefinition(-1, -1, type); // StructureDefinition sd = getDefinition(-1, -1, type);
if (sd == null) // if (sd == null)
return null; // return null;
//
Element result = new Element(type, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities)); // Element result = new Element(type, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
result.setPath(type); // result.setPath(type);
checkObject(obj, result, path); // checkObject(obj, result, path);
result.setType(type); // result.setType(type);
parseChildren(path, obj, result, true); // parseChildren(path, obj, result, true);
result.numberChildren(); // result.numberChildren();
return result; // return result;
} // }
@Override @Override
public List<NamedElement> parse(InputStream stream) throws IOException, FHIRException { public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRException {
byte[] content = TextFile.streamToBytes(inStream);
NamedElement ctxt = new NamedElement("focus", "json", content);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
// if we're parsing at this point, then we're going to use the custom parser // if we're parsing at this point, then we're going to use the custom parser
List<NamedElement> res = new ArrayList<>();
String source = TextFile.streamToString(stream); String source = TextFile.streamToString(stream);
JsonObject obj = null; JsonObject obj = null;
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
try { try {
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true); obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true);
} catch (Exception e) { } catch (Exception e) {
logError(ValidationMessage.NO_RULE_DATE, -1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL); logError(ctxt.getErrors(), ValidationMessage.NO_RULE_DATE, -1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
return null;
} }
} else { } else {
obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true); obj = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(source, true, true);
} }
Element e = parse(obj); ctxt.setElement(parse(ctxt.getErrors(), obj));
if (e != null) {
res.add(new NamedElement(null, e)); List<NamedElement> res = new ArrayList<>();
} res.add(ctxt);
return res; return res;
} }
public Element parse(JsonObject object) throws FHIRException { public Element parse(List<ValidationMessage> errors, JsonObject object) throws FHIRException {
StructureDefinition sd = getLogical(); StructureDefinition sd = getLogical();
String name; String name;
String path; String path;
if (sd == null) { if (sd == null) {
JsonElement rt = object.get("resourceType"); JsonElement rt = object.get("resourceType");
if (rt == null) { if (rt == null) {
logError(ValidationMessage.NO_RULE_DATE, line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
return null; return null;
} else if (!rt.isJsonString()) { } else if (!rt.isJsonString()) {
logError("2022-11-26", line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.RESOURCETYPE_PROPERTY_WRONG_TYPE, rt.type().toName()), IssueSeverity.FATAL); logError(errors, "2022-11-26", line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.RESOURCETYPE_PROPERTY_WRONG_TYPE, rt.type().toName()), IssueSeverity.FATAL);
return null; return null;
} else { } else {
name = rt.asString(); name = rt.asString();
sd = getDefinition(line(object), col(object), name); sd = getDefinition(errors, line(object), col(object), name);
if (sd == null) { if (sd == null) {
return null; return null;
} }
@ -162,25 +168,25 @@ public class JsonParser extends ParserBase {
path = sd.getTypeTail(); path = sd.getTypeTail();
} }
baseElement = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities)); baseElement = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities));
checkObject(object, baseElement, path); checkObject(errors, object, baseElement, path);
baseElement.markLocation(line(object), col(object)); baseElement.markLocation(line(object), col(object));
baseElement.setType(name); baseElement.setType(name);
baseElement.setPath(baseElement.fhirTypeRoot()); baseElement.setPath(baseElement.fhirTypeRoot());
parseChildren(path, object, baseElement, true); parseChildren(errors, path, object, baseElement, true);
baseElement.numberChildren(); baseElement.numberChildren();
return baseElement; return baseElement;
} }
private void checkObject(JsonObject object, Element b, String path) { private void checkObject(List<ValidationMessage> errors, JsonObject object, Element b, String path) {
checkComments(object, b, path); checkComments(errors, object, b, path);
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
if (object.getProperties().size() == 0) { if (object.getProperties().size() == 0) {
logError(ValidationMessage.NO_RULE_DATE, line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
} }
} }
} }
private void checkComments(JsonElement element, Element b, String path) throws FHIRFormatError { private void checkComments(List<ValidationMessage> errors, JsonElement element, Element b, String path) throws FHIRFormatError {
if (element != null && element.hasComments()) { if (element != null && element.hasComments()) {
if (allowComments) { if (allowComments) {
for (JsonComment c : element.getComments()) { for (JsonComment c : element.getComments()) {
@ -188,13 +194,13 @@ public class JsonParser extends ParserBase {
} }
} else { } else {
for (JsonComment c : element.getComments()) { for (JsonComment c : element.getComments()) {
logError("2022-11-26", c.getStart().getLine(), c.getStart().getCol(), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMENTS_NOT_ALLOWED), IssueSeverity.ERROR); logError(errors, "2022-11-26", c.getStart().getLine(), c.getStart().getCol(), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMENTS_NOT_ALLOWED), IssueSeverity.ERROR);
} }
} }
} }
} }
private void parseChildren(String path, JsonObject object, Element element, boolean hasResourceType) throws FHIRException { private void parseChildren(List<ValidationMessage> errors, String path, JsonObject object, Element element, boolean hasResourceType) throws FHIRException {
reapComments(object, element); reapComments(object, element);
List<Property> properties = element.getProperty().getChildProperties(element.getName(), null); List<Property> properties = element.getProperty().getChildProperties(element.getName(), null);
Set<String> processed = new HashSet<String>(); Set<String> processed = new HashSet<String>();
@ -205,13 +211,13 @@ public class JsonParser extends ParserBase {
Set<String> unique = new HashSet<>(); Set<String> unique = new HashSet<>();
for (JsonProperty p : object.getProperties()) { for (JsonProperty p : object.getProperties()) {
if (p.isUnquotedName()) { if (p.isUnquotedName()) {
logError("2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_NO_QUOTES, p.getName()), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_NO_QUOTES, p.getName()), IssueSeverity.ERROR);
} }
if (p.isNoComma()) { if (p.isNoComma()) {
logError("2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_MISSING), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_MISSING), IssueSeverity.ERROR);
} }
if (unique.contains(p.getName())) { if (unique.contains(p.getName())) {
logError("2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY, p.getName()), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(p.getValue()), col(p.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY, p.getName()), IssueSeverity.ERROR);
} else { } else {
unique.add(p.getName()); unique.add(p.getName());
recognisedChildren.put(p.getName(), p); recognisedChildren.put(p.getName(), p);
@ -221,7 +227,7 @@ public class JsonParser extends ParserBase {
// note that we do not trouble ourselves to maintain the wire format order here - we don't even know what it was anyway // note that we do not trouble ourselves to maintain the wire format order here - we don't even know what it was anyway
// first pass: process the properties // first pass: process the properties
for (Property property : properties) { for (Property property : properties) {
parseChildItem(path, recognisedChildren, element, processed, property); parseChildItem(errors, path, recognisedChildren, element, processed, property);
} }
// second pass: check for things not processed // second pass: check for things not processed
@ -231,32 +237,32 @@ public class JsonParser extends ParserBase {
StructureDefinition sd = element.getProperty().isLogical() ? new ContextUtilities(context).fetchByJsonName(e.getKey()) : null; StructureDefinition sd = element.getProperty().isLogical() ? new ContextUtilities(context).fetchByJsonName(e.getKey()) : null;
if (sd != null) { if (sd != null) {
Property property = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, element.getProperty().getUtils()); Property property = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, element.getProperty().getUtils());
parseChildItem(path, recognisedChildren, element, null, property); parseChildItem(errors, path, recognisedChildren, element, null, property);
} else if ("fhir_comments".equals(e.getKey()) && (VersionUtilities.isR2BVer(context.getVersion()) || VersionUtilities.isR2Ver(context.getVersion()))) { } else if ("fhir_comments".equals(e.getKey()) && (VersionUtilities.isR2BVer(context.getVersion()) || VersionUtilities.isR2Ver(context.getVersion()))) {
if (!e.getValue().getValue().isJsonArray()) { if (!e.getValue().getValue().isJsonArray()) {
logError("2022-12-17", line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.ILLEGAL_COMMENT_TYPE, e.getValue().getValue().type().toName()), IssueSeverity.ERROR); logError(errors, "2022-12-17", line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.ILLEGAL_COMMENT_TYPE, e.getValue().getValue().type().toName()), IssueSeverity.ERROR);
} else { } else {
for (JsonElement c : e.getValue().getValue().asJsonArray()) { for (JsonElement c : e.getValue().getValue().asJsonArray()) {
if (!c.isJsonString()) { if (!c.isJsonString()) {
logError("2022-12-17", line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.ILLEGAL_COMMENT_TYPE, c.type().toName()), IssueSeverity.ERROR); logError(errors, "2022-12-17", line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.ILLEGAL_COMMENT_TYPE, c.type().toName()), IssueSeverity.ERROR);
} else { } else {
element.getComments().add(c.asString()); element.getComments().add(c.asString());
} }
} }
} }
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e.getValue().getValue()), col(e.getValue().getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR);
} }
} }
} }
} }
if (object.isExtraComma()) { if (object.isExtraComma()) {
logError("2022-11-26", object.getEnd().getLine(), object.getEnd().getCol(), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR); logError(errors, "2022-11-26", object.getEnd().getLine(), object.getEnd().getCol(), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR);
} }
} }
public void parseChildItem(String path, Map<String, JsonProperty> children, Element context, Set<String> processed, Property property) { public void parseChildItem(List<ValidationMessage> errors, String path, Map<String, JsonProperty> children, Element context, Set<String> processed, Property property) {
if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) { if (property.isChoice() || property.getDefinition().getPath().endsWith("data[x]")) {
if (property.isJsonPrimitiveChoice()) { if (property.isJsonPrimitiveChoice()) {
if (children.containsKey(property.getJsonName())) { if (children.containsKey(property.getJsonName())) {
@ -264,30 +270,30 @@ public class JsonParser extends ParserBase {
if (processed != null) processed.add(property.getJsonName()); if (processed != null) processed.add(property.getJsonName());
String type = getTypeFromJsonType(je); String type = getTypeFromJsonType(je);
if (type == null) { if (type == null) {
logError(ValidationMessage.NO_RULE_DATE, line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(je), property.getName(), property.typeSummary()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(je), property.getName(), property.typeSummary()), IssueSeverity.ERROR);
} else if (property.hasType(type)) { } else if (property.hasType(type)) {
Property np = new Property(property.getContext(), property.getDefinition(), property.getStructure(), property.getUtils(), type); Property np = new Property(property.getContext(), property.getDefinition(), property.getStructure(), property.getUtils(), type);
parseChildPrimitive(children, context, processed, np, path, property.getName(), false); parseChildPrimitive(errors, children, context, processed, np, path, property.getName(), false);
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(je), property.getName(), type, property.typeSummary()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(je), property.getName(), type, property.typeSummary()), IssueSeverity.ERROR);
} }
} }
} else { } else {
for (TypeRefComponent type : property.getDefinition().getType()) { for (TypeRefComponent type : property.getDefinition().getType()) {
String eName = property.getJsonName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode()); String eName = property.getJsonName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
if (!isPrimitive(type.getWorkingCode()) && children.containsKey(eName)) { if (!isPrimitive(type.getWorkingCode()) && children.containsKey(eName)) {
parseChildComplex(path, children, context, processed, property, eName, false); parseChildComplex(errors, path, children, context, processed, property, eName, false);
break; break;
} else if (isPrimitive(type.getWorkingCode()) && (children.containsKey(eName) || children.containsKey("_"+eName))) { } else if (isPrimitive(type.getWorkingCode()) && (children.containsKey(eName) || children.containsKey("_"+eName))) {
parseChildPrimitive(children, context, processed, property, path, eName, false); parseChildPrimitive(errors, children, context, processed, property, path, eName, false);
break; break;
} }
} }
} }
} else if (property.isPrimitive(property.getType(null))) { } else if (property.isPrimitive(property.getType(null))) {
parseChildPrimitive(children, context, processed, property, path, property.getJsonName(), property.hasJsonName()); parseChildPrimitive(errors, children, context, processed, property, path, property.getJsonName(), property.hasJsonName());
} else if (children.containsKey(property.getJsonName())) { } else if (children.containsKey(property.getJsonName())) {
parseChildComplex(path, children, context, processed, property, property.getJsonName(), property.hasJsonName()); parseChildComplex(errors, path, children, context, processed, property, property.getJsonName(), property.hasJsonName());
} }
} }
@ -311,7 +317,7 @@ public class JsonParser extends ParserBase {
} }
} }
private void parseChildComplex(String path, Map<String, JsonProperty> children, Element element, Set<String> processed, Property property, String name, boolean isJsonName) throws FHIRException { private void parseChildComplex(List<ValidationMessage> errors, String path, Map<String, JsonProperty> children, Element element, Set<String> processed, Property property, String name, boolean isJsonName) throws FHIRException {
if (processed != null) { if (processed != null) {
processed.add(name); processed.add(name);
} }
@ -322,49 +328,49 @@ 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.isExtraComma()) { if (arr.isExtraComma()) {
logError("2022-11-26", arr.getEnd().getLine(), arr.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR); logError(errors, "2022-11-26", arr.getEnd().getLine(), arr.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR);
} }
if (arr.size() == 0) { if (arr.size() == 0) {
if (property.canBeEmpty()) { if (property.canBeEmpty()) {
// nothing // nothing
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, 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) {
parseChildComplexInstance(npath+"["+c+"]", fpath+"["+c+"]", element, property, name, am, c == 0 ? arr : null, path); parseChildComplexInstance(errors, npath+"["+c+"]", fpath+"["+c+"]", element, property, name, am, c == 0 ? arr : null, path);
c++; c++;
} }
} else if (property.isJsonKeyArray()) { } else if (property.isJsonKeyArray()) {
String code = property.getJsonKeyProperty(); String code = property.getJsonKeyProperty();
List<Property> properties = property.getChildProperties(element.getName(), null); List<Property> properties = property.getChildProperties(element.getName(), null);
if (properties.size() != 2) { if (properties.size() != 2) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT, propNames(properties)), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT, propNames(properties)), IssueSeverity.ERROR);
} else { } else {
Property propK = properties.get(0); Property propK = properties.get(0);
Property propV = properties.get(1); Property propV = properties.get(1);
if (!propK.getName().equals(code)) { if (!propK.getName().equals(code)) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME, propNames(properties)), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME, propNames(properties)), IssueSeverity.ERROR);
} else if (!propK.isPrimitive()) { } else if (!propK.isPrimitive()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE, propNames(properties), propK.typeSummary()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE, propNames(properties), propK.typeSummary()), IssueSeverity.ERROR);
} else if (propV.isList()) { } else if (propV.isList()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST, propV.getName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST, propV.getName()), IssueSeverity.ERROR);
} else if (propV.isChoice() && propV.getName().endsWith("[x]")) { } else if (propV.isChoice() && propV.getName().endsWith("[x]")) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE, propV.getName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE, propV.getName()), IssueSeverity.ERROR);
} else if (!(e instanceof JsonObject)) { } else if (!(e instanceof JsonObject)) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR);
} else { } else {
JsonObject o = (JsonObject) e; JsonObject o = (JsonObject) e;
if (o.isExtraComma()) { if (o.isExtraComma()) {
logError("2022-11-26", o.getEnd().getLine(), o.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR); logError(errors, "2022-11-26", o.getEnd().getLine(), o.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR);
} }
int i = 0; int i = 0;
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
for (JsonProperty pv : o.getProperties()) { for (JsonProperty pv : o.getProperties()) {
if (names.contains(pv.getName())) { if (names.contains(pv.getName())) {
logError("2022-11-26", line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY_KEY, pv.getName()), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY_KEY, pv.getName()), IssueSeverity.ERROR);
} else { } else {
names.add(pv.getName()); names.add(pv.getName());
} }
@ -378,7 +384,7 @@ public class JsonParser extends ParserBase {
// handle the key // handle the key
String fpathKey = fpathArr+"."+propK.getName(); String fpathKey = fpathArr+"."+propK.getName();
Element nKey = new Element(code, propK).markLocation(line(pv.getValue()), col(pv.getValue())); Element nKey = new Element(code, propK).markLocation(line(pv.getValue()), col(pv.getValue()));
checkComments(pv.getValue(), n, fpathArr); checkComments(errors, pv.getValue(), n, fpathArr);
nKey.setPath(fpathKey); nKey.setPath(fpathKey);
n.getChildren().add(nKey); n.getChildren().add(nKey);
nKey.setValue(pv.getName()); nKey.setValue(pv.getName());
@ -390,12 +396,12 @@ public class JsonParser extends ParserBase {
ok = false; ok = false;
String type = getTypeFromJsonType(pv.getValue()); String type = getTypeFromJsonType(pv.getValue());
if (type == null) { if (type == null) {
logError(ValidationMessage.NO_RULE_DATE, line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(pv.getValue()), propV.getName(), propV.typeSummary()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(pv.getValue()), propV.getName(), propV.typeSummary()), IssueSeverity.ERROR);
} else if (propV.hasType(type)) { } else if (propV.hasType(type)) {
pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type); pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type);
ok = true; ok = true;
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(pv.getValue()), propV.getName(), type, propV.typeSummary()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(pv.getValue()), col(pv.getValue()), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE_WRONG, describeType(pv.getValue()), propV.getName(), type, propV.typeSummary()), IssueSeverity.ERROR);
} }
} }
if (ok) { if (ok) {
@ -403,11 +409,11 @@ public class JsonParser extends ParserBase {
String npathV = npathArr+"."+pvl.getName(); String npathV = npathArr+"."+pvl.getName();
String fpathV = fpathArr+"."+pvl.getName(); String fpathV = fpathArr+"."+pvl.getName();
if (propV.isPrimitive(pvl.getType(null))) { if (propV.isPrimitive(pvl.getType(null))) {
parseChildPrimitiveInstance(n, pvl, pvl.getName(), false, npathV, fpathV, pv.getValue(), null); parseChildPrimitiveInstance(errors, n, pvl, pvl.getName(), false, npathV, fpathV, pv.getValue(), null);
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) { } else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue(), null, null); parseChildComplexInstance(errors, npathV, fpathV, n, pvl, pvl.getName(), pv.getValue(), null, null);
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
} }
} }
i++; i++;
@ -416,9 +422,9 @@ public class JsonParser extends ParserBase {
} }
} else { } else {
if (property.isList()) { if (property.isList()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(e), name, path), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(e), name, path), IssueSeverity.ERROR);
} }
parseChildComplexInstance(npath, fpath, element, property, name, e, null, null); parseChildComplexInstance(errors, npath, fpath, element, property, name, e, null, null);
} }
} }
@ -430,7 +436,7 @@ public class JsonParser extends ParserBase {
return b.toString(); return b.toString();
} }
private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e, JsonElement commentContext, String commentPath) throws FHIRException { private void parseChildComplexInstance(List<ValidationMessage> errors, String npath, String fpath, Element element, Property property, String name, JsonElement e, JsonElement commentContext, String commentPath) throws FHIRException {
if (property.hasTypeSpecifier()) { if (property.hasTypeSpecifier()) {
FHIRPathEngine fpe = new FHIRPathEngine(context); FHIRPathEngine fpe = new FHIRPathEngine(context);
String type = null; String type = null;
@ -445,19 +451,19 @@ public class JsonParser extends ParserBase {
if (type != null) { if (type != null) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, type); StructureDefinition sd = context.fetchResource(StructureDefinition.class, type);
if (sd == null) { if (sd == null) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ILLEGAL_TYPE, type, cond), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ILLEGAL_TYPE, type, cond), IssueSeverity.ERROR);
} else { } else {
if (sd.getAbstract()) { if (sd.getAbstract()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ABSTRACT_TYPE, type, cond), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ABSTRACT_TYPE, type, cond), IssueSeverity.ERROR);
} }
property = property.cloneToType(sd); property = property.cloneToType(sd);
} }
} else { } else {
StructureDefinition sd = context.fetchTypeDefinition(property.getType()); StructureDefinition sd = context.fetchTypeDefinition(property.getType());
if (sd == null) { if (sd == null) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ILLEGAL_TYPE, property.getType()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ILLEGAL_TYPE, property.getType()), IssueSeverity.ERROR);
} else if (sd.getAbstract()) { } else if (sd.getAbstract()) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ABSTRACT_TYPE, property.getType()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ABSTRACT_TYPE, property.getType()), IssueSeverity.ERROR);
} }
} }
} }
@ -465,26 +471,26 @@ public class JsonParser extends ParserBase {
JsonObject child = (JsonObject) e; JsonObject child = (JsonObject) e;
Element n = new Element(name, property).markLocation(line(child), col(child)); Element n = new Element(name, property).markLocation(line(child), col(child));
n.setPath(fpath); n.setPath(fpath);
checkComments(commentContext, n, commentPath); checkComments(errors, commentContext, n, commentPath);
checkObject(child, n, npath); checkObject(errors, child, n, npath);
element.getChildren().add(n); element.getChildren().add(n);
if (property.isResource()) { if (property.isResource()) {
parseResource(npath, child, n, property); parseResource(errors, npath, child, n, property);
} else { } else {
parseChildren(npath, child, n, false); parseChildren(errors, npath, child, n, false);
} }
} else if (property.isNullable() && e instanceof JsonNull) { } else if (property.isNullable() && e instanceof JsonNull) {
// we create an element marked as a null element so we know something was present // we create an element marked as a null element so we know something was present
JsonNull child = (JsonNull) e; JsonNull child = (JsonNull) e;
Element n = new Element(name, property).markLocation(line(child), col(child)); Element n = new Element(name, property).markLocation(line(child), col(child));
checkComments(commentContext, n, commentPath); checkComments(errors, commentContext, n, commentPath);
checkComments(child, n, fpath); checkComments(errors, child, n, fpath);
n.setPath(fpath); n.setPath(fpath);
element.getChildren().add(n); element.getChildren().add(n);
n.setNull(true); n.setNull(true);
// nothing to do, it's ok, but we treat it like it doesn't exist // nothing to do, it's ok, but we treat it like it doesn't exist
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, 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(errors, ValidationMessage.NO_RULE_DATE, 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);
} }
} }
@ -508,7 +514,7 @@ public class JsonParser extends ParserBase {
return e.type().toName(); return e.type().toName();
} }
private void parseChildPrimitive(Map<String, JsonProperty> children, Element element, Set<String> processed, Property property, String path, String name, boolean isJsonName) throws FHIRException { private void parseChildPrimitive(List<ValidationMessage> errors, Map<String, JsonProperty> children, Element element, Set<String> processed, Property property, String path, String name, boolean isJsonName) throws FHIRException {
String npath = path+"."+property.getName(); String npath = path+"."+property.getName();
String fpath = element.getPath()+"."+property.getName(); String fpath = element.getPath()+"."+property.getName();
processed.add(name); processed.add(name);
@ -516,40 +522,40 @@ public class JsonParser extends ParserBase {
JsonProperty main = children.containsKey(name) ? children.get(name) : null; JsonProperty main = children.containsKey(name) ? children.get(name) : null;
JsonProperty fork = children.containsKey("_"+name) ? children.get("_"+name) : null; JsonProperty fork = children.containsKey("_"+name) ? children.get("_"+name) : null;
if (main != null && main.getValue().isJsonString() && main.isUnquotedValue()) { if (main != null && main.getValue().isJsonString() && main.isUnquotedValue()) {
logError("2022-11-26", line(main.getValue()), col(main.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_VALUE_NO_QUOTES, main.getName(), main.getValue().asString()), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(main.getValue()), col(main.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_VALUE_NO_QUOTES, main.getName(), main.getValue().asString()), IssueSeverity.ERROR);
} }
if (main != null || fork != null) { if (main != null || fork != null) {
if (property.isList()) { if (property.isList()) {
boolean ok = true; boolean ok = true;
if (!(main == null || main.getValue() instanceof JsonArray)) { if (!(main == null || main.getValue() instanceof JsonArray)) {
logError(ValidationMessage.NO_RULE_DATE, line(main.getValue()), col(main.getValue()), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main.getValue()), name, path), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(main.getValue()), col(main.getValue()), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main.getValue()), name, path), IssueSeverity.ERROR);
ok = false; ok = false;
} }
if (!(fork == null || fork.getValue() instanceof JsonArray)) { if (!(fork == null || fork.getValue() instanceof JsonArray)) {
logError(ValidationMessage.NO_RULE_DATE, line(fork.getValue()), col(fork.getValue()), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main.getValue()), name, path), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(fork.getValue()), col(fork.getValue()), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main.getValue()), name, path), IssueSeverity.ERROR);
ok = false; ok = false;
} }
if (ok) { if (ok) {
JsonArray arr1 = (JsonArray) (main == null ? null : main.getValue()); JsonArray arr1 = (JsonArray) (main == null ? null : main.getValue());
JsonArray arr2 = (JsonArray) (fork == null ? null : fork.getValue()); JsonArray arr2 = (JsonArray) (fork == null ? null : fork.getValue());
if (arr1 != null && arr1.isExtraComma()) { if (arr1 != null && arr1.isExtraComma()) {
logError("2022-11-26", arr1.getEnd().getLine(), arr1.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR); logError(errors, "2022-11-26", arr1.getEnd().getLine(), arr1.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR);
} }
if (arr2 != null && arr2.isExtraComma()) { if (arr2 != null && arr2.isExtraComma()) {
logError("2022-11-26", arr2.getEnd().getLine(), arr2.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR); logError(errors, "2022-11-26", arr2.getEnd().getLine(), arr2.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Array"), IssueSeverity.ERROR);
} }
for (int i = 0; i < Math.max(arrC(arr1), arrC(arr2)); i++) { for (int i = 0; i < Math.max(arrC(arr1), arrC(arr2)); i++) {
JsonElement m = arrI(arr1, i); JsonElement m = arrI(arr1, i);
JsonElement f = arrI(arr2, i); JsonElement f = arrI(arr2, i);
if (m != null && m.isJsonString() && arr1.isUnquoted(i)) { if (m != null && m.isJsonString() && arr1.isUnquoted(i)) {
logError("2022-11-26", line(m), col(m), path+"."+name+"["+i+"]", IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_VALUE_NO_QUOTES, "item", m.asString()), IssueSeverity.ERROR); logError(errors, "2022-11-26", line(m), col(m), path+"."+name+"["+i+"]", IssueType.INVALID, context.formatMessage(I18nConstants.JSON_PROPERTY_VALUE_NO_QUOTES, "item", m.asString()), IssueSeverity.ERROR);
} }
parseChildPrimitiveInstance(element, property, name, isJsonName, npath, fpath, m, f); parseChildPrimitiveInstance(errors, element, property, name, isJsonName, npath, fpath, m, f);
} }
} }
} else { } else {
parseChildPrimitiveInstance(element, property, name, isJsonName, npath, fpath, main == null ? null : main.getValue(), fork == null ? null : fork.getValue()); parseChildPrimitiveInstance(errors, element, property, name, isJsonName, npath, fpath, main == null ? null : main.getValue(), fork == null ? null : fork.getValue());
} }
} }
} }
@ -562,19 +568,19 @@ public class JsonParser extends ParserBase {
return arr == null ? 0 : arr.size(); return arr == null ? 0 : arr.size();
} }
private void parseChildPrimitiveInstance(Element element, Property property, String name, boolean isJsonName, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException { private void parseChildPrimitiveInstance(List<ValidationMessage> errors, Element element, Property property, String name, boolean isJsonName, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException {
if (main != null && !(main.isJsonBoolean() || main.isJsonNumber() || main.isJsonString())) { if (main != null && !(main.isJsonBoolean() || main.isJsonNumber() || main.isJsonString())) {
logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage( logError(errors, ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(
I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR); I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR);
} else if (fork != null && !(fork instanceof JsonObject)) { } else if (fork != null && !(fork instanceof JsonObject)) {
logError(ValidationMessage.NO_RULE_DATE, line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(fork), name, npath), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(fork), name, npath), IssueSeverity.ERROR);
} else { } else {
Element n = new Element(isJsonName ? property.getName() : name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork)); Element n = new Element(isJsonName ? property.getName() : name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork));
if (main != null) { if (main != null) {
checkComments(main, n, npath); checkComments(errors, main, n, npath);
} }
if (fork != null) { if (fork != null) {
checkComments(fork, n, npath); checkComments(errors, fork, n, npath);
} }
n.setPath(fpath); n.setPath(fpath);
element.getChildren().add(n); element.getChildren().add(n);
@ -587,55 +593,55 @@ public class JsonParser extends ParserBase {
n.setXhtml(xhtml.setXmlMode(true).parse(n.getValue(), null).getDocumentElement()); n.setXhtml(xhtml.setXmlMode(true).parse(n.getValue(), null).getDocumentElement());
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
for (StringPair s : xhtml.getValidationIssues()) { for (StringPair s : xhtml.getValidationIssues()) {
logError("2022-11-17", line(main), col(main), npath, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR); logError(errors, "2022-11-17", line(main), col(main), npath, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR);
} }
} }
} catch (Exception e) { } catch (Exception e) {
logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR);
} }
} }
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
// now we cross-check the primitive format against the stated type // now we cross-check the primitive format against the stated type
if (Utilities.existsInList(n.getType(), "boolean")) { if (Utilities.existsInList(n.getType(), "boolean")) {
if (!p.isJsonBoolean()) { if (!p.isJsonBoolean()) {
logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR);
} }
} else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) { } else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) {
if (!p.isJsonNumber()) if (!p.isJsonNumber())
logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
} else if (!p.isJsonString()) { } else if (!p.isJsonString()) {
logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
} }
} }
} }
if (fork != null) { if (fork != null) {
JsonObject child = (JsonObject) fork; JsonObject child = (JsonObject) fork;
checkObject(child, n, npath); checkObject(errors, child, n, npath);
parseChildren(npath, child, n, false); parseChildren(errors, npath, child, n, false);
} }
} }
} }
private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException { private void parseResource(List<ValidationMessage> errors, String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException {
JsonElement rt = res.get("resourceType"); JsonElement rt = res.get("resourceType");
if (rt == null) { if (rt == null) {
logError(ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
} else if (!rt.isJsonString()) { } else if (!rt.isJsonString()) {
logError("2022-11-26", line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.RESOURCETYPE_PROPERTY_WRONG_TYPE, rt.type().toName()), IssueSeverity.FATAL); logError(errors, "2022-11-26", line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.RESOURCETYPE_PROPERTY_WRONG_TYPE, rt.type().toName()), IssueSeverity.FATAL);
} else { } else {
String name = rt.asString(); String name = rt.asString();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null)); StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
if (sd == null) { if (sd == null) {
logError(ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL);
} else { } else {
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty); parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
parent.setType(name); parent.setType(name);
parseChildren(npath, res, parent, true); parseChildren(errors, npath, res, parent, true);
} }
} }
if (res.isExtraComma()) { if (res.isExtraComma()) {
logError("2022-11-26", res.getEnd().getLine(), res.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR); logError(errors, "2022-11-26", res.getEnd().getLine(), res.getEnd().getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.JSON_COMMA_EXTRA, "Object"), IssueSeverity.ERROR);
} }
} }

View File

@ -48,9 +48,10 @@ import org.hl7.fhir.r5.model.StructureDefinition;
public class Manager { public class Manager {
//TODO use EnumMap //TODO use EnumMap
public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR, SHC, FML; public enum FhirFormat { XML, JSON, TURTLE, TEXT, VBAR, SHC, SHL, FML;
// SHC = smart health cards, including as text versions of QR codes // SHC = smart health cards, including as text versions of QR codes
// SHL = smart health links, also a text version of the QR code
public String getExtension() { public String getExtension() {
switch (this) { switch (this) {
case JSON: case JSON:
@ -65,6 +66,8 @@ public class Manager {
return "hl7"; return "hl7";
case SHC: case SHC:
return "shc"; return "shc";
case SHL:
return "shl";
case FML: case FML:
return "fml"; return "fml";
} }
@ -85,6 +88,8 @@ public class Manager {
return VBAR; return VBAR;
case "shc": case "shc":
return SHC; return SHC;
case "shl":
return SHL;
case "fml": case "fml":
return FML; return FML;
} }
@ -106,7 +111,7 @@ public class Manager {
} }
public static Element parseSingle(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException { public static Element parseSingle(IWorkerContext context, InputStream source, FhirFormat inputFormat) throws FHIRFormatError, DefinitionException, IOException, FHIRException {
return makeParser(context, inputFormat).parseSingle(source); return makeParser(context, inputFormat).parseSingle(source, null);
} }
@ -124,6 +129,7 @@ public class Manager {
case TURTLE : return new TurtleParser(context); case TURTLE : return new TurtleParser(context);
case VBAR : return new VerticalBarParser(context); case VBAR : return new VerticalBarParser(context);
case SHC : return new SHCParser(context); case SHC : return new SHCParser(context);
case SHL : return new SHLParser(context);
case FML : return new FmlParser(context); case FML : return new FmlParser(context);
case TEXT : throw new Error("Programming logic error: do not call makeParser for a text resource"); case TEXT : throw new Error("Programming logic error: do not call makeParser for a text resource");
} }

View File

@ -71,18 +71,49 @@ public abstract class ParserBase {
public class NamedElement { public class NamedElement {
private String name; private String name;
private String extension;
private Element element; private Element element;
public NamedElement(String name, Element element) { private byte[] content;
private List<ValidationMessage> errors = new ArrayList<>();
public NamedElement(String name, String extension, Element element, byte[] content) {
super(); super();
this.name = name; this.name = name;
this.element = element; this.element = element;
this.content = content;
this.extension = extension;
} }
public NamedElement(String name, String extension, byte[] content) {
super();
this.name = name;
this.content = content;
this.extension = extension;
}
public String getName() { public String getName() {
return name; return name;
} }
public Element getElement() { public Element getElement() {
return element; return element;
} }
public byte[] getContent() {
return content;
}
public List<ValidationMessage> getErrors() {
return errors;
}
public void setElement(Element element) {
this.element = element;
}
public String getFilename() {
return name+"."+extension;
}
} }
@ -106,7 +137,6 @@ public abstract class ParserBase {
protected IWorkerContext context; protected IWorkerContext context;
protected ValidationPolicy policy; protected ValidationPolicy policy;
protected List<ValidationMessage> errors;
protected ILinkResolver linkResolver; protected ILinkResolver linkResolver;
protected boolean showDecorations; protected boolean showDecorations;
protected IdRenderingPolicy idPolicy = IdRenderingPolicy.All; protected IdRenderingPolicy idPolicy = IdRenderingPolicy.All;
@ -118,30 +148,32 @@ public abstract class ParserBase {
policy = ValidationPolicy.NONE; policy = ValidationPolicy.NONE;
} }
public void setupValidation(ValidationPolicy policy, List<ValidationMessage> errors) { public void setupValidation(ValidationPolicy policy) {
this.policy = policy; this.policy = policy;
this.errors = errors;
} }
public abstract List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException; public abstract List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException;
public Element parseSingle(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { public Element parseSingle(InputStream stream, List<ValidationMessage> errors) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
if (errors == null) {
errors = new ArrayList<>();
}
List<NamedElement> res = parse(stream); List<NamedElement> res = parse(stream);
if (res == null) {
throw new FHIRException("Parsing FHIR content failed: "+errorSummary());
} else if (res.size() == 0) {
throw new FHIRException("Parsing FHIR content returned no elements in a context where one element is required because: "+errorSummary());
}
if (res.size() != 1) { if (res.size() != 1) {
throw new FHIRException("Parsing FHIR content returned multiple elements in a context where only one element is allowed"); throw new FHIRException("Parsing FHIR content returned multiple elements in a context where only one element is allowed");
} }
return res.get(0).getElement(); var resE = res.get(0);
if (resE.getElement() == null) {
throw new FHIRException("Parsing FHIR content failed: "+errorSummary(resE.errors));
} else if (res.size() == 0) {
throw new FHIRException("Parsing FHIR content returned no elements in a context where one element is required because: "+errorSummary(resE.errors));
}
if (errors != null) {
errors.addAll(resE.getErrors());
}
return resE.getElement();
} }
private String errorSummary() { private String errorSummary(List<ValidationMessage> errors) {
if (errors == null || errors.size() == 0) { if (errors == null || errors.size() == 0) {
return "(no error description)"; return "(no error description)";
} else { } else {
@ -152,7 +184,7 @@ public abstract class ParserBase {
public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException; public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException;
//FIXME: i18n should be done here //FIXME: i18n should be done here
public void logError(String ruleDate, int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError { public void logError(List<ValidationMessage> errors, String ruleDate, int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError {
if (errors != null) { if (errors != null) {
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level); ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level);
@ -164,13 +196,13 @@ public abstract class ParserBase {
} }
protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError { protected StructureDefinition getDefinition(List<ValidationMessage> errors, int line, int col, String ns, String name) throws FHIRFormatError {
if (ns == null) { if (ns == null) {
logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS__CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAMESPACE, name), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS__CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAMESPACE, name), IssueSeverity.FATAL);
return null; return null;
} }
if (name == null) { if (name == null) {
logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL);
return null; return null;
} }
for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) { for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) {
@ -183,7 +215,7 @@ public abstract class ParserBase {
return sd; return sd;
} }
} }
logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAMESPACENAME_, ns, name), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAMESPACENAME_, ns, name), IssueSeverity.FATAL);
return null; return null;
} }
@ -191,9 +223,9 @@ public abstract class ParserBase {
return type == null || !type.contains("/") ? type : type.substring(type.lastIndexOf("/")+1); return type == null || !type.contains("/") ? type : type.substring(type.lastIndexOf("/")+1);
} }
protected StructureDefinition getDefinition(int line, int col, String name) throws FHIRFormatError { protected StructureDefinition getDefinition(List<ValidationMessage> errors, int line, int col, String name) throws FHIRFormatError {
if (name == null) { if (name == null) {
logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL);
return null; return null;
} }
// first pass: only look at base definitions // first pass: only look at base definitions
@ -209,7 +241,7 @@ public abstract class ParserBase {
return sd; return sd;
} }
} }
logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL);
return null; return null;
} }

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r5.elementmodel; package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -17,6 +18,7 @@ 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.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
@ -56,20 +58,25 @@ public class SHCParser extends ParserBase {
jsonParser = new JsonParser(context); jsonParser = new JsonParser(context);
} }
public List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
byte[] content = TextFile.streamToBytes(inStream);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
List<NamedElement> res = new ArrayList<>(); List<NamedElement> res = new ArrayList<>();
NamedElement shc = new NamedElement("shc", "json", content);
res.add(shc);
String src = TextFile.streamToString(stream).trim(); String src = TextFile.streamToString(stream).trim();
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
String pfx = null; String pfx = null;
if (src.startsWith("{")) { if (src.startsWith("{")) {
JsonObject json = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(src); JsonObject json = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(src);
if (checkProperty(json, "$", "verifiableCredential", true, "Array")) { if (checkProperty(shc.getErrors(), json, "$", "verifiableCredential", true, "Array")) {
pfx = "verifiableCredential"; pfx = "verifiableCredential";
JsonArray arr = json.getJsonArray("verifiableCredential"); JsonArray arr = json.getJsonArray("verifiableCredential");
int i = 0; int i = 0;
for (JsonElement e : arr) { for (JsonElement e : arr) {
if (!(e instanceof JsonPrimitive)) { if (!(e instanceof JsonPrimitive)) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), "$.verifiableCredential["+i+"]", IssueType.STRUCTURE, "Wrong Property verifiableCredential in JSON Payload. Expected : String but found "+e.type().toName(), IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, line(e), col(e), "$.verifiableCredential["+i+"]", IssueType.STRUCTURE, "Wrong Property verifiableCredential in JSON Payload. Expected : String but found "+e.type().toName(), IssueSeverity.ERROR);
} else { } else {
list.add(e.asString()); list.add(e.asString());
} }
@ -87,66 +94,65 @@ public class SHCParser extends ParserBase {
c++; c++;
JWT jwt = null; JWT jwt = null;
try { try {
jwt = decodeJWT(ssrc); jwt = decodeJWT(shc.getErrors(), ssrc);
} catch (Exception e) { } catch (Exception e) {
logError(ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INVALID, "Unable to decode JWT token", IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INVALID, "Unable to decode JWT token", IssueSeverity.ERROR);
return res; return res;
} }
checkNamedProperties(jwt.getPayload(), prefix+"payload", "iss", "nbf", "vc"); checkNamedProperties(shc.getErrors(), jwt.getPayload(), prefix+"payload", "iss", "nbf", "vc");
checkProperty(jwt.getPayload(), prefix+"payload", "iss", true, "String"); checkProperty(shc.getErrors(), jwt.getPayload(), prefix+"payload", "iss", true, "String");
logError(ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INFORMATIONAL, "The FHIR Validator does not check the JWT signature "+ logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INFORMATIONAL, "The FHIR Validator does not check the JWT signature "+
"(see https://demo-portals.smarthealth.cards/VerifierPortal.html or https://github.com/smart-on-fhir/health-cards-dev-tools) (Issuer = '"+jwt.getPayload().asString("iss")+"')", IssueSeverity.INFORMATION); "(see https://demo-portals.smarthealth.cards/VerifierPortal.html or https://github.com/smart-on-fhir/health-cards-dev-tools) (Issuer = '"+jwt.getPayload().asString("iss")+"')", IssueSeverity.INFORMATION);
checkProperty(jwt.getPayload(), prefix+"payload", "nbf", true, "Number"); checkProperty(shc.getErrors(), jwt.getPayload(), prefix+"payload", "nbf", true, "Number");
JsonObject vc = jwt.getPayload().getJsonObject("vc"); JsonObject vc = jwt.getPayload().getJsonObject("vc");
if (vc == null) { if (vc == null) {
logError(ValidationMessage.NO_RULE_DATE, 1, 1, "JWT", IssueType.STRUCTURE, "Unable to find property 'vc' in the payload", IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, 1, 1, "JWT", IssueType.STRUCTURE, "Unable to find property 'vc' in the payload", IssueSeverity.ERROR);
return res; return res;
} }
String path = prefix+"payload.vc"; String path = prefix+"payload.vc";
checkNamedProperties(vc, path, "type", "credentialSubject"); checkNamedProperties(shc.getErrors(), vc, path, "type", "credentialSubject");
if (!checkProperty(vc, path, "type", true, "Array")) { if (!checkProperty(shc.getErrors(), vc, path, "type", true, "Array")) {
return res; return res;
} }
JsonArray type = vc.getJsonArray("type"); JsonArray type = vc.getJsonArray("type");
int i = 0; int i = 0;
for (JsonElement e : type) { for (JsonElement e : type) {
if (e.type() != JsonElementType.STRING) { if (e.type() != JsonElementType.STRING) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), path+".type["+i+"]", IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : String but found "+e.type().toName(), IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, line(e), col(e), path+".type["+i+"]", IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : String but found "+e.type().toName(), IssueSeverity.ERROR);
} else { } else {
types.add(e.asString()); types.add(e.asString());
} }
i++; i++;
} }
if (!types.contains("https://smarthealth.cards#health-card")) { if (!types.contains("https://smarthealth.cards#health-card")) {
logError(ValidationMessage.NO_RULE_DATE, line(vc), col(vc), path, IssueType.STRUCTURE, "Card does not claim to be of type https://smarthealth.cards#health-card, cannot validate", IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, line(vc), col(vc), path, IssueType.STRUCTURE, "Card does not claim to be of type https://smarthealth.cards#health-card, cannot validate", IssueSeverity.ERROR);
return res; return res;
} }
if (!checkProperty(vc, path, "credentialSubject", true, "Object")) { if (!checkProperty(shc.getErrors(), vc, path, "credentialSubject", true, "Object")) {
return res; return res;
} }
JsonObject cs = vc.getJsonObject("credentialSubject"); JsonObject cs = vc.getJsonObject("credentialSubject");
path = path+".credentialSubject"; path = path+".credentialSubject";
if (!checkProperty(cs, path, "fhirVersion", true, "String")) { if (!checkProperty(shc.getErrors(), cs, path, "fhirVersion", true, "String")) {
return res; return res;
} }
JsonElement fv = cs.get("fhirVersion"); JsonElement fv = cs.get("fhirVersion");
if (!VersionUtilities.versionsCompatible(context.getVersion(), fv.asString())) { if (!VersionUtilities.versionsCompatible(context.getVersion(), fv.asString())) {
logError(ValidationMessage.NO_RULE_DATE, line(fv), col(fv), path+".fhirVersion", IssueType.STRUCTURE, "Card claims to be of version "+fv.asString()+", cannot be validated against version "+context.getVersion(), IssueSeverity.ERROR); logError(shc.getErrors(), ValidationMessage.NO_RULE_DATE, line(fv), col(fv), path+".fhirVersion", IssueType.STRUCTURE, "Card claims to be of version "+fv.asString()+", cannot be validated against version "+context.getVersion(), IssueSeverity.ERROR);
return res; return res;
} }
if (!checkProperty(cs, path, "fhirBundle", true, "Object")) { if (!checkProperty(shc.getErrors(), cs, path, "fhirBundle", true, "Object")) {
return res; return res;
} }
// ok. all checks passed, we can now validate the bundle // ok. all checks passed, we can now validate the bundle
Element e = jsonParser.parse(cs.getJsonObject("fhirBundle")); NamedElement bnd = new NamedElement(path, "json", org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(cs.getJsonObject("fhirBundle")));
if (e != null) { res.add(bnd);
res.add(new NamedElement(path, e)); bnd.setElement(jsonParser.parse(bnd.getErrors(), cs.getJsonObject("fhirBundle")));
} }
}
return res; return res;
} }
@Override @Override
public String getImpliedProfile() { public String getImpliedProfile() {
@ -163,27 +169,27 @@ public class SHCParser extends ParserBase {
} }
private boolean checkProperty(JsonObject obj, String path, String name, boolean required, String type) { private boolean checkProperty(List<ValidationMessage> errors, JsonObject obj, String path, String name, boolean required, String type) {
JsonElement e = obj.get(name); JsonElement e = obj.get(name);
if (e != null) { if (e != null) {
String t = e.type().toName(); String t = e.type().toName();
if (!type.equals(t)) { if (!type.equals(t)) {
logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), path+"."+name, IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : "+type+" but found "+t, IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(e), col(e), path+"."+name, IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : "+type+" but found "+t, IssueSeverity.ERROR);
} else { } else {
return true; return true;
} }
} else if (required) { } else if (required) {
logError(ValidationMessage.NO_RULE_DATE, line(obj), col(obj), path, IssueType.STRUCTURE, "Missing Property in JSON Payload: "+name, IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(obj), col(obj), path, IssueType.STRUCTURE, "Missing Property in JSON Payload: "+name, IssueSeverity.ERROR);
} else { } else {
return true; return true;
} }
return false; return false;
} }
private void checkNamedProperties(JsonObject obj, String path, String... names) { private void checkNamedProperties(List<ValidationMessage> errors, JsonObject obj, String path, String... names) {
for (JsonProperty e : obj.getProperties()) { for (JsonProperty e : obj.getProperties()) {
if (!Utilities.existsInList(e.getName(), names)) { if (!Utilities.existsInList(e.getName(), names)) {
logError(ValidationMessage.NO_RULE_DATE, line(e.getValue()), col(e.getValue()), path+"."+e.getName(), IssueType.STRUCTURE, "Unknown Property in JSON Payload", IssueSeverity.WARNING); logError(errors, ValidationMessage.NO_RULE_DATE, line(e.getValue()), col(e.getValue()), path+"."+e.getName(), IssueType.STRUCTURE, "Unknown Property in JSON Payload", IssueSeverity.WARNING);
} }
} }
} }
@ -242,12 +248,12 @@ public class SHCParser extends ParserBase {
return b.toString(); return b.toString();
} }
public JWT decodeJWT(String jwt) throws IOException, DataFormatException { public JWT decodeJWT(List<ValidationMessage> errors, String jwt) throws IOException, DataFormatException {
if (jwt.startsWith("shc:/")) { if (jwt.startsWith("shc:/")) {
jwt = decodeQRCode(jwt); jwt = decodeQRCode(jwt);
} }
if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) { if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) {
logError(ValidationMessage.NO_RULE_DATE, -1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is "+MAX_ALLOWED_SHC_LENGTH+" bytes for a single image - this has "+jwt.length()+" bytes", IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, -1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is "+MAX_ALLOWED_SHC_LENGTH+" bytes for a single image - this has "+jwt.length()+" bytes", IssueSeverity.ERROR);
} }
String[] parts = splitToken(jwt); String[] parts = splitToken(jwt);

View File

@ -0,0 +1,468 @@
package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.DataFormatException;
import java.util.Date;
import java.util.zip.Inflater;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonElementType;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.model.JsonPrimitive;
import org.hl7.fhir.utilities.json.model.JsonProperty;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.crypto.DirectDecrypter;
/**
* this class is actually a smart health link retreiver.
* It's going to parse the link, check it, and then return
* 2 items, the link with validation information in an Element, and the
* parsed whatever that the link pointed to
*
* Error locations in the first item are in the decoded JSON file the URL contains, or 0,0 if not in the json file
* Error locations in the second item are in the decoded payload
*
* @author grahame
*
*/
public class SHLParser extends ParserBase {
private static boolean testMode;
private boolean post = true;
private String url = null;
private byte[] key = null;
private String ct;
public SHLParser(IWorkerContext context) {
super(context);
}
public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
byte[] content = TextFile.streamToBytes(inStream);
List<NamedElement> res = new ArrayList<>();
NamedElement shl = addNamedElement(res, "shl", "txt", content);
String src = TextFile.bytesToString(content);
if (src.startsWith("shlink:/")) {
src = src.substring(8);
} else if (src.contains("#shlink:/")) {
String pfx = src.substring(0, src.indexOf("#shlink:/"));
src = src.substring(src.indexOf("#shlink:/")+9);
if (!Utilities.isAbsoluteUrlLinkable(pfx)) {
logError(shl.getErrors(), "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "if a prefix is present, it must be a URL, not "+pfx, IssueSeverity.ERROR);
}
} else {
logError(shl.getErrors(), "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "This content does not appear to be an Smart Health Link", IssueSeverity.ERROR);
src = null;
}
if (src != null) {
byte[] cntin = Base64.getUrlDecoder().decode(src);
NamedElement json = addNamedElement(res, "json", "json", cntin);
JsonObject j = null;
try {
j = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(cntin);
} catch (Exception e) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json", IssueType.STRUCTURE, "The JSON is not valid: "+e.getMessage(), IssueSeverity.ERROR);
}
if (j != null) {
byte[] cntout = org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j, false);
if (!Arrays.equals(cntin, cntout)) {
logError(shl.getErrors(), "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "The JSON does not seem to be minified properly", IssueSeverity.ERROR);
}
if (checkJson(json.getErrors(), j)) {
HTTPResult cnt = null;
if (post) {
try {
cnt = fetchManifest();
} catch (UnknownHostException e) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json", IssueType.STRUCTURE, "The manifest could not be fetched because the host "+e.getMessage()+" is unknown", IssueSeverity.ERROR);
} catch (Exception e) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json", IssueType.STRUCTURE, "The manifest could not be fetched: "+e.getMessage(), IssueSeverity.ERROR);
}
if (cnt != null) {
if (cnt.getContentType() == null) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.NOTFOUND, "The server did not return a Content-Type header - should be 'application/json'", IssueSeverity.WARNING);
} else if (!"application/json".equals(cnt.getContentType())) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.STRUCTURE, "The server returned the wrong Content-Type header '"+cnt.getContentType()+"' - must be 'application/json'", IssueSeverity.ERROR);
}
checkManifest(res, cnt);
}
} else {
try {
cnt = fetchFile(url+"?recipient=FHIR%20Validator", "application/jose");
} catch (Exception e) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl,json.url", IssueType.STRUCTURE, "The document could not be fetched: "+e.getMessage(), IssueSeverity.ERROR);
}
if (cnt != null) {
if (cnt.getContentType() == null) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.NOTFOUND, "The server did not return a Content-Type header - should be 'application/jose'", IssueSeverity.WARNING);
} else if (!"application/json".equals(cnt.getContentType())) {
logError(json.getErrors(), "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.STRUCTURE, "The server returned the wrong Content-Type header '"+cnt.getContentType()+"' - must be 'application/jose'", IssueSeverity.ERROR);
}
processContent(res, json.getErrors(), "shl.url.fetched()", "document", cnt.getContentAsString(), ct);
}
}
}
}
}
return res;
}
private void checkManifest(List<NamedElement> res, HTTPResult cnt) throws IOException {
NamedElement manifest = addNamedElement(res, "manifest", "json", cnt.getContent());
if (!cnt.getContentType().equals("application/json")) {
logError(manifest.getErrors(), "202-08-31", 1, 1, "manifest", IssueType.STRUCTURE, "The mime type should be application/json not "+cnt.getContentType(), IssueSeverity.ERROR);
} else {
JsonObject j = null;
try {
j = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(cnt.getContent());
} catch (Exception e) {
logError(manifest.getErrors(), "202-08-31", 1, 1, "manifest", IssueType.STRUCTURE, "The JSON is not valid: "+e.getMessage(), IssueSeverity.ERROR);
}
if (j != null) {
for (JsonProperty p : j.getProperties()) {
if (!p.getName().equals("files")) {
logError(manifest.getErrors(), "202-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "manifest."+p.getName(),
IssueType.STRUCTURE, "Unexpected property name "+p.getName(), IssueSeverity.WARNING);
}
}
}
if (j.has("files")) {
JsonElement f = j.get("files");
if (f.isJsonArray()) {
int i = 0;
for (JsonElement e : f.asJsonArray()) {
if (e.isJsonObject()) {
processManifestEntry(res, manifest.getErrors(), e.asJsonObject(), "manifest.files["+i+"]", "files["+i+"]");
} else {
logError(manifest.getErrors(), "202-08-31", e.getStart().getLine(), e.getStart().getCol(), "manifest.files["+i+"]",
IssueType.STRUCTURE, "files must be an object, not a "+f.type().name(), IssueSeverity.ERROR);
}
}
} else {
logError(manifest.getErrors(), "202-08-31", f.getStart().getLine(), f.getStart().getCol(), "manifest.files",
IssueType.STRUCTURE, "files must be an array, not a "+f.type().name(), IssueSeverity.ERROR);
}
} else {
logError(manifest.getErrors(), "202-08-31", j.getStart().getLine(), j.getStart().getCol(), "manifest",
IssueType.STRUCTURE, "files not found", IssueSeverity.WARNING);
}
}
}
private void processManifestEntry(List<NamedElement> res, List<ValidationMessage> errors, JsonObject j, String path, String name) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
for (JsonProperty p : j.getProperties()) {
if (!Utilities.existsInList(p.getName(), "contentType", "location", "embedded")) {
logError(errors, "202-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "manifest."+p.getName(),
IssueType.STRUCTURE, "Unexpected property "+p.getName(), IssueSeverity.WARNING);
}
}
JsonElement cte = j.get("contentType");
JsonElement loce = j.get("location");
JsonElement embe = j.get("embedded");
String ct = null;
if (cte == null) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path, IssueType.STRUCTURE, "contentType not found", IssueSeverity.ERROR);
} else if (!cte.isJsonString()) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path+".contentType", IssueType.STRUCTURE, "contentType must be a string not a "+cte.type().name(), IssueSeverity.ERROR);
} else {
ct = cte.asString();
if (!Utilities.existsInList(ct, "application/smart-health-card", "application/smart-api-access", "application/fhir+json")) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path+".contentType", IssueType.STRUCTURE, "contentType must be one of application/smart-health-card, application/smart-api-access or application/fhir+json", IssueSeverity.ERROR);
ct = null;
}
}
if (loce != null && !loce.isJsonString()) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path+".location", IssueType.STRUCTURE, "location must be a string not a "+loce.type().name(), IssueSeverity.ERROR);
}
if (embe != null && !embe.isJsonString()) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path+".embedded", IssueType.STRUCTURE, "embedded must be a string not a "+embe.type().name(), IssueSeverity.ERROR);
}
if (loce == null && embe == null) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path, IssueType.STRUCTURE, "Found neither a location nor an embedded property", IssueSeverity.ERROR);
} else if (loce != null && embe != null) {
logError(errors, "202-08-31", j.getStart().getLine(), j.getStart().getCol(), path, IssueType.STRUCTURE, "Found both a location nor an embedded property - only one can be present", IssueSeverity.ERROR);
} else if (ct != null) {
if (embe != null) {
processContent(res, errors, path+".embedded", name, embe.asString(), ct);
} else if (loce != null) { // it will be, just removes a warning
HTTPResult cnt = null;
try {
cnt = fetchFile(loce.asString(), "application/jose");
} catch (Exception e) {
logError(errors, "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "The document could not be fetched: "+e.getMessage(), IssueSeverity.ERROR);
}
if (cnt != null) {
if (cnt.getContentType() == null) {
logError(errors, "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.NOTFOUND, "The server did not return a Content-Type header - should be 'application/jose'", IssueSeverity.WARNING);
} else if (!"application/json".equals(cnt.getContentType())) {
logError(errors, "202-08-31", 1, 1, "shl.json.url.fetch()", IssueType.STRUCTURE, "The server returned the wrong Content-Type header '"+cnt.getContentType()+"' - must be 'application/jose'", IssueSeverity.ERROR);
}
processContent(res, errors, path+".url.fetch()", name, cnt.getContentAsString(), ct);
}
}
}
}
private void processContent(List<NamedElement> res, List<ValidationMessage> errors, String path, String name, String jose, String ct) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
NamedElement bin = addNamedElement(res, "encrypted", "jose", TextFile.stringToBytes(jose, false));
byte[] cnt = null;
JWEObject jwe;
try {
jwe = JWEObject.parse(jose);
jwe.decrypt(new DirectDecrypter(key));
cnt = jwe.getPayload().toBytes();
} catch (Exception e) {
logError(bin.getErrors(), "202-08-31", 1, 1, path, IssueType.STRUCTURE, "Decruption failed: "+e.getMessage(), IssueSeverity.ERROR);
}
if (cnt != null) {
switch (ct) {
case "application/smart-health-card":
//a JSON file with a .verifiableCredential array containing SMART Health Card JWS strings, as specified by https://spec.smarthealth.cards#via-file-download.
SHCParser shc = new SHCParser(context);
res.addAll(shc.parse(new ByteArrayInputStream(cnt)));
break;
case "application/fhir+json":
NamedElement doc = addNamedElement(res, name, "json", cnt);
// a JSON file containing any FHIR resource (e.g., an individual resource or a Bundle of resources). Generally this format may not be tamper-proof.
logError(doc.getErrors(), "202-08-31", 1, 1, name, IssueType.STRUCTURE, "Processing content of type 'application/smart-api-access' is not done yet", IssueSeverity.INFORMATION);
break;
case "application/smart-api-access":
doc = addNamedElement(res, name, "api.json", cnt);
// a JSON file with a SMART Access Token Response (see SMART App Launch). Two additional properties are defined:
// aud Required string indicating the FHIR Server Base URL where this token can be used (e.g., "https://server.example.org/fhir")
// query: Optional array of strings acting as hints to the client, indicating queries it might want to make (e.g., ["Coverage?patient=123&_tag=family-insurance"])
logError(doc.getErrors(), "202-08-31", 1, 1, name, IssueType.STRUCTURE, "Processing content of type 'application/smart-api-access' is not done yet", IssueSeverity.INFORMATION);
break;
default:
doc = addNamedElement(res, name, "bin", cnt);
logError(doc.getErrors(), "202-08-31", 1, 1, name, IssueType.STRUCTURE, "The Content-Type '"+ct+"' is not known", IssueSeverity.INFORMATION);
}
}
}
private NamedElement addNamedElement(List<NamedElement> res, String name, String type, byte[] content) {
NamedElement result = new NamedElement(name, type, content);
res.add(result);
return result;
}
private HTTPResult fetchFile(String url, String ct) throws IOException {
SimpleHTTPClient fetcher = new SimpleHTTPClient();
fetcher.addHeader("Accept", ct);
HTTPResult res = fetcher.get(url);
res.checkThrowException();
return res;
}
private HTTPResult fetchManifest() throws IOException {
if (testMode) {
return new HTTPResult(url, 200, "OK", "application/json", TextFile.streamToBytes(TestingUtilities.loadTestResourceStream("validator", "shlink.manifest.json")));
}
SimpleHTTPClient fetcher = new SimpleHTTPClient();
JsonObject j = new JsonObject();
j.add("recipient", "FHIR Validator");
HTTPResult res = fetcher.post(url, "application/json", org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j), "application/json");
res.checkThrowException();
return res;
}
private boolean checkJson(List<ValidationMessage> errors, JsonObject j) {
boolean ok = true;
boolean fUrl = false;
boolean fKey = false;
boolean fCty = false;
boolean hp = false;
boolean hu = false;
for (JsonProperty p : j.getProperties()) {
switch (p.getName()) {
case "url":
fUrl = true;
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "url must be a string", IssueSeverity.ERROR);
ok = false;
} else if (!Utilities.isAbsoluteUrlLinkable(p.getValue().asString())) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "url is not valid: "+p.getValue().asString(), IssueSeverity.ERROR);
ok = false;
} else {
url = p.getValue().asString();
}
break;
case "key":
fKey = true;
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "key must be a string", IssueSeverity.ERROR);
ok = false;
} else if (p.getValue().asString().length() != 43) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "key must contain 43 chars", IssueSeverity.ERROR);
ok = false;
} else {
key = Base64.getUrlDecoder().decode(p.getValue().asString());
}
break;
case "exp":
if (!p.getValue().isJsonNumber()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "exp must be a number", IssueSeverity.ERROR);
} else if (!Utilities.isDecimal(p.getValue().asJsonNumber().getValue(), false)) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "exp must be a valid number", IssueSeverity.ERROR);
} else {
String v = p.getValue().asJsonNumber().getValue();
if (v.contains(".")) {
v = v.substring(0, v.indexOf("."));
}
long epochSecs = Long.valueOf(v);
LocalDateTime date = LocalDateTime.ofEpochSecond(epochSecs, 0, ZoneOffset.UTC);
LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
Duration duration = Duration.between(now, date);
if (date.isBefore(now)) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "The content has expired (by "+Utilities.describeDuration(duration)+")", IssueSeverity.WARNING);
}
}
break;
case "flag":
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "flag must be a string", IssueSeverity.ERROR);
} else {
String flag = p.getValue().asString();
for (char c : flag.toCharArray()) {
switch (c) {
case 'L': // ok
break;
case 'P':
hp = true;
break;
case 'U':
hu = true;
break;
default:
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "Illegal Character "+c+" in flag", IssueSeverity.ERROR);
}
}
if (hu && hp) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "Illegal combination in flag: both P and U are present", IssueSeverity.ERROR);
}
if (hp) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.BUSINESSRULE, "The validator is unable to retrieve the content referred to by the URL because a password is required", IssueSeverity.INFORMATION);
ok = false;
}
if (hu) {
post = false;
}
}
break;
case "label":
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "label must be a string", IssueSeverity.ERROR);
} else if (p.getValue().asString().length() > 80) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "label must be no longer than 80 chars", IssueSeverity.ERROR);
}
break;
case "cty" :
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "cty must be a string", IssueSeverity.ERROR);
} else if (!Utilities.existsInList(p.getValue().asString(), "application/smart-health-card", "application/smart-api-access", "application/fhir+json")) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "cty must be one of 'application/smart-health-card/, 'application/smart-api-access', 'application/fhir+json'", IssueSeverity.ERROR);
} else {
ct = p.getValue().asString();
}
break;
case "v":
if (!p.getValue().isJsonString()) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "v must be a string", IssueSeverity.ERROR);
} else if (p.getValue().asString().length() <= 80) {
logError(errors, "2023-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "if present, v must be '1'", IssueSeverity.ERROR);
}
break;
default:
logError(errors, "202-08-31", p.getValue().getStart().getLine(), p.getValue().getStart().getCol(), "shl."+p.getName(),
IssueType.STRUCTURE, "Illegal property name "+p.getName(), IssueSeverity.ERROR);
}
}
if (hu && !fCty) {
logError(errors, "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "Flag 'U' found, but no 'cty' header which is required for the U flag", IssueSeverity.ERROR);
ok = false;
}
if (!fUrl) {
logError(errors, "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "No url found", IssueSeverity.ERROR);
ok = false;
}
if (!fKey) {
logError(errors, "202-08-31", 1, 1, "shl", IssueType.STRUCTURE, "No key found", IssueSeverity.ERROR);
ok = false;
}
return ok;
}
public void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException {
throw new FHIRFormatError("Writing resources is not supported for the SHL format");
// because then we'd have to try to sign, and we're just not going to be doing that from the element model
}
public static boolean isTestMode() {
return testMode;
}
public static void setTestMode(boolean testMode) {
SHLParser.testMode = testMode;
}
}

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.r5.elementmodel; package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -43,6 +45,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; import org.hl7.fhir.r5.elementmodel.Element.SpecialElement;
import org.hl7.fhir.r5.elementmodel.ParserBase.NamedElement;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
@ -78,53 +81,52 @@ public class TurtleParser extends ParserBase {
super(context); super(context);
} }
@Override @Override
public List<NamedElement> parse(InputStream input) throws IOException, FHIRException { public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRException {
List<NamedElement> res = new ArrayList<>(); byte[] content = TextFile.streamToBytes(inStream);
NamedElement ctxt = new NamedElement("focus", "ttl", content);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
Turtle src = new Turtle(); Turtle src = new Turtle();
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
try { try {
src.parse(TextFile.streamToString(input)); src.parse(TextFile.streamToString(stream));
} catch (Exception e) { } catch (Exception e) {
logError(ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_TURTLE_, e.getMessage()), IssueSeverity.FATAL); logError(ctxt.getErrors(), ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_TURTLE_, e.getMessage()), IssueSeverity.FATAL);
return null; return null;
} }
Element e = parse(src); ctxt.setElement(parse(ctxt.getErrors(), src));
if (e != null) {
res.add(new NamedElement(null, e));
}
} else { } else {
src.parse(TextFile.streamToString(input)); src.parse(TextFile.streamToString(stream));
Element e = parse(src); ctxt.setElement(parse(ctxt.getErrors(), src));
if (e != null) {
res.add(new NamedElement(null, e));
}
} }
List<NamedElement> res = new ArrayList<>();
res.add(ctxt);
return res; return res;
} }
private Element parse(Turtle src) throws FHIRException { private Element parse(List<ValidationMessage> errors, Turtle src) throws FHIRException {
// we actually ignore the stated URL here // we actually ignore the stated URL here
for (TTLComplex cmp : src.getObjects().values()) { for (TTLComplex cmp : src.getObjects().values()) {
for (String p : cmp.getPredicates().keySet()) { for (String p : cmp.getPredicates().keySet()) {
if ((FHIR_URI_BASE + "nodeRole").equals(p) && cmp.getPredicates().get(p).hasValue(FHIR_URI_BASE + "treeRoot")) { if ((FHIR_URI_BASE + "nodeRole").equals(p) && cmp.getPredicates().get(p).hasValue(FHIR_URI_BASE + "treeRoot")) {
return parse(src, cmp); return parse(errors, src, cmp);
} }
} }
} }
// still here: well, we didn't find a start point // still here: well, we didn't find a start point
String msg = "Error parsing Turtle: unable to find any node maked as the entry point (where " + FHIR_URI_BASE + "nodeRole = " + FHIR_URI_BASE + "treeRoot)"; String msg = "Error parsing Turtle: unable to find any node maked as the entry point (where " + FHIR_URI_BASE + "nodeRole = " + FHIR_URI_BASE + "treeRoot)";
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
logError(ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, msg, IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, msg, IssueSeverity.FATAL);
return null; return null;
} else { } else {
throw new FHIRFormatError(msg); throw new FHIRFormatError(msg);
} }
} }
private Element parse(Turtle src, TTLComplex cmp) throws FHIRException { private Element parse(List<ValidationMessage> errors, Turtle src, TTLComplex cmp) throws FHIRException {
TTLObject type = cmp.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type"); TTLObject type = cmp.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type");
if (type == null) { if (type == null) {
logError(ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL);
return null; return null;
} }
if (type instanceof TTLList) { if (type instanceof TTLList) {
@ -137,7 +139,7 @@ public class TurtleParser extends ParserBase {
} }
} }
if (!(type instanceof TTLURL)) { if (!(type instanceof TTLURL)) {
logError(ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL);
return null; return null;
} }
String name = ((TTLURL) type).getUri(); String name = ((TTLURL) type).getUri();
@ -145,19 +147,19 @@ public class TurtleParser extends ParserBase {
name = name.substring(name.lastIndexOf("/")+1); name = name.substring(name.lastIndexOf("/")+1);
String path = "/"+name; String path = "/"+name;
StructureDefinition sd = getDefinition(cmp.getLine(), cmp.getCol(), ns, name); StructureDefinition sd = getDefinition(errors, cmp.getLine(), cmp.getCol(), ns, name);
if (sd == null) if (sd == null)
return null; return null;
Element result = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd)); Element result = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd));
result.markLocation(cmp.getLine(), cmp.getCol()); result.markLocation(cmp.getLine(), cmp.getCol());
result.setType(name); result.setType(name);
parseChildren(src, path, cmp, result, false); parseChildren(errors, src, path, cmp, result, false);
result.numberChildren(); result.numberChildren();
return result; return result;
} }
private void parseChildren(Turtle src, String path, TTLComplex object, Element element, boolean primitive) throws FHIRException { private void parseChildren(List<ValidationMessage> errors, Turtle src, String path, TTLComplex object, Element element, boolean primitive) throws FHIRException {
List<Property> properties = element.getProperty().getChildProperties(element.getName(), null); List<Property> properties = element.getProperty().getChildProperties(element.getName(), null);
Set<String> processed = new HashSet<String>(); Set<String> processed = new HashSet<String>();
@ -170,10 +172,10 @@ public class TurtleParser extends ParserBase {
if (property.isChoice()) { if (property.isChoice()) {
for (TypeRefComponent type : property.getDefinition().getType()) { for (TypeRefComponent type : property.getDefinition().getType()) {
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getCode()); String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getCode());
parseChild(src, object, element, processed, property, path, getFormalName(property, eName)); parseChild(errors, src, object, element, processed, property, path, getFormalName(property, eName));
} }
} else { } else {
parseChild(src, object, element, processed, property, path, getFormalName(property)); parseChild(errors, src, object, element, processed, property, path, getFormalName(property));
} }
} }
@ -182,13 +184,13 @@ public class TurtleParser extends ParserBase {
for (String u : object.getPredicates().keySet()) { for (String u : object.getPredicates().keySet()) {
if (!processed.contains(u)) { if (!processed.contains(u)) {
TTLObject n = object.getPredicates().get(u); TTLObject n = object.getPredicates().get(u);
logError(ValidationMessage.NO_RULE_DATE, n.getLine(), n.getCol(), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PREDICATE_, u), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, n.getLine(), n.getCol(), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PREDICATE_, u), IssueSeverity.ERROR);
} }
} }
} }
} }
private void parseChild(Turtle src, TTLComplex object, Element context, Set<String> processed, Property property, String path, String name) throws FHIRException { private void parseChild(List<ValidationMessage> errors, Turtle src, TTLComplex object, Element context, Set<String> processed, Property property, String path, String name) throws FHIRException {
processed.add(name); processed.add(name);
String npath = path+"/"+property.getName(); String npath = path+"/"+property.getName();
TTLObject e = object.getPredicates().get(FHIR_URI_BASE + name); TTLObject e = object.getPredicates().get(FHIR_URI_BASE + name);
@ -197,22 +199,22 @@ public class TurtleParser extends ParserBase {
if (property.isList() && (e instanceof TTLList)) { if (property.isList() && (e instanceof TTLList)) {
TTLList arr = (TTLList) e; TTLList arr = (TTLList) e;
for (TTLObject am : arr.getList()) { for (TTLObject am : arr.getList()) {
parseChildInstance(src, npath, object, context, property, name, am); parseChildInstance(errors, src, npath, object, context, property, name, am);
} }
} else { } else {
parseChildInstance(src, npath, object, context, property, name, e); parseChildInstance(errors, src, npath, object, context, property, name, e);
} }
} }
private void parseChildInstance(Turtle src, String npath, TTLComplex object, Element element, Property property, String name, TTLObject e) throws FHIRException { private void parseChildInstance(List<ValidationMessage> errors, Turtle src, String npath, TTLComplex object, Element element, Property property, String name, TTLObject e) throws FHIRException {
if (property.isResource()) if (property.isResource())
parseResource(src, npath, object, element, property, name, e); parseResource(errors, src, npath, object, element, property, name, e);
else if (e instanceof TTLComplex) { else if (e instanceof TTLComplex) {
TTLComplex child = (TTLComplex) e; TTLComplex child = (TTLComplex) e;
Element n = new Element(tail(name), property).markLocation(e.getLine(), e.getCol()); Element n = new Element(tail(name), property).markLocation(e.getLine(), e.getCol());
element.getChildren().add(n); element.getChildren().add(n);
if (property.isPrimitive(property.getType(tail(name)))) { if (property.isPrimitive(property.getType(tail(name)))) {
parseChildren(src, npath, child, n, true); parseChildren(errors, src, npath, child, n, true);
TTLObject val = child.getPredicates().get(FHIR_URI_BASE + "value"); TTLObject val = child.getPredicates().get(FHIR_URI_BASE + "value");
if (val != null) { if (val != null) {
if (val instanceof TTLLiteral) { if (val instanceof TTLLiteral) {
@ -221,13 +223,13 @@ public class TurtleParser extends ParserBase {
// todo: check type // todo: check type
n.setValue(value); n.setValue(value);
} else } else
logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_LITERAL_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_LITERAL_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR);
} }
} else } else
parseChildren(src, npath, child, n, false); parseChildren(errors, src, npath, child, n, false);
} else } else
logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_URI_OR_BNODE_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_URI_OR_BNODE_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR);
} }
@ -235,7 +237,7 @@ public class TurtleParser extends ParserBase {
return name.substring(name.lastIndexOf(".")+1); return name.substring(name.lastIndexOf(".")+1);
} }
private void parseResource(Turtle src, String npath, TTLComplex object, Element element, Property property, String name, TTLObject e) throws FHIRException { private void parseResource(List<ValidationMessage> errors, Turtle src, String npath, TTLComplex object, Element element, Property property, String name, TTLObject e) throws FHIRException {
TTLComplex obj; TTLComplex obj;
if (e instanceof TTLComplex) if (e instanceof TTLComplex)
obj = (TTLComplex) e; obj = (TTLComplex) e;
@ -243,7 +245,7 @@ public class TurtleParser extends ParserBase {
String url = ((TTLURL) e).getUri(); String url = ((TTLURL) e).getUri();
obj = src.getObject(url); obj = src.getObject(url);
if (obj == null) { if (obj == null) {
logError(ValidationMessage.NO_RULE_DATE, e.getLine(), e.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.REFERENCE_TO__CANNOT_BE_RESOLVED, url), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, e.getLine(), e.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.REFERENCE_TO__CANNOT_BE_RESOLVED, url), IssueSeverity.FATAL);
return; return;
} }
} else } else
@ -251,7 +253,7 @@ public class TurtleParser extends ParserBase {
TTLObject type = obj.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type"); TTLObject type = obj.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type");
if (type == null) { if (type == null) {
logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL);
return; return;
} }
if (type instanceof TTLList) { if (type instanceof TTLList) {
@ -264,14 +266,14 @@ public class TurtleParser extends ParserBase {
} }
} }
if (!(type instanceof TTLURL)) { if (!(type instanceof TTLURL)) {
logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL); logError(errors, ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL);
return; return;
} }
String rt = ((TTLURL) type).getUri(); String rt = ((TTLURL) type).getUri();
String ns = rt.substring(0, rt.lastIndexOf("/")); String ns = rt.substring(0, rt.lastIndexOf("/"));
rt = rt.substring(rt.lastIndexOf("/")+1); rt = rt.substring(rt.lastIndexOf("/")+1);
StructureDefinition sd = getDefinition(object.getLine(), object.getCol(), ns, rt); StructureDefinition sd = getDefinition(errors, object.getLine(), object.getCol(), ns, rt);
if (sd == null) if (sd == null)
return; return;
@ -279,7 +281,7 @@ public class TurtleParser extends ParserBase {
element.getChildren().add(n); element.getChildren().add(n);
n.updateProperty(new Property(this.context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(n.getProperty()), property); n.updateProperty(new Property(this.context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(n.getProperty()), property);
n.setType(rt); n.setType(rt);
parseChildren(src, npath, obj, n, false); parseChildren(errors, src, npath, obj, n, false);
} }
private String getFormalName(Property property) { private String getFormalName(Property property) {

View File

@ -32,6 +32,7 @@ package org.hl7.fhir.r5.elementmodel;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -45,6 +46,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.utilities.TextFile;
/** /**
* This class provides special support for parsing v2 by the v2 logical model * This class provides special support for parsing v2 by the v2 logical model
@ -452,16 +454,18 @@ public class VerticalBarParser extends ParserBase {
private Delimiters delimiters = new Delimiters(); private Delimiters delimiters = new Delimiters();
@Override @Override
public List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException { public List<NamedElement> parse(InputStream inStream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/v2/StructureDefinition/Message"); StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/v2/StructureDefinition/Message");
Element message = new Element("Message", new Property(context, sd.getSnapshot().getElementFirstRep(), sd)); Element message = new Element("Message", new Property(context, sd.getSnapshot().getElementFirstRep(), sd));
byte[] content = TextFile.streamToBytes(inStream);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
VerticalBarParserReader reader = new VerticalBarParserReader(new BufferedInputStream(stream), charset); VerticalBarParserReader reader = new VerticalBarParserReader(new BufferedInputStream(stream), charset);
preDecode(reader); preDecode(reader);
while (!reader.isFinished()) // && (getOptions().getSegmentLimit() == 0 || getOptions().getSegmentLimit() > message.getSegments().size())) while (!reader.isFinished()) // && (getOptions().getSegmentLimit() == 0 || getOptions().getSegmentLimit() > message.getSegments().size()))
readSegment(message, reader); readSegment(message, reader);
List<NamedElement> res = new ArrayList<>(); List<NamedElement> res = new ArrayList<>();
res.add(new NamedElement(null, message)); res.add(new NamedElement("focus", "hl7", message, content));
return res; return res;
} }

View File

@ -1,5 +1,7 @@
package org.hl7.fhir.r5.elementmodel; package org.hl7.fhir.r5.elementmodel;
import java.io.ByteArrayInputStream;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -64,6 +66,7 @@ import org.hl7.fhir.r5.utils.formats.XmlLocationAnnotator;
import org.hl7.fhir.r5.utils.formats.XmlLocationData; import org.hl7.fhir.r5.utils.formats.XmlLocationData;
import org.hl7.fhir.utilities.ElementDecoration; import org.hl7.fhir.utilities.ElementDecoration;
import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage;
@ -108,8 +111,12 @@ public class XmlParser extends ParserBase {
this.allowXsiLocation = allowXsiLocation; this.allowXsiLocation = allowXsiLocation;
} }
public List<NamedElement> parse(InputStream stream) throws FHIRFormatError, DefinitionException, FHIRException, IOException { public List<NamedElement> parse(InputStream inStream) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
List<NamedElement> res = new ArrayList<>();
byte[] content = TextFile.streamToBytes(inStream);
NamedElement context = new NamedElement("focus", "xml", content);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
Document doc = null; Document doc = null;
try { try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@ -125,11 +132,11 @@ public class XmlParser extends ParserBase {
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
// The SAX interface appears to not work when reporting the correct version/encoding. // The SAX interface appears to not work when reporting the correct version/encoding.
// if we can, we'll inspect the header/encoding ourselves // if we can, we'll inspect the header/encoding ourselves
if (stream.markSupported()) {
stream.mark(1024); stream.mark(1024);
version = checkHeader(stream); version = checkHeader(context.getErrors(), stream);
stream.reset(); stream.reset();
}
// use a slower parser that keeps location data // use a slower parser that keeps location data
TransformerFactory transformerFactory = TransformerFactory.newInstance(); TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer nullTransformer = transformerFactory.newTransformer(); Transformer nullTransformer = transformerFactory.newTransformer();
@ -161,18 +168,17 @@ public class XmlParser extends ParserBase {
if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) { if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) {
int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0); int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0);
int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0); int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0);
logError(ValidationMessage.NO_RULE_DATE, line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL); logError(context.getErrors(), ValidationMessage.NO_RULE_DATE, line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL);
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, 0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL); logError(context.getErrors(), ValidationMessage.NO_RULE_DATE, 0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
} }
doc = null; doc = null;
} }
if (doc != null) { if (doc != null) {
Element e = parse(doc); context.setElement(parse(context.getErrors(), doc));
if (e != null) {
res.add(new NamedElement(null, e));
}
} }
List<NamedElement> res = new ArrayList<>();
res.add(context);
return res; return res;
} }
@ -182,12 +188,12 @@ public class XmlParser extends ParserBase {
src = src.substring(0, src.indexOf(";")).trim(); src = src.substring(0, src.indexOf(";")).trim();
return src; return src;
} }
private void checkForProcessingInstruction(Document document) throws FHIRFormatError { private void checkForProcessingInstruction(List<ValidationMessage> errors, Document document) throws FHIRFormatError {
if (policy == ValidationPolicy.EVERYTHING && FormatUtilities.FHIR_NS.equals(document.getDocumentElement().getNamespaceURI())) { if (policy == ValidationPolicy.EVERYTHING && FormatUtilities.FHIR_NS.equals(document.getDocumentElement().getNamespaceURI())) {
Node node = document.getFirstChild(); Node node = document.getFirstChild();
while (node != null) { while (node != null) {
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE)
logError(ValidationMessage.NO_RULE_DATE, line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage( logError(errors, ValidationMessage.NO_RULE_DATE, line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage(
I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR); I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR);
node = node.getNextSibling(); node = node.getNextSibling();
} }
@ -205,27 +211,27 @@ public class XmlParser extends ParserBase {
return loc == null ? 0 : end ? loc.getEndColumn() : loc.getStartColumn(); return loc == null ? 0 : end ? loc.getEndColumn() : loc.getStartColumn();
} }
public Element parse(Document doc) throws FHIRFormatError, DefinitionException, FHIRException, IOException { public Element parse(List<ValidationMessage> errors, Document doc) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
checkForProcessingInstruction(doc); checkForProcessingInstruction(errors, doc);
org.w3c.dom.Element element = doc.getDocumentElement(); org.w3c.dom.Element element = doc.getDocumentElement();
return parse(element); return parse(errors, element);
} }
public Element parse(org.w3c.dom.Element element) throws FHIRFormatError, DefinitionException, FHIRException, IOException { public Element parse(List<ValidationMessage> errors, org.w3c.dom.Element element) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
String ns = element.getNamespaceURI(); String ns = element.getNamespaceURI();
String name = element.getLocalName(); String name = element.getLocalName();
String path = "/"+pathPrefix(ns)+name; String path = "/"+pathPrefix(ns)+name;
StructureDefinition sd = getDefinition(line(element, false), col(element, false), (ns == null ? "noNamespace" : ns), name); StructureDefinition sd = getDefinition(errors, line(element, false), col(element, false), (ns == null ? "noNamespace" : ns), name);
if (sd == null) if (sd == null)
return null; return null;
Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd)); Element result = new Element(element.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
result.setPath(element.getLocalName()); result.setPath(element.getLocalName());
checkElement(element, path, result.getProperty()); checkElement(errors, element, path, result.getProperty());
result.markLocation(line(element, false), col(element, false)); result.markLocation(line(element, false), col(element, false));
result.setType(element.getLocalName()); result.setType(element.getLocalName());
parseChildren(path, element, result); parseChildren(errors, path, element, result);
result.numberChildren(); result.numberChildren();
return result; return result;
} }
@ -264,33 +270,33 @@ public class XmlParser extends ParserBase {
return true; return true;
} }
private void checkElement(org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError { private void checkElement(List<ValidationMessage> errors, org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError {
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content
logError(ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
String ns = prop.getXmlNamespace(); String ns = prop.getXmlNamespace();
String elementNs = element.getNamespaceURI(); String elementNs = element.getNamespaceURI();
if (elementNs == null) { if (elementNs == null) {
elementNs = "noNamespace"; elementNs = "noNamespace";
} }
if (!elementNs.equals(ns)) if (!elementNs.equals(ns))
logError(ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR);
} }
} }
public Element parse(org.w3c.dom.Element base, String type) throws Exception { public Element parse(List<ValidationMessage> errors, org.w3c.dom.Element base, String type) throws Exception {
StructureDefinition sd = getDefinition(0, 0, FormatUtilities.FHIR_NS, type); StructureDefinition sd = getDefinition(errors, 0, 0, FormatUtilities.FHIR_NS, type);
Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd)); Element result = new Element(base.getLocalName(), new Property(context, sd.getSnapshot().getElement().get(0), sd));
result.setPath(base.getLocalName()); result.setPath(base.getLocalName());
String path = "/"+pathPrefix(base.getNamespaceURI())+base.getLocalName(); String path = "/"+pathPrefix(base.getNamespaceURI())+base.getLocalName();
checkElement(base, path, result.getProperty()); checkElement(errors, base, path, result.getProperty());
result.setType(base.getLocalName()); result.setType(base.getLocalName());
parseChildren(path, base, result); parseChildren(errors, path, base, result);
result.numberChildren(); result.numberChildren();
return result; return result;
} }
private void parseChildren(String path, org.w3c.dom.Element node, Element element) throws FHIRFormatError, FHIRException, IOException, DefinitionException { private void parseChildren(List<ValidationMessage> errors, String path, org.w3c.dom.Element node, Element element) throws FHIRFormatError, FHIRException, IOException, DefinitionException {
// this parsing routine retains the original order in a the XML file, to support validation // this parsing routine retains the original order in a the XML file, to support validation
reapComments(node, element); reapComments(node, element);
List<Property> properties = element.getProperty().getChildProperties(element.getName(), XMLUtil.getXsiType(node)); List<Property> properties = element.getProperty().getChildProperties(element.getName(), XMLUtil.getXsiType(node));
@ -333,7 +339,7 @@ public class XmlParser extends ParserBase {
} }
line = line(nt, end); line = line(nt, end);
col = col(nt, end); col = col(nt, end);
logError(ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(n.getTextContent().trim())), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(n.getTextContent().trim())), IssueSeverity.ERROR);
} }
n = n.getNextSibling(); n = n.getNextSibling();
} }
@ -344,7 +350,7 @@ public class XmlParser extends ParserBase {
Node attr = node.getAttributes().item(i); Node attr = node.getAttributes().item(i);
String value = attr.getNodeValue(); String value = attr.getNodeValue();
if (!validAttrValue(value)) { if (!validAttrValue(value)) {
logError(ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR);
} }
if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) { if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) {
Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI()); Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI());
@ -369,7 +375,7 @@ public class XmlParser extends ParserBase {
ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content
ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so
if (!ok) { if (!ok) {
logError(ValidationMessage.NO_RULE_DATE, line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
} }
} }
} }
@ -397,7 +403,7 @@ public class XmlParser extends ParserBase {
xhtml = xp.parseHtmlNode((org.w3c.dom.Element) child); xhtml = xp.parseHtmlNode((org.w3c.dom.Element) child);
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
for (StringPair s : xp.getValidationIssues()) { for (StringPair s : xp.getValidationIssues()) {
logError("2022-11-17", line(child, false), col(child, false), path, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR); logError(errors, "2022-11-17", line(child, false), col(child, false), path, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR);
} }
} }
} }
@ -412,7 +418,7 @@ public class XmlParser extends ParserBase {
} else { } else {
n.setPath(element.getPath()+"."+property.getName()); n.setPath(element.getPath()+"."+property.getName());
} }
checkElement((org.w3c.dom.Element) child, npath, n.getProperty()); checkElement(errors, (org.w3c.dom.Element) child, npath, n.getProperty());
boolean ok = true; boolean ok = true;
if (property.isChoice()) { if (property.isChoice()) {
if (property.getDefinition().hasRepresentation(PropertyRepresentation.TYPEATTR)) { if (property.getDefinition().hasRepresentation(PropertyRepresentation.TYPEATTR)) {
@ -422,7 +428,7 @@ public class XmlParser extends ParserBase {
xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype"); xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype");
n.setType(xsiType); n.setType(xsiType);
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR);
ok = false; ok = false;
} }
} else { } else {
@ -437,18 +443,18 @@ public class XmlParser extends ParserBase {
element.getChildren().add(n); element.getChildren().add(n);
if (ok) { if (ok) {
if (property.isResource()) if (property.isResource())
parseResource(npath, (org.w3c.dom.Element) child, n, property); parseResource(errors, npath, (org.w3c.dom.Element) child, n, property);
else else
parseChildren(npath, (org.w3c.dom.Element) child, n); parseChildren(errors, npath, (org.w3c.dom.Element) child, n);
} }
} }
} else { } else {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName(), path), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName(), path), IssueSeverity.ERROR);
} }
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){ } else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) { } else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {
logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR);
} }
child = child.getNextSibling(); child = child.getNextSibling();
} }
@ -542,7 +548,7 @@ public class XmlParser extends ParserBase {
throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATE_FORMAT_, fmt)); throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATE_FORMAT_, fmt));
} }
private void parseResource(String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException { private void parseResource(List<ValidationMessage> errors, String string, org.w3c.dom.Element container, Element parent, Property elementProperty) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
org.w3c.dom.Element res = XMLUtil.getFirstChild(container); org.w3c.dom.Element res = XMLUtil.getFirstChild(container);
String name = res.getLocalName(); String name = res.getLocalName();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null)); StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
@ -550,7 +556,7 @@ public class XmlParser extends ParserBase {
throw new FHIRFormatError(context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, res.getLocalName())); throw new FHIRFormatError(context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, res.getLocalName()));
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty); parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
parent.setType(name); parent.setType(name);
parseChildren(res.getLocalName(), res, parent); parseChildren(errors, res.getLocalName(), res, parent);
} }
private void reapComments(org.w3c.dom.Element element, Element context) { private void reapComments(org.w3c.dom.Element element, Element context) {
@ -767,7 +773,7 @@ public class XmlParser extends ParserBase {
} }
} }
private String checkHeader(InputStream stream) throws IOException { private String checkHeader(List<ValidationMessage> errors, InputStream stream) throws IOException {
try { try {
// the stream will either start with the UTF-8 BOF or with <xml // the stream will either start with the UTF-8 BOF or with <xml
int i0 = stream.read(); int i0 = stream.read();
@ -803,7 +809,7 @@ public class XmlParser extends ParserBase {
} }
} }
if (e != null && !"UTF-8".equalsIgnoreCase(e)) { if (e != null && !"UTF-8".equalsIgnoreCase(e)) {
logError(ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, context.formatMessage(I18nConstants.XML_ENCODING_INVALID), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, context.formatMessage(I18nConstants.XML_ENCODING_INVALID), IssueSeverity.ERROR);
} }
i = header.indexOf("version=\""); i = header.indexOf("version=\"");
@ -818,7 +824,7 @@ public class XmlParser extends ParserBase {
return "?xml-p1?"; return "?xml-p1?";
} catch (Exception e) { } catch (Exception e) {
// suppress this error // suppress this error
logError(ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, e.getMessage(), IssueSeverity.ERROR); logError(errors, ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, e.getMessage(), IssueSeverity.ERROR);
} }
return "?xml-p2?"; return "?xml-p2?";
} }

View File

@ -105,7 +105,7 @@ public class CodeSystemUtilities {
@Override @Override
public int compare(ConceptDefinitionComponent o1, ConceptDefinitionComponent o2) { public int compare(ConceptDefinitionComponent o1, ConceptDefinitionComponent o2) {
return o1.getCode().compareToIgnoreCase(o2.getCode()); return o1.hasCode() ? o1.getCode().compareToIgnoreCase(o2.getCode()) : 0;
} }
} }
@ -252,7 +252,7 @@ public class CodeSystemUtilities {
private static String defineProperty(CodeSystem cs, String code, PropertyType pt) { private static String defineProperty(CodeSystem cs, String code, PropertyType pt) {
String url = "http://hl7.org/fhir/concept-properties#"+code; String url = "http://hl7.org/fhir/concept-properties#"+code;
for (PropertyComponent p : cs.getProperty()) { for (PropertyComponent p : cs.getProperty()) {
if (p.getCode().equals(code)) { if (p.hasCode() && p.getCode().equals(code)) {
if (!p.getUri().equals(url)) { if (!p.getUri().equals(url)) {
throw new Error("URI mismatch for code "+code+" url = "+p.getUri()+" vs "+url); throw new Error("URI mismatch for code "+code+" url = "+p.getUri()+" vs "+url);
} }
@ -391,7 +391,7 @@ public class CodeSystemUtilities {
public static void defineCodeSystemProperty(CodeSystem cs, String code, String description, PropertyType type) { public static void defineCodeSystemProperty(CodeSystem cs, String code, String description, PropertyType type) {
for (PropertyComponent p : cs.getProperty()) { for (PropertyComponent p : cs.getProperty()) {
if (p.getCode().equals(code)) if (p.hasCode() && p.getCode().equals(code))
return; return;
} }
cs.addProperty().setCode(code).setDescription(description).setType(type).setUri("http://hl7.org/fhir/concept-properties#"+code); cs.addProperty().setCode(code).setDescription(description).setType(type).setUri("http://hl7.org/fhir/concept-properties#"+code);
@ -466,7 +466,7 @@ public class CodeSystemUtilities {
public static ConceptDefinitionComponent findCode(List<ConceptDefinitionComponent> list, String code) { public static ConceptDefinitionComponent findCode(List<ConceptDefinitionComponent> list, String code) {
for (ConceptDefinitionComponent c : list) { for (ConceptDefinitionComponent c : list) {
if (c.getCode().equals(code)) if (c.hasCode() && c.getCode().equals(code))
return c; return c;
ConceptDefinitionComponent s = findCode(c.getConcept(), code); ConceptDefinitionComponent s = findCode(c.getConcept(), code);
if (s != null) if (s != null)
@ -477,7 +477,7 @@ public class CodeSystemUtilities {
public static ConceptDefinitionComponent findCodeOrAltCode(List<ConceptDefinitionComponent> list, String code, String use) { public static ConceptDefinitionComponent findCodeOrAltCode(List<ConceptDefinitionComponent> list, String code, String use) {
for (ConceptDefinitionComponent c : list) { for (ConceptDefinitionComponent c : list) {
if (c.getCode().equals(code)) if (c.hasCode() && c.getCode().equals(code))
return c; return c;
for (ConceptPropertyComponent p : c.getProperty()) { for (ConceptPropertyComponent p : c.getProperty()) {
if ("alternateCode".equals(p.getCode()) && (use == null || hasUse(p, use)) && p.hasValue() && p.getValue().isPrimitive() && code.equals(p.getValue().primitiveValue())) { if ("alternateCode".equals(p.getCode()) && (use == null || hasUse(p, use)) && p.hasValue() && p.getValue().isPrimitive() && code.equals(p.getValue().primitiveValue())) {
@ -537,29 +537,30 @@ public class CodeSystemUtilities {
public static DataType readProperty(ConceptDefinitionComponent concept, String code) { public static DataType readProperty(ConceptDefinitionComponent concept, String code) {
for (ConceptPropertyComponent p : concept.getProperty()) for (ConceptPropertyComponent p : concept.getProperty())
if (p.getCode().equals(code)) if (p.hasCode() && p.getCode().equals(code))
return p.getValue(); return p.getValue();
return null; return null;
} }
public static ConceptPropertyComponent getProperty(ConceptDefinitionComponent concept, String code) { public static ConceptPropertyComponent getProperty(ConceptDefinitionComponent concept, String code) {
for (ConceptPropertyComponent p : concept.getProperty()) for (ConceptPropertyComponent p : concept.getProperty())
if (p.getCode().equals(code)) if (p.hasCode() && p.getCode().equals(code))
return p; return p;
return null; return null;
} }
public static List<ConceptPropertyComponent> getPropertyValues(ConceptDefinitionComponent concept, String code) { public static List<ConceptPropertyComponent> getPropertyValues(ConceptDefinitionComponent concept, String code) {
List<ConceptPropertyComponent> res = new ArrayList<>(); List<ConceptPropertyComponent> res = new ArrayList<>();
for (ConceptPropertyComponent p : concept.getProperty()) { if (code != null) {
if (p.getCode().equals(code)) { for (ConceptPropertyComponent p : concept.getProperty()) {
res.add(p); if (code.equals(p.getCode())) {
res.add(p);
}
} }
} }
return res; return res;
} }
// see http://hl7.org/fhir/R4/codesystem.html#hierachy // see http://hl7.org/fhir/R4/codesystem.html#hierachy
// returns additional parents not in the heirarchy // returns additional parents not in the heirarchy
public static List<String> getOtherChildren(CodeSystem cs, ConceptDefinitionComponent c) { public static List<String> getOtherChildren(CodeSystem cs, ConceptDefinitionComponent c) {
@ -828,7 +829,7 @@ public class CodeSystemUtilities {
private static String defineProperty(CodeSystem cs, PropertyComponent pd, PropertyType pt) { private static String defineProperty(CodeSystem cs, PropertyComponent pd, PropertyType pt) {
for (PropertyComponent p : cs.getProperty()) { for (PropertyComponent p : cs.getProperty()) {
if (p.getCode().equals(pd.getCode())) { if (p.hasCode() && p.getCode().equals(pd.getCode())) {
if (!p.getUri().equals(pd.getUri())) { if (!p.getUri().equals(pd.getUri())) {
throw new Error("URI mismatch for code "+pd.getCode()+" url = "+p.getUri()+" vs "+pd.getUri()); throw new Error("URI mismatch for code "+pd.getCode()+" url = "+p.getUri()+" vs "+pd.getUri());
} }
@ -846,7 +847,7 @@ public class CodeSystemUtilities {
private static PropertyComponent getPropertyDefinition(CodeSystem cs, ConceptPropertyComponent p) { private static PropertyComponent getPropertyDefinition(CodeSystem cs, ConceptPropertyComponent p) {
for (PropertyComponent t : cs.getProperty()) { for (PropertyComponent t : cs.getProperty()) {
if (t.getCode().equals(p.getCode())) { if (t.hasCode() && t.getCode().equals(p.getCode())) {
return t; return t;
} }
} }
@ -881,7 +882,7 @@ public class CodeSystemUtilities {
public static boolean hasPropertyDef(CodeSystem cs, String property) { public static boolean hasPropertyDef(CodeSystem cs, String property) {
for (PropertyComponent pd : cs.getProperty()) { for (PropertyComponent pd : cs.getProperty()) {
if (pd.getCode().equals(property)) { if (pd.hasCode() && pd.getCode().equals(property)) {
return true; return true;
} }
} }

View File

@ -688,10 +688,10 @@ public class ValueSetValidator extends ValueSetProcessBase {
ConceptDefinitionComponent cc = cs.hasUserData("tx.cs.special") ? ((SpecialCodeSystem) cs.getUserData("tx.cs.special")).findConcept(code) : findCodeInConcept(cs.getConcept(), code.getCode(), allAltCodes); ConceptDefinitionComponent cc = cs.hasUserData("tx.cs.special") ? ((SpecialCodeSystem) cs.getUserData("tx.cs.special")).findConcept(code) : findCodeInConcept(cs.getConcept(), code.getCode(), allAltCodes);
if (cc == null) { if (cc == null) {
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) { if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_FRAGMENT, code.getCode(), cs.getUrl()); String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_FRAGMENT, code.getCode(), cs.getVersionedUrl());
return new ValidationResult(IssueSeverity.WARNING, msg, makeIssue(IssueSeverity.ERROR, IssueType.CODEINVALID, path+".code", msg)); return new ValidationResult(IssueSeverity.WARNING, msg, makeIssue(IssueSeverity.ERROR, IssueType.CODEINVALID, path+".code", msg));
} else { } else {
String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_, code.getCode(), cs.getUrl()); String msg = context.formatMessage(I18nConstants.UNKNOWN_CODE__IN_, code.getCode(), cs.getVersionedUrl());
return new ValidationResult(IssueSeverity.ERROR, msg, makeIssue(IssueSeverity.ERROR, IssueType.CODEINVALID, path+".code", msg)); return new ValidationResult(IssueSeverity.ERROR, msg, makeIssue(IssueSeverity.ERROR, IssueType.CODEINVALID, path+".code", msg));
} }
} }

View File

@ -122,6 +122,14 @@ public class CommaSeparatedStringBuilder {
return b.toString(); return b.toString();
} }
public static String join(String sep, String[] list) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(sep);
for (String s : list) {
b.append(s);
}
return b.toString();
}
public static String build(List<String> list) { public static String build(List<String> list) {
CommaSeparatedStringBuilder self = new CommaSeparatedStringBuilder(); CommaSeparatedStringBuilder self = new CommaSeparatedStringBuilder();
for (String s : list) { for (String s : list) {

View File

@ -25,7 +25,7 @@ public class SimpleHTTPClient {
TOKEN TOKEN
} }
public class Header { public static class Header {
private String name; private String name;
private String value; private String value;
public Header(String name, String value) { public Header(String name, String value) {
@ -44,7 +44,7 @@ public class SimpleHTTPClient {
private static final int MAX_REDIRECTS = 5; private static final int MAX_REDIRECTS = 5;
private static int counter = 1; private static int counter = 1;
public class HTTPResult { public static class HTTPResult {
private int code; private int code;
private String contentType; private String contentType;
private byte[] content; private byte[] content;
@ -90,6 +90,10 @@ public class SimpleHTTPClient {
public String getMessage() { public String getMessage() {
return message; return message;
}
public String getContentAsString() {
return new String(content, StandardCharsets.UTF_8);
} }
} }

View File

@ -67,7 +67,22 @@ public class PackageList {
json.set("date", date); json.set("date", date);
} }
public boolean isPartofMainSpec() { public List<String> subPackages() {
List<String> list = new ArrayList<>();
if (json.has("sub-packages")) {
list.addAll(json.getStrings("sub-packages"));
}
return list;
}
public void clearSubPackages() {
json.remove("sub-packages");
}
public void addSubPackage(String s) {
json.forceArray("sub-packages").add(s);
}
private boolean isPartofMainSpec() {
return Utilities.startsWithInList(path(), "http://hl7.org/fhir/DSTU2", "http://hl7.org/fhir/2015Sep", "http://hl7.org/fhir/2015May"); return Utilities.startsWithInList(path(), "http://hl7.org/fhir/DSTU2", "http://hl7.org/fhir/2015Sep", "http://hl7.org/fhir/2015May");
} }

View File

@ -787,22 +787,22 @@ BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU = Entry {0} matches the reference {1} by type
BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU = Entry {0} matches the reference {1} by type and id but it''s fullUrl {2} does not match the full target URL {3} by Bundle resolution rules BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU = Entry {0} matches the reference {1} by type and id but it''s fullUrl {2} does not match the full target URL {3} by Bundle resolution rules
SD_ILLEGAL_CHARACTERISTICS = This element has a {0} but the types {1} do not make this kind of constraint relevant SD_ILLEGAL_CHARACTERISTICS = This element has a {0} but the types {1} do not make this kind of constraint relevant
SD_VALUE_COMPLEX_FIXED = For the complex type {0}, consider using a pattern rather than a fixed value to avoid over-constraining the instance SD_VALUE_COMPLEX_FIXED = For the complex type {0}, consider using a pattern rather than a fixed value to avoid over-constraining the instance
VALUESET_SHAREABLE_MISSING = The ShareableValueSet profile says that the {0} element is mandatory, but it is not present. Published value sets SHOULD conform to the ShareableValueSet profile VALUESET_SHAREABLE_MISSING = Published value sets SHOULD conform to the ShareableValueSet profile, which says that the element ValueSet.{0} is mandatory, but it is not present
VALUESET_SHAREABLE_EXTRA_MISSING = The ShareableValueSet profile recommends that the {0} element is populated, but it is not present. Published value sets SHOULD conform to the ShareableValueSet profile VALUESET_SHAREABLE_EXTRA_MISSING = Published value sets SHOULD conform to the ShareableValueSet profile, which says that the element ValueSet.{0} should be present, but it is not
VALUESET_SHAREABLE_MISSING_HL7 = The ShareableValueSet profile says that the {0} element is mandatory, but it is not found. HL7 Published value sets SHALL conform to the ShareableValueSet profile VALUESET_SHAREABLE_MISSING_HL7 = Published value sets SHALL conform to the ShareableValueSet profile, which says that the element ValueSet.{0} is mandatory, but it is not present
VALUESET_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableValueSet profile recommends that the {0} element is populated, but it is not found. HL7 Published value sets SHALL conform to the ShareableValueSet profile VALUESET_SHAREABLE_EXTRA_MISSING_HL7 = Published value sets SHALL conform to the ShareableValueSet profile, which says that the element ValueSet.{0} should be present, but it is not
CODESYSTEM_SHAREABLE_MISSING = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not present. Published code systems SHOULD conform to the ShareableCodeSystem profile CODESYSTEM_SHAREABLE_MISSING = Published code systems SHOULD conform to the ShareableCodeSystem profile, which says that the element CodeSystem.{0} is mandatory, but it is not present
CODESYSTEM_SHAREABLE_EXTRA_MISSING = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not present. Published code systems SHOULD conform to the ShareableCodeSystem profile CODESYSTEM_SHAREABLE_EXTRA_MISSING = Published code systems SHOULD conform to the ShareableCodeSystem profile, which says that the element CodeSystem.{0} should be present, but it is not
CODESYSTEM_SHAREABLE_MISSING_HL7 = The ShareableCodeSystem profile says that the {0} element is mandatory, but it is not found. HL7 Published code systems SHALL conform to the ShareableCodeSystem profile CODESYSTEM_SHAREABLE_MISSING_HL7 = Published code systems SHALL conform to the ShareableCodeSystem profile, which says that the element CodeSystem.{0} is mandatory, but it is not present
CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableCodeSystem profile recommends that the {0} element is populated, but it is not found. HL7 Published code systems SHALL conform to the ShareableCodeSystem profile CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7 = Published code systems SHALL conform to the ShareableCodeSystem profile, which says that the element CodeSystem.{0} should be present, but it is not
CONCEPTMAP_SHAREABLE_MISSING = The ShareableConceptMap profile says that the {0} element is mandatory, but it is not present. Published concept maps SHOULD conform to the ShareableConceptMap profile CONCEPTMAP_SHAREABLE_MISSING = Published concept maps SHOULD conform to the ShareableConceptMap profile, which says that the element ConceptMap.{0} is mandatory, but it is not present
CONCEPTMAP_SHAREABLE_EXTRA_MISSING = The ShareableConceptMap profile recommends that the {0} element is populated, but it is not present. Published concept maps SHOULD conform to the ShareableConceptMap profile CONCEPTMAP_SHAREABLE_EXTRA_MISSING = Published concept maps SHOULD conform to the ShareableConceptMap profile, which says that the element ConceptMap.{0} should be present, but it is not
CONCEPTMAP_SHAREABLE_MISSING_HL7 = The ShareableConceptMap profile says that the {0} element is mandatory, but it is not found. HL7 Published concept maps SHALL conform to the ShareableConceptMap profile CONCEPTMAP_SHAREABLE_MISSING_HL7 = Published concept maps SHALL conform to the ShareableConceptMap profile, which says that the element ConceptMap.{0} is mandatory, but it is not present
CONCEPTMAP_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableConceptMap profile recommends that the {0} element is populated, but it is not found. HL7 Published concept maps SHALL conform to the ShareableConceptMap profile CONCEPTMAP_SHAREABLE_EXTRA_MISSING_HL7 = Published concept maps SHALL conform to the ShareableConceptMap profile, which says that the element ConceptMap.{0} should be present, but it is not
MEASURE_SHAREABLE_MISSING = The ShareableMeasure profile says that the {0} element is mandatory, but it is not present. Published measures SHOULD conform to the ShareableMeasure profile MEASURE_SHAREABLE_MISSING = Published measures SHOULD conform to the ShareableMeasure profile, which says that the element Measure.{0} is mandatory, but it is not present
MEASURE_SHAREABLE_EXTRA_MISSING = The ShareableMeasure profile recommends that the {0} element is populated, but it is not present. Published measures SHOULD conform to the ShareableMeasure profile MEASURE_SHAREABLE_EXTRA_MISSING = Published measures SHOULD conform to the ShareableMeasure profile, which says that the element Measure.{0} should be present, but it is not
MEASURE_SHAREABLE_MISSING_HL7 = The ShareableMeasure profile says that the {0} element is mandatory, but it is not found. HL7 Published measures SHALL conform to the ShareableMeasure profile MEASURE_SHAREABLE_MISSING_HL7 = Published measures SHALL conform to the ShareableMeasure profile, which says that the element Measure.{0} is mandatory, but it is not present
MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = The ShareableMeasure profile recommends that the {0} element is populated, but it is not found. HL7 Published measures SHALL conform to the ShareableMeasure profile MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = Published measures SHALL conform to the ShareableMeasure profile, which says that the element Measure.{0} should be present, but it is not
TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML = The markdown contains content that appears to be an embedded HTML tag starting at ''{0}''. This will (or SHOULD) be escaped by the presentation layer. The content should be checked to confirm that this is the desired behaviour TYPE_SPECIFIC_CHECKS_DT_MARKDOWN_HTML = The markdown contains content that appears to be an embedded HTML tag starting at ''{0}''. This will (or SHOULD) be escaped by the presentation layer. The content should be checked to confirm that this is the desired behaviour
TYPE_SPECIFIER_ILLEGAL_TYPE = The Type specifier {1} specified an invalid type {0} TYPE_SPECIFIER_ILLEGAL_TYPE = The Type specifier {1} specified an invalid 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}

View File

@ -69,6 +69,9 @@ public class ResourceChecker {
if (src.startsWith("shc:/")) { if (src.startsWith("shc:/")) {
return FhirFormat.SHC; return FhirFormat.SHC;
} }
if (src.startsWith("shlink:/") || src.contains("#shlink:/")) {
return FhirFormat.SHL;
}
} catch (Exception e) { } catch (Exception e) {
} }
return Manager.FhirFormat.TEXT; return Manager.FhirFormat.TEXT;
@ -101,9 +104,13 @@ public class ResourceChecker {
} }
try { try {
String s = new String(cnt, StandardCharsets.UTF_8); String s = new String(cnt, StandardCharsets.UTF_8);
if (s.startsWith("shc:/")) if (s.startsWith("shlink:/") || s.contains("#shlink:/")) {
return FhirFormat.SHL;
}
if (s.startsWith("shc:/")) {
s = SHCParser.decodeQRCode(s); s = SHCParser.decodeQRCode(s);
JWT jwt = new SHCParser(context).decodeJWT(s); }
JWT jwt = new SHCParser(context).decodeJWT(null, s);
return Manager.FhirFormat.SHC; return Manager.FhirFormat.SHC;
} catch (Exception e) { } catch (Exception e) {
if (debug) { if (debug) {

View File

@ -700,7 +700,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (sourceSD.getKind() == StructureDefinition.StructureDefinitionKind.LOGICAL) { if (sourceSD.getKind() == StructureDefinition.StructureDefinitionKind.LOGICAL) {
parser.setLogical(sourceSD); parser.setLogical(sourceSD);
} }
org.hl7.fhir.r5.elementmodel.Element src = parser.parseSingle(new ByteArrayInputStream(source.getBytes())); org.hl7.fhir.r5.elementmodel.Element src = parser.parseSingle(new ByteArrayInputStream(source.getBytes()), null);
scu.transform(null, src, map, resource); scu.transform(null, src, map, resource);
resource.populatePaths(null); resource.populatePaths(null);
return resource; return resource;

View File

@ -283,6 +283,24 @@ public class ValidatorCli {
res.add("hl7.fhir.uv.ips#1.1.0"); res.add("hl7.fhir.uv.ips#1.1.0");
res.add("-profile"); res.add("-profile");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips"); res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips");
res.add("-extension");
res.add("any");
res.add("-bundle");
res.add("Composition:0");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Composition-uv-ips");
} else if (a.equals("-ips:au")) {
res.add("-version");
res.add("4.0");
res.add("-check-ips-codes");
res.add("-ig");
res.add("hl7.fhir.au.ips#current");
res.add("-profile");
res.add("http://hl7.org.au/fhir/ips/StructureDefinition/Bundle-au-ips");
res.add("-extension");
res.add("any");
res.add("-bundle");
res.add("Composition:0");
res.add("http://hl7.org.au/fhir/ips/StructureDefinition/Composition-au-ips");
} else if (a.equals("-ips#")) { } else if (a.equals("-ips#")) {
res.add("-version"); res.add("-version");
res.add("4.0"); res.add("4.0");
@ -291,6 +309,11 @@ public class ValidatorCli {
res.add("hl7.fhir.uv.ips#"+a.substring(5)); res.add("hl7.fhir.uv.ips#"+a.substring(5));
res.add("-profile"); res.add("-profile");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips"); res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips");
res.add("-extension");
res.add("any");
res.add("-bundle");
res.add("Composition:0");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Composition-uv-ips");
} else if (a.startsWith("-ips$")) { } else if (a.startsWith("-ips$")) {
res.add("-version"); res.add("-version");
res.add("4.0"); res.add("4.0");
@ -299,6 +322,11 @@ public class ValidatorCli {
res.add("hl7.fhir.uv.ips#current$"+a.substring(5)); res.add("hl7.fhir.uv.ips#current$"+a.substring(5));
res.add("-profile"); res.add("-profile");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips"); res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips");
res.add("-extension");
res.add("any");
res.add("-bundle");
res.add("Composition:0");
res.add("http://hl7.org/fhir/uv/ips/StructureDefinition/Composition-uv-ips");
} else { } else {
res.add(a); res.add(a);
} }

View File

@ -176,6 +176,7 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkDownProcessor; import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.SIDUtilities; import org.hl7.fhir.utilities.SIDUtilities;
import org.hl7.fhir.utilities.StandardsStatus; import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.UnicodeUtilities; import org.hl7.fhir.utilities.UnicodeUtilities;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.Utilities.DecimalStatus; import org.hl7.fhir.utilities.Utilities.DecimalStatus;
@ -269,6 +270,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
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 static final boolean DEBUG_ELEMENT = false;
private static final boolean SAVE_INTERMEDIARIES = false; // set this to true to get the intermediary formats while we are waiting for a UI around this z(SHC/SHL)
private static final HashSet<String> NO_TX_SYSTEM_EXEMPT = new HashSet<>(Arrays.asList("http://loinc.org", "http://unitsofmeasure.org", "http://hl7.org/fhir/sid/icd-9-cm", "http://snomed.info/sct", "http://www.nlm.nih.gov/research/umls/rxnorm")); private static final HashSet<String> NO_TX_SYSTEM_EXEMPT = new HashSet<>(Arrays.asList("http://loinc.org", "http://unitsofmeasure.org", "http://hl7.org/fhir/sid/icd-9-cm", "http://snomed.info/sct", "http://www.nlm.nih.gov/research/umls/rxnorm"));
private static final HashSet<String> NO_HTTPS_LIST = new HashSet<>(Arrays.asList("https://loinc.org", "https://unitsofmeasure.org", "https://snomed.info/sct", "https://www.nlm.nih.gov/research/umls/rxnorm")); private static final HashSet<String> NO_HTTPS_LIST = new HashSet<>(Arrays.asList("https://loinc.org", "https://unitsofmeasure.org", "https://snomed.info/sct", "https://www.nlm.nih.gov/research/umls/rxnorm"));
@ -514,6 +516,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private Map<String, CanonicalResourceLookupResult> crLookups = new HashMap<>(); private Map<String, CanonicalResourceLookupResult> crLookups = new HashMap<>();
private boolean logProgress; private boolean logProgress;
private CodingsObserver codingObserver; private CodingsObserver codingObserver;
public List<NamedElement> validatedContent;
public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) { public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) {
super(theContext, xverManager, false); super(theContext, xverManager, false);
@ -724,7 +727,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (parser instanceof XmlParser) { if (parser instanceof XmlParser) {
((XmlParser) parser).setAllowXsiLocation(allowXsiLocation); ((XmlParser) parser).setAllowXsiLocation(allowXsiLocation);
} }
parser.setupValidation(ValidationPolicy.EVERYTHING, errors); parser.setupValidation(ValidationPolicy.EVERYTHING);
if (parser instanceof XmlParser) { if (parser instanceof XmlParser) {
((XmlParser) parser).setAllowXsiLocation(allowXsiLocation); ((XmlParser) parser).setAllowXsiLocation(allowXsiLocation);
} }
@ -732,14 +735,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
((JsonParser) parser).setAllowComments(allowComments); ((JsonParser) parser).setAllowComments(allowComments);
} }
long t = System.nanoTime(); long t = System.nanoTime();
List<NamedElement> list = null; validatedContent = null;
try { try {
list = parser.parse(stream); validatedContent = parser.parse(stream);
} catch (IOException e1) { } catch (IOException e1) {
throw new FHIRException(e1); throw new FHIRException(e1);
} }
timeTracker.load(t); timeTracker.load(t);
if (list != null && !list.isEmpty()) { if (validatedContent != null && !validatedContent.isEmpty()) {
if (SAVE_INTERMEDIARIES) {
int index = 0;
for (NamedElement ne : validatedContent) {
index++;
saveValidatedContent(ne, index);
}
}
String url = parser.getImpliedProfile(); String url = parser.getImpliedProfile();
if (url != null) { if (url != null) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
@ -749,11 +759,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
profiles.add(sd); profiles.add(sd);
} }
} }
for (NamedElement ne : list) { for (NamedElement ne : validatedContent) {
validate(appContext, errors, ne.getName(), ne.getElement(), profiles); if (ne.getElement() != null) {
validate(appContext, ne.getErrors(), validatedContent.size() > 1 ? ne.getName() : null, ne.getElement(), profiles);
}
errors.addAll(ne.getErrors());
} }
} }
return (list == null || list.isEmpty()) ? null : list.get(0).getElement(); // todo: this is broken, but fixing it really complicates things elsewhere, so we do this for now return (validatedContent == null || validatedContent.isEmpty()) ? null : validatedContent.get(0).getElement(); // todo: this is broken, but fixing it really complicates things elsewhere, so we do this for now
}
private void saveValidatedContent(NamedElement ne, int index) {
String tgt = null;
try {
tgt = Utilities.path("[tmp]", "validator", "content");
Utilities.createDirectory(tgt);
tgt = Utilities.path(tgt, "content-"+index+"-"+ne.getFilename());
TextFile.bytesToFile(ne.getContent(), tgt);
} catch (Exception e) {
System.out.println("Error saving internal content to '"+tgt+"': "+e.getLocalizedMessage());
}
} }
@Override @Override
@ -796,11 +822,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
@Override @Override
public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, org.w3c.dom.Element element, List<StructureDefinition> profiles) throws FHIRException { public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, org.w3c.dom.Element element, List<StructureDefinition> profiles) throws FHIRException {
XmlParser parser = new XmlParser(context); XmlParser parser = new XmlParser(context);
parser.setupValidation(ValidationPolicy.EVERYTHING, errors); parser.setupValidation(ValidationPolicy.EVERYTHING);
long t = System.nanoTime(); long t = System.nanoTime();
Element e; Element e;
try { try {
e = parser.parse(element); e = parser.parse(errors, element);
} catch (IOException e1) { } catch (IOException e1) {
throw new FHIRException(e1); throw new FHIRException(e1);
} }
@ -828,11 +854,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
@Override @Override
public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, Document document, List<StructureDefinition> profiles) throws FHIRException { public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, Document document, List<StructureDefinition> profiles) throws FHIRException {
XmlParser parser = new XmlParser(context); XmlParser parser = new XmlParser(context);
parser.setupValidation(ValidationPolicy.EVERYTHING, errors); parser.setupValidation(ValidationPolicy.EVERYTHING);
long t = System.nanoTime(); long t = System.nanoTime();
Element e; Element e;
try { try {
e = parser.parse(document); e = parser.parse(errors, document);
} catch (IOException e1) { } catch (IOException e1) {
throw new FHIRException(e1); throw new FHIRException(e1);
} }
@ -859,9 +885,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
@Override @Override
public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, JsonObject object, List<StructureDefinition> profiles) throws FHIRException { public org.hl7.fhir.r5.elementmodel.Element validate(Object appContext, List<ValidationMessage> errors, JsonObject object, List<StructureDefinition> profiles) throws FHIRException {
JsonParser parser = new JsonParser(context, new ProfileUtilities(context, null, null, fpe)); JsonParser parser = new JsonParser(context, new ProfileUtilities(context, null, null, fpe));
parser.setupValidation(ValidationPolicy.EVERYTHING, errors); parser.setupValidation(ValidationPolicy.EVERYTHING);
long t = System.nanoTime(); long t = System.nanoTime();
Element e = parser.parse(object); Element e = parser.parse(errors, object);
timeTracker.load(t); timeTracker.load(t);
if (e != null) if (e != null)
validate(appContext, errors, null, e, profiles); validate(appContext, errors, null, e, profiles);
@ -4982,6 +5008,30 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
pct.done(); pct.done();
} }
if (defn.hasExtension(ToolingExtensions.EXT_SD_IMPOSE_PROFILE)) {
for (Extension ext : defn.getExtensionsByUrl(ToolingExtensions.EXT_SD_IMPOSE_PROFILE)) {
StructureDefinition sdi = context.fetchResource(StructureDefinition.class, ext.getValue().primitiveValue());
if (sdi == null) {
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), defn.getVersionedUrl());
} else {
if (crumbTrails) {
element.addMessage(signpost(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_DEP, sdi.getUrl(), defn.getVersionedUrl()));
}
stack.resetIds();
if (pctOwned) {
pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sdi.getUrl(), logProgress);
}
ok = startInner(hostContext, errors, resource, element, sdi, stack, false, pct, mode.withSource(ProfileSource.ProfileDependency)) && ok;
if (pctOwned) {
pct.done();
}
}
}
}
Element meta = element.getNamedChild(META); Element meta = element.getNamedChild(META);
if (meta != null) { if (meta != null) {
List<Element> profiles = new ArrayList<Element>(); List<Element> profiles = new ArrayList<Element>();

View File

@ -348,7 +348,7 @@ public class R4R5MapTester implements IValidatorResourceFetcher {
private int testRoundTrip(JsonObject json, StructureDefinition sd, StructureDefinition tsd, ResolvedGroup tgtG, ResolvedGroup srcG, Stats stats, InputStream stream, String code) throws FHIRFormatError, DefinitionException, FHIRException, IOException { private int testRoundTrip(JsonObject json, StructureDefinition sd, StructureDefinition tsd, ResolvedGroup tgtG, ResolvedGroup srcG, Stats stats, InputStream stream, String code) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
stats.example(); stats.example();
Element r4 = new org.hl7.fhir.r5.elementmodel.JsonParser(context).setLogical(tsd).parseSingle(stream); Element r4 = new org.hl7.fhir.r5.elementmodel.JsonParser(context).setLogical(tsd).parseSingle(stream, null);
stats.parsed(); stats.parsed();
int elementCountBefore = r4.countDescendents()+1; int elementCountBefore = r4.countDescendents()+1;
String id = r4.getIdBase(); String id = r4.getIdBase();

View File

@ -21,9 +21,9 @@ public class GeneralTests {
org.hl7.fhir.r5.elementmodel.XmlParser xp = new org.hl7.fhir.r5.elementmodel.XmlParser(TestingUtilities.getSharedWorkerContext()); org.hl7.fhir.r5.elementmodel.XmlParser xp = new org.hl7.fhir.r5.elementmodel.XmlParser(TestingUtilities.getSharedWorkerContext());
xp.setAllowXsiLocation(true); xp.setAllowXsiLocation(true);
List<ValidationMessage> errorList = new ArrayList<>(); List<ValidationMessage> errorList = new ArrayList<>();
xp.setupValidation(ValidationPolicy.EVERYTHING, errorList); xp.setupValidation(ValidationPolicy.EVERYTHING);
try { try {
Object resource = xp.parse(stream); xp.parseSingle(stream, errorList);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -34,6 +34,7 @@ import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Manager; import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.elementmodel.ObjectConverter; import org.hl7.fhir.r5.elementmodel.ObjectConverter;
import org.hl7.fhir.r5.elementmodel.SHLParser;
import org.hl7.fhir.r5.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.formats.XmlParser;
@ -170,6 +171,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
TestingUtilities.injectCorePackageLoader(); TestingUtilities.injectCorePackageLoader();
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
// SHLParser.setTestMode(true);
long setup = System.nanoTime(); long setup = System.nanoTime();
logOutput("---- " + name + " ---------------------------------------------------------------- ("+System.getProperty("java.vm.name")+")"); logOutput("---- " + name + " ---------------------------------------------------------------- ("+System.getProperty("java.vm.name")+")");
@ -692,16 +694,16 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
if (url.equals("Patient/test")) { if (url.equals("Patient/test")) {
res = new ObjectConverter(vCurr.getContext()).convert(new Patient()); res = new ObjectConverter(vCurr.getContext()).convert(new Patient());
} else if (TestingUtilities.findTestResource("validator", url.replace("/", "-").toLowerCase() + ".json")) { } else if (TestingUtilities.findTestResource("validator", url.replace("/", "-").toLowerCase() + ".json")) {
res = Manager.makeParser(vCurr.getContext(), FhirFormat.JSON).parseSingle(TestingUtilities.loadTestResourceStream("validator", url.replace("/", "-").toLowerCase() + ".json")); res = Manager.makeParser(vCurr.getContext(), FhirFormat.JSON).parseSingle(TestingUtilities.loadTestResourceStream("validator", url.replace("/", "-").toLowerCase() + ".json"), null);
} else if (TestingUtilities.findTestResource("validator", url.replace("/", "-").toLowerCase() + ".xml")) { } else if (TestingUtilities.findTestResource("validator", url.replace("/", "-").toLowerCase() + ".xml")) {
res = Manager.makeParser(vCurr.getContext(), FhirFormat.XML).parseSingle(TestingUtilities.loadTestResourceStream("validator", url.replace("/", "-").toLowerCase() + ".xml")); res = Manager.makeParser(vCurr.getContext(), FhirFormat.XML).parseSingle(TestingUtilities.loadTestResourceStream("validator", url.replace("/", "-").toLowerCase() + ".xml"), null);
} }
if (res == null && url.contains("/")) { if (res == null && url.contains("/")) {
String tail = url.substring(url.indexOf("/") + 1); String tail = url.substring(url.indexOf("/") + 1);
if (TestingUtilities.findTestResource("validator", tail.replace("/", "-").toLowerCase() + ".json")) { if (TestingUtilities.findTestResource("validator", tail.replace("/", "-").toLowerCase() + ".json")) {
res = Manager.makeParser(vCurr.getContext(), FhirFormat.JSON).parseSingle(TestingUtilities.loadTestResourceStream("validator", tail.replace("/", "-").toLowerCase() + ".json")); res = Manager.makeParser(vCurr.getContext(), FhirFormat.JSON).parseSingle(TestingUtilities.loadTestResourceStream("validator", tail.replace("/", "-").toLowerCase() + ".json"), null);
} else if (TestingUtilities.findTestResource("validator", tail.replace("/", "-").toLowerCase() + ".xml")) { } else if (TestingUtilities.findTestResource("validator", tail.replace("/", "-").toLowerCase() + ".xml")) {
res = Manager.makeParser(vCurr.getContext(), FhirFormat.XML).parseSingle(TestingUtilities.loadTestResourceStream("validator", tail.replace("/", "-").toLowerCase() + ".xml")); res = Manager.makeParser(vCurr.getContext(), FhirFormat.XML).parseSingle(TestingUtilities.loadTestResourceStream("validator", tail.replace("/", "-").toLowerCase() + ".xml"), null);
} }
} }
return res; return res;

View File

@ -15,7 +15,6 @@ v: {
"code" : "207", "code" : "207",
"system" : "http://hl7.org/fhir/sid/cvx", "system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406", "version" : "20210406",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -37,7 +36,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'X SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose' for http://hl7.org/fhir/sid/cvx#207 - should be 'SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'X SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose' for http://hl7.org/fhir/sid/cvx#207 - should be 'SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -59,7 +57,6 @@ v: {
"code" : "208", "code" : "208",
"system" : "http://hl7.org/fhir/sid/cvx", "system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406", "version" : "20210406",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -81,7 +78,6 @@ v: {
"code" : "208", "code" : "208",
"system" : "http://hl7.org/fhir/sid/cvx", "system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406", "version" : "20210406",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -102,6 +98,225 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unknown Code '209' in the system 'http://hl7.org/fhir/sid/cvx'; The provided code 'http://hl7.org/fhir/sid/cvx#209' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unknown Code '209' in the system 'http://hl7.org/fhir/sid/cvx'; The provided code 'http://hl7.org/fhir/sid/cvx#209' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "115"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "tetanus toxoid, reduced diphtheria toxoid, and acellular pertussis vaccine, adsorbed",
"code" : "115",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "10"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "poliovirus vaccine, inactivated",
"code" : "10",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "85"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "hepatitis A vaccine, unspecified formulation",
"code" : "85",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "25"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "typhoid vaccine, live, oral",
"code" : "25",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "37"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "yellow fever vaccine",
"code" : "37",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "185"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Seasonal, quadrivalent, recombinant, injectable influenza vaccine, preservative free",
"code" : "185",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "150"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Influenza, injectable, quadrivalent, preservative free",
"code" : "150",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "207"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose",
"code" : "207",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "171"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Influenza, injectable, Madin Darby Canine Kidney, preservative free, quadrivalent",
"code" : "171",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://hl7.org/fhir/sid/cvx",
"code" : "88"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "influenza virus vaccine, unspecified formulation",
"code" : "88",
"system" : "http://hl7.org/fhir/sid/cvx",
"version" : "20210406",
"unknown-systems" : "", "unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"

View File

@ -15,6 +15,28 @@ v: {
"code" : "20049000", "code" : "20049000",
"system" : "http://standardterms.edqm.eu", "system" : "http://standardterms.edqm.eu",
"version" : "5 March 2019", "version" : "5 March 2019",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://standardterms.edqm.eu",
"code" : "20053000",
"display" : "Oral use"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Oral use",
"code" : "20053000",
"system" : "http://standardterms.edqm.eu",
"version" : "5 March 2019",
"unknown-systems" : "", "unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"

View File

@ -15,7 +15,6 @@ v: {
"code" : "NO", "code" : "NO",
"system" : "urn:iso:std:iso:3166", "system" : "urn:iso:std:iso:3166",
"version" : "2018", "version" : "2018",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -37,7 +36,6 @@ v: {
"code" : "US", "code" : "US",
"system" : "urn:iso:std:iso:3166", "system" : "urn:iso:std:iso:3166",
"version" : "2018", "version" : "2018",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -59,7 +57,6 @@ v: {
"code" : "US", "code" : "US",
"system" : "urn:iso:std:iso:3166", "system" : "urn:iso:std:iso:3166",
"version" : "2018", "version" : "2018",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -81,6 +78,27 @@ v: {
"code" : "NO", "code" : "NO",
"system" : "urn:iso:std:iso:3166", "system" : "urn:iso:std:iso:3166",
"version" : "2018", "version" : "2018",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "urn:iso:std:iso:3166",
"code" : "NO",
"display" : "Alderney"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"severity" : "error",
"error" : "Wrong Display Name 'Alderney' for urn:iso:std:iso:3166#NO - should be 'Norway' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN",
"unknown-systems" : "", "unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"

View File

@ -15,7 +15,6 @@ v: {
"code" : "1000990", "code" : "1000990",
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm", "system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"version" : "??", "version" : "??",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -38,7 +37,6 @@ v: {
"code" : "1010603", "code" : "1010603",
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm", "system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"version" : "??", "version" : "??",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -61,7 +59,6 @@ v: {
"code" : "1298088", "code" : "1298088",
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm", "system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"version" : "??", "version" : "??",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -84,7 +81,6 @@ v: {
"code" : "1010600", "code" : "1010600",
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm", "system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"version" : "??", "version" : "??",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -106,6 +102,27 @@ v: {
"code" : "1591957", "code" : "1591957",
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm", "system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"version" : "??", "version" : "??",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://www.nlm.nih.gov/research/umls/rxnorm",
"code" : "617311",
"display" : "atorvastatin 40mg Oral Tablet"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"severity" : "error",
"error" : "Wrong Display Name 'atorvastatin 40mg Oral Tablet' for http://www.nlm.nih.gov/research/umls/rxnorm#617311 - should be one of 3 choices: 'atorvastatin 40 MG Oral Tablet', 'atorvastatin (as atorvastatin calcium) 40 MG Oral Tablet' or 'atorvastatin calcium 40 MG Oral Tablet' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN",
"unknown-systems" : "", "unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"

View File

@ -15,7 +15,6 @@ v: {
"code" : "721912009", "code" : "721912009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -38,7 +37,6 @@ v: {
"code" : "91935009", "code" : "91935009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -61,7 +59,6 @@ v: {
"code" : "3718001", "code" : "3718001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -83,7 +80,6 @@ v: {
"code" : "255604002", "code" : "255604002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -106,7 +102,6 @@ v: {
"code" : "255604002", "code" : "255604002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -128,7 +123,6 @@ v: {
"code" : "255604002", "code" : "255604002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -151,7 +145,6 @@ v: {
"code" : "409002", "code" : "409002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -173,7 +166,6 @@ v: {
"code" : "6736007", "code" : "6736007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -195,7 +187,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Moderate' for http://snomed.info/sct#6736007 - should be one of 4 choices: 'Midgrade', 'Moderate (severity modifier) (qualifier value)', 'Moderate (severity modifier)' or 'Moderate severity' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Moderate' for http://snomed.info/sct#6736007 - should be one of 4 choices: 'Midgrade', 'Moderate (severity modifier) (qualifier value)', 'Moderate (severity modifier)' or 'Moderate severity' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -217,7 +208,6 @@ v: {
"code" : "6736007", "code" : "6736007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -240,7 +230,6 @@ v: {
"code" : "437009", "code" : "437009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -263,7 +252,6 @@ v: {
"code" : "9846003", "code" : "9846003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -286,7 +274,6 @@ v: {
"code" : "189009", "code" : "189009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -309,7 +296,6 @@ v: {
"code" : "911003", "code" : "911003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -332,7 +318,6 @@ v: {
"code" : "112144000", "code" : "112144000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -355,7 +340,6 @@ v: {
"code" : "80943009", "code" : "80943009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -378,7 +362,6 @@ v: {
"code" : "77176002", "code" : "77176002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -401,7 +384,6 @@ v: {
"code" : "38341003", "code" : "38341003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -424,7 +406,6 @@ v: {
"code" : "1419004", "code" : "1419004",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome", "resourceType" : "OperationOutcome",
"issue" : [{ "issue" : [{
@ -482,7 +463,6 @@ v: {
"code" : "93880001", "code" : "93880001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -505,7 +485,6 @@ v: {
"code" : "248986005", "code" : "248986005",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -528,7 +507,6 @@ v: {
"code" : "161714006", "code" : "161714006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -551,7 +529,6 @@ v: {
"code" : "161713000", "code" : "161713000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -574,7 +551,6 @@ v: {
"code" : "445872007", "code" : "445872007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -597,7 +573,6 @@ v: {
"code" : "722446000", "code" : "722446000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -620,7 +595,6 @@ v: {
"code" : "371531000", "code" : "371531000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -643,7 +617,6 @@ v: {
"code" : "4241000179101", "code" : "4241000179101",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -666,7 +639,6 @@ v: {
"code" : "422735006", "code" : "422735006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -688,7 +660,6 @@ v: {
"code" : "440545006", "code" : "440545006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -711,7 +682,6 @@ v: {
"code" : "324252006", "code" : "324252006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome", "resourceType" : "OperationOutcome",
"issue" : [{ "issue" : [{
@ -747,7 +717,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Traveller's Diarrhea (disorder)' for http://snomed.info/sct#11840006 - should be one of 4 choices: 'Traveler's diarrhea', 'Turista', 'Traveler's diarrhoea' or 'Traveler's diarrhea (disorder)' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Traveller's Diarrhea (disorder)' for http://snomed.info/sct#11840006 - should be one of 4 choices: 'Traveler's diarrhea', 'Turista', 'Traveler's diarrhoea' or 'Traveler's diarrhea (disorder)' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -770,7 +739,6 @@ v: {
"code" : "21522001", "code" : "21522001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -793,7 +761,6 @@ v: {
"code" : "311504000", "code" : "311504000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -816,7 +783,6 @@ v: {
"code" : "26643006", "code" : "26643006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -839,7 +805,6 @@ v: {
"code" : "421521009", "code" : "421521009",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -862,7 +827,6 @@ v: {
"code" : "602001", "code" : "602001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome", "resourceType" : "OperationOutcome",
"issue" : [{ "issue" : [{
@ -899,7 +863,6 @@ v: {
"code" : "8821006", "code" : "8821006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -921,7 +884,6 @@ v: {
"code" : "112144000", "code" : "112144000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -943,7 +905,6 @@ v: {
"code" : "112144000", "code" : "112144000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -965,7 +926,6 @@ v: {
"code" : "722446000", "code" : "722446000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -987,7 +947,6 @@ v: {
"code" : "722446000", "code" : "722446000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1009,7 +968,6 @@ v: {
"code" : "371531000", "code" : "371531000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1031,7 +989,6 @@ v: {
"code" : "371531000", "code" : "371531000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1053,7 +1010,6 @@ v: {
"code" : "4241000179101", "code" : "4241000179101",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1075,7 +1031,6 @@ v: {
"code" : "4241000179101", "code" : "4241000179101",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1097,7 +1052,6 @@ v: {
"code" : "422735006", "code" : "422735006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1119,7 +1073,6 @@ v: {
"code" : "422735006", "code" : "422735006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1140,7 +1093,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "The provided code 'http://snomed.info/sct#77176002' is not in the value set 'https://mednet.swiss/fhir/ValueSet/mni-obs-bloodGroup--0|0.5.0' (from Tx-Server)", "error" : "The provided code 'http://snomed.info/sct#77176002' is not in the value set 'https://mednet.swiss/fhir/ValueSet/mni-obs-bloodGroup--0|0.5.0' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1161,7 +1113,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "The provided code 'http://snomed.info/sct#38341003' is not in the value set 'https://mednet.swiss/fhir/ValueSet/mni-obs-bloodGroup--0|0.5.0' (from Tx-Server)", "error" : "The provided code 'http://snomed.info/sct#38341003' is not in the value set 'https://mednet.swiss/fhir/ValueSet/mni-obs-bloodGroup--0|0.5.0' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1185,7 +1136,6 @@ v: {
"code" : "454281000124100", "code" : "454281000124100",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/731000124108/version/20230301", "version" : "http://snomed.info/sct/731000124108/version/20230301",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1207,7 +1157,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Progress note' for http://snomed.info/sct#371532007 - should be one of 3 choices: 'Progress report', 'Report of subsequent visit' or 'Progress report (record artifact)' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Progress note' for http://snomed.info/sct#371532007 - should be one of 3 choices: 'Progress report', 'Report of subsequent visit' or 'Progress report (record artifact)' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1230,7 +1179,6 @@ v: {
"code" : "371525003", "code" : "371525003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1252,7 +1200,6 @@ v: {
"code" : "371532007", "code" : "371532007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1274,7 +1221,6 @@ v: {
"code" : "371532007", "code" : "371532007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1296,7 +1242,6 @@ v: {
"code" : "371525003", "code" : "371525003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1318,7 +1263,6 @@ v: {
"code" : "371525003", "code" : "371525003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1341,7 +1285,6 @@ v: {
"code" : "419891008", "code" : "419891008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1364,7 +1307,6 @@ v: {
"code" : "371525003", "code" : "371525003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1387,7 +1329,6 @@ v: {
"code" : "17621005", "code" : "17621005",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1410,7 +1351,6 @@ v: {
"code" : "722172003", "code" : "722172003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1433,7 +1373,6 @@ v: {
"code" : "394609007", "code" : "394609007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1456,7 +1395,6 @@ v: {
"code" : "71388002", "code" : "71388002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1502,7 +1440,6 @@ v: {
"code" : "410534003", "code" : "410534003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1525,7 +1462,6 @@ v: {
"code" : "10828004", "code" : "10828004",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1548,7 +1484,6 @@ v: {
"code" : "233588003", "code" : "233588003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1571,7 +1506,6 @@ v: {
"code" : "324689003", "code" : "324689003",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1594,7 +1528,6 @@ v: {
"code" : "442311008", "code" : "442311008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1617,7 +1550,6 @@ v: {
"code" : "840539006", "code" : "840539006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1639,7 +1571,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'COVID-19' for http://snomed.info/sct#840535000 - should be one of 7 choices: 'Antibody to 2019 novel coronavirus', 'Antibody to 2019-nCoV', 'Antibody to severe acute respiratory syndrome coronavirus 2 (substance)', 'Antibody to severe acute respiratory syndrome coronavirus 2', 'Antibody to SARS-CoV-2', 'Severe acute respiratory syndrome coronavirus 2 Ab' or 'Severe acute respiratory syndrome coronavirus 2 antibody' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'COVID-19' for http://snomed.info/sct#840535000 - should be one of 7 choices: 'Antibody to 2019 novel coronavirus', 'Antibody to 2019-nCoV', 'Antibody to severe acute respiratory syndrome coronavirus 2 (substance)', 'Antibody to severe acute respiratory syndrome coronavirus 2', 'Antibody to SARS-CoV-2', 'Severe acute respiratory syndrome coronavirus 2 Ab' or 'Severe acute respiratory syndrome coronavirus 2 antibody' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1662,7 +1593,6 @@ v: {
"code" : "840535000", "code" : "840535000",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1685,7 +1615,6 @@ v: {
"code" : "32485007", "code" : "32485007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1708,7 +1637,6 @@ v: {
"code" : "32713005", "code" : "32713005",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1730,7 +1658,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 10821000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10821000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10821000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 10821000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10821000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10821000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1752,7 +1679,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Diagnostisk med biopsi' for http://snomed.info/sct#446745002 - should be one of 2 choices: 'Colonoscopy and biopsy of colon (procedure)' or 'Colonoscopy and biopsy of colon' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Diagnostisk med biopsi' for http://snomed.info/sct#446745002 - should be one of 2 choices: 'Colonoscopy and biopsy of colon (procedure)' or 'Colonoscopy and biopsy of colon' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1775,7 +1701,6 @@ v: {
"code" : "73761001", "code" : "73761001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1797,7 +1722,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8921000202108 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8921000202108' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8921000202108' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8921000202108 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8921000202108' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8921000202108' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1819,7 +1743,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8951000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8951000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8951000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8951000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8951000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8951000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1842,7 +1765,6 @@ v: {
"code" : "300577008", "code" : "300577008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1864,7 +1786,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 10291000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10291000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10291000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 10291000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10291000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10291000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1887,7 +1808,6 @@ v: {
"code" : "722818007", "code" : "722818007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1909,7 +1829,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8901000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8901000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8901000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8901000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8901000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8901000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1932,7 +1851,6 @@ v: {
"code" : "10291000132101", "code" : "10291000132101",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1954,7 +1872,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8911000202100 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8911000202100' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8911000202100' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8911000202100 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8911000202100' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8911000202100' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1977,7 +1894,6 @@ v: {
"code" : "10301000132102", "code" : "10301000132102",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -1999,7 +1915,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8891000202103 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8891000202103' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8891000202103' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8891000202103 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8891000202103' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8891000202103' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2022,7 +1937,6 @@ v: {
"code" : "10311000132100", "code" : "10311000132100",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2044,7 +1958,6 @@ v: {
"code" : "10291000132101", "code" : "10291000132101",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2066,7 +1979,6 @@ v: {
"code" : "10301000132102", "code" : "10301000132102",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2088,7 +2000,6 @@ v: {
"code" : "10311000132100", "code" : "10311000132100",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2110,7 +2021,6 @@ v: {
"code" : "246206008", "code" : "246206008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2132,7 +2042,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 15991000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '15991000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#15991000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 15991000202102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '15991000202102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#15991000202102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2154,7 +2063,6 @@ v: {
"code" : "17621005", "code" : "17621005",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2177,7 +2085,6 @@ v: {
"code" : "712510007", "code" : "712510007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2199,7 +2106,6 @@ v: {
"code" : "32485007", "code" : "32485007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2221,7 +2127,6 @@ v: {
"code" : "32713005", "code" : "32713005",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2242,7 +2147,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 10821000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10821000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10821000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 10821000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '10821000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#10821000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2264,7 +2168,6 @@ v: {
"code" : "446745002", "code" : "446745002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2285,7 +2188,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8921000202108 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8921000202108' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8921000202108' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8921000202108 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8921000202108' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8921000202108' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2306,7 +2208,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 8951000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8951000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8951000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 8951000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '8951000202101' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#8951000202101' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2328,7 +2229,6 @@ v: {
"code" : "712510007", "code" : "712510007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2350,7 +2250,6 @@ v: {
"code" : "372756006", "code" : "372756006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2372,7 +2271,6 @@ v: {
"code" : "387458008", "code" : "387458008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2395,7 +2293,6 @@ v: {
"code" : "372756006", "code" : "372756006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2418,7 +2315,6 @@ v: {
"code" : "387458008", "code" : "387458008",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2486,7 +2382,6 @@ v: {
"code" : "276885007", "code" : "276885007",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2509,7 +2404,6 @@ v: {
"code" : "58108001", "code" : "58108001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome", "resourceType" : "OperationOutcome",
"issue" : [{ "issue" : [{
@ -2601,7 +2495,6 @@ v: {
"code" : "119339001", "code" : "119339001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2623,7 +2516,6 @@ v: {
"code" : "5933001", "code" : "5933001",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2691,7 +2583,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Paracetamol 500mg tablets' for http://snomed.info/sct#322236009 - should be one of 3 choices: 'Acetaminophen 500 mg oral tablet', 'Paracetamol 500 mg oral tablet' or 'Product containing precisely paracetamol 500 milligram/1 each conventional release oral tablet (clinical drug)' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Paracetamol 500mg tablets' for http://snomed.info/sct#322236009 - should be one of 3 choices: 'Acetaminophen 500 mg oral tablet', 'Paracetamol 500 mg oral tablet' or 'Product containing precisely paracetamol 500 milligram/1 each conventional release oral tablet (clinical drug)' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2713,7 +2604,6 @@ v: {
"code" : "428673006", "code" : "428673006",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2735,7 +2625,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 35901911000001104 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '35901911000001104' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#35901911000001104' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 35901911000001104 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '35901911000001104' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#35901911000001104' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2757,7 +2646,6 @@ v: {
"code" : "258773002", "code" : "258773002",
"system" : "http://snomed.info/sct", "system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731", "version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2779,7 +2667,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Wrong Display Name 'Ibuprofen 200mg tablets' for http://snomed.info/sct#329652003 - should be one of 2 choices: 'Ibuprofen 200 mg oral tablet' or 'Product containing precisely ibuprofen 200 milligram/1 each conventional release oral tablet (clinical drug)' (for the language(s) '--') (from Tx-Server)", "error" : "Wrong Display Name 'Ibuprofen 200mg tablets' for http://snomed.info/sct#329652003 - should be one of 2 choices: 'Ibuprofen 200 mg oral tablet' or 'Product containing precisely ibuprofen 200 milligram/1 each conventional release oral tablet (clinical drug)' (for the language(s) '--') (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2801,7 +2688,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 39695211000001102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '39695211000001102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#39695211000001102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 39695211000001102 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '39695211000001102' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#39695211000001102' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2823,7 +2709,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 56248011000036107 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '56248011000036107' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#56248011000036107' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 56248011000036107 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '56248011000036107' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#56248011000036107' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2844,7 +2729,6 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 1 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '1' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#1' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 1 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '1' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#1' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"
} }
@ -2865,6 +2749,74 @@ v: {
"severity" : "error", "severity" : "error",
"error" : "Unable to find code 2 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '2' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#2' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)", "error" : "Unable to find code 2 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20230731); Unknown Code '2' in the system 'http://snomed.info/sct'; The provided code 'http://snomed.info/sct#2' is not in the value set 'http://hl7.org/fhir/ValueSet/@all' (from Tx-Server)",
"class" : "UNKNOWN", "class" : "UNKNOWN",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://snomed.info/sct",
"code" : "38341003",
"display" : "HT - Hypertension"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "High blood pressure",
"code" : "38341003",
"system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://snomed.info/sct",
"code" : "42343007",
"display" : "Congestive heart failure"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Congestive heart failure",
"code" : "42343007",
"system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "",
"issues" : {
"resourceType" : "OperationOutcome"
}
}
-------------------------------------------------------------------------------------
{"code" : {
"system" : "http://snomed.info/sct",
"code" : "9014002",
"display" : "Psoriasis"
}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"true", "guessSystem":"false", "valueSetMode":"ALL_CHECKS", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
"resourceType" : "Parameters",
"parameter" : [{
"name" : "profile-url",
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
}]
}}####
v: {
"display" : "Psoriasis",
"code" : "9014002",
"system" : "http://snomed.info/sct",
"version" : "http://snomed.info/sct/900000000000207008/version/20230731",
"unknown-systems" : "", "unknown-systems" : "",
"issues" : { "issues" : {
"resourceType" : "OperationOutcome" "resourceType" : "OperationOutcome"

View File

@ -20,7 +20,7 @@
<properties> <properties>
<guava_version>32.0.1-jre</guava_version> <guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version> <hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.4.1</validator_test_case_version> <validator_test_case_version>1.4.2-SNAPSHOT</validator_test_case_version>
<jackson_version>2.15.2</jackson_version> <jackson_version>2.15.2</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version> <junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version> <junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
@ -283,6 +283,13 @@
<artifactId>xpp3</artifactId> <artifactId>xpp3</artifactId>
<version>1.1.6</version> <version>1.1.6</version>
</dependency> </dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.30.2</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>