Search in sources :

Example 16 with DefinitionNavigator

use of org.hl7.fhir.r4.utils.DefinitionNavigator in project org.hl7.fhir.core by hapifhir.

the class ProfileComparer method compareElements.

/**
 * left and right refer to the same element. Are they compatible?
 * @param outcome
 * @param outcome
 * @param path
 * @param left
 * @param right
 * @- if there's a problem that needs fixing in this code
 * @throws DefinitionException
 * @throws IOException
 * @throws FHIRFormatError
 */
private boolean compareElements(ProfileComparison outcome, String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException, FHIRFormatError {
    // preconditions:
    assert (path != null);
    assert (left != null);
    assert (right != null);
    assert (left.path().equals(right.path()));
    // we ignore slicing right now - we're going to clone the root one anyway, and then think about clones
    // simple stuff
    ElementDefinition subset = new ElementDefinition();
    subset.setPath(left.path());
    // not allowed to be different:
    // can't be bothered even testing this one
    subset.getRepresentation().addAll(left.current().getRepresentation());
    if (!outcome.ruleCompares(subset, left.current().getDefaultValue(), right.current().getDefaultValue(), path + ".defaultValue[x]", BOTH_NULL))
        return false;
    subset.setDefaultValue(left.current().getDefaultValue());
    if (!outcome.ruleEqual(path, subset, left.current().getMeaningWhenMissing(), right.current().getMeaningWhenMissing(), "meaningWhenMissing Must be the same", true))
        return false;
    subset.setMeaningWhenMissing(left.current().getMeaningWhenMissing());
    if (!outcome.ruleEqual(subset, left.current().getIsModifier(), right.current().getIsModifier(), path, "isModifier"))
        return false;
    subset.setIsModifier(left.current().getIsModifier());
    if (!outcome.ruleEqual(subset, left.current().getIsSummary(), right.current().getIsSummary(), path, "isSummary"))
        return false;
    subset.setIsSummary(left.current().getIsSummary());
    // descriptive properties from ElementDefinition - merge them:
    subset.setLabel(mergeText(subset, outcome, path, "label", left.current().getLabel(), right.current().getLabel()));
    subset.setShort(mergeText(subset, outcome, path, "short", left.current().getShort(), right.current().getShort()));
    subset.setDefinition(mergeText(subset, outcome, path, "definition", left.current().getDefinition(), right.current().getDefinition()));
    subset.setComment(mergeText(subset, outcome, path, "comments", left.current().getComment(), right.current().getComment()));
    subset.setRequirements(mergeText(subset, outcome, path, "requirements", left.current().getRequirements(), right.current().getRequirements()));
    subset.getCode().addAll(mergeCodings(left.current().getCode(), right.current().getCode()));
    subset.getAlias().addAll(mergeStrings(left.current().getAlias(), right.current().getAlias()));
    subset.getMapping().addAll(mergeMappings(left.current().getMapping(), right.current().getMapping()));
    // left will win for example
    subset.setExample(left.current().hasExample() ? left.current().getExample() : right.current().getExample());
    subset.setMustSupport(left.current().getMustSupport() || right.current().getMustSupport());
    ElementDefinition superset = subset.copy();
    // compare and intersect
    superset.setMin(unionMin(left.current().getMin(), right.current().getMin()));
    superset.setMax(unionMax(left.current().getMax(), right.current().getMax()));
    subset.setMin(intersectMin(left.current().getMin(), right.current().getMin()));
    subset.setMax(intersectMax(left.current().getMax(), right.current().getMax()));
    outcome.rule(subset, subset.getMax().equals("*") || Integer.parseInt(subset.getMax()) >= subset.getMin(), path, "Cardinality Mismatch: " + card(left) + "/" + card(right));
    superset.getType().addAll(unionTypes(path, left.current().getType(), right.current().getType()));
    subset.getType().addAll(intersectTypes(subset, outcome, path, left.current().getType(), right.current().getType()));
    outcome.rule(subset, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch:\r\n  " + typeCode(left) + "\r\n  " + typeCode(right));
    // <fixed[x]><!-- ?? 0..1 * Value must be exactly this --></fixed[x]>
    // <pattern[x]><!-- ?? 0..1 * Value must have at least these property values --></pattern[x]>
    superset.setMaxLengthElement(unionMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
    subset.setMaxLengthElement(intersectMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
    if (left.current().hasBinding() || right.current().hasBinding()) {
        compareBindings(outcome, subset, superset, path, left.current(), right.current());
    }
    // note these are backwards
    superset.getConstraint().addAll(intersectConstraints(path, left.current().getConstraint(), right.current().getConstraint()));
    subset.getConstraint().addAll(unionConstraints(subset, outcome, path, left.current().getConstraint(), right.current().getConstraint()));
    // now process the slices
    if (left.current().hasSlicing() || right.current().hasSlicing()) {
        if (isExtension(left.path()))
            return compareExtensions(outcome, path, superset, subset, left, right);
        else // return true;
        {
            ElementDefinitionSlicingComponent slicingL = left.current().getSlicing();
            ElementDefinitionSlicingComponent slicingR = right.current().getSlicing();
            throw new DefinitionException("Slicing is not handled yet");
        }
    // todo: name
    }
    // add the children
    outcome.subset.getSnapshot().getElement().add(subset);
    outcome.superset.getSnapshot().getElement().add(superset);
    return compareChildren(subset, outcome, path, left, right);
}
Also used : ElementDefinitionSlicingComponent(org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionSlicingComponent) ElementDefinition(org.hl7.fhir.r4.model.ElementDefinition) DefinitionException(org.hl7.fhir.exceptions.DefinitionException)

Example 17 with DefinitionNavigator

use of org.hl7.fhir.r4.utils.DefinitionNavigator in project org.hl7.fhir.core by hapifhir.

the class ProfileComparer method compare.

public ProfileComparison compare(StructureDefinition left, StructureDefinition right) throws DefinitionException, FHIRFormatError, IOException {
    check(left, "left");
    check(right, "right");
    ProfileComparison res = new ProfileComparison(left, right);
    session.identify(res);
    StructureDefinition sd = new StructureDefinition();
    res.setUnion(sd);
    session.identify(sd);
    sd.setName("Union" + left.getName() + "And" + right.getName());
    sd.setTitle("Union of " + left.getTitle() + " And " + right.getTitle());
    sd.setStatus(left.getStatus());
    sd.setDate(new Date());
    StructureDefinition sd1 = new StructureDefinition();
    res.setIntersection(sd1);
    session.identify(sd1);
    sd1.setName("Intersection" + left.getName() + "And" + right.getName());
    sd1.setTitle("Intersection of " + left.getTitle() + " And " + right.getTitle());
    sd1.setStatus(left.getStatus());
    sd1.setDate(new Date());
    compareMetadata(left, right, res.getMetadata(), res);
    comparePrimitives("fhirVersion", left.getFhirVersionElement(), right.getFhirVersionElement(), res.getMetadata(), IssueSeverity.WARNING, res);
    comparePrimitives("kind", left.getKindElement(), right.getKindElement(), res.getMetadata(), IssueSeverity.WARNING, res);
    comparePrimitives("abstract", left.getAbstractElement(), right.getAbstractElement(), res.getMetadata(), IssueSeverity.WARNING, res);
    comparePrimitives("type", left.getTypeElement(), right.getTypeElement(), res.getMetadata(), IssueSeverity.ERROR, res);
    comparePrimitives("baseDefinition", left.getBaseDefinitionElement(), right.getBaseDefinitionElement(), res.getMetadata(), IssueSeverity.ERROR, res);
    if (left.getType().equals(right.getType())) {
        DefinitionNavigator ln = new DefinitionNavigator(session.getContextLeft(), left);
        DefinitionNavigator rn = new DefinitionNavigator(session.getContextRight(), right);
        StructuralMatch<ElementDefinitionNode> sm = new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(left, ln.current()), new ElementDefinitionNode(right, rn.current()));
        compareElements(res, sm, ln.path(), null, ln, rn);
        res.combined = sm;
    }
    return res;
}
Also used : StructureDefinition(org.hl7.fhir.r5.model.StructureDefinition) DefinitionNavigator(org.hl7.fhir.r5.utils.DefinitionNavigator) Date(java.util.Date)

Example 18 with DefinitionNavigator

use of org.hl7.fhir.r4.utils.DefinitionNavigator in project org.hl7.fhir.core by hapifhir.

the class ProfileComparer method compareChildren.

private boolean compareChildren(ElementDefinition ed, ProfileComparison outcome, String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException {
    List<DefinitionNavigator> lc = left.children();
    List<DefinitionNavigator> rc = right.children();
    // walk into it
    if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0)))
        lc = left.childrenFromType(right.current().getType().get(0));
    if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0)))
        rc = right.childrenFromType(left.current().getType().get(0));
    if (lc.size() != rc.size()) {
        outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Different number of children at " + path + " (" + Integer.toString(lc.size()) + "/" + Integer.toString(rc.size()) + ")", IssueSeverity.ERROR));
        status(ed, ProfileUtilities.STATUS_ERROR);
        return false;
    } else {
        for (int i = 0; i < lc.size(); i++) {
            DefinitionNavigator l = lc.get(i);
            DefinitionNavigator r = rc.get(i);
            String cpath = comparePaths(l.path(), r.path(), path, l.nameTail(), r.nameTail());
            if (cpath != null) {
                if (!compareElements(outcome, cpath, l, r))
                    return false;
            } else {
                outcome.messages.add(new ValidationMessage(Source.ProfileComparer, IssueType.STRUCTURE, path, "Different path at " + path + "[" + Integer.toString(i) + "] (" + l.path() + "/" + r.path() + ")", IssueSeverity.ERROR));
                status(ed, ProfileUtilities.STATUS_ERROR);
                return false;
            }
        }
    }
    return true;
}
Also used : ValidationMessage(org.hl7.fhir.utilities.validation.ValidationMessage)

Example 19 with DefinitionNavigator

use of org.hl7.fhir.r4.utils.DefinitionNavigator in project org.hl7.fhir.core by hapifhir.

the class DefinitionNavigator method loadChildren.

private void loadChildren() throws DefinitionException {
    children = new ArrayList<DefinitionNavigator>();
    String prefix = current().getPath() + ".";
    Map<String, DefinitionNavigator> nameMap = new HashMap<String, DefinitionNavigator>();
    for (int i = index + 1; i < structure.getSnapshot().getElement().size(); i++) {
        String path = structure.getSnapshot().getElement().get(i).getPath();
        if (path.startsWith(prefix) && !path.substring(prefix.length()).contains(".")) {
            DefinitionNavigator dn = new DefinitionNavigator(context, structure, i, this.path + "." + tail(path), names, null);
            if (nameMap.containsKey(path)) {
                DefinitionNavigator master = nameMap.get(path);
                if (!master.current().hasSlicing())
                    throw new DefinitionException("Found slices with no slicing details at " + dn.current().getPath());
                if (master.slices == null)
                    master.slices = new ArrayList<DefinitionNavigator>();
                master.slices.add(dn);
            } else {
                nameMap.put(path, dn);
                children.add(dn);
            }
        } else if (path.length() < prefix.length())
            break;
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DefinitionException(org.hl7.fhir.exceptions.DefinitionException)

Example 20 with DefinitionNavigator

use of org.hl7.fhir.r4.utils.DefinitionNavigator in project org.hl7.fhir.core by hapifhir.

the class ProfileComparer method compareChildren.

private void compareChildren(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException, FHIRFormatError {
    List<DefinitionNavigator> lc = left.children();
    List<DefinitionNavigator> rc = right.children();
    // walk into it
    if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0)))
        lc = left.childrenFromType(right.current().getType().get(0));
    if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0)))
        rc = right.childrenFromType(left.current().getType().get(0));
    List<DefinitionNavigator> matchR = new ArrayList<>();
    for (DefinitionNavigator l : lc) {
        DefinitionNavigator r = findInList(rc, l);
        if (r == null) {
            comp.getUnion().getSnapshot().getElement().add(l.current().copy());
            res.getChildren().add(new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(l.getStructure(), l.current()), vmI(IssueSeverity.INFORMATION, "Removed this element", path)));
        } else {
            matchR.add(r);
            StructuralMatch<ElementDefinitionNode> sm = new StructuralMatch<ElementDefinitionNode>(new ElementDefinitionNode(l.getStructure(), l.current()), new ElementDefinitionNode(r.getStructure(), r.current()));
            res.getChildren().add(sm);
            compareElements(comp, sm, l.path(), null, l, r);
        }
    }
    for (DefinitionNavigator r : rc) {
        if (!matchR.contains(r)) {
            comp.getUnion().getSnapshot().getElement().add(r.current().copy());
            res.getChildren().add(new StructuralMatch<ElementDefinitionNode>(vmI(IssueSeverity.INFORMATION, "Added this element", path), new ElementDefinitionNode(r.getStructure(), r.current())));
        }
    }
}
Also used : DefinitionNavigator(org.hl7.fhir.r4b.utils.DefinitionNavigator) ArrayList(java.util.ArrayList)

Aggregations

DefinitionException (org.hl7.fhir.exceptions.DefinitionException)20 ArrayList (java.util.ArrayList)8 HashMap (java.util.HashMap)6 ValidationMessage (org.hl7.fhir.utilities.validation.ValidationMessage)4 Date (java.util.Date)2 StructureDefinition (org.hl7.fhir.dstu2.model.StructureDefinition)2 StructureDefinition (org.hl7.fhir.dstu2016may.model.StructureDefinition)2 StructureDefinition (org.hl7.fhir.dstu3.model.StructureDefinition)2 DefinitionNavigator (org.hl7.fhir.dstu3.utils.DefinitionNavigator)2 StructureDefinition (org.hl7.fhir.r4.model.StructureDefinition)2 DefinitionNavigator (org.hl7.fhir.r4.utils.DefinitionNavigator)2 StructureDefinition (org.hl7.fhir.r4b.model.StructureDefinition)2 DefinitionNavigator (org.hl7.fhir.r4b.utils.DefinitionNavigator)2 StructureDefinition (org.hl7.fhir.r5.model.StructureDefinition)2 DefinitionNavigator (org.hl7.fhir.r5.utils.DefinitionNavigator)2 ElementDefinition (org.hl7.fhir.dstu2.model.ElementDefinition)1 ElementDefinition (org.hl7.fhir.dstu2016may.model.ElementDefinition)1 ElementDefinition (org.hl7.fhir.dstu3.model.ElementDefinition)1 ElementDefinition (org.hl7.fhir.r4.model.ElementDefinition)1 ElementDefinitionSlicingComponent (org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionSlicingComponent)1