use of org.hl7.fhir.definitions.model.DefinedCode in project kindling by HL7.
the class ResourceValidator method check.
// private List<ValidationMessage> check(String n, BindingSpecification cd) throws Exception {
// List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
// check(errors, n, cd);
// return errors;
// }
private void check(List<ValidationMessage> errors, String path, BindingSpecification cd, String sd, ElementDefn e) throws Exception {
// basic integrity checks
List<DefinedCode> ac = cd.getAllCodes(definitions.getCodeSystems(), definitions.getValuesets(), false);
for (DefinedCode c : ac) {
String d = c.getCode();
if (Utilities.noString(d))
d = c.getId();
if (Utilities.noString(d))
d = c.getDisplay();
if (Utilities.noString(d))
d = c.getDisplay();
if (Utilities.noString(c.getSystem()))
warning(errors, IssueType.STRUCTURE, "Binding @ " + path, !Utilities.noString(c.getDefinition()), "Code " + d + " must have a definition");
rule(errors, IssueType.STRUCTURE, "Binding @ " + path, !(Utilities.noString(c.getId()) && Utilities.noString(c.getSystem())), "Code " + d + " must have a id or a system");
}
// trigger processing into a Heirachical set if necessary
// rule(errors, IssueType.STRUCTURE, "Binding @ "+path, !cd.isHeirachical() || (cd.getChildCodes().size() < cd.getCodes().size()), "Logic error processing Hirachical code set");
// now, rules for the source
hint(errors, IssueType.STRUCTURE, "Binding @ " + path, cd.getBinding() != BindingMethod.Unbound, "Need to provide a binding");
rule(errors, IssueType.STRUCTURE, "Binding @ " + path, Utilities.noString(cd.getDefinition()) || (cd.getDefinition().charAt(0) == cd.getDefinition().toUpperCase().charAt(0)), "Definition cannot start with a lowercase letter");
if (cd.getBinding() == BindingMethod.CodeList || (cd.getBinding() == BindingMethod.ValueSet && cd.getStrength() == BindingStrength.REQUIRED && ac.size() > 0 && "code".equals(e.typeCode()))) {
if (path.toLowerCase().endsWith("status")) {
if (rule(errors, IssueType.STRUCTURE, path, definitions.getStatusCodes().containsKey(path), "Status element not registered in status-codes.xml")) {
// rule(errors, IssueType.STRUCTURE, path, e.isModifier(), "Status elements that map to status-codes should be labelled as a modifier");
ArrayList<String> list = definitions.getStatusCodes().get(path);
for (DefinedCode c : ac) {
boolean ok = false;
for (String s : list) {
String[] parts = s.split("\\,");
for (String p : parts) if (p.trim().equals(c.getCode()))
ok = true;
}
rule(errors, IssueType.STRUCTURE, path, ok, "Status element code \"" + c.getCode() + "\" not found in status-codes.xml");
}
for (String s : list) {
String[] parts = s.split("\\,");
for (String p : parts) {
List<String> cl = new ArrayList<>();
if (!Utilities.noString(p)) {
boolean ok = false;
for (DefinedCode c : ac) {
cl.add(c.getCode());
if (p.trim().equals(c.getCode()))
ok = true;
}
if (!ok)
rule(errors, IssueType.STRUCTURE, path, ok, "Status element code \"" + p + "\" found for " + path + " in status-codes.xml but has no matching code in the resource (codes = " + cl + ")");
}
}
}
}
}
StringBuilder b = new StringBuilder();
for (DefinedCode c : ac) {
if (!c.getAbstract())
b.append(" | ").append(c.getCode());
}
if (sd.equals("*")) {
e.setShortDefn(b.toString().substring(3));
sd = b.toString().substring(3);
}
if (sd.contains("|")) {
if (b.length() < 3)
throw new Error("surprise");
String esd = b.substring(3);
rule(errors, IssueType.STRUCTURE, path, sd.startsWith(esd) || (sd.endsWith("+") && b.substring(3).startsWith(sd.substring(0, sd.length() - 1))), "The short description \"" + sd + "\" does not match the expected (\"" + b.substring(3) + "\")");
} else {
rule(errors, IssueType.STRUCTURE, path, cd.getStrength() != BindingStrength.REQUIRED || ac.size() > 12 || ac.size() <= 1 || !hasGoodCode(ac) || isExemptFromCodeList(path), "The short description of an element with a code list should have the format code | code | etc (is " + sd.toString() + ") (" + ac.size() + " codes = \"" + b.toString() + "\")");
}
}
boolean isComplex = !e.typeCode().equals("code");
if (isComplex && cd.getValueSet() != null && hasInternalReference(cd.getValueSet()) && cd.getStrength() != BindingStrength.EXAMPLE) {
hint(errors, IssueType.BUSINESSRULE, path, false, "The value " + cd.getValueSet().getUrl() + " defines codes, but is used by a Coding/CodeableConcept @ " + path + ", so it should not use FHIR defined codes");
cd.getValueSet().setUserData("vs-val-warned", true);
}
if (cd.getElementType() == ElementType.Unknown) {
if (isComplex)
cd.setElementType(ElementType.Complex);
else
cd.setElementType(ElementType.Simple);
} else if (isComplex && !cd.hasMax())
rule(errors, IssueType.STRUCTURE, path, cd.getElementType() == ElementType.Complex, "Cannot use a binding from both code and Coding/CodeableConcept elements");
else
rule(errors, IssueType.STRUCTURE, path, cd.getElementType() == ElementType.Simple, "Cannot use a binding from both code and Coding/CodeableConcept elements");
if (isComplex && cd.getValueSet() != null) {
for (ConceptSetComponent inc : cd.getValueSet().getCompose().getInclude()) if (inc.hasSystem())
txurls.add(inc.getSystem());
}
rule(errors, IssueType.STRUCTURE, "Binding @ " + path, (cd.getElementType() != ElementType.Simple || cd.getStrength() == BindingStrength.REQUIRED || cd.hasMax()) || isExemptFromProperBindingRules(path), "Must be a required binding if bound to a code instead of a Coding/CodeableConcept");
rule(errors, IssueType.STRUCTURE, "Binding @ " + path, cd.getElementType() != ElementType.Simple || cd.getBinding() != BindingMethod.Unbound, "Need to provide a binding for code elements");
if (!isComplex && !externalException(path)) {
ValueSet vs = cd.getValueSet();
if (warning(errors, IssueType.REQUIRED, path, vs != null || cd.hasReference(), "Unable to resolve value set on 'code' Binding")) {
hint(errors, IssueType.REQUIRED, path, noExternals(vs), "Bindings for code data types should only use internally defined codes (" + vs.getUrl() + ")");
// don't disable this without discussion on Zulip
}
}
}
use of org.hl7.fhir.definitions.model.DefinedCode in project kindling by HL7.
the class JsonLDGenerator method generateElement.
private void generateElement(ElementDefn root, String name, ElementDefn e, JsonObject base, Set<String> types) throws Exception {
if ((e.getTypes().size() == 1 && e.getTypes().get(0).isWildcardType())) {
if (!e.getName().contains("[x]"))
throw new Exception("Element " + e.getName() + " in " + root.getName() + " has multiple types as a choice doesn't have a [x] in the element name");
for (TypeRef tr : datatypes) {
String tn = tr.getName();
if (tn.equals("SimpleQuantity"))
tn = "Quantity";
else
tn = Utilities.capitalize(tn);
String en = e.getName().substring(0, e.getName().length() - 3) + tn;
JsonObject property = new JsonObject();
base.add(name + "." + en, property);
property.addProperty("@id", "http://hl7.org/fhir/" + name + "." + en);
}
// if (e.getTypes().size() == 1)
// generateAny(root, e, e.getName().replace("[x]", ""), props, relative);
// else {
// for (TypeRef t : e.getTypes()) {
// JsonObject property = new JsonObject();
// JsonObject property_ = null;
// String en = e.getName().replace("[x]", "");
// props.add(en+upFirst(t.getName()), property);
// property.addProperty("description", e.getDefinition());
// String tref = null;
// String type = null;
// String pattern = null;
// if (definitions.getPrimitives().containsKey(t.getName())) {
// DefinedCode def = definitions.getPrimitives().get(t.getName());
// type = def.getJsonType();
// pattern = def.getRegex();
// if (!Utilities.noString(pattern))
// property.addProperty("pattern", pattern);
//
// property.addProperty("type", type);
// property_ = new JsonObject();
// props.add("_"+en+upFirst(t.getName()), property_);
// property_.addProperty("description", "Extensions for "+en+upFirst(t.getName()));
// tref = (relative ? "#" : "Element.schema.json#") +"/definitions/Element";
// property_.addProperty("$ref", tref);
// } else {
// String tn = encodeType(e, t, true);
// tref = (relative ? "#" : tn.replace(".", "_")+".schema.json#") +"/definitions/"+tn.replace(".", "_");
// property.addProperty("$ref", tref);
// }
// }
// }
} else if (e.getName().endsWith("[x]")) {
for (TypeRef tr : e.getTypes()) {
String tn = tr.getName();
if (tn.equals("SimpleQuantity"))
tn = "Quantity";
else
tn = Utilities.capitalize(tn);
String en = e.getName().substring(0, e.getName().length() - 3) + tn;
JsonObject property = new JsonObject();
base.add(name + "." + en, property);
property.addProperty("@id", "http://hl7.org/fhir/" + name + "." + en);
}
} else {
JsonObject property = new JsonObject();
base.add(name + "." + e.getName(), property);
if (e.getPath() == null)
property.addProperty("@id", "http://hl7.org/fhir/" + name + "." + e.getName());
else
property.addProperty("@id", "http://hl7.org/fhir/" + e.getPath());
// if we're using lists:
// if (e.unbounded())
// property.addProperty("@container", "@list");
// property.addProperty("fhir-@type", "http://hl7.org/fhir/"+e.typeCode());
// String tref = null;
// String type = null;
// String pattern = null;
//
// if (e.usesCompositeType()/* && types.containsKey(root.getElementByName(e.typeCode().substring(1)))*/) {
// ElementDefn ref = root.getElementByName(definitions, e.typeCode().substring(1), true, false);
// String rtn = types.get(ref);
// if (rtn == null)
// throw new Exception("logic error in schema generator (null composite reference in "+types.toString()+")");
//
// if(rtn == "Type")
// rtn = "Element";
// type=rtn;
// tref = "#/definitions/"+rtn.replace(".", "_");
// } else if (e.getTypes().size() == 0 && e.getElements().size() > 0){
// tref = "#/definitions/"+types.get(e).replace(".", "_");
// type=types.get(e).replace(".", "_");
// } else if (e.getTypes().size() == 1) {
// String tn = encodeType(e, e.getTypes().get(0), true);
// type=tn;
// if (definitions.getPrimitives().containsKey(e.typeCode())) {
// DefinedCode def = definitions.getPrimitives().get(e.typeCode());
// type = def.getJsonType();
// pattern = def.getRegex();
// property_ = new JsonObject();
// props.add("_"+e.getName(), property_);
// property_.addProperty("description", "Extensions for "+e.getName());
// tref = (relative ? "#" : "Element.schema.json#") +"/definitions/Element";
// BindingSpecification cd = e.getBinding();
//
// if (cd != null && (cd.getBinding() == BindingSpecification.BindingMethod.CodeList)) {
// ValueSet vs = cd.getValueSet();
// if (vs!= null) {
// ValueSet ex = workerContext.expandVS(vs, true, false).getValueset();
// JsonArray enums = new JsonArray();
// for (ValueSetExpansionContainsComponent cc : ex.getExpansion().getContains()) {
// enums.add(new JsonPrimitive(cc.getCode()));
// }
// property.add("enum", enums);
// pattern = null;
// }
// }
// } else {
// tref = (relative ? "#" : tn.replace(".", "_")+".schema.json#") +"/definitions/"+tn.replace(".", "_");
// }
// } else
// throw new Exception("how do we get here? "+e.getName()+" in "+root.getName()+" "+Integer.toString(e.getTypes().size()));
//
// if (e.unbounded()) {
// property.addProperty("type", "array");
// if (property_ != null) {
// property_.addProperty("type", "array");
// JsonObject items = new JsonObject();
// property.add("items", items);
// items.addProperty("type", type);
// if (!Utilities.noString(pattern))
// items.addProperty("pattern", pattern);
//
// items = new JsonObject();
// property_.add("items", items);
// items.addProperty("$ref", tref);
// } else {
// JsonObject items = new JsonObject();
// property.add("items", items);
// items.addProperty("$ref", tref);
// }
// } else {
// if (property_ != null) {
// property.addProperty("type", type);
// if (!Utilities.noString(pattern))
// property.addProperty("pattern", pattern);
//
// property_.addProperty("$ref", tref);
// } else if("div".equals(e.getName()) && "xhtml".equals(type)) {
// // Is there a better type, or ref for html?
// property.addProperty("type", "string");
// } else {
// property.addProperty("$ref", tref);
// }
// }
// if (e.getMinCardinality() > 0 && property_ == null)
// required.add(e.getName());
}
}
use of org.hl7.fhir.definitions.model.DefinedCode in project kindling by HL7.
the class SchemaGenerator method processSchemaIncludes.
private String processSchemaIncludes(Definitions definitions, String filename, String src, boolean singleMode) throws Exception {
List<String> names = new ArrayList<String>();
names.addAll(definitions.getResources().keySet());
names.add("Parameters");
Collections.sort(names);
while (src.contains("<!--%") || src.contains("<%")) {
int i2;
String s1;
String s2;
String s3;
int i1 = src.indexOf("<!--%");
if (i1 > -1) {
i2 = src.indexOf("%-->");
s1 = src.substring(0, i1);
s2 = src.substring(i1 + 5, i2).trim();
s3 = src.substring(i2 + 4);
} else {
i1 = src.indexOf("<%");
i2 = src.indexOf("%>");
s1 = src.substring(0, i1);
s2 = src.substring(i1 + 2, i2).trim();
s3 = src.substring(i2 + 2);
}
String[] com = s2.split(" ");
if (com[0].equals("genDate"))
src = s1 + genDate + s3;
else if (com[0].equals("version"))
src = s1 + version + s3;
else if (com[0].equals("includes")) {
if (singleMode)
src = s1 + "<xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"fhir-single.schema.json\"/>" + s3;
else
src = s1 + "<xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"fhir-all.schema.json\"/>" + s3;
} else if (com[0].equals("resources")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:include schemaLocation=\"" + n.toLowerCase() + ".schema.json\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("atom.imports")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"" + n + ".schema.json\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("atom.elements")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:element ref=\"fhir:" + n + "\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("enum")) {
Collection<DefinedCode> values;
if (com[1].equals("resource")) {
values = definitions.getKnownResources().values();
} else {
throw new Error("fix this");
// values = definitions.getBindingByName(com[1]).getCodes();
}
StringBuilder enums = new StringBuilder();
for (DefinedCode c : values) {
if (!c.getAbstract()) {
enums.append(" <xs:enumeration value=\"" + c.getCode() + "\">\r\n");
enums.append(" <xs:annotation>\r\n");
enums.append(" <xs:documentation xml:lang=\"en\">" + Utilities.escapeXml(c.getDefinition()) + "</xs:documentation>\r\n");
for (String l : c.getLangs().keySet()) enums.append(" <xs:documentation xml:lang=\"" + l + "\">" + Utilities.escapeXml(c.getLangs().get(l)) + "</xs:documentation>\r\n");
enums.append(" </xs:annotation>\r\n");
enums.append(" </xs:enumeration>\r\n");
}
}
src = s1 + enums.toString() + s3;
} else
throw new Exception("Instruction <%" + s2 + "%> not understood parsing page " + filename);
}
return src;
}
use of org.hl7.fhir.definitions.model.DefinedCode in project kindling by HL7.
the class SchemaGenerator method generate.
public void generate(Definitions definitions, IniFile ini, String tmpResDir, String xsdDir, String dstDir, String srcDir, String version, String genDate, BuildWorkerContext workerContext) throws Exception {
this.genDate = genDate;
this.version = version;
this.workerContext = workerContext;
File dir = new CSFile(xsdDir);
File[] list = dir.listFiles();
if (list != null) {
for (File f : list) {
if (!f.isDirectory() && f.getName().endsWith(".schema.json"))
f.delete();
}
}
JsonObject schema = new JsonObject();
schema.addProperty("$schema", "http://json-schema.org/draft-06/schema#");
schema.addProperty("id", "http://hl7.org/fhir/json-schema/" + version.substring(0, version.lastIndexOf(".")));
// schema.addProperty("$ref", "#/definitions/ResourceList");
schema.addProperty("description", "see http://hl7.org/fhir/json.html#schema for information about the FHIR Json Schemas");
List<String> names = new ArrayList<String>();
names.addAll(definitions.getResources().keySet());
names.addAll(definitions.getBaseResources().keySet());
addAllResourcesChoice(definitions, schema, names);
names.clear();
names.addAll(definitions.getPrimitives().keySet());
Collections.sort(names);
for (String n : names) {
new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(definitions.getPrimitives().get(n), version, genDate, schema);
}
new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(new DefinedCode().setCode("xhtml").setDefinition("xhtml - escaped html (see specfication)"), version, genDate, schema);
for (TypeRef tr : definitions.getKnownTypes()) {
if (!definitions.getPrimitives().containsKey(tr.getName()) && !definitions.getConstraints().containsKey(tr.getName())) {
TypeDefn root = definitions.getElementDefn(tr.getName());
if (!isBackboneElement(root.getName())) {
JsonObject s = new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(root, version, genDate, null);
save(s, tmpResDir + root.getName().replace(".", "_") + ".schema.json");
new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(root, version, genDate, schema);
}
}
}
names.clear();
names.addAll(definitions.getResources().keySet());
names.addAll(definitions.getBaseResources().keySet());
Collections.sort(names);
for (String name : names) {
ResourceDefn root = definitions.getResourceByName(name);
JsonObject s = new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(root.getRoot(), version, genDate, null);
save(s, tmpResDir + root.getName().replace(".", "_") + ".schema.json");
if (!root.isAbstract()) {
new JsonGenerator(definitions, workerContext, definitions.getKnownTypes(), version).generate(root.getRoot(), version, genDate, schema);
}
}
// save(generateAllResourceChoice(names), xsdDir+"ResourceList.schema.json");
save(schema, xsdDir + "fhir.schema.json");
dir = new CSFile(xsdDir);
list = dir.listFiles();
for (File f : list) {
if (!f.isDirectory() && f.getName().endsWith(".schema.json"))
Utilities.copyFile(f, new CSFile(dstDir + f.getName()));
}
}
use of org.hl7.fhir.definitions.model.DefinedCode in project kindling by HL7.
the class SchemaGenerator method processSchemaIncludes.
private String processSchemaIncludes(Definitions definitions, String filename, String src, boolean singleMode) throws Exception {
List<String> names = new ArrayList<String>();
names.addAll(definitions.getResources().keySet());
names.add("Parameters");
Collections.sort(names);
while (src.contains("<!--%") || src.contains("<%")) {
int i2;
String s1;
String s2;
String s3;
int i1 = src.indexOf("<!--%");
if (i1 > -1) {
i2 = src.indexOf("%-->");
s1 = src.substring(0, i1);
s2 = src.substring(i1 + 5, i2).trim();
s3 = src.substring(i2 + 4);
} else {
i1 = src.indexOf("<%");
i2 = src.indexOf("%>");
s1 = src.substring(0, i1);
s2 = src.substring(i1 + 2, i2).trim();
s3 = src.substring(i2 + 2);
}
String[] com = s2.split(" ");
if (com[0].equals("genDate"))
src = s1 + genDate + s3;
else if (com[0].equals("version"))
src = s1 + version + s3;
else if (com[0].equals("includes")) {
if (singleMode)
src = s1 + "<xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"fhir-single.xsd\"/>" + s3;
else
src = s1 + "<xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"fhir-all.xsd\"/>" + s3;
} else if (com[0].equals("resources")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:include schemaLocation=\"" + n.toLowerCase() + ".xsd\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("atom.imports")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:import namespace=\"http://hl7.org/fhir\" schemaLocation=\"" + n + ".xsd\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("atom.elements")) {
StringBuilder includes = new StringBuilder();
for (String n : names) includes.append(" <xs:element ref=\"fhir:" + n + "\"/>\r\n");
src = s1 + includes.toString() + s3;
} else if (com[0].equals("enum")) {
Collection<DefinedCode> values;
if (com[1].equals("resource")) {
values = definitions.getKnownResources().values();
} else {
throw new Error("fix this");
// values = definitions.getBindingByName(com[1]).getCodes();
}
StringBuilder enums = new StringBuilder();
for (DefinedCode c : values) {
if (!c.getAbstract()) {
enums.append(" <xs:enumeration value=\"" + c.getCode() + "\">\r\n");
enums.append(" <xs:annotation>\r\n");
enums.append(" <xs:documentation xml:lang=\"en\">" + Utilities.escapeXml(c.getDefinition()) + "</xs:documentation>\r\n");
for (String l : c.getLangs().keySet()) enums.append(" <xs:documentation xml:lang=\"" + l + "\">" + Utilities.escapeXml(c.getLangs().get(l)) + "</xs:documentation>\r\n");
enums.append(" </xs:annotation>\r\n");
enums.append(" </xs:enumeration>\r\n");
}
}
src = s1 + enums.toString() + s3;
} else
throw new Exception("Instruction <%" + s2 + "%> not understood parsing page " + filename);
}
return src;
}
Aggregations