Merge master

This commit is contained in:
dotasek 2022-10-31 09:50:26 -04:00
commit 269680608f
7 changed files with 233 additions and 63 deletions

View File

@ -4289,6 +4289,8 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (hasDef && element.getType().size() > 1) { } else if (hasDef && element.getType().size() > 1) {
if (allAreReference(element.getType())) { if (allAreReference(element.getType())) {
row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE); row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE);
} else if (element.hasExtension(ToolingExtensions.EXT_JSON_PRIMITIVE_CHOICE)) {
row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE);
} else { } else {
row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE); row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE);
typesRow = row; typesRow = row;
@ -5002,9 +5004,9 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY); String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY);
if ("present".equals(code)) { if ("present".equals(code)) {
c.getPieces().add(gen.new Piece(null, "This element is present as a JSON Array even when there are no items in the instance", null)); c.getPieces().add(gen.new Piece(null, "JSON: This element is present as a JSON Array even when there are no items in the instance", null));
} else { } else {
c.getPieces().add(gen.new Piece(null, "This element may be present as a JSON Array even when there are no items in the instance", null)); c.getPieces().add(gen.new Piece(null, "JSON: This element may be present as a JSON Array even when there are no items in the instance", null));
} }
} }
String jn = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_NAME); String jn = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_NAME);
@ -5021,21 +5023,25 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
if (ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_PRIMITIVE_CHOICE)) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.getPieces().add(gen.new Piece(null, "JSON: The type of this element is inferred from the JSON type in the instance", null));
}
if (ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_NULLABLE)) { if (ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_NULLABLE)) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.getPieces().add(gen.new Piece(null, "This object can be represented as null in the JSON structure (which counts as 'present' for cardinality purposes)", null)); c.getPieces().add(gen.new Piece(null, "JSON: This object can be represented as null in the JSON structure (which counts as 'present' for cardinality purposes)", null));
} }
if (definition.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) { if (definition.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY); String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY);
c.getPieces().add(gen.new Piece(null, "Represented as a single JSON Object with named properties using the value of the "+code+" child as the key", null)); c.getPieces().add(gen.new Piece(null, "JSON: Represented as a single JSON Object with named properties using the value of the "+code+" child as the key", null));
} }
if (definition.hasExtension(ToolingExtensions.EXT_TYPE_SPEC)) { if (definition.hasExtension(ToolingExtensions.EXT_TYPE_SPEC)) {
for (Extension e : definition.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_SPEC)) { for (Extension e : definition.getExtensionsByUrl(ToolingExtensions.EXT_TYPE_SPEC)) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
String cond = ToolingExtensions.readStringExtension(e, "condition"); String cond = ToolingExtensions.readStringExtension(e, "condition");
String type = ToolingExtensions.readStringExtension(e, "type"); String type = ToolingExtensions.readStringExtension(e, "type");
c.getPieces().add(gen.new Piece(null, "If ", null)); c.getPieces().add(gen.new Piece(null, "JSON: If ", null));
Piece piece = gen.new Piece("code"); Piece piece = gen.new Piece("code");
piece.addHtml(new XhtmlNode(NodeType.Text).setContent(cond)); piece.addHtml(new XhtmlNode(NodeType.Text).setContent(cond));
c.getPieces().add(piece); c.getPieces().add(piece);

View File

@ -22,6 +22,7 @@ import org.hl7.fhir.r5.model.NamingSystem.NamingSystemIdentifierType;
import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent; import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.r5.model.Identifier; import org.hl7.fhir.r5.model.Identifier;
import org.hl7.fhir.r5.model.NamingSystem; import org.hl7.fhir.r5.model.NamingSystem;
@ -342,5 +343,16 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
} }
public StructureDefinition fetchByJsonName(String key) {
for (StructureDefinition sd : context.fetchResourcesByType(StructureDefinition.class)) {
ElementDefinition ed = sd.getSnapshot().getElementFirstRep();
if (sd.getKind() == StructureDefinitionKind.LOGICAL && ed != null && ed.hasExtension(ToolingExtensions.EXT_JSON_NAME) &&
key.equals(ToolingExtensions.readStringExtension(ed, ToolingExtensions.EXT_JSON_NAME))) {
return sd;
}
}
return null;
}
} }

