Search in sources :

Example 21 with ElementDefinitionConstraintComponent

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

the class XLSXWriter method itemList.

private String itemList(List l) {
    StringBuilder s = new StringBuilder();
    for (int i = 0; i < l.size(); i++) {
        Object o = l.get(i);
        String val = "";
        if (o instanceof StringType) {
            val = ((StringType) o).getValue();
        } else if (o instanceof UriType) {
            val = ((UriType) o).getValue();
        } else if (o instanceof IdType) {
            val = ((IdType) o).getValue();
        } else if (o instanceof Enumeration<?>) {
            val = o.toString();
        } else if (o instanceof TypeRefComponent) {
            TypeRefComponent t = (TypeRefComponent) o;
            val = t.getWorkingCode();
            if (val == null)
                val = "";
            if (val.startsWith("http://hl7.org/fhir/StructureDefinition/"))
                val = val.substring(40);
            if (t.hasTargetProfile())
                val = val + "(" + canonicalList(t.getTargetProfile()) + ")";
            if (t.hasProfile())
                val = val + " {" + canonicalList(t.getProfile()) + "}";
            if (t.hasAggregation())
                val = val + " <<" + aggList(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.r4b.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent) CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder) StringType(org.hl7.fhir.r4b.model.StringType) TypeRefComponent(org.hl7.fhir.r4b.model.ElementDefinition.TypeRefComponent) Coding(org.hl7.fhir.r4b.model.Coding) ElementDefinitionConstraintComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionConstraintComponent) UriType(org.hl7.fhir.r4b.model.UriType) IdType(org.hl7.fhir.r4b.model.IdType)

Example 22 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.r5.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.r5.model.ElementDefinition.ElementDefinitionConstraintComponent) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) ParseException(java.text.ParseException) FileNotFoundException(java.io.FileNotFoundException) UriType(org.hl7.fhir.r5.model.UriType) StructureDefinition(org.hl7.fhir.r5.model.StructureDefinition) TypeRefComponent(org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent) StructureDefinitionSnapshotComponent(org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionSnapshotComponent) StructureDefinitionDifferentialComponent(org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionDifferentialComponent) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) ElementDefinition(org.hl7.fhir.r5.model.ElementDefinition) ElementDefinitionMappingComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent)

Example 23 with ElementDefinitionConstraintComponent

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

the class ProfileUtilities method generateDescription.

private Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, 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.r5.model.ElementDefinition.ElementDefinitionExampleComponent) StructureDefinition(org.hl7.fhir.r5.model.StructureDefinition) BindingResolution(org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution) StructureDefinitionMappingComponent(org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent) Piece(org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece) Cell(org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell) ElementDefinitionBindingComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent) ElementDefinitionConstraintComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent) ElementDefinitionMappingComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent)

Example 24 with ElementDefinitionConstraintComponent

use of org.hl7.fhir.r5.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.r5.model.ExpressionNode) ElementDefinition(org.hl7.fhir.r5.model.ElementDefinition) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) ParseException(java.text.ParseException) FileNotFoundException(java.io.FileNotFoundException)

Example 25 with ElementDefinitionConstraintComponent

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

the class ProfileUtilities method generateForChildren.

private void generateForChildren(SchematronWriter sch, String xpath, ElementDefinition ed, StructureDefinition structure, StructureDefinition base) throws IOException {
    // generateForChild(txt, structure, child);
    List<ElementDefinition> children = getChildList(structure, ed);
    String sliceName = null;
    ElementDefinitionSlicingComponent slicing = null;
    for (ElementDefinition child : children) {
        String name = tail(child.getPath());
        if (child.hasSlicing()) {
            sliceName = name;
            slicing = child.getSlicing();
        } else if (!name.equals(sliceName))
            slicing = null;
        ElementDefinition based = getByPath(base, child.getPath());
        boolean doMin = (child.getMin() > 0) && (based == null || (child.getMin() != based.getMin()));
        boolean doMax = child.hasMax() && !child.getMax().equals("*") && (based == null || (!child.getMax().equals(based.getMax())));
        Slicer slicer = slicing == null ? new Slicer(true) : generateSlicer(child, slicing, structure);
        if (slicer.check) {
            if (doMin || doMax) {
                Section s = sch.section(xpath);
                Rule r = s.rule(xpath);
                if (doMin)
                    r.assrt("count(f:" + name + slicer.criteria + ") >= " + Integer.toString(child.getMin()), name + slicer.name + ": minimum cardinality of '" + name + "' is " + Integer.toString(child.getMin()));
                if (doMax)
                    r.assrt("count(f:" + name + slicer.criteria + ") <= " + child.getMax(), name + slicer.name + ": maximum cardinality of '" + name + "' is " + child.getMax());
            }
        }
    }
    for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
        if (inv.hasXpath()) {
            Section s = sch.section(ed.getPath());
            Rule r = s.rule(xpath);
            r.assrt(inv.getXpath(), (inv.hasId() ? inv.getId() + ": " : "") + inv.getHuman() + (inv.hasUserData(IS_DERIVED) ? " (inherited)" : ""));
        }
    }
    if (!ed.hasContentReference()) {
        for (ElementDefinition child : children) {
            String name = tail(child.getPath());
            generateForChildren(sch, xpath + "/f:" + name, child, structure, base);
        }
    }
}
Also used : ElementDefinitionSlicingComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent) ElementDefinition(org.hl7.fhir.r5.model.ElementDefinition) Rule(org.hl7.fhir.utilities.xml.SchematronWriter.Rule) TypeDerivationRule(org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule) Section(org.hl7.fhir.utilities.xml.SchematronWriter.Section) ElementDefinitionConstraintComponent(org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent)

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