Search in sources :

Example 16 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.dstu2.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.getCode() + (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();
}
Also used : ElementDefinitionSlicingDiscriminatorComponent(org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent) StringType(org.hl7.fhir.dstu3.model.StringType) TypeRefComponent(org.hl7.fhir.dstu3.model.ElementDefinition.TypeRefComponent) Coding(org.hl7.fhir.dstu3.model.Coding) ElementDefinitionConstraintComponent(org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionConstraintComponent) UriType(org.hl7.fhir.dstu3.model.UriType) IdType(org.hl7.fhir.dstu3.model.IdType)

Example 17 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.dstu2.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, 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;
}
Also used : ElementDefinitionExampleComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionExampleComponent) StructureDefinition(org.hl7.fhir.r4b.model.StructureDefinition) BindingResolution(org.hl7.fhir.r4b.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution) StructureDefinitionMappingComponent(org.hl7.fhir.r4b.model.StructureDefinition.StructureDefinitionMappingComponent) Piece(org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece) Cell(org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell) ElementDefinitionBindingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent) ElementDefinitionConstraintComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionConstraintComponent) ElementDefinitionMappingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionMappingComponent)

Example 18 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.dstu2.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.

the class ProfileUtilities method generateSnapshot.

/**
 * Given a base (snapshot) profile structure, and a differential profile, generate a new snapshot profile
 *
 * @param base - the base structure on which the differential will be applied
 * @param differential - the differential to apply to the base
 * @param url - where the base has relative urls for profile references, these need to be converted to absolutes by prepending this URL (e.g. the canonical URL)
 * @param webUrl - where the base has relative urls in markdown, these need to be converted to absolutes by prepending this URL (this is not the same as the canonical URL)
 * @param trimDifferential - if this is true, then the snap short generator will remove any material in the element definitions that is not different to the base
 * @return
 * @throws FHIRException
 * @throws DefinitionException
 * @throws Exception
 */
public void generateSnapshot(StructureDefinition base, StructureDefinition derived, String url, String webUrl, String profileName) throws DefinitionException, FHIRException {
    if (base == null) {
        throw new DefinitionException(context.formatMessage(I18nConstants.NO_BASE_PROFILE_PROVIDED));
    }
    if (derived == null) {
        throw new DefinitionException(context.formatMessage(I18nConstants.NO_DERIVED_STRUCTURE_PROVIDED));
    }
    checkNotGenerating(base, "Base for generating a snapshot for the profile " + derived.getUrl());
    checkNotGenerating(derived, "Focus for generating a snapshot");
    if (!base.hasType()) {
        throw new DefinitionException(context.formatMessage(I18nConstants.BASE_PROFILE__HAS_NO_TYPE, base.getUrl()));
    }
    if (!derived.hasType()) {
        throw new DefinitionException(context.formatMessage(I18nConstants.DERIVED_PROFILE__HAS_NO_TYPE, derived.getUrl()));
    }
    if (!derived.hasDerivation()) {
        throw new DefinitionException(context.formatMessage(I18nConstants.DERIVED_PROFILE__HAS_NO_DERIVATION_VALUE_AND_SO_CANT_BE_PROCESSED, derived.getUrl()));
    }
    if (!base.getType().equals(derived.getType()) && derived.getDerivation() == TypeDerivationRule.CONSTRAINT) {
        throw new DefinitionException(context.formatMessage(I18nConstants.BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___, base.getUrl(), base.getType(), derived.getUrl(), derived.getType()));
    }
    if (snapshotStack.contains(derived.getUrl())) {
        throw new DefinitionException(context.formatMessage(I18nConstants.CIRCULAR_SNAPSHOT_REFERENCES_DETECTED_CANNOT_GENERATE_SNAPSHOT_STACK__, snapshotStack.toString()));
    }
    derived.setUserData("profileutils.snapshot.generating", true);
    snapshotStack.add(derived.getUrl());
    try {
        if (!Utilities.noString(webUrl) && !webUrl.endsWith("/"))
            webUrl = webUrl + '/';
        if (defWebRoot == null)
            defWebRoot = webUrl;
        derived.setSnapshot(new StructureDefinitionSnapshotComponent());
        try {
            checkDifferential(derived.getDifferential().getElement(), typeName(derived.getType()), derived.getUrl());
            checkDifferentialBaseType(derived);
            // so we have two lists - the base list, and the differential list
            // the differential list is only allowed to include things that are in the base list, but
            // is allowed to include them multiple times - thereby slicing them
            // our approach is to walk through the base list, and see whether the differential
            // says anything about them.
            int baseCursor = 0;
            // we need a diff cursor because we can only look ahead, in the bound scoped by longer paths
            int diffCursor = 0;
            for (ElementDefinition e : derived.getDifferential().getElement()) e.clearUserData(GENERATED_IN_SNAPSHOT);
            // we actually delegate the work to a subroutine so we can re-enter it with a different cursors
            // we make a copy here because we're sometimes going to hack the differential while processing it. Have to migrate user data back afterwards
            StructureDefinitionDifferentialComponent diff = cloneDiff(derived.getDifferential());
            StructureDefinitionSnapshotComponent baseSnapshot = base.getSnapshot();
            if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
                String derivedType = derived.getType();
                if (StructureDefinitionKind.LOGICAL.equals(derived.getKind()) && derived.getType().contains("/")) {
                    derivedType = derivedType.substring(derivedType.lastIndexOf("/") + 1);
                }
                baseSnapshot = cloneSnapshot(baseSnapshot, base.getType(), derivedType);
            }
            // if (derived.getId().equals("2.16.840.1.113883.10.20.22.2.1.1")) {
            // debug = true;
            // }
            processPaths("", derived.getSnapshot(), baseSnapshot, diff, baseCursor, diffCursor, baseSnapshot.getElement().size() - 1, derived.getDifferential().hasElement() ? derived.getDifferential().getElement().size() - 1 : -1, url, webUrl, derived.present(), null, null, false, base.getUrl(), null, false, null, null, new ArrayList<ElementRedirection>(), base);
            checkGroupConstraints(derived);
            if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
                for (ElementDefinition e : diff.getElement()) {
                    if (!e.hasUserData(GENERATED_IN_SNAPSHOT)) {
                        ElementDefinition outcome = updateURLs(url, webUrl, e.copy());
                        e.setUserData(GENERATED_IN_SNAPSHOT, outcome);
                        derived.getSnapshot().addElement(outcome);
                    }
                }
            }
            if (derived.getKind() != StructureDefinitionKind.LOGICAL && !derived.getSnapshot().getElementFirstRep().getType().isEmpty())
                throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_SNAPSHOT_ELEMENT_FOR__IN__FROM_, derived.getSnapshot().getElementFirstRep().getPath(), derived.getUrl(), base.getUrl()));
            updateMaps(base, derived);
            setIds(derived, false);
            if (debug) {
                System.out.println("Differential: ");
                for (ElementDefinition ed : derived.getDifferential().getElement()) System.out.println("  " + ed.getId() + " : " + typeSummaryWithProfile(ed) + "[" + ed.getMin() + ".." + ed.getMax() + "]" + sliceSummary(ed) + "  " + constraintSummary(ed));
                System.out.println("Snapshot: ");
                for (ElementDefinition ed : derived.getSnapshot().getElement()) System.out.println("  " + ed.getId() + " : " + typeSummaryWithProfile(ed) + "[" + ed.getMin() + ".." + ed.getMax() + "]" + sliceSummary(ed) + "  " + constraintSummary(ed));
            }
            CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
            // Check that all differential elements have a corresponding snapshot element
            int ce = 0;
            for (ElementDefinition e : diff.getElement()) {
                if (!e.hasUserData("diff-source"))
                    throw new Error(context.formatMessage(I18nConstants.UNXPECTED_INTERNAL_CONDITION__NO_SOURCE_ON_DIFF_ELEMENT));
                else {
                    if (e.hasUserData(DERIVATION_EQUALS))
                        ((Base) e.getUserData("diff-source")).setUserData(DERIVATION_EQUALS, e.getUserData(DERIVATION_EQUALS));
                    if (e.hasUserData(DERIVATION_POINTER))
                        ((Base) e.getUserData("diff-source")).setUserData(DERIVATION_POINTER, e.getUserData(DERIVATION_POINTER));
                }
                if (!e.hasUserData(GENERATED_IN_SNAPSHOT)) {
                    b.append(e.hasId() ? "id: " + e.getId() : "path: " + e.getPath());
                    ce++;
                    if (e.hasId()) {
                        String msg = "No match found in the generated snapshot: check that the path and definitions are legal in the differential (including order)";
                        messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url + "#" + e.getId(), msg, ValidationMessage.IssueSeverity.ERROR));
                    }
                }
            }
            if (!Utilities.noString(b.toString())) {
                String msg = "The profile " + derived.getUrl() + " has " + ce + " " + Utilities.pluralize("element", ce) + " in the differential (" + b.toString() + ") that don't have a matching element in the snapshot: check that the path and definitions are legal in the differential (including order)";
                System.out.println("Error in snapshot generation: " + msg);
                if (!debug) {
                    System.out.println("Differential: ");
                    for (ElementDefinition ed : derived.getDifferential().getElement()) System.out.println("  " + ed.getId() + " = " + ed.getPath() + " : " + typeSummaryWithProfile(ed) + "[" + ed.getMin() + ".." + ed.getMax() + "]" + sliceSummary(ed) + "  " + constraintSummary(ed));
                    System.out.println("Snapshot: ");
                    for (ElementDefinition ed : derived.getSnapshot().getElement()) System.out.println("  " + ed.getId() + " = " + ed.getPath() + " : " + typeSummaryWithProfile(ed) + "[" + ed.getMin() + ".." + ed.getMax() + "]" + sliceSummary(ed) + "  " + constraintSummary(ed));
                }
                if (exception)
                    throw new DefinitionException(msg);
                else
                    messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url, msg, ValidationMessage.IssueSeverity.ERROR));
            }
            // hack around a problem in R4 definitions (somewhere?)
            for (ElementDefinition ed : derived.getSnapshot().getElement()) {
                for (ElementDefinitionMappingComponent mm : ed.getMapping()) {
                    if (mm.hasMap()) {
                        mm.setMap(mm.getMap().trim());
                    }
                }
                for (ElementDefinitionConstraintComponent s : ed.getConstraint()) {
                    if (s.hasSource()) {
                        String ref = s.getSource();
                        if (!Utilities.isAbsoluteUrl(ref)) {
                            if (ref.contains(".")) {
                                s.setSource("http://hl7.org/fhir/StructureDefinition/" + ref.substring(0, ref.indexOf(".")) + "#" + ref);
                            } else {
                                s.setSource("http://hl7.org/fhir/StructureDefinition/" + ref);
                            }
                        }
                    }
                }
            }
            if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
                for (ElementDefinition ed : derived.getSnapshot().getElement()) {
                    if (!ed.hasBase()) {
                        ed.getBase().setPath(ed.getPath()).setMin(ed.getMin()).setMax(ed.getMax());
                    }
                }
            }
            // last, check for wrong profiles or target profiles
            for (ElementDefinition ed : derived.getSnapshot().getElement()) {
                for (TypeRefComponent t : ed.getType()) {
                    for (UriType u : t.getProfile()) {
                        StructureDefinition sd = context.fetchResource(StructureDefinition.class, u.getValue());
                        if (sd == null) {
                            if (xver != null && xver.matchingUrl(u.getValue()) && xver.status(u.getValue()) == XVerExtensionStatus.Valid) {
                                sd = xver.makeDefinition(u.getValue());
                            }
                        }
                        if (sd == null) {
                            if (messages != null) {
                                messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url + "#" + ed.getId(), "The type of profile " + u.getValue() + " cannot be checked as the profile is not known", IssueSeverity.WARNING));
                            }
                        } else {
                            String wt = t.getWorkingCode();
                            if (ed.getPath().equals("Bundle.entry.response.outcome")) {
                                wt = "OperationOutcome";
                            }
                            if (!sd.getType().equals(wt)) {
                                boolean ok = isCompatibleType(wt, sd);
                                if (!ok) {
                                    String smsg = "The profile " + u.getValue() + " has type " + sd.getType() + " which is not consistent with the stated type " + wt;
                                    if (exception)
                                        throw new DefinitionException(smsg);
                                    else
                                        messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url + "#" + ed.getId(), smsg, IssueSeverity.ERROR));
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            // if we had an exception generating the snapshot, make sure we don't leave any half generated snapshot behind
            derived.setSnapshot(null);
            derived.clearUserData("profileutils.snapshot.generating");
            throw e;
        }
    } finally {
        derived.clearUserData("profileutils.snapshot.generating");
        snapshotStack.remove(derived.getUrl());
    }
}
Also used : ValidationMessage(org.hl7.fhir.utilities.validation.ValidationMessage) FHIRFormatError(org.hl7.fhir.exceptions.FHIRFormatError) CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder) ElementDefinitionConstraintComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionConstraintComponent) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) FileNotFoundException(java.io.FileNotFoundException) UriType(org.hl7.fhir.r4b.model.UriType) StructureDefinition(org.hl7.fhir.r4b.model.StructureDefinition) TypeRefComponent(org.hl7.fhir.r4b.model.ElementDefinition.TypeRefComponent) StructureDefinitionSnapshotComponent(org.hl7.fhir.r4b.model.StructureDefinition.StructureDefinitionSnapshotComponent) StructureDefinitionDifferentialComponent(org.hl7.fhir.r4b.model.StructureDefinition.StructureDefinitionDifferentialComponent) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) ElementDefinition(org.hl7.fhir.r4b.model.ElementDefinition) ElementDefinitionMappingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionMappingComponent)

Example 19 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.dstu2.model.ElementDefinition.ElementDefinitionConstraintComponent 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);
    }
}
Also used : ElementDefinitionExampleComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionExampleComponent) ValidationMessage(org.hl7.fhir.utilities.validation.ValidationMessage) StringType(org.hl7.fhir.r4b.model.StringType) FHIRFormatError(org.hl7.fhir.exceptions.FHIRFormatError) ElementDefinitionConstraintComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionConstraintComponent) IdType(org.hl7.fhir.r4b.model.IdType) Extension(org.hl7.fhir.r4b.model.Extension) StructureDefinition(org.hl7.fhir.r4b.model.StructureDefinition) TypeRefComponent(org.hl7.fhir.r4b.model.ElementDefinition.TypeRefComponent) ValueSetExpansionOutcome(org.hl7.fhir.r4b.terminologies.ValueSetExpander.ValueSetExpansionOutcome) ElementDefinition(org.hl7.fhir.r4b.model.ElementDefinition) ValueSet(org.hl7.fhir.r4b.model.ValueSet) ElementDefinitionBindingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent) ElementDefinitionMappingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionMappingComponent)

Example 20 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.dstu2.model.ElementDefinition.ElementDefinitionConstraintComponent in project org.hl7.fhir.core by hapifhir.

the class ProfileUtilities method processConstraint.

private ElementChoiceGroup processConstraint(List<ElementDefinition> children, ElementDefinitionConstraintComponent c) {
    if (!c.hasExpression()) {
        return null;
    }
    ExpressionNode expr = null;
    try {
        expr = fpe.parse(c.getExpression());
    } catch (Exception e) {
        return null;
    }
    if (expr.getKind() != Kind.Group || expr.getOpNext() == null || !(expr.getOperation() == Operation.Equals || expr.getOperation() == Operation.LessOrEqual)) {
        return null;
    }
    ExpressionNode n1 = expr.getGroup();
    ExpressionNode n2 = expr.getOpNext();
    if (n2.getKind() != Kind.Constant || n2.getInner() != null || n2.getOpNext() != null || !"1".equals(n2.getConstant().primitiveValue())) {
        return null;
    }
    ElementChoiceGroup grp = new ElementChoiceGroup(c.getKey(), expr.getOperation() == Operation.Equals);
    while (n1 != null) {
        if (n1.getKind() != Kind.Name || n1.getInner() != null) {
            return null;
        }
        grp.elements.add(n1.getName());
        if (n1.getOperation() == null || n1.getOperation() == Operation.Union) {
            n1 = n1.getOpNext();
        } else {
            return null;
        }
    }
    int total = 0;
    for (String n : grp.elements) {
        boolean found = false;
        for (ElementDefinition child : children) {
            String name = tail(child.getPath());
            if (n.equals(name)) {
                found = true;
                if (!"0".equals(child.getMax())) {
                    total++;
                }
            }
        }
        if (!found) {
            return null;
        }
    }
    if (total <= 1) {
        return null;
    }
    return grp;
}
Also used : ExpressionNode(org.hl7.fhir.r4b.model.ExpressionNode) ElementDefinition(org.hl7.fhir.r4b.model.ElementDefinition) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) FileNotFoundException(java.io.FileNotFoundException)

Aggregations

ElementDefinitionConstraintComponent (org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent)31 ValidationMessage (org.hl7.fhir.utilities.validation.ValidationMessage)25 ArrayList (java.util.ArrayList)23 ElementDefinition (org.hl7.fhir.r5.model.ElementDefinition)16 CommaSeparatedStringBuilder (org.hl7.fhir.utilities.CommaSeparatedStringBuilder)15 ElementDefinitionConstraintComponent (org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionConstraintComponent)14 StructureDefinition (org.hl7.fhir.r5.model.StructureDefinition)12 Cell (org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell)10 Piece (org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece)10 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)9 FHIRException (org.hl7.fhir.exceptions.FHIRException)9 ElementDefinition (org.hl7.fhir.r4b.model.ElementDefinition)9 StructureDefinition (org.hl7.fhir.r4b.model.StructureDefinition)9 Test (org.junit.jupiter.api.Test)8 FHIRFormatError (org.hl7.fhir.exceptions.FHIRFormatError)7 ElementDefinitionConstraintComponent (org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionConstraintComponent)7 TypeRefComponent (org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent)7 Rule (org.hl7.fhir.utilities.xml.SchematronWriter.Rule)7 Section (org.hl7.fhir.utilities.xml.SchematronWriter.Section)7 IOException (java.io.IOException)6