View File

@ -47,6 +47,7 @@ import java.util.Set;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
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.formats.IParser.OutputStyle; import org.hl7.fhir.r5.formats.IParser.OutputStyle;
@ -58,12 +59,14 @@ import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.json.JsonTrackingParser; import org.hl7.fhir.utilities.json.JsonTrackingParser;
import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData; import org.hl7.fhir.utilities.json.JsonTrackingParser.LocationData;
import org.hl7.fhir.utilities.json.JsonUtilities;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.xhtml.XhtmlParser; import org.hl7.fhir.utilities.xhtml.XhtmlParser;
@ -208,7 +211,13 @@ public class JsonParser extends ParserBase {
if (policy != ValidationPolicy.NONE) { if (policy != ValidationPolicy.NONE) {
for (Entry<String, JsonElement> e : object.entrySet()) { for (Entry<String, JsonElement> e : object.entrySet()) {
if (!processed.contains(e.getKey())) { if (!processed.contains(e.getKey())) {
logError(line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR); StructureDefinition sd = element.getProperty().isLogical() ? new ContextUtilities(context).fetchByJsonName(e.getKey()) : null;
if (sd != null) {
Property property = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, element.getProperty().getUtils());
parseChildItem(path, object, element, null, property);
} else {
logError(line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR);
}
} }
} }
} }
@ -216,25 +225,63 @@ public class JsonParser extends ParserBase {
public void parseChildItem(String path, JsonObject object, Element context, Set<String> processed, Property property) { public void parseChildItem(String path, JsonObject object, 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]")) {
for (TypeRefComponent type : property.getDefinition().getType()) { if (property.isJsonPrimitiveChoice()) {
String eName = property.getName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode()); if (object.has(property.getJsonName())) {
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) { JsonElement je = object.get(property.getJsonName());
parseChildComplex(path, object, context, processed, property, eName); if (processed != null) processed.add(property.getJsonName());
break; String type = getTypeFromJsonType(je);
} else if (isPrimitive(type.getWorkingCode()) && (object.has(eName) || object.has("_"+eName))) { if (type == null) {
parseChildPrimitive(object, context, processed, property, path, eName); logError(line(je), col(je), path, IssueType.STRUCTURE, this.context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_TYPE, describeType(je), property.getName(), property.typeSummary()), IssueSeverity.ERROR);
break; } else if (property.hasType(type)) {
Property np = new Property(property.getContext(), property.getDefinition(), property.getStructure(), property.getUtils(), type);
parseChildPrimitive(object, context, processed, np, path, property.getName());
} else {
logError(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 {
for (TypeRefComponent type : property.getDefinition().getType()) {
String eName = property.getJsonName().substring(0, property.getName().length()-3) + Utilities.capitalize(type.getWorkingCode());
if (!isPrimitive(type.getWorkingCode()) && object.has(eName)) {
parseChildComplex(path, object, context, processed, property, eName);
break;
} else if (isPrimitive(type.getWorkingCode()) && (object.has(eName) || object.has("_"+eName))) {
parseChildPrimitive(object, context, processed, property, path, eName);
break;
}
} }
} }
} else if (property.isPrimitive(property.getType(null))) { } else if (property.isPrimitive(property.getType(null))) {
parseChildPrimitive(object, context, processed, property, path, property.getName()); parseChildPrimitive(object, context, processed, property, path, property.getJsonName());
} else if (object.has(property.getName())) { } else if (object.has(property.getJsonName())) {
parseChildComplex(path, object, context, processed, property, property.getName()); parseChildComplex(path, object, context, processed, property, property.getJsonName());
}
}
private String getTypeFromJsonType(JsonElement je) {
if (je.isJsonPrimitive()) {
JsonPrimitive p = je.getAsJsonPrimitive();
if (p.isString()) {
return "string";
} else if (p.isBoolean()) {
return "boolean";
} else {
String s = p.getAsString();
if (Utilities.isInteger(s)) {
return "integer";
} else {
return "decimal";
}
}
} else {
return null;
} }
} }
private void parseChildComplex(String path, JsonObject object, Element element, Set<String> processed, Property property, String name) throws FHIRException { private void parseChildComplex(String path, JsonObject object, Element element, Set<String> processed, Property property, String name) throws FHIRException {
processed.add(name); if (processed != null) {
processed.add(name);
}
String npath = path+"."+property.getName(); String npath = path+"."+property.getName();
String fpath = element.getPath()+"."+property.getName(); String fpath = element.getPath()+"."+property.getName();
JsonElement e = object.get(name); JsonElement e = object.get(name);
@ -256,18 +303,18 @@ public class JsonParser extends ParserBase {
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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT), IssueSeverity.ERROR); logError(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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME), IssueSeverity.ERROR); logError(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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE), IssueSeverity.ERROR); logError(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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST), IssueSeverity.ERROR); logError(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()) { } else if (propV.isChoice() && propV.getName().endsWith("[x]")) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE), IssueSeverity.ERROR); logError(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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR); logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR);
} else { } else {
@ -288,15 +335,32 @@ public class JsonParser extends ParserBase {
n.getChildren().add(nKey); n.getChildren().add(nKey);
nKey.setValue(pv.getKey()); nKey.setValue(pv.getKey());
// handle the value
String npathV = npathArr+"."+propV.getName(); boolean ok = true;
String fpathV = fpathArr+"."+propV.getName(); Property pvl = propV;
if (propV.isPrimitive(propV.getType(null))) { if (propV.isJsonPrimitiveChoice()) {
parseChildPrimitiveInstance(n, propV, propV.getName(), npathV, fpathV, pv.getValue(), null); ok = false;
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) { String type = getTypeFromJsonType(pv.getValue());
parseChildComplexInstance(npathV, fpathV, n, propV, propV.getName(), pv.getValue()); if (type == null) {
} else { logError(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(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR); } else if (propV.hasType(type)) {
pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type);
ok = true;
} else {
logError(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) {
// handle the value
String npathV = npathArr+"."+pvl.getName();
String fpathV = fpathArr+"."+pvl.getName();
if (propV.isPrimitive(pvl.getType(null))) {
parseChildPrimitiveInstance(n, pvl, pvl.getName(), npathV, fpathV, pv.getValue(), null);
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue());
} else {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
}
} }
i++; i++;
} }
@ -304,22 +368,18 @@ public class JsonParser extends ParserBase {
} }
} else { } else {
if (property.isList()) { if (property.isList()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describeType(e), name, path), IssueSeverity.ERROR); logError(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); parseChildComplexInstance(npath, fpath, element, property, name, e);
} }
} }
private String describeType(JsonElement e) { private Object propNames(List<Property> properties) {
if (e.isJsonArray()) CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
return "an Array"; for (Property p: properties) {
if (e.isJsonObject()) b.append(p.getName());
return "an Object"; }
if (e.isJsonPrimitive()) return b.toString();
return "a primitive property";
if (e.isJsonNull())
return "a Null";
return null;
} }
private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e) throws FHIRException { private void parseChildComplexInstance(String npath, String fpath, Element element, Property property, String name, JsonElement e) throws FHIRException {
@ -379,15 +439,41 @@ public class JsonParser extends ParserBase {
private String describe(JsonElement e) { private String describe(JsonElement e) {
if (e instanceof JsonArray) { if (e instanceof JsonArray) {
return "an array"; return "an Array";
} }
if (e instanceof JsonObject) { if (e instanceof JsonObject) {
return "an object"; return "an Object";
}
if (e instanceof JsonNull) {
return "a Null";
}
if (e instanceof JsonPrimitive) {
return "a Primitive property";
}
return null;
}
private String describeType(JsonElement e) {
if (e instanceof JsonArray) {
return "array";
}
if (e instanceof JsonObject) {
return "object";
} }
if (e instanceof JsonNull) { if (e instanceof JsonNull) {
return "null"; return "null";
} }
return "a primitive property"; if (e instanceof JsonPrimitive) {
JsonPrimitive p = (JsonPrimitive) e;
if (p.isString()) {
return "string";
} else if (p.isBoolean()) {
return "boolean";
} else if (p.isNumber()) {
return "number";
}
}
return "??";
} }
private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException { private void parseChildPrimitive(JsonObject object, Element element, Set<String> processed, Property property, String path, String name) throws FHIRException {

View File

@ -51,6 +51,7 @@ import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.TypeDetails; import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.TypesUtilities; import org.hl7.fhir.r5.utils.TypesUtilities;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
@ -59,8 +60,8 @@ public class Property {
private IWorkerContext context; private IWorkerContext context;
private ElementDefinition definition; private ElementDefinition definition;
private StructureDefinition structure; private StructureDefinition structure;
private Boolean canBePrimitive; private ProfileUtilities profileUtilities;
private ProfileUtilities profileUtilities; private TypeRefComponent type;
public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure, ProfileUtilities profileUtilities) { public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure, ProfileUtilities profileUtilities) {
this.context = context; this.context = context;
@ -70,6 +71,18 @@ public class Property {
} }
public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure, ProfileUtilities profileUtilities, String type) {
this.context = context;
this.definition = definition;
this.structure = structure;
this.profileUtilities = profileUtilities;
for (TypeRefComponent tr : definition.getType()) {
if (tr.getWorkingCode().equals(type)) {
this.type = tr;
}
}
}
public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure) { public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure) {
this(context, definition, structure, new ProfileUtilities(context, null, null)); this(context, definition, structure, new ProfileUtilities(context, null, null));
} }
@ -78,6 +91,14 @@ public class Property {
return definition.getPath().substring(definition.getPath().lastIndexOf(".")+1); return definition.getPath().substring(definition.getPath().lastIndexOf(".")+1);
} }
public String getJsonName() {
if (definition.hasExtension(ToolingExtensions.EXT_JSON_NAME)) {
return ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_NAME);
} else {
return getName();
}
}
public String getXmlName() { public String getXmlName() {
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) { if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) {
return ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_XML_NAME); return ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_XML_NAME);
@ -101,7 +122,9 @@ public class Property {
} }
public String getType() { public String getType() {
if (definition.getType().size() == 0) if (type != null) {
return type.getWorkingCode();
} else if (definition.getType().size() == 0)
return null; return null;
else if (definition.getType().size() > 1) { else if (definition.getType().size() > 1) {
String tn = definition.getType().get(0).getWorkingCode(); String tn = definition.getType().get(0).getWorkingCode();
@ -115,7 +138,10 @@ public class Property {
} }
public String getType(String elementName) { public String getType(String elementName) {
if (!definition.getPath().contains(".")) if (type != null) {
return type.getWorkingCode();
}
if (!definition.getPath().contains("."))
return definition.getPath(); return definition.getPath();
ElementDefinition ed = definition; ElementDefinition ed = definition;
if (definition.hasContentReference()) { if (definition.hasContentReference()) {
@ -175,9 +201,18 @@ public class Property {
} }
public boolean hasType(String elementName) { public boolean hasType(String elementName) {
if (definition.getType().size() == 0) if (type != null) {
return false; // ?
} else if (definition.getType().size() == 0) {
return false; return false;
else if (definition.getType().size() > 1) { } else if (isJsonPrimitiveChoice()) {
for (TypeRefComponent tr : definition.getType()) {
if (elementName.equals(tr.getWorkingCode())) {
return true;
}
}
return false;
} else if (definition.getType().size() > 1) {
String t = definition.getType().get(0).getCode(); String t = definition.getType().get(0).getCode();
boolean all = true; boolean all = true;
for (TypeRefComponent tr : definition.getType()) { for (TypeRefComponent tr : definition.getType()) {
@ -188,7 +223,7 @@ public class Property {
return true; return true;
String tail = definition.getPath().substring(definition.getPath().lastIndexOf(".")+1); String tail = definition.getPath().substring(definition.getPath().lastIndexOf(".")+1);
if (tail.endsWith("[x]") && elementName.startsWith(tail.substring(0, tail.length()-3))) { if (tail.endsWith("[x]") && elementName.startsWith(tail.substring(0, tail.length()-3))) {
String name = elementName.substring(tail.length()-3); // String name = elementName.substring(tail.length()-3);
return true; return true;
} else } else
return false; return false;
@ -230,7 +265,10 @@ public class Property {
} }
public boolean isResource() { public boolean isResource() {
if (definition.getType().size() > 0) { if (type != null) {
String tc = type.getCode();
return (("Resource".equals(tc) || "DomainResource".equals(tc)) || Utilities.existsInList(tc, context.getResourceNames()));
} else if (definition.getType().size() > 0) {
String tc = definition.getType().get(0).getCode(); String tc = definition.getType().get(0).getCode();
return definition.getType().size() == 1 && (("Resource".equals(tc) || "DomainResource".equals(tc)) || Utilities.existsInList(tc, context.getResourceNames())); return definition.getType().size() == 1 && (("Resource".equals(tc) || "DomainResource".equals(tc)) || Utilities.existsInList(tc, context.getResourceNames()));
} }
@ -268,7 +306,6 @@ public class Property {
// if (canBePrimitive!= null) // if (canBePrimitive!= null)
// return canBePrimitive; // return canBePrimitive;
canBePrimitive = false;
if (structure.getKind() != StructureDefinitionKind.LOGICAL) if (structure.getKind() != StructureDefinitionKind.LOGICAL)
return false; return false;
if (!hasType(name)) if (!hasType(name))
@ -282,7 +319,6 @@ public class Property {
return false; return false;
for (ElementDefinition ed : sd.getSnapshot().getElement()) { for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().equals(sd.getId()+".value") && ed.getType().size() == 1 && isPrimitive(ed.getType().get(0).getCode())) { if (ed.getPath().equals(sd.getId()+".value") && ed.getType().size() == 1 && isPrimitive(ed.getType().get(0).getCode())) {
canBePrimitive = true;
return true; return true;
} }
} }
@ -290,6 +326,9 @@ public class Property {
} }
public boolean isChoice() { public boolean isChoice() {
if (type != null) {
return true;
}
if (definition.getType().size() <= 1) if (definition.getType().size() <= 1)
return false; return false;
String tn = definition.getType().get(0).getCode(); String tn = definition.getType().get(0).getCode();
@ -532,4 +571,26 @@ public class Property {
} }
public boolean isLogical() {
return structure.getKind() == StructureDefinitionKind.LOGICAL;
}
public ProfileUtilities getUtils() {
return profileUtilities;
}
public boolean isJsonPrimitiveChoice() {
return ToolingExtensions.readBoolExtension(definition, ToolingExtensions.EXT_JSON_PRIMITIVE_CHOICE);
}
public Object typeSummary() {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(" | ");
for (TypeRefComponent t : definition.getType()) {
b.append(t.getCode());
}
return b.toString();
}
} }

View File

@ -222,6 +222,7 @@ public class ToolingExtensions {
public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix"; public static final String EXT_IMPLIED_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/implied-string-prefix";
public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format"; public static final String EXT_DATE_FORMAT = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-date-format";
public static final String EXT_ID_EXPECTATION = "http://hl7.org/fhir/tools/StructureDefinition/id-expectation"; public static final String EXT_ID_EXPECTATION = "http://hl7.org/fhir/tools/StructureDefinition/id-expectation";
public static final String EXT_JSON_PRIMITIVE_CHOICE = "http://hl7.org/fhir/tools/StructureDefinition/json-primitive-choice";
// unregistered? - don't know what these are used for // unregistered? - don't know what these are used for

View File

@ -583,6 +583,8 @@ public class I18nConstants {
public static final String UNRECOGNISED_EXTENSION_CONTEXT_ = "Unrecognised_extension_context_"; public static final String UNRECOGNISED_EXTENSION_CONTEXT_ = "Unrecognised_extension_context_";
public static final String UNRECOGNISED_PREDICATE_ = "Unrecognised_predicate_"; public static final String UNRECOGNISED_PREDICATE_ = "Unrecognised_predicate_";
public static final String UNRECOGNISED_PROPERTY_ = "Unrecognised_property_"; public static final String UNRECOGNISED_PROPERTY_ = "Unrecognised_property_";
public static final String UNRECOGNISED_PROPERTY_TYPE = "UNRECOGNISED_PROPERTY_TYPE";
public static final String UNRECOGNISED_PROPERTY_TYPE_WRONG = "UNRECOGNISED_PROPERTY_TYPE_WRONG";
public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__extensions_are_not_allowed__for_discriminator_for_slice_"; public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__extensions_are_not_allowed__for_discriminator_for_slice_";
public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__MUST_HAVE_AT_LEAST_ONE_CODING__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__must_have_at_least_one_coding__for_discriminator_for_slice_"; public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__MUST_HAVE_AT_LEAST_ONE_CODING__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__must_have_at_least_one_coding__for_discriminator_for_slice_";
public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__USING_TEXT__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__using_text__for_discriminator_for_slice_"; public static final String UNSUPPORTED_CODEABLECONCEPT_PATTERN__USING_TEXT__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_CodeableConcept_pattern__using_text__for_discriminator_for_slice_";

View File

@ -395,12 +395,12 @@ This_property_must_be_an_object_not_ = This property must be an object, not {0}
This_property_must_be_an_simple_value_not_ = This property must be an simple value, not {0} ({1} at {2}) This_property_must_be_an_simple_value_not_ = This property must be an simple value, not {0} ({1} at {2})
This_property_must_be__not_ = The property {2} must be {0}, not {1} (at {3}) This_property_must_be__not_ = The property {2} must be {0}, not {1} (at {3})
This_property_must_be_an_Array_not_ = The property {1} must be a JSON Array, not {0} (at {2}) This_property_must_be_an_Array_not_ = The property {1} must be a JSON Array, not {0} (at {2})
OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT = This object cannot be an keyed Array in Json because it does not have two children in the definitions OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT = This object cannot be an keyed Array in Json because it does not have two children in the definitions (children = {0})
OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME = This object is defined as a keyed Array in Json but the definition does not name the first child element as the key OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME = This object is defined as a keyed Array in Json but the definition does not name the first child element as the key (children = {0})
OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE = This object is defined as a keyed Array in Json but the key property named in the definitions is not a primitive type OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_TYPE = This object is defined as a keyed Array in Json but the key property named in the definitions is not a primitive type (children = {0}, type = {1})
OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE = This object is defined as a keyed Array in Json but the value property named in the definitions is a choice - this is not supported OBJECT_CANNOT_BE_KEYED_ARRAY_NO_CHOICE = This object is defined as a keyed Array in Json but the value property named in the definitions is a choice - this is not supported (value property = {0})
OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST = This object is defined as a keyed Array in Json but the value property named in the definitions is a list - this is not supported OBJECT_CANNOT_BE_KEYED_ARRAY_NO_LIST = This object is defined as a keyed Array in Json but the value property named in the definitions is a list - this is not supported (value property = {0})
Unrecognised_property_ = Unrecognized property ''@{0}'' Unrecognised_property_ = Unrecognized property ''{0}''
Object_must_have_some_content = Object must have some content Object_must_have_some_content = Object must have some content
Error_parsing_JSON_ = Error parsing JSON: {0} Error_parsing_JSON_ = Error parsing JSON: {0}
Node_type__is_not_allowed = Node type {0} is not allowed Node_type__is_not_allowed = Node type {0} is not allowed
@ -769,4 +769,6 @@ TYPE_SPECIFIER_NM_ILLEGAL_TYPE = No Type specifier matched, and the underlying t
TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract TYPE_SPECIFIER_NM_ABSTRACT_TYPE = No Type specifier matched, and the underlying type {0} is not abstract
ELEMENT_CANNOT_BE_NULL = The element is not allowed to be 'null' ELEMENT_CANNOT_BE_NULL = The element is not allowed to be 'null'
MULTIPLE_LOGICAL_MODELS_PLURAL={0} Logical Models found in supplied profiles, so unable to parse logical model (can only be one, found {1}) MULTIPLE_LOGICAL_MODELS_PLURAL={0} Logical Models found in supplied profiles, so unable to parse logical model (can only be one, found {1})
UNRECOGNISED_PROPERTY_TYPE = Invalid JSON type {0} for the element {1}; valid types = {2}
UNRECOGNISED_PROPERTY_TYPE_WRONG = Invalid type {2} for the element {1}; valid types = {3}, JSON type = {0}