Search in sources :

Example 81 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project kindling by HL7.

the class ResourceValidator method check.

// private List<ValidationMessage> check(String n, BindingSpecification cd) throws Exception {
// List<ValidationMessage> errors = new ArrayList<ValidationMessage>();
// check(errors, n, cd);
// return errors;
// }
private void check(List<ValidationMessage> errors, String path, BindingSpecification cd, String sd, ElementDefn e) throws Exception {
    // basic integrity checks
    List<DefinedCode> ac = cd.getAllCodes(definitions.getCodeSystems(), definitions.getValuesets(), false);
    for (DefinedCode c : ac) {
        String d = c.getCode();
        if (Utilities.noString(d))
            d = c.getId();
        if (Utilities.noString(d))
            d = c.getDisplay();
        if (Utilities.noString(d))
            d = c.getDisplay();
        if (Utilities.noString(c.getSystem()))
            warning(errors, IssueType.STRUCTURE, "Binding @ " + path, !Utilities.noString(c.getDefinition()), "Code " + d + " must have a definition");
        rule(errors, IssueType.STRUCTURE, "Binding @ " + path, !(Utilities.noString(c.getId()) && Utilities.noString(c.getSystem())), "Code " + d + " must have a id or a system");
    }
    // trigger processing into a Heirachical set if necessary
    // rule(errors, IssueType.STRUCTURE, "Binding @ "+path, !cd.isHeirachical() || (cd.getChildCodes().size() < cd.getCodes().size()), "Logic error processing Hirachical code set");
    // now, rules for the source
    hint(errors, IssueType.STRUCTURE, "Binding @ " + path, cd.getBinding() != BindingMethod.Unbound, "Need to provide a binding");
    rule(errors, IssueType.STRUCTURE, "Binding @ " + path, Utilities.noString(cd.getDefinition()) || (cd.getDefinition().charAt(0) == cd.getDefinition().toUpperCase().charAt(0)), "Definition cannot start with a lowercase letter");
    if (cd.getBinding() == BindingMethod.CodeList || (cd.getBinding() == BindingMethod.ValueSet && cd.getStrength() == BindingStrength.REQUIRED && ac.size() > 0 && "code".equals(e.typeCode()))) {
        if (path.toLowerCase().endsWith("status")) {
            if (rule(errors, IssueType.STRUCTURE, path, definitions.getStatusCodes().containsKey(path), "Status element not registered in status-codes.xml")) {
                // rule(errors, IssueType.STRUCTURE, path, e.isModifier(), "Status elements that map to status-codes should be labelled as a modifier");
                ArrayList<String> list = definitions.getStatusCodes().get(path);
                for (DefinedCode c : ac) {
                    boolean ok = false;
                    for (String s : list) {
                        String[] parts = s.split("\\,");
                        for (String p : parts) if (p.trim().equals(c.getCode()))
                            ok = true;
                    }
                    rule(errors, IssueType.STRUCTURE, path, ok, "Status element code \"" + c.getCode() + "\" not found in status-codes.xml");
                }
                for (String s : list) {
                    String[] parts = s.split("\\,");
                    for (String p : parts) {
                        List<String> cl = new ArrayList<>();
                        if (!Utilities.noString(p)) {
                            boolean ok = false;
                            for (DefinedCode c : ac) {
                                cl.add(c.getCode());
                                if (p.trim().equals(c.getCode()))
                                    ok = true;
                            }
                            if (!ok)
                                rule(errors, IssueType.STRUCTURE, path, ok, "Status element code \"" + p + "\" found for " + path + " in status-codes.xml but has no matching code in the resource (codes = " + cl + ")");
                        }
                    }
                }
            }
        }
        StringBuilder b = new StringBuilder();
        for (DefinedCode c : ac) {
            if (!c.getAbstract())
                b.append(" | ").append(c.getCode());
        }
        if (sd.equals("*")) {
            e.setShortDefn(b.toString().substring(3));
            sd = b.toString().substring(3);
        }
        if (sd.contains("|")) {
            if (b.length() < 3)
                throw new Error("surprise");
            String esd = b.substring(3);
            rule(errors, IssueType.STRUCTURE, path, sd.startsWith(esd) || (sd.endsWith("+") && b.substring(3).startsWith(sd.substring(0, sd.length() - 1))), "The short description \"" + sd + "\" does not match the expected (\"" + b.substring(3) + "\")");
        } else {
            rule(errors, IssueType.STRUCTURE, path, cd.getStrength() != BindingStrength.REQUIRED || ac.size() > 12 || ac.size() <= 1 || !hasGoodCode(ac) || isExemptFromCodeList(path), "The short description of an element with a code list should have the format code | code | etc (is " + sd.toString() + ") (" + ac.size() + " codes = \"" + b.toString() + "\")");
        }
    }
    boolean isComplex = !e.typeCode().equals("code");
    if (isComplex && cd.getValueSet() != null && hasInternalReference(cd.getValueSet()) && cd.getStrength() != BindingStrength.EXAMPLE) {
        hint(errors, IssueType.BUSINESSRULE, path, false, "The value " + cd.getValueSet().getUrl() + " defines codes, but is used by a Coding/CodeableConcept @ " + path + ", so it should not use FHIR defined codes");
        cd.getValueSet().setUserData("vs-val-warned", true);
    }
    if (cd.getElementType() == ElementType.Unknown) {
        if (isComplex)
            cd.setElementType(ElementType.Complex);
        else
            cd.setElementType(ElementType.Simple);
    } else if (isComplex && !cd.hasMax())
        rule(errors, IssueType.STRUCTURE, path, cd.getElementType() == ElementType.Complex, "Cannot use a binding from both code and Coding/CodeableConcept elements");
    else
        rule(errors, IssueType.STRUCTURE, path, cd.getElementType() == ElementType.Simple, "Cannot use a binding from both code and Coding/CodeableConcept elements");
    if (isComplex && cd.getValueSet() != null) {
        for (ConceptSetComponent inc : cd.getValueSet().getCompose().getInclude()) if (inc.hasSystem())
            txurls.add(inc.getSystem());
    }
    rule(errors, IssueType.STRUCTURE, "Binding @ " + path, (cd.getElementType() != ElementType.Simple || cd.getStrength() == BindingStrength.REQUIRED || cd.hasMax()) || isExemptFromProperBindingRules(path), "Must be a required binding if bound to a code instead of a Coding/CodeableConcept");
    rule(errors, IssueType.STRUCTURE, "Binding @ " + path, cd.getElementType() != ElementType.Simple || cd.getBinding() != BindingMethod.Unbound, "Need to provide a binding for code elements");
    if (!isComplex && !externalException(path)) {
        ValueSet vs = cd.getValueSet();
        if (warning(errors, IssueType.REQUIRED, path, vs != null || cd.hasReference(), "Unable to resolve value set on 'code' Binding")) {
            hint(errors, IssueType.REQUIRED, path, noExternals(vs), "Bindings for code data types should only use internally defined codes (" + vs.getUrl() + ")");
        // don't disable this without discussion on Zulip
        }
    }
}
Also used : ConceptSetComponent(org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent) ValueSet(org.hl7.fhir.r5.model.ValueSet)

Example 82 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project kindling by HL7.

the class ValueSetValidator method validate.

public void validate(List<ValidationMessage> errors, String nameForErrors, ValueSet vs, boolean internal, boolean exemptFromCopyrightRule) throws FHIRException {
    int o_warnings = 0;
    for (ValidationMessage em : errors) {
        if (em.getLevel() == IssueSeverity.WARNING)
            o_warnings++;
    }
    if (!handled.contains(vs.getId())) {
        handled.add(vs.getId());
        duplicateList.add(new VSDuplicateList(vs));
    }
    String oid = getOid(vs);
    if (oid != null) {
        if (!oids.containsKey(oid)) {
            oids.put(oid, vs);
        } else
            rule(errors, IssueType.DUPLICATE, getWg(vs) + ":ValueSet[" + vs.getId() + "]", oid.endsWith(".0") || oids.get(oid).getUrl().equals(vs.getUrl()), "Duplicate OID for " + oid + " on " + oids.get(oid).getUrl() + " and " + vs.getUrl());
    }
    rule(errors, IssueType.BUSINESSRULE, getWg(vs) + ":ValueSet[" + vs.getId() + "]", vs.hasDescription(), "Value Sets in the build must have a description");
    if (Utilities.noString(vs.getCopyright()) && !exemptFromCopyrightRule) {
        Set<String> sources = getListOfSources(vs);
        for (String s : sources) {
            ruleHtml(errors, IssueType.BUSINESSRULE, getWg(vs) + ":ValueSet[" + vs.getId() + "].copyright", !s.equals("http://snomed.info/sct") && !s.equals("http://loinc.org"), "Value set " + nameForErrors + " (" + vs.getName() + "): A copyright statement is required for any value set that includes Snomed or Loinc codes", "<a href=\"" + vs.getUserString("path") + "\">Value set " + nameForErrors + " (" + vs.getName() + ")</a>: A copyright statement is required for any value set that includes Snomed or Loinc codes");
            warning(errors, IssueType.BUSINESSRULE, getWg(vs) + ":ValueSet[" + vs.getId() + "].copyright", s.startsWith("http://hl7.org") || s.startsWith("http://terminology.hl7.org") || s.startsWith("urn:iso") || s.startsWith("urn:ietf") || s.startsWith("http://need.a.uri.org") || s.contains("cdc.gov") || s.startsWith("urn:oid:"), "Value set " + nameForErrors + " (" + vs.getName() + "): A copyright statement should be present for any value set that includes non-HL7 sourced codes (" + s + ")", "<a href=\"" + vs.getUserString("path") + "\">Value set " + nameForErrors + " (" + vs.getName() + ")</a>: A copyright statement should be present for any value set that includes non-HL7 sourced codes (" + s + ")");
        }
    }
    if (vs.hasCompose()) {
        if (!context.hasResource(CodeSystem.class, "http://terminology.hl7.org/CodeSystem/data-absent-reason") && !vs.getUrl().contains("v3") && !vs.getUrl().contains("v2"))
            throw new Error("d-a-r not found");
        int i = 0;
        for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
            i++;
            checkValueSetCode(errors, nameForErrors, vs, i, inc);
        }
    }
    int warnings = 0;
    for (ValidationMessage em : errors) {
        if (em.getLevel() == IssueSeverity.WARNING)
            warnings++;
    }
    vs.setUserData("warnings", o_warnings - warnings);
}
Also used : ConceptSetComponent(org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent) ValidationMessage(org.hl7.fhir.utilities.validation.ValidationMessage) CodeSystem(org.hl7.fhir.r5.model.CodeSystem)

Example 83 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project kindling by HL7.

the class PageProcessor method sourceSummary.

private String sourceSummary(ValueSet vs) {
    StringBuilder b = new StringBuilder();
    List<String> done = new ArrayList<String>();
    if (vs.hasCompose())
        for (ConceptSetComponent c : vs.getCompose().getInclude()) {
            String uri = c.getSystem();
            String n = "Other";
            if (uri != null) {
                if ("http://snomed.info/sct".equals(uri))
                    n = "SNOMED CT";
                if ("http://loinc.org".equals(uri))
                    n = "LOINC";
                if ("http://dicom.nema.org/resources/ontology/DCM".equals(uri))
                    n = "DICOM";
                if ("http://hl7.org/fhir/resource-types".equals(uri))
                    n = "FHIR";
                if ("http://hl7.org/fhir/restful-interaction".equals(uri))
                    n = "FHIR";
                if ("http://unitsofmeasure.org".equals(uri))
                    n = "FHIR";
                if (uri.startsWith("http://terminology.hl7.org/CodeSystem/v3-"))
                    n = "V3";
                else if (uri.startsWith("http://terminology.hl7.org/CodeSystem/v2-"))
                    n = "V2";
                else if (uri.startsWith("http://hl7.org/fhir"))
                    n = "Internal";
            }
            if (!done.contains(n))
                b.append(", ").append(n);
            done.add(n);
        }
    return b.length() == 0 ? "" : b.substring(2);
}
Also used : ConceptSetComponent(org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent) CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder) ArrayList(java.util.ArrayList)

Example 84 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project kindling by HL7.

the class PageProcessor method genScList.

private String genScList(String path) throws Exception {
    ResourceDefn r = definitions.getResourceByName(path.substring(0, path.indexOf(".")));
    if (r == null)
        throw new Exception("Unable to process sclist (1): " + path);
    ElementDefn e = r.getRoot().getElementByName(definitions, path.substring(path.indexOf(".") + 1), true, false);
    if (e == null)
        throw new Exception("Unable to process sclist (2): " + path);
    if (e.typeCode().equals("boolean"))
        return "true | false";
    else {
        StringBuilder b = new StringBuilder();
        boolean first = true;
        for (ConceptSetComponent inc : e.getBinding().getValueSet().getCompose().getInclude()) {
            CodeSystem cs = definitions.getCodeSystems().get(inc.getSystem());
            if (cs != null) {
                for (ConceptDefinitionComponent cc : cs.getConcept()) {
                    if (first)
                        first = false;
                    else
                        b.append(" | ");
                    b.append("<span title=\"" + cc.getDisplay() + ": " + Utilities.escapeXml(cc.getDefinition()) + "\">" + cc.getCode() + "</span>");
                }
            }
        }
        return b.toString();
    }
}
Also used : ConceptSetComponent(org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent) CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder) ConceptDefinitionComponent(org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent) ElementDefn(org.hl7.fhir.definitions.model.ElementDefn) ResourceDefn(org.hl7.fhir.definitions.model.ResourceDefn) CodeSystem(org.hl7.fhir.r5.model.CodeSystem) UcumException(org.fhir.ucum.UcumException) TransformerException(javax.xml.transform.TransformerException) TransformerConfigurationException(javax.xml.transform.TransformerConfigurationException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) URISyntaxException(java.net.URISyntaxException) PathEngineException(org.hl7.fhir.exceptions.PathEngineException) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) FileNotFoundException(java.io.FileNotFoundException) NotImplementedException(org.apache.commons.lang3.NotImplementedException)

Example 85 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project kindling by HL7.

the class PageProcessor method generateCSUsage.

private String generateCSUsage(CodeSystem cs, String prefix) throws Exception {
    StringBuilder b = new StringBuilder();
    for (ValueSet vs : definitions.getValuesets().getList()) {
        boolean uses = false;
        for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
            if (inc.hasSystem() && inc.getSystem().equals(cs.getUrl()))
                uses = true;
        }
        for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
            if (inc.hasSystem() && inc.getSystem().equals(cs.getUrl()))
                uses = true;
        }
        if (uses) {
            if (vs.hasUserData("external.url"))
                b.append(" <li>ValueSet: <a href=\"").append(vs.getUserString("external.url")).append("\">").append(vs.present()).append("</a> (").append(Utilities.escapeXml(vs.getDescription())).append(")</li>\r\n");
            else if (!vs.hasUserData("path"))
                b.append(" <li>ValueSet: <a href=\"").append(prefix + "valueset-" + vs.getId()).append("\">").append(vs.present()).append("</a> (").append(Utilities.escapeXml(vs.getDescription())).append(")</li>\r\n");
            else
                b.append(" <li>ValueSet: <a href=\"").append(prefix + vs.getUserString("path")).append("\">").append(vs.present()).append("</a> (").append(Utilities.escapeXml(vs.getDescription())).append(")</li>\r\n");
        }
    }
    if (b.length() == 0)
        return "<p>\r\nThis Code system is not currently used\r\n</p>\r\n";
    else
        return "<p>\r\nThis Code system is used in the following value sets:\r\n</p>\r\n<ul>\r\n" + b.toString() + "</ul>\r\n";
}
Also used : ConceptSetComponent(org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent) CommaSeparatedStringBuilder(org.hl7.fhir.utilities.CommaSeparatedStringBuilder) ValueSet(org.hl7.fhir.r5.model.ValueSet)

Aggregations

ConceptSetComponent (org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent)25 ArrayList (java.util.ArrayList)22 ConceptSetComponent (org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent)21 IOException (java.io.IOException)20 TerminologyServiceException (org.hl7.fhir.exceptions.TerminologyServiceException)20 XhtmlNode (org.hl7.fhir.utilities.xhtml.XhtmlNode)19 FHIRException (org.hl7.fhir.exceptions.FHIRException)17 HashMap (java.util.HashMap)15 ConceptSetComponent (org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent)14 ConceptReferenceComponent (org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent)14 ValueSet (org.hl7.fhir.r4.model.ValueSet)13 ValueSet (org.hl7.fhir.r5.model.ValueSet)13 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)12 NoTerminologyServiceException (org.hl7.fhir.exceptions.NoTerminologyServiceException)12 ConceptSetComponent (org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent)12 FileNotFoundException (java.io.FileNotFoundException)10 NotImplementedException (org.apache.commons.lang3.NotImplementedException)10 CodeSystem (org.hl7.fhir.r5.model.CodeSystem)10 CommaSeparatedStringBuilder (org.hl7.fhir.utilities.CommaSeparatedStringBuilder)10 ValueSet (org.hl7.fhir.dstu3.model.ValueSet)9