use of org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileValidator method validate.
public List<ValidationMessage> validate(StructureDefinition profile, boolean forBuild) {
List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
// must have a FHIR version- GF#3160
warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), "Profiles SHOULD state the FHIR Version on which they are based");
warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), "Profiles SHOULD state their own version");
// extensions must be defined
for (ElementDefinition ec : profile.getDifferential().getElement()) checkExtensions(profile, errors, "differential", ec);
rule(errors, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "missing Snapshot at " + profile.getName() + "." + profile.getName());
for (ElementDefinition ec : profile.getSnapshot().getElement()) checkExtensions(profile, errors, "snapshot", ec);
if (rule(errors, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "A snapshot is required")) {
Hashtable<String, ElementDefinition> snapshotElements = new Hashtable<String, ElementDefinition>();
for (ElementDefinition ed : profile.getSnapshot().getElement()) {
snapshotElements.put(ed.getId(), ed);
checkExtensions(profile, errors, "snapshot", ed);
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
if (forBuild) {
if (!inExemptList(inv.getKey())) {
if (rule(errors, IssueType.BUSINESSRULE, profile.getId() + "::" + ed.getPath() + "::" + inv.getKey(), inv.hasExpression(), "The invariant has no FHIR Path expression (" + inv.getXpath() + ")")) {
try {
// , inv.hasXpath() && inv.getXpath().startsWith("@value")
new FHIRPathEngine(context).check(null, profile.getType(), ed.getPath(), inv.getExpression());
} catch (Exception e) {
// rule(errors, IssueType.STRUCTURE, profile.getId()+"::"+ed.getPath()+"::"+inv.getId(), exprExt != null, e.getMessage());
}
}
}
}
}
}
if (snapshotElements != null) {
for (ElementDefinition diffElement : profile.getDifferential().getElement()) {
if (diffElement == null)
throw new Error("Diff Element is null - this is not an expected thing");
ElementDefinition snapElement = snapshotElements.get(diffElement.getId());
if (snapElement != null) {
// Happens with profiles in the main build - should be able to fix once snapshot generation is fixed - Lloyd
warning(errors, IssueType.BUSINESSRULE, diffElement.getId(), !checkMustSupport || snapElement.hasMustSupport(), "Elements included in the differential should declare mustSupport");
if (checkAggregation) {
for (TypeRefComponent type : snapElement.getType()) {
if ("http://hl7.org/fhir/Reference".equals(type.getWorkingCode()) || "http://hl7.org/fhir/canonical".equals(type.getWorkingCode())) {
warning(errors, IssueType.BUSINESSRULE, diffElement.getId(), type.hasAggregation(), "Elements with type Reference or canonical should declare aggregation");
}
}
}
}
}
}
}
return errors;
}
use of org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method generateForChildren.
private void generateForChildren(SchematronWriter sch, String xpath, ElementDefinition ed, StructureDefinition structure, StructureDefinition base) throws IOException {
// generateForChild(txt, structure, child);
List<ElementDefinition> children = getChildList(structure, ed);
String sliceName = null;
ElementDefinitionSlicingComponent slicing = null;
for (ElementDefinition child : children) {
String name = tail(child.getPath());
if (child.hasSlicing()) {
sliceName = name;
slicing = child.getSlicing();
} else if (!name.equals(sliceName))
slicing = null;
ElementDefinition based = getByPath(base, child.getPath());
boolean doMin = (child.getMin() > 0) && (based == null || (child.getMin() != based.getMin()));
boolean doMax = child.hasMax() && !child.getMax().equals("*") && (based == null || (!child.getMax().equals(based.getMax())));
Slicer slicer = slicing == null ? new Slicer(true) : generateSlicer(child, slicing, structure);
if (slicer.check) {
if (doMin || doMax) {
Section s = sch.section(xpath);
Rule r = s.rule(xpath);
if (doMin)
r.assrt("count(f:" + name + slicer.criteria + ") >= " + Integer.toString(child.getMin()), name + slicer.name + ": minimum cardinality of '" + name + "' is " + Integer.toString(child.getMin()));
if (doMax)
r.assrt("count(f:" + name + slicer.criteria + ") <= " + child.getMax(), name + slicer.name + ": maximum cardinality of '" + name + "' is " + child.getMax());
}
}
}
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
if (inv.hasXpath()) {
Section s = sch.section(ed.getPath());
Rule r = s.rule(xpath);
r.assrt(inv.getXpath(), (inv.hasId() ? inv.getId() + ": " : "") + inv.getHuman() + (inv.hasUserData(IS_DERIVED) ? " (inherited)" : ""));
}
}
for (ElementDefinition child : children) {
String name = tail(child.getPath());
generateForChildren(sch, xpath + "/f:" + name, child, structure, base);
}
}
use of org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method generateDescription.
private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn) throws IOException {
Cell c = gen.new Cell();
row.getCells().add(c);
if (used) {
if (logicalModel && ToolingExtensions.hasExtension(profile, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace")) {
if (root) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(profile, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"), null));
} else if (!root && ToolingExtensions.hasExtension(definition, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace") && !ToolingExtensions.readStringExtension(definition, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace").equals(ToolingExtensions.readStringExtension(profile, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"))) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(definition, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"), null));
}
}
if (definition.hasContentReference()) {
ElementDefinition ed = getElementByName(profile.getSnapshot().getElement(), definition.getContentReference());
if (ed == null)
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Unknown reference to %s", definition.getContentReference()), null));
else
c.getPieces().add(gen.new Piece("#" + ed.getPath(), translate("sd.table", "See %s", ed.getPath()), null));
}
if (definition.getPath().endsWith("url") && definition.hasFixed()) {
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "\"" + buildJson(definition.getFixed()) + "\"", null).addStyle("color: darkgreen")));
} else {
if (definition != null && definition.hasShort()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.addPiece(checkForNoChange(definition.getShortElement(), gen.new Piece(null, gt(definition.getShortElement()), null)));
} else if (fallback != null && fallback.hasShort()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.addPiece(checkForNoChange(fallback.getShortElement(), gen.new Piece(null, gt(fallback.getShortElement()), null)));
}
if (url != null) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
String fullUrl = url.startsWith("#") ? baseURL + url : url;
StructureDefinition ed = context.fetchResource(StructureDefinition.class, url);
String ref = null;
if (ed != null) {
String p = ed.getUserString("path");
if (p != null) {
ref = p.startsWith("http:") || igmode ? p : Utilities.pathURL(corePath, p);
}
}
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(ref, fullUrl, null));
}
if (definition.hasSlicing()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Slice") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, describeSlice(definition.getSlicing()), null));
}
if (definition != null) {
ElementDefinitionBindingComponent binding = null;
if (valueDefn != null && valueDefn.hasBinding() && !valueDefn.getBinding().isEmpty())
binding = valueDefn.getBinding();
else if (definition.hasBinding())
binding = definition.getBinding();
if (binding != null && !binding.isEmpty()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
BindingResolution br = pkp.resolveBinding(profile, binding, definition.getPath());
c.getPieces().add(checkForNoChange(binding, gen.new Piece(null, translate("sd.table", "Binding") + ": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(binding, gen.new Piece(br.url == null ? null : Utilities.isAbsoluteUrl(br.url) || !pkp.prependLinks() ? br.url : corePath + br.url, br.display, null)));
if (binding.hasStrength()) {
c.getPieces().add(checkForNoChange(binding, gen.new Piece(null, " (", null)));
c.getPieces().add(checkForNoChange(binding, gen.new Piece(corePath + "terminologies.html#" + binding.getStrength().toCode(), egt(binding.getStrengthElement()), binding.getStrength().getDefinition())));
c.getPieces().add(gen.new Piece(null, ")", null));
}
}
for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) {
if (!inv.hasSource() || allInvariants) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, inv.getKey() + ": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, gt(inv.getHumanElement()), null)));
}
}
if ((definition.hasBase() && definition.getBase().getMax().equals("*")) || (definition.hasMax() && definition.getMax().equals("*"))) {
if (c.getPieces().size() > 0)
c.addPiece(gen.new Piece("br"));
if (definition.hasOrderMeaning()) {
c.getPieces().add(gen.new Piece(null, "This repeating element order: " + definition.getOrderMeaning(), null));
} else {
// don't show this, this it's important: c.getPieces().add(gen.new Piece(null, "This repeating element has no defined order", null));
}
}
if (definition.hasFixed()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, translate("sd.table", "Fixed Value") + ": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, buildJson(definition.getFixed()), null).addStyle("color: darkgreen")));
if (isCoded(definition.getFixed()) && !hasDescription(definition.getFixed())) {
Piece p = describeCoded(gen, definition.getFixed());
if (p != null)
c.getPieces().add(p);
}
} else if (definition.hasPattern()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, translate("sd.table", "Required Pattern") + ": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
} else if (definition.hasExample()) {
for (ElementDefinitionExampleComponent ex : definition.getExample()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, translate("sd.table", "Example") + ("".equals("General") ? "" : " " + ex.getLabel() + "'") + ": ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, buildJson(ex.getValue()), null).addStyle("color: darkgreen")));
}
}
if (definition.hasMaxLength() && definition.getMaxLength() != 0) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, "Max Length: ", null).addStyle("font-weight:bold")));
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, Integer.toString(definition.getMaxLength()), null).addStyle("color: darkgreen")));
}
if (profile != null) {
for (StructureDefinitionMappingComponent md : profile.getMapping()) {
if (md.hasExtension(ToolingExtensions.EXT_TABLE_NAME)) {
ElementDefinitionMappingComponent map = null;
for (ElementDefinitionMappingComponent m : definition.getMapping()) if (m.getIdentity().equals(md.getIdentity()))
map = m;
if (map != null) {
for (int i = 0; i < definition.getMapping().size(); i++) {
c.addPiece(gen.new Piece("br"));
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(md, ToolingExtensions.EXT_TABLE_NAME) + ": " + map.getMap(), null));
}
}
}
}
}
}
}
}
return c;
}
use of org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileComparer method unionConstraints.
// we can't really know about constraints. We create warnings, and collate them
private List<ElementDefinitionConstraintComponent> unionConstraints(ElementDefinition ed, ProfileComparison outcome, String path, List<ElementDefinitionConstraintComponent> left, List<ElementDefinitionConstraintComponent> right) {
List<ElementDefinitionConstraintComponent> result = new ArrayList<ElementDefinitionConstraintComponent>();
for (ElementDefinitionConstraintComponent l : left) {
boolean found = false;
for (ElementDefinitionConstraintComponent r : right) if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity()))
found = true;
if (!found) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "StructureDefinition " + outcome.leftName() + " has a constraint that is not found in " + outcome.rightName() + " and it is uncertain whether they are compatible (" + l.getXpath() + ")", ValidationMessage.IssueSeverity.INFORMATION));
status(ed, ProfileUtilities.STATUS_WARNING);
}
result.add(l);
}
for (ElementDefinitionConstraintComponent r : right) {
boolean found = false;
for (ElementDefinitionConstraintComponent l : left) if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity()))
found = true;
if (!found) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "StructureDefinition " + outcome.rightName() + " has a constraint that is not found in " + outcome.leftName() + " and it is uncertain whether they are compatible (" + r.getXpath() + ")", ValidationMessage.IssueSeverity.INFORMATION));
status(ed, ProfileUtilities.STATUS_WARNING);
result.add(r);
}
}
return result;
}
use of org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.
the class CSVWriter method itemList.
private String itemList(List l) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < l.size(); i++) {
Object o = l.get(i);
String val = "";
if (o instanceof StringType) {
val = ((StringType) o).getValue();
} else if (o instanceof UriType) {
val = ((UriType) o).getValue();
} else if (o instanceof IdType) {
val = ((IdType) o).getValue();
} else if (o instanceof Enumeration<?>) {
val = o.toString();
} else if (o instanceof TypeRefComponent) {
TypeRefComponent t = (TypeRefComponent) o;
val = t.getWorkingCode() + (t.getProfile() == null ? "" : " {" + t.getProfile() + "}") + (t.getTargetProfile() == null ? "" : " {" + t.getTargetProfile() + "}") + (t.getAggregation() == null || t.getAggregation().isEmpty() ? "" : " (" + itemList(t.getAggregation()) + ")");
} else if (o instanceof Coding) {
Coding t = (Coding) o;
val = (t.getSystem() == null ? "" : t.getSystem()) + (t.getCode() == null ? "" : "#" + t.getCode()) + (t.getDisplay() == null ? "" : " (" + t.getDisplay() + ")");
} else if (o instanceof ElementDefinitionConstraintComponent) {
ElementDefinitionConstraintComponent c = (ElementDefinitionConstraintComponent) o;
val = c.getKey() + ":" + c.getHuman() + " {" + c.getExpression() + "}";
} else if (o instanceof ElementDefinitionSlicingDiscriminatorComponent) {
ElementDefinitionSlicingDiscriminatorComponent c = (ElementDefinitionSlicingDiscriminatorComponent) o;
val = c.getType().toCode() + ":" + c.getPath() + "}";
} else {
val = o.toString();
val = val.substring(val.indexOf("[") + 1);
val = val.substring(0, val.indexOf("]"));
}
s = s.append(val);
if (i == 0)
s.append("\n");
}
return s.toString();
}
Aggregations