use of org.hl7.elm.r1.Slice in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method determineSlicing.
private void determineSlicing(ElementDefinition slicer, List<ElementDefinition> slices) {
// first, name them
int i = 0;
for (ElementDefinition ed : slices) {
if (ed.hasUserData("slice-name")) {
ed.setSliceName(ed.getUserString("slice-name"));
} else {
i++;
ed.setSliceName("slice-" + Integer.toString(i));
}
}
// right now, we hard code this...
if (slicer.getPath().endsWith(".extension") || slicer.getPath().endsWith(".modifierExtension"))
slicer.getSlicing().addDiscriminator().setType(DiscriminatorType.VALUE).setPath("url");
else if (slicer.getPath().equals("DiagnosticReport.result"))
slicer.getSlicing().addDiscriminator().setType(DiscriminatorType.VALUE).setPath("reference.code");
else if (slicer.getPath().equals("Observation.related"))
slicer.getSlicing().addDiscriminator().setType(DiscriminatorType.VALUE).setPath("target.reference.code");
else if (slicer.getPath().equals("Bundle.entry"))
slicer.getSlicing().addDiscriminator().setType(DiscriminatorType.VALUE).setPath("resource.@profile");
else
throw new Error("No slicing for " + slicer.getPath());
}
use of org.hl7.elm.r1.Slice 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);
}
}
use of org.hl7.elm.r1.Slice in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method makeExtensionSlicing.
private ElementDefinitionSlicingComponent makeExtensionSlicing() {
ElementDefinitionSlicingComponent slice = new ElementDefinitionSlicingComponent();
slice.addDiscriminator().setPath("url").setType(DiscriminatorType.VALUE);
slice.setOrdered(false);
slice.setRules(SlicingRules.OPEN);
return slice;
}
use of org.hl7.elm.r1.Slice in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method genElementNameCell.
public Cell genElementNameCell(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef, boolean ext, UnusedTracker used, String ref, String sName, List<ElementDefinition> elements) throws IOException {
String hint = "";
hint = checkAdd(hint, (element.hasSliceName() ? translate("sd.table", "Slice") + " " + element.getSliceName() : ""));
if (hasDef && element.hasDefinition()) {
hint = checkAdd(hint, (hasDef && element.hasSliceName() ? ": " : ""));
hint = checkAdd(hint, !hasDef ? null : gt(element.getDefinitionElement()));
}
if (element.hasSlicing() && slicesExist(elements, element)) {
// some elements set up slicing but don't actually slice, so we don't augment the name
sName = "Slices for " + sName;
}
Cell left = gen.new Cell(null, ref, sName, hint, null);
row.getCells().add(left);
return left;
}
use of org.hl7.elm.r1.Slice in project org.hl7.fhir.core by hapifhir.
the class ProfileUtilities method getChildList.
public List<ElementDefinition> getChildList(StructureDefinition profile, String path, String id, boolean diff, boolean refs) {
List<ElementDefinition> res = new ArrayList<ElementDefinition>();
boolean capturing = id == null;
if (id == null && !path.contains("."))
capturing = true;
List<ElementDefinition> list = diff ? profile.getDifferential().getElement() : profile.getSnapshot().getElement();
for (ElementDefinition e : list) {
if (e == null)
throw new Error(context.formatMessage(I18nConstants.ELEMENT__NULL_, profile.getUrl()));
if (e.getId() == null)
throw new Error(context.formatMessage(I18nConstants.ELEMENT_ID__NULL__ON_, e.toString(), profile.getUrl()));
if (!capturing && id != null && e.getId().equals(id)) {
capturing = true;
}
// If our element is a slice, stop capturing children as soon as we see the next slice
if (capturing && e.hasId() && id != null && !e.getId().equals(id) && e.getPath().equals(path))
break;
if (capturing) {
String p = e.getPath();
if (refs && !Utilities.noString(e.getContentReference()) && path.startsWith(p)) {
if (path.length() > p.length()) {
return getChildList(profile, e.getContentReference() + "." + path.substring(p.length() + 1), null, diff);
} else if (e.getContentReference().startsWith("#")) {
return getChildList(profile, e.getContentReference().substring(1), null, diff);
} else if (e.getContentReference().contains("#")) {
String url = e.getContentReference().substring(0, e.getContentReference().indexOf("#"));
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null) {
throw new DefinitionException("Unable to find Structure " + url);
}
return getChildList(sd, e.getContentReference().substring(e.getContentReference().indexOf("#") + 1), null, diff);
} else {
return getChildList(profile, e.getContentReference(), null, diff);
}
} else if (p.startsWith(path + ".") && !p.equals(path)) {
String tail = p.substring(path.length() + 1);
if (!tail.contains(".")) {
res.add(e);
}
}
}
}
return res;
}
Aggregations