use of org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileComparer method unionBindings.
private ElementDefinitionBindingComponent unionBindings(ElementDefinition ed, ProfileComparison outcome, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right) {
ElementDefinitionBindingComponent union = new ElementDefinitionBindingComponent();
if (left.getStrength().compareTo(right.getStrength()) < 0)
union.setStrength(left.getStrength());
else
union.setStrength(right.getStrength());
union.setDescription(mergeText(ed, outcome, path, "binding.description", left.getDescription(), right.getDescription()));
if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false))
union.setValueSet(left.getValueSet());
else {
ValueSet lvs = resolveVS(outcome.left, left.getValueSet());
ValueSet rvs = resolveVS(outcome.left, right.getValueSet());
if (lvs != null && rvs != null)
union.setValueSet(new Reference().setReference("#" + addValueSet(unite(ed, outcome, path, lvs, rvs))));
else if (lvs != null)
union.setValueSet(new Reference().setReference("#" + addValueSet(lvs)));
else if (rvs != null)
union.setValueSet(new Reference().setReference("#" + addValueSet(rvs)));
}
return union;
}
use of org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileComparer method compareBindings.
private boolean compareBindings(ProfileComparison outcome, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) {
assert (lDef.hasBinding() || rDef.hasBinding());
if (!lDef.hasBinding()) {
subset.setBinding(rDef.getBinding());
// technically, the super set is unbound, but that's not very useful - so we use the provided on as an example
superset.setBinding(rDef.getBinding().copy());
superset.getBinding().setStrength(BindingStrength.EXAMPLE);
return true;
}
if (!rDef.hasBinding()) {
subset.setBinding(lDef.getBinding());
superset.setBinding(lDef.getBinding().copy());
superset.getBinding().setStrength(BindingStrength.EXAMPLE);
return true;
}
ElementDefinitionBindingComponent left = lDef.getBinding();
ElementDefinitionBindingComponent right = rDef.getBinding();
if (Base.compareDeep(left, right, false)) {
subset.setBinding(left);
superset.setBinding(right);
}
// superset:
if (isPreferredOrExample(left) && isPreferredOrExample(right)) {
if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Example/preferred bindings differ at " + path + " using binding from " + outcome.rightName(), IssueSeverity.INFORMATION));
status(subset, ProfileUtilities.STATUS_HINT);
subset.setBinding(right);
superset.setBinding(unionBindings(superset, outcome, path, left, right));
} else {
if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Example/preferred bindings differ at " + path + " using binding from " + outcome.leftName(), IssueSeverity.INFORMATION));
status(subset, ProfileUtilities.STATUS_HINT);
}
subset.setBinding(left);
superset.setBinding(unionBindings(superset, outcome, path, left, right));
}
return true;
}
// if either of them are extensible/required, then it wins
if (isPreferredOrExample(left)) {
subset.setBinding(right);
superset.setBinding(unionBindings(superset, outcome, path, left, right));
return true;
}
if (isPreferredOrExample(right)) {
subset.setBinding(left);
superset.setBinding(unionBindings(superset, outcome, path, left, right));
return true;
}
// ok, both are extensible or required.
ElementDefinitionBindingComponent subBinding = new ElementDefinitionBindingComponent();
subset.setBinding(subBinding);
ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent();
superset.setBinding(superBinding);
subBinding.setDescription(mergeText(subset, outcome, path, "description", left.getDescription(), right.getDescription()));
superBinding.setDescription(mergeText(subset, outcome, null, "description", left.getDescription(), right.getDescription()));
if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED)
subBinding.setStrength(BindingStrength.REQUIRED);
else
subBinding.setStrength(BindingStrength.EXTENSIBLE);
if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE)
superBinding.setStrength(BindingStrength.EXTENSIBLE);
else
superBinding.setStrength(BindingStrength.REQUIRED);
if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
subBinding.setValueSet(left.getValueSet());
superBinding.setValueSet(left.getValueSet());
return true;
} else if (!left.hasValueSet()) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "No left Value set at " + path, IssueSeverity.ERROR));
return true;
} else if (!right.hasValueSet()) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "No right Value set at " + path, IssueSeverity.ERROR));
return true;
} else {
// ok, now we compare the value sets. This may be unresolvable.
ValueSet lvs = resolveVS(outcome.left, left.getValueSet());
ValueSet rvs = resolveVS(outcome.right, right.getValueSet());
if (lvs == null) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Unable to resolve left value set " + left.getValueSet().toString() + " at " + path, IssueSeverity.ERROR));
return true;
} else if (rvs == null) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Unable to resolve right value set " + right.getValueSet().toString() + " at " + path, IssueSeverity.ERROR));
return true;
} else {
// first, we'll try to do it by definition
ValueSet cvs = intersectByDefinition(lvs, rvs);
if (cvs == null) {
// if that didn't work, we'll do it by expansion
ValueSetExpansionOutcome le;
ValueSetExpansionOutcome re;
try {
le = context.expandVS(lvs, true);
re = context.expandVS(rvs, true);
if (!closed(le.getValueset()) || !closed(re.getValueset()))
throw new DefinitionException("unclosed value sets are not handled yet");
cvs = intersectByExpansion(lvs, rvs);
if (!cvs.getCompose().hasInclude()) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "The value sets " + lvs.getUrl() + " and " + rvs.getUrl() + " do not intersect", IssueSeverity.ERROR));
status(subset, ProfileUtilities.STATUS_ERROR);
return false;
}
} catch (Exception e) {
outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Unable to expand or process value sets " + lvs.getUrl() + " and " + rvs.getUrl() + ": " + e.getMessage(), IssueSeverity.ERROR));
status(subset, ProfileUtilities.STATUS_ERROR);
return false;
}
}
subBinding.setValueSet(new Reference().setReference("#" + addValueSet(cvs)));
superBinding.setValueSet(new Reference().setReference("#" + addValueSet(unite(superset, outcome, path, lvs, rvs))));
}
}
return false;
}
use of org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent 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, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException {
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 (root) {
if (profile != null && profile.getAbstract()) {
if (!c.getPieces().isEmpty()) {
c.addPiece(gen.new Piece("br"));
}
c.addPiece(gen.new Piece(null, "This is an abstract profile", 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(gen.new Piece(null, gt(fallback.getShortElement()), null).addStyle("opacity: 0.5"));
}
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;
String ref2 = null;
String fixedUrl = null;
if (ed != null) {
String p = ed.getUserString("path");
if (p != null) {
ref = p.startsWith("http:") || igmode ? p : Utilities.pathURL(corePath, p);
}
fixedUrl = getFixedUrl(ed);
if (fixedUrl != null) {
// if its null, we guess that it's not a profiled extension?
if (fixedUrl.equals(url))
fixedUrl = null;
else {
StructureDefinition ed2 = context.fetchResource(StructureDefinition.class, fixedUrl);
if (ed2 != null) {
String p2 = ed2.getUserString("path");
if (p2 != null) {
ref2 = p2.startsWith("http:") || igmode ? p2 : Utilities.pathURL(corePath, p2);
}
}
}
}
}
if (fixedUrl == null) {
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));
} else {
// reference to a profile take on the extension show the base URL
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(ref2, fixedUrl, null));
c.getPieces().add(gen.new Piece(null, translate("sd.table", " profiled by ") + " ", 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.getPath().contains(".") && ToolingExtensions.hasExtension(profile, ToolingExtensions.EXT_BINDING_STYLE)) {
if (!c.getPieces().isEmpty()) {
c.addPiece(gen.new Piece("br"));
}
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Binding") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, "This type can be bound to a value set using the ", null));
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_BINDING_STYLE), null));
c.getPieces().add(gen.new Piece(null, " binding style", null));
}
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAME)) {
if (!c.getPieces().isEmpty()) {
c.addPiece(gen.new Piece("br"));
}
if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAME), null));
c.getPieces().add(gen.new Piece(null, " (", null));
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
c.getPieces().add(gen.new Piece(null, ")", null));
} else {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Element Name") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAME), null));
}
} else if (definition.hasExtension(ToolingExtensions.EXT_XML_NAMESPACE)) {
if (!c.getPieces().isEmpty()) {
c.addPiece(gen.new Piece("br"));
}
c.getPieces().add(gen.new Piece(null, translate("sd.table", "XML Namespace") + ": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(null, definition.getExtensionString(ToolingExtensions.EXT_XML_NAMESPACE), null));
}
if (definition != null) {
ElementDefinitionBindingComponent binding = null;
if (valueDefn != null && valueDefn.hasBinding() && !valueDefn.getBinding().isEmpty())
binding = makeUnifiedBinding(valueDefn.getBinding(), valueDefn);
else if (definition.hasBinding())
binding = makeUnifiedBinding(definition.getBinding(), definition);
if (binding != null && !binding.isEmpty()) {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
BindingResolution br = pkp == null ? makeNullBr(binding) : 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.getValueSetElement(), 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.getStrengthElement(), gen.new Piece(null, " (", null)));
c.getPieces().add(checkForNoChange(binding.getStrengthElement(), gen.new Piece(corePath + "terminologies.html#" + binding.getStrength().toCode(), egt(binding.getStrengthElement()), binding.getStrength().getDefinition())));
c.getPieces().add(checkForNoChange(binding.getStrengthElement(), gen.new Piece(null, ")", null)));
}
if (binding.hasDescription() && MarkDownProcessor.isSimpleMarkdown(binding.getDescription())) {
c.getPieces().add(gen.new Piece(null, ": ", null));
c.addMarkdownNoPara(PublicationHacker.fixBindingDescriptions(context, binding.getDescriptionElement()).asStringValue(), checkForNoChange(PublicationHacker.fixBindingDescriptions(context, binding.getDescriptionElement())));
}
AdditionalBindingsRenderer abr = new AdditionalBindingsRenderer(pkp, corePath, profile, definition.getPath(), rc, null);
if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET)) {
abr.seeMaxBinding(ToolingExtensions.getExtension(binding, ToolingExtensions.EXT_MAX_VALUESET));
}
if (binding.hasExtension(ToolingExtensions.EXT_MIN_VALUESET)) {
abr.seeMinBinding(ToolingExtensions.getExtension(binding, ToolingExtensions.EXT_MIN_VALUESET));
}
if (binding.hasExtension(ToolingExtensions.EXT_BINDING_ADDITIONAL)) {
abr.seeAdditionalBindings(binding.getExtensionsByUrl(ToolingExtensions.EXT_BINDING_ADDITIONAL));
}
abr.render(gen, c);
}
for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) {
if (!inv.hasSource() || profile == null || inv.getSource().equals(profile.getUrl()) || 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() && "*".equals(definition.getBase().getMax())) || (definition.hasMax() && "*".equals(definition.getMax()))) {
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")));
if (!useTableForFixedValues || !allowSubRows || definition.getFixed().isPrimitive()) {
String s = buildJson(definition.getFixed());
String link = null;
if (Utilities.isAbsoluteUrl(s))
link = pkp.getLinkForUrl(corePath, s);
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(link, s, null).addStyle("color: darkgreen")));
} else {
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "As shown", null).addStyle("color: darkgreen")));
genFixedValue(gen, row, definition.getFixed(), snapshot, false, corePath, false);
}
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")));
if (!useTableForFixedValues || !allowSubRows || definition.getPattern().isPrimitive())
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
else {
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, "At least the following", null).addStyle("color: darkgreen")));
genFixedValue(gen, row, definition.getPattern(), snapshot, true, corePath, mustSupportOnly);
}
} 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.r4b.model.ElementDefinition.ElementDefinitionBindingComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileComparer method compareBindings.
private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException {
assert (lDef.hasBinding() || rDef.hasBinding());
if (!lDef.hasBinding()) {
subset.setBinding(rDef.getBinding());
// technically, the super set is unbound, but that's not very useful - so we use the provided on as an example
superset.setBinding(rDef.getBinding().copy());
superset.getBinding().setStrength(BindingStrength.EXAMPLE);
return true;
}
if (!rDef.hasBinding()) {
subset.setBinding(lDef.getBinding());
superset.setBinding(lDef.getBinding().copy());
superset.getBinding().setStrength(BindingStrength.EXAMPLE);
return true;
}
ElementDefinitionBindingComponent left = lDef.getBinding();
ElementDefinitionBindingComponent right = rDef.getBinding();
if (Base.compareDeep(left, right, false)) {
subset.setBinding(left);
superset.setBinding(right);
}
// superset:
if (isPreferredOrExample(left) && isPreferredOrExample(right)) {
if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at " + path + " using binding from " + comp.getRight().getName(), path, comp.getMessages(), res.getMessages());
subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right));
} else {
if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at " + path + " using binding from " + comp.getLeft().getName(), path, comp.getMessages(), res.getMessages());
}
subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right));
}
return true;
}
// if either of them are extensible/required, then it wins
if (isPreferredOrExample(left)) {
subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right));
return true;
}
if (isPreferredOrExample(right)) {
subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right));
return true;
}
// ok, both are extensible or required.
ElementDefinitionBindingComponent subBinding = new ElementDefinitionBindingComponent();
subset.setBinding(subBinding);
ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent();
superset.setBinding(superBinding);
subBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription(), false));
superBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription(), false));
if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED)
subBinding.setStrength(BindingStrength.REQUIRED);
else
subBinding.setStrength(BindingStrength.EXTENSIBLE);
if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE)
superBinding.setStrength(BindingStrength.EXTENSIBLE);
else
superBinding.setStrength(BindingStrength.REQUIRED);
if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
subBinding.setValueSet(left.getValueSet());
superBinding.setValueSet(left.getValueSet());
return true;
} else if (!left.hasValueSet()) {
vm(IssueSeverity.ERROR, "No left Value set at " + path, path, comp.getMessages(), res.getMessages());
return true;
} else if (!right.hasValueSet()) {
vm(IssueSeverity.ERROR, "No right Value set at " + path, path, comp.getMessages(), res.getMessages());
return true;
} else {
// ok, now we compare the value sets. This may be unresolvable.
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), session.getContextRight());
if (lvs == null) {
vm(IssueSeverity.ERROR, "Unable to resolve left value set " + left.getValueSet().toString() + " at " + path, path, comp.getMessages(), res.getMessages());
return true;
} else if (rvs == null) {
vm(IssueSeverity.ERROR, "Unable to resolve right value set " + right.getValueSet().toString() + " at " + path, path, comp.getMessages(), res.getMessages());
return true;
} else if (sameValueSets(lvs, rvs)) {
subBinding.setValueSet(lvs.getUrl());
superBinding.setValueSet(lvs.getUrl());
} else {
ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs);
if (compP != null) {
subBinding.setValueSet(compP.getIntersection().getUrl());
superBinding.setValueSet(compP.getUnion().getUrl());
}
}
}
return false;
}
use of org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method updateFromDefinition.
private void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD) throws DefinitionException, FHIRException {
source.setUserData(GENERATED_IN_SNAPSHOT, dest);
// we start with a clone of the base profile ('dest') and we copy from the profile ('source')
// over the top for anything the source has
ElementDefinition base = dest;
ElementDefinition derived = source;
derived.setUserData(DERIVATION_POINTER, base);
boolean isExtension = checkExtensionDoco(base);
// Before applying changes, apply them to what's in the profile
StructureDefinition profile = null;
if (base.hasSliceName())
profile = base.getType().size() == 1 && base.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, base.getTypeFirstRep().getProfile().get(0).getValue()) : null;
if (profile == null)
profile = source.getType().size() == 1 && source.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, source.getTypeFirstRep().getProfile().get(0).getValue()) : null;
if (profile != null) {
ElementDefinition e = profile.getSnapshot().getElement().get(0);
String webroot = profile.getUserString("webroot");
if (e.hasDefinition()) {
base.setDefinition(processRelativeUrls(e.getDefinition(), webroot, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, null, true));
}
base.setShort(e.getShort());
if (e.hasCommentElement())
base.setCommentElement(e.getCommentElement());
if (e.hasRequirementsElement())
base.setRequirementsElement(e.getRequirementsElement());
base.getAlias().clear();
base.getAlias().addAll(e.getAlias());
base.getMapping().clear();
base.getMapping().addAll(e.getMapping());
}
if (derived != null) {
if (derived.hasSliceName()) {
base.setSliceName(derived.getSliceName());
}
if (derived.hasShortElement()) {
if (!Base.compareDeep(derived.getShortElement(), base.getShortElement(), false))
base.setShortElement(derived.getShortElement().copy());
else if (trimDifferential)
derived.setShortElement(null);
else if (derived.hasShortElement())
derived.getShortElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasDefinitionElement()) {
if (derived.getDefinition().startsWith("..."))
base.setDefinition(base.getDefinition() + "\r\n" + derived.getDefinition().substring(3));
else if (!Base.compareDeep(derived.getDefinitionElement(), base.getDefinitionElement(), false))
base.setDefinitionElement(derived.getDefinitionElement().copy());
else if (trimDifferential)
derived.setDefinitionElement(null);
else if (derived.hasDefinitionElement())
derived.getDefinitionElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasCommentElement()) {
if (derived.getComment().startsWith("..."))
base.setComment(base.getComment() + "\r\n" + derived.getComment().substring(3));
else if (derived.hasCommentElement() != base.hasCommentElement() || !Base.compareDeep(derived.getCommentElement(), base.getCommentElement(), false))
base.setCommentElement(derived.getCommentElement().copy());
else if (trimDifferential)
base.setCommentElement(derived.getCommentElement().copy());
else if (derived.hasCommentElement())
derived.getCommentElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasLabelElement()) {
if (derived.getLabel().startsWith("..."))
base.setLabel(base.getLabel() + "\r\n" + derived.getLabel().substring(3));
else if (!base.hasLabelElement() || !Base.compareDeep(derived.getLabelElement(), base.getLabelElement(), false))
base.setLabelElement(derived.getLabelElement().copy());
else if (trimDifferential)
base.setLabelElement(derived.getLabelElement().copy());
else if (derived.hasLabelElement())
derived.getLabelElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasRequirementsElement()) {
if (derived.getRequirements().startsWith("..."))
base.setRequirements(base.getRequirements() + "\r\n" + derived.getRequirements().substring(3));
else if (!base.hasRequirementsElement() || !Base.compareDeep(derived.getRequirementsElement(), base.getRequirementsElement(), false))
base.setRequirementsElement(derived.getRequirementsElement().copy());
else if (trimDifferential)
base.setRequirementsElement(derived.getRequirementsElement().copy());
else if (derived.hasRequirementsElement())
derived.getRequirementsElement().setUserData(DERIVATION_EQUALS, true);
}
// sdf-9
if (derived.hasRequirements() && !base.getPath().contains("."))
derived.setRequirements(null);
if (base.hasRequirements() && !base.getPath().contains("."))
base.setRequirements(null);
if (derived.hasAlias()) {
if (!Base.compareDeep(derived.getAlias(), base.getAlias(), false))
for (StringType s : derived.getAlias()) {
if (!base.hasAlias(s.getValue()))
base.getAlias().add(s.copy());
}
else if (trimDifferential)
derived.getAlias().clear();
else
for (StringType t : derived.getAlias()) t.setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMinElement()) {
if (!Base.compareDeep(derived.getMinElement(), base.getMinElement(), false)) {
if (// in a slice, minimum cardinality rules do not apply
derived.getMin() < base.getMin() && !derived.hasSliceName())
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + source.getPath(), "Element " + base.getPath() + ": derived min (" + Integer.toString(derived.getMin()) + ") cannot be less than base min (" + Integer.toString(base.getMin()) + ")", ValidationMessage.IssueSeverity.ERROR));
base.setMinElement(derived.getMinElement().copy());
} else if (trimDifferential)
derived.setMinElement(null);
else
derived.getMinElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMaxElement()) {
if (!Base.compareDeep(derived.getMaxElement(), base.getMaxElement(), false)) {
if (isLargerMax(derived.getMax(), base.getMax()))
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + source.getPath(), "Element " + base.getPath() + ": derived max (" + derived.getMax() + ") cannot be greater than base max (" + base.getMax() + ")", ValidationMessage.IssueSeverity.ERROR));
base.setMaxElement(derived.getMaxElement().copy());
} else if (trimDifferential)
derived.setMaxElement(null);
else
derived.getMaxElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasFixed()) {
if (!Base.compareDeep(derived.getFixed(), base.getFixed(), true)) {
base.setFixed(derived.getFixed().copy());
} else if (trimDifferential)
derived.setFixed(null);
else
derived.getFixed().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasPattern()) {
if (!Base.compareDeep(derived.getPattern(), base.getPattern(), false)) {
base.setPattern(derived.getPattern().copy());
} else if (trimDifferential)
derived.setPattern(null);
else
derived.getPattern().setUserData(DERIVATION_EQUALS, true);
}
for (ElementDefinitionExampleComponent ex : derived.getExample()) {
boolean found = false;
for (ElementDefinitionExampleComponent exS : base.getExample()) if (Base.compareDeep(ex, exS, false))
found = true;
if (!found)
base.addExample(ex.copy());
else if (trimDifferential)
derived.getExample().remove(ex);
else
ex.setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMaxLengthElement()) {
if (!Base.compareDeep(derived.getMaxLengthElement(), base.getMaxLengthElement(), false))
base.setMaxLengthElement(derived.getMaxLengthElement().copy());
else if (trimDifferential)
derived.setMaxLengthElement(null);
else
derived.getMaxLengthElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMaxValue()) {
if (!Base.compareDeep(derived.getMaxValue(), base.getMaxValue(), false))
base.setMaxValue(derived.getMaxValue().copy());
else if (trimDifferential)
derived.setMaxValue(null);
else
derived.getMaxValue().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMinValue()) {
if (!Base.compareDeep(derived.getMinValue(), base.getMinValue(), false))
base.setMinValue(derived.getMinValue().copy());
else if (trimDifferential)
derived.setMinValue(null);
else
derived.getMinValue().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMustSupportElement()) {
if (!(base.hasMustSupportElement() && Base.compareDeep(derived.getMustSupportElement(), base.getMustSupportElement(), false))) {
if (base.hasMustSupport() && base.getMustSupport() && !derived.getMustSupport()) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "Illegal constraint [must-support = false] when [must-support = true] in the base profile", ValidationMessage.IssueSeverity.ERROR));
}
base.setMustSupportElement(derived.getMustSupportElement().copy());
} else if (trimDifferential)
derived.setMustSupportElement(null);
else
derived.getMustSupportElement().setUserData(DERIVATION_EQUALS, true);
}
// but extensions can change isModifier
if (isExtension) {
if (derived.hasIsModifierElement() && !(base.hasIsModifierElement() && Base.compareDeep(derived.getIsModifierElement(), base.getIsModifierElement(), false)))
base.setIsModifierElement(derived.getIsModifierElement().copy());
else if (trimDifferential)
derived.setIsModifierElement(null);
else if (derived.hasIsModifierElement())
derived.getIsModifierElement().setUserData(DERIVATION_EQUALS, true);
if (derived.hasIsModifierReasonElement() && !(base.hasIsModifierReasonElement() && Base.compareDeep(derived.getIsModifierReasonElement(), base.getIsModifierReasonElement(), false)))
base.setIsModifierReasonElement(derived.getIsModifierReasonElement().copy());
else if (trimDifferential)
derived.setIsModifierReasonElement(null);
else if (derived.hasIsModifierReasonElement())
derived.getIsModifierReasonElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasBinding()) {
if (!base.hasBinding() || !Base.compareDeep(derived.getBinding(), base.getBinding(), false)) {
if (base.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && derived.getBinding().getStrength() != BindingStrength.REQUIRED)
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "illegal attempt to change the binding on " + derived.getPath() + " from " + base.getBinding().getStrength().toCode() + " to " + derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR));
else // throw new DefinitionException("StructureDefinition "+pn+" at "+derived.getPath()+": illegal attempt to change a binding from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode());
if (base.hasBinding() && derived.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && base.getBinding().hasValueSet() && derived.getBinding().hasValueSet()) {
ValueSet baseVs = context.fetchResource(ValueSet.class, base.getBinding().getValueSet());
ValueSet contextVs = context.fetchResource(ValueSet.class, derived.getBinding().getValueSet());
if (baseVs == null) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + base.getPath(), "Binding " + base.getBinding().getValueSet() + " could not be located", ValidationMessage.IssueSeverity.WARNING));
} else if (contextVs == null) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "Binding " + derived.getBinding().getValueSet() + " could not be located", ValidationMessage.IssueSeverity.WARNING));
} else {
ValueSetExpansionOutcome expBase = context.expandVS(baseVs, true, false);
ValueSetExpansionOutcome expDerived = context.expandVS(contextVs, true, false);
if (expBase.getValueset() == null)
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + base.getPath(), "Binding " + base.getBinding().getValueSet() + " could not be expanded", ValidationMessage.IssueSeverity.WARNING));
else if (expDerived.getValueset() == null)
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "Binding " + derived.getBinding().getValueSet() + " could not be expanded", ValidationMessage.IssueSeverity.WARNING));
else if (ToolingExtensions.hasExtension(expBase.getValueset().getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY))
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "Unable to check if " + derived.getBinding().getValueSet() + " is a proper subset of " + base.getBinding().getValueSet() + " - base value set is too large to check", ValidationMessage.IssueSeverity.WARNING));
else if (!isSubset(expBase.getValueset(), expDerived.getValueset()))
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn + "." + derived.getPath(), "Binding " + derived.getBinding().getValueSet() + " is not a subset of binding " + base.getBinding().getValueSet(), ValidationMessage.IssueSeverity.ERROR));
}
}
ElementDefinitionBindingComponent d = derived.getBinding();
ElementDefinitionBindingComponent nb = base.getBinding().copy();
if (!COPY_BINDING_EXTENSIONS) {
nb.getExtension().clear();
}
nb.setDescription(null);
nb.getExtension().addAll(d.getExtension());
if (d.hasStrength()) {
nb.setStrength(d.getStrength());
}
if (d.hasDescription()) {
nb.setDescription(d.getDescription());
}
if (d.hasValueSet()) {
nb.setValueSet(d.getValueSet());
}
base.setBinding(nb);
} else if (trimDifferential)
derived.setBinding(null);
else
derived.getBinding().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasIsSummaryElement()) {
if (!Base.compareDeep(derived.getIsSummaryElement(), base.getIsSummaryElement(), false)) {
if (// work around a known issue with some 1.4.0 cosntraints
base.hasIsSummary() && !context.getVersion().equals("1.4.0"))
throw new Error(context.formatMessage(I18nConstants.ERROR_IN_PROFILE__AT__BASE_ISSUMMARY___DERIVED_ISSUMMARY__, purl, derived.getPath(), base.getIsSummaryElement().asStringValue(), derived.getIsSummaryElement().asStringValue()));
base.setIsSummaryElement(derived.getIsSummaryElement().copy());
} else if (trimDifferential)
derived.setIsSummaryElement(null);
else
derived.getIsSummaryElement().setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasType()) {
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
if (base.hasType()) {
for (TypeRefComponent ts : derived.getType()) {
checkTypeDerivation(purl, srcSD, base, derived, ts);
}
}
base.getType().clear();
for (TypeRefComponent t : derived.getType()) {
TypeRefComponent tt = t.copy();
// tt.setUserData(DERIVATION_EQUALS, true);
base.getType().add(tt);
}
} else if (trimDifferential)
derived.getType().clear();
else
for (TypeRefComponent t : derived.getType()) t.setUserData(DERIVATION_EQUALS, true);
}
if (derived.hasMapping()) {
// todo: mappings are not cumulative - one replaces another
if (!Base.compareDeep(derived.getMapping(), base.getMapping(), false)) {
for (ElementDefinitionMappingComponent s : derived.getMapping()) {
boolean found = false;
for (ElementDefinitionMappingComponent d : base.getMapping()) {
found = found || (d.getIdentity().equals(s.getIdentity()) && d.getMap().equals(s.getMap()));
}
if (!found) {
base.getMapping().add(s);
}
}
} else if (trimDifferential) {
derived.getMapping().clear();
} else {
for (ElementDefinitionMappingComponent t : derived.getMapping()) {
t.setUserData(DERIVATION_EQUALS, true);
}
}
}
for (ElementDefinitionMappingComponent m : base.getMapping()) {
if (m.hasMap()) {
m.setMap(m.getMap().trim());
}
}
// todo: constraints are cumulative. there is no replacing
for (ElementDefinitionConstraintComponent s : base.getConstraint()) {
s.setUserData(IS_DERIVED, true);
if (!s.hasSource()) {
s.setSource(srcSD.getUrl());
}
}
if (derived.hasConstraint()) {
for (ElementDefinitionConstraintComponent s : derived.getConstraint()) {
if (!base.hasConstraint(s.getKey())) {
ElementDefinitionConstraintComponent inv = s.copy();
base.getConstraint().add(inv);
}
}
}
for (IdType id : derived.getCondition()) {
if (!base.hasCondition(id)) {
base.getCondition().add(id);
}
}
// now, check that we still have a bindable type; if not, delete the binding - see task 8477
if (dest.hasBinding() && !hasBindableType(dest)) {
dest.setBinding(null);
}
// finally, we copy any extensions from source to dest
for (Extension ex : derived.getExtension()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ex.getUrl());
if (sd == null || sd.getSnapshot() == null || sd.getSnapshot().getElementFirstRep().getMax().equals("1")) {
ToolingExtensions.removeExtension(dest, ex.getUrl());
}
dest.addExtension(ex.copy());
}
}
if (dest.hasFixed()) {
checkTypeOk(dest, dest.getFixed().fhirType(), srcSD);
}
if (dest.hasPattern()) {
checkTypeOk(dest, dest.getPattern().fhirType(), srcSD);
}
}
Aggregations