From d203b17c7d735885dad41d109779a82fc60b1e09 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sun, 10 May 2020 08:15:40 +1000 Subject: [PATCH] update to use new secondary package server --- .../comparison/CanonicalResourceComparer.java | 18 +- .../r5/comparison/CodeSystemComparer.java | 22 +- .../fhir/r5/comparison/ComparisonSession.java | 100 +++ .../fhir/r5/comparison/ProfileComparer.java | 751 +++++++++--------- .../fhir/r5/comparison/ResourceComparer.java | 40 +- .../fhir/r5/comparison/ValueSetComparer.java | 66 +- .../hl7/fhir/r5/test/PackageClientTests.java | 12 +- .../utilities/cache/PackageCacheManager.java | 2 +- .../comparison/tests/ComparisonTests.java | 9 +- 9 files changed, 569 insertions(+), 451 deletions(-) create mode 100644 org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CanonicalResourceComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CanonicalResourceComparer.java index acf6f3e4a..8dc438f98 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CanonicalResourceComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CanonicalResourceComparer.java @@ -32,7 +32,7 @@ import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Title; public abstract class CanonicalResourceComparer extends ResourceComparer { - public class CanonicalResourceComparison extends ResourceCmparison { + public class CanonicalResourceComparison extends ResourceComparison { protected T left; protected T right; @@ -91,8 +91,8 @@ public abstract class CanonicalResourceComparer extends ResourceComparer { } - public CanonicalResourceComparer(IWorkerContext context) { - super(context); + public CanonicalResourceComparer(ComparisonSession session) { + super(session); } protected void compareMetadata(CanonicalResource left, CanonicalResource right, Map> comp, CanonicalResourceComparison res) { @@ -115,19 +115,19 @@ public abstract class CanonicalResourceComparer extends ResourceComparer { if (l.isEmpty() && r.isEmpty()) { match = new StructuralMatch<>(null, null, null); } else if (l.isEmpty()) { - match = new StructuralMatch<>(null, r.primitiveValue(), vm(IssueSeverity.INFORMATION, "Added this item", fhirType()+"."+name)); + match = new StructuralMatch<>(null, r.primitiveValue(), vmI(IssueSeverity.INFORMATION, "Added this item", fhirType()+"."+name)); } else if (r.isEmpty()) { - match = new StructuralMatch<>(l.primitiveValue(), null, vm(IssueSeverity.INFORMATION, "Removed this item", fhirType()+"."+name)); + match = new StructuralMatch<>(l.primitiveValue(), null, vmI(IssueSeverity.INFORMATION, "Removed this item", fhirType()+"."+name)); } else if (!l.hasValue() && !r.hasValue()) { - match = new StructuralMatch<>(null, null, vm(IssueSeverity.INFORMATION, "No Value", fhirType()+"."+name)); + match = new StructuralMatch<>(null, null, vmI(IssueSeverity.INFORMATION, "No Value", fhirType()+"."+name)); } else if (!l.hasValue()) { - match = new StructuralMatch<>(null, r.primitiveValue(), vm(IssueSeverity.INFORMATION, "No Value on Left", fhirType()+"."+name)); + match = new StructuralMatch<>(null, r.primitiveValue(), vmI(IssueSeverity.INFORMATION, "No Value on Left", fhirType()+"."+name)); } else if (!r.hasValue()) { - match = new StructuralMatch<>(l.primitiveValue(), null, vm(IssueSeverity.INFORMATION, "No Value on Right", fhirType()+"."+name)); + match = new StructuralMatch<>(l.primitiveValue(), null, vmI(IssueSeverity.INFORMATION, "No Value on Right", fhirType()+"."+name)); } else if (l.getValue().equals(r.getValue())) { match = new StructuralMatch<>(l.primitiveValue(), r.primitiveValue(), null); } else { - match = new StructuralMatch<>(l.primitiveValue(), r.primitiveValue(), vm(level, "Values Differ", fhirType()+"."+name)); + match = new StructuralMatch<>(l.primitiveValue(), r.primitiveValue(), vmI(level, "Values Differ", fhirType()+"."+name)); if (level != IssueSeverity.NULL) { res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, fhirType()+"."+name, "Values for "+name+" differ: '"+l.primitiveValue()+"' vs '"+r.primitiveValue()+"'", level)); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CodeSystemComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CodeSystemComparer.java index f92e42216..e48038944 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CodeSystemComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/CodeSystemComparer.java @@ -54,9 +54,8 @@ public class CodeSystemComparer extends CanonicalResourceComparer { private CodeSystem right; - public CodeSystemComparer(IWorkerContext context) { - super(context); - this.context = context; + public CodeSystemComparer(ComparisonSession session) { + super(session); } public CodeSystemComparison compare(CodeSystem left, CodeSystem right) { @@ -67,10 +66,10 @@ public class CodeSystemComparer extends CanonicalResourceComparer { CodeSystemComparison res = new CodeSystemComparison(left, right); + session.identify(res); CodeSystem cs = new CodeSystem(); res.setUnion(cs); - cs.setId(UUID.randomUUID().toString().toLowerCase()); - cs.setUrl("urn:uuid:"+cs.getId()); + session.identify(cs); cs.setName("Union"+left.getName()+"And"+right.getName()); cs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); cs.setStatus(left.getStatus()); @@ -90,8 +89,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer { CodeSystem cs1 = new CodeSystem(); res.setIntersection(cs1); - cs1.setId(UUID.randomUUID().toString().toLowerCase()); - cs1.setUrl("urn:uuid:"+cs1.getId()); + session.identify(cs1); cs1.setName("Intersection"+left.getName()+"And"+right.getName()); cs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); cs1.setStatus(left.getStatus()); @@ -144,7 +142,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer { ConceptDefinitionComponent r = findInList(right, l); if (r == null) { union.add(l); - combined.getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed this concept", path))); + combined.getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed this concept", path))); } else { matchR.add(r); ConceptDefinitionComponent cdM = merge(l, r, csU.getProperty(), res); @@ -160,7 +158,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer { for (ConceptDefinitionComponent r : right) { if (!matchR.contains(r)) { union.add(r); - combined.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added this concept", path), r)); + combined.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added this concept", path), r)); } } } @@ -182,15 +180,15 @@ public class CodeSystemComparer extends CanonicalResourceComparer { private void compareStrings(String path, List msgs, String left, String right, String name, IssueSeverity level, CodeSystemComparison res) { if (!Utilities.noString(right)) { if (Utilities.noString(left)) { - msgs.add(vm(level, "Value for "+name+" added", path)); + msgs.add(vmI(level, "Value for "+name+" added", path)); } else if (!left.equals(right)) { if (level != IssueSeverity.NULL) { res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path+"."+name, "Changed value for "+name+": '"+left+"' vs '"+right+"'", level)); } - msgs.add(vm(level, name+" changed from left to right", path)); + msgs.add(vmI(level, name+" changed from left to right", path)); } } else if (!Utilities.noString(left)) { - msgs.add(vm(level, "Value for "+name+" removed", path)); + msgs.add(vmI(level, "Value for "+name+" removed", path)); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java new file mode 100644 index 000000000..0d6d6c7aa --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ComparisonSession.java @@ -0,0 +1,100 @@ +package org.hl7.fhir.r5.comparison; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; +import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison; +import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison; +import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.xhtml.XhtmlComposer; + +public class ComparisonSession { + + private Map compares = new HashMap<>(); + private IWorkerContext context; + private String sessiondId; + private int count; + + public ComparisonSession(IWorkerContext context) { + super(); + this.context = context; + this.sessiondId = UUID.randomUUID().toString().toLowerCase(); + } + + public IWorkerContext getContext() { + return context; + } + + public ResourceComparison compare(String left, String right) throws DefinitionException, FHIRFormatError, IOException { + CanonicalResource l = (CanonicalResource) context.fetchResource(Resource.class, left); + if (l == null) { + throw new DefinitionException("Unable to resolve "+left); + } + CanonicalResource r = (CanonicalResource) context.fetchResource(Resource.class, right); + if (r == null) { + throw new DefinitionException("Unable to resolve "+right); + } + return compare(l, r); + } + + public ResourceComparison compare(CanonicalResource left, CanonicalResource right) throws DefinitionException, FHIRFormatError, IOException { + String key = key(left.getUrl(), left.getVersion(), right.getUrl(), right.getVersion()); + if (compares.containsKey(key)) { + // if null then the comparison is in progress. + // this can happen when profiles refer to each other + return compares.get(key); + } + compares.put(key, null); + if (left instanceof CodeSystem && right instanceof CodeSystem) { + CodeSystemComparer cs = new CodeSystemComparer(this); + CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right); + compares.put(key, csc); + return csc; + } else if (left instanceof ValueSet && right instanceof ValueSet) { + ValueSetComparer cs = new ValueSetComparer(this); + ValueSetComparison csc = cs.compare((ValueSet) left, (ValueSet) right); + compares.put(key, csc); + return csc; + } else if (left instanceof StructureDefinition && right instanceof StructureDefinition) { + ProfileComparer cs = new ProfileComparer(this); + ProfileComparison csc = cs.compare((StructureDefinition) left, (StructureDefinition) right); + compares.put(key, csc); + return csc; + } else { + throw new FHIRException("Unable to compare "); + } + } + + private String key(String urlL, String verL, String urlR, String verR) { + return urlL+"|"+verL+"||"+urlR+"|"+verR; + } + + + public void identify(CanonicalResource res) { + count++; + res.setId(sessiondId+"-"+count); + res.setUrl("http://hl7.org/fhir/comparison/"+res.fhirType()+"/"+res.getId()); + } + + public void identify(ResourceComparison res) { + count++; + res.setId(sessiondId+"-"+count); + + } +} diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java index e650fa2dd..9557374a7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ProfileComparer.java @@ -17,12 +17,14 @@ import org.hl7.fhir.r5.comparison.OldProfileComparer.ProfileComparison; import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.formats.IParser; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.IntegerType; +import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; @@ -42,13 +44,11 @@ import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.utils.DefinitionNavigator; +import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.model.ValueSet; public class ProfileComparer extends CanonicalResourceComparer { - private static final int BOTH_NULL = 0; - private static final int EITHER_NULL = 1; - public class ProfileComparison extends CanonicalResourceComparison { private StructuralMatch combined; @@ -63,8 +63,8 @@ public class ProfileComparer extends CanonicalResourceComparer { } } - public ProfileComparer(IWorkerContext context) { - super(context); + public ProfileComparer(ComparisonSession session) { + super(session); } @Override @@ -77,10 +77,10 @@ public class ProfileComparer extends CanonicalResourceComparer { check(right, "right"); ProfileComparison res = new ProfileComparison(left, right); + session.identify(res); StructureDefinition sd = new StructureDefinition(); res.setUnion(sd); - sd.setId(UUID.randomUUID().toString().toLowerCase()); - sd.setUrl("urn:uuid:"+sd.getId()); + session.identify(sd); sd.setName("Union"+left.getName()+"And"+right.getName()); sd.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); sd.setStatus(left.getStatus()); @@ -88,8 +88,7 @@ public class ProfileComparer extends CanonicalResourceComparer { StructureDefinition sd1 = new StructureDefinition(); res.setIntersection(sd1); - sd1.setId(UUID.randomUUID().toString().toLowerCase()); - sd1.setUrl("urn:uuid:"+sd1.getId()); + session.identify(sd1); sd1.setName("Intersection"+left.getName()+"And"+right.getName()); sd1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); sd1.setStatus(left.getStatus()); @@ -103,10 +102,10 @@ public class ProfileComparer extends CanonicalResourceComparer { comparePrimitives("baseDefinition", left.getBaseDefinitionElement(), right.getBaseDefinitionElement(), res.getMetadata(), IssueSeverity.ERROR, res); if (left.getType().equals(right.getType())) { - DefinitionNavigator ln = new DefinitionNavigator(context, left); - DefinitionNavigator rn = new DefinitionNavigator(context, right); - // StructuralMatch res = new StructuralMatch(left.current(), right.current()); - // compareElements(res, res.getCombined(), ln.path(), null, ln, rn, sd, sd1); + DefinitionNavigator ln = new DefinitionNavigator(session.getContext(), left); + DefinitionNavigator rn = new DefinitionNavigator(session.getContext(), right); + StructuralMatch sm = new StructuralMatch(ln.current(), rn.current()); + compareElements(res, sm, ln.path(), null, ln, rn); } return res; } @@ -131,10 +130,10 @@ public class ProfileComparer extends CanonicalResourceComparer { assert(left.path().equals(right.path())); // not allowed to be different: - ruleCompares(comp, res, left.current().getDefaultValue(), right.current().getDefaultValue(), path+".defaultValue[x]", BOTH_NULL); - ruleEqual(comp, res, path, left.current().getMeaningWhenMissing(), right.current().getMeaningWhenMissing(), "meaningWhenMissing Must be the same", true); - ruleEqual(comp, res, left.current().getIsModifier(), right.current().getIsModifier(), path, "isModifier"); - ruleEqual(comp, res, left.current().getIsSummary(), right.current().getIsSummary(), path, "isSummary"); + ruleEqual(comp, res, left.current().getDefaultValue(), right.current().getDefaultValue(), "defaultValue", path); + ruleEqual(comp, res, left.current().getMeaningWhenMissingElement(), right.current().getMeaningWhenMissingElement(), "meaningWhenMissing", path); + ruleEqual(comp, res, left.current().getIsModifierElement(), right.current().getIsModifierElement(), "isModifier", path); + ruleEqual(comp, res, left.current().getIsSummaryElement(), right.current().getIsSummaryElement(), "isSummary", path); // we ignore slicing right now - we're going to clone the root one anyway, and then think about clones // simple stuff @@ -173,7 +172,7 @@ public class ProfileComparer extends CanonicalResourceComparer { subset.setMax(intersectMax(left.current().getMax(), right.current().getMax())); rule(comp, res, 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())); + superset.getType().addAll(unionTypes(comp, res, path, left.current().getType(), right.current().getType())); subset.getType().addAll(intersectTypes(comp, res, subset, path, left.current().getType(), right.current().getType())); rule(comp, res, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch:\r\n "+typeCode(left)+"\r\n "+typeCode(right)); // @@ -268,7 +267,7 @@ public class ProfileComparer extends CanonicalResourceComparer { DefinitionNavigator r = findInList(rc, l); if (r == null) { comp.getUnion().getSnapshot().getElement().add(l.current().copy()); - res.getChildren().add(new StructuralMatch(l.current(), vm(IssueSeverity.INFORMATION, "Removed this element", path))); + res.getChildren().add(new StructuralMatch(l.current(), vmI(IssueSeverity.INFORMATION, "Removed this element", path))); } else { matchR.add(r); StructuralMatch sm = new StructuralMatch(l.current(), r.current()); @@ -279,88 +278,73 @@ public class ProfileComparer extends CanonicalResourceComparer { for (DefinitionNavigator r : rc) { if (!matchR.contains(r)) { comp.getUnion().getSnapshot().getElement().add(r.current().copy()); - res.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added this element", path), r.current())); + res.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added this element", path), r.current())); } } } private DefinitionNavigator findInList(List rc, DefinitionNavigator l) { - // TODO: fix + for (DefinitionNavigator t : rc) { + if (t.current().getPath().equals(l.current().getPath())) { + return t; + } + } return null; } - private boolean ruleCompares(ProfileComparison comp, StructuralMatch res, DataType vLeft, DataType vRight, String path, int nullStatus) throws IOException { - // TODO: fix -// if (vLeft == null && vRight == null && nullStatus == BOTH_NULL) -// return true; -// if (vLeft == null && vRight == null) { -// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Must be the same and not null (null/null)", ValidationMessage.IssueSeverity.ERROR)); -// status(ed, ProfileUtilities.STATUS_ERROR); -// } -// if (vLeft == null && nullStatus == EITHER_NULL) -// return true; -// if (vRight == null && nullStatus == EITHER_NULL) -// return true; -// if (vLeft == null || vRight == null || !Base.compareDeep(vLeft, vRight, false)) { -// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Must be the same ("+toString(vLeft)+"/"+toString(vRight)+")", ValidationMessage.IssueSeverity.ERROR)); -// status(ed, ProfileUtilities.STATUS_ERROR); -// } - return true; + private void ruleEqual(ProfileComparison comp, StructuralMatch res, DataType vLeft, DataType vRight, String name, String path) throws IOException { + if (vLeft == null && vRight == null) { + // nothing + } else if (vLeft == null) { + vm(IssueSeverity.ERROR, "Added "+name, path, comp.getMessages(), res.getMessages()); + } else if (vRight == null) { + vm(IssueSeverity.ERROR, "Removed "+name, path, comp.getMessages(), res.getMessages()); + } else if (Base.compareDeep(vLeft, vRight, false)) { + vm(IssueSeverity.ERROR, name+" be the same ("+toString(vLeft)+"/"+toString(vRight)+")", path, comp.getMessages(), res.getMessages()); + } } + private String toString(DataType val) throws IOException { + if (val instanceof PrimitiveType) + return "\"" + ((PrimitiveType) val).getValueAsString()+"\""; + + IParser jp = session.getContext().newJsonParser(); + return jp.composeString(val, "value"); + } + + private String stripLinks(String s) { + while (s.contains("](")) { + int i = s.indexOf("]("); + int j = s.substring(i).indexOf(")"); + if (j == -1) + return s; + else + s = s.substring(0, i+1)+s.substring(i+j+1); + } + return s; + } + private boolean rule(ProfileComparison comp, StructuralMatch res, boolean test, String path, String message) { - // TODO: fix -// if (!test) { -// messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, message, ValidationMessage.IssueSeverity.ERROR)); -// status(ed, ProfileUtilities.STATUS_ERROR); -// } + if (!test) { + vm(IssueSeverity.ERROR, message, path, comp.getMessages(), res.getMessages()); + } return test; } - - private boolean ruleEqual(ProfileComparison comp, StructuralMatch res, boolean vLeft, boolean vRight, String path, String elementName) { - // TODO: fix -// if (vLeft != vRight) { -// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, elementName+" must be the same ("+vLeft+"/"+vRight+")", ValidationMessage.IssueSeverity.ERROR)); -// status(ed, ProfileUtilities.STATUS_ERROR); -// } - return true; - } - - private boolean ruleEqual(ProfileComparison comp, StructuralMatch res, String path, String vLeft, String vRight, String description, boolean nullOK) { - // TODO: fix -// if (vLeft == null && vRight == null && nullOK) -// return true; -// if (vLeft == null && vRight == null) { -// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, description+" and not null (null/null)", ValidationMessage.IssueSeverity.ERROR)); -// if (ed != null) -// status(ed, ProfileUtilities.STATUS_ERROR); -// } -// if (vLeft == null || !vLeft.equals(vRight)) { -// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, description+" ("+vLeft+"/"+vRight+")", ValidationMessage.IssueSeverity.ERROR)); -// if (ed != null) -// status(ed, ProfileUtilities.STATUS_ERROR); -// } - return true; - } - - private String mergeText(ProfileComparison outcome, StructuralMatch sm, String path, String name, String left, String right) { - // TODO: fix -// if (left == null && right == null) -// return null; -// if (left == null) -// return right; -// if (right == null) -// return left; -// left = stripLinks(left); -// right = stripLinks(right); -// if (left.equalsIgnoreCase(right)) -// return left; -// if (path != null) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.INFORMATIONAL, path, "Elements differ in definition for "+name+":\r\n \""+left+"\"\r\n \""+right+"\"", -// "Elements differ in definition for "+name+":
\""+Utilities.escapeXml(left)+"\"
\""+Utilities.escapeXml(right)+"\"", ValidationMessage.IssueSeverity.INFORMATION)); -// status(ed, ProfileUtilities.STATUS_HINT); -// } + private String mergeText(ProfileComparison comp, StructuralMatch res, String path, String name, String left, String right) { + if (left == null && right == null) + return null; + if (left == null) + return right; + if (right == null) + return left; + left = stripLinks(left); + right = stripLinks(right); + if (left.equalsIgnoreCase(right)) + return left; + if (path != null) { + vm(IssueSeverity.ERROR, "Elements differ in definition for "+name+":\r\n \""+left+"\"\r\n \""+right+"\"", path, comp.getMessages(), res.getMessages()); + } return "left: "+left+"; right: "+right; } @@ -467,84 +451,83 @@ public class ProfileComparer extends CanonicalResourceComparer { } - private Collection unionTypes(String path, List left, List right) throws DefinitionException, IOException, FHIRFormatError { + private Collection unionTypes(ProfileComparison comp, StructuralMatch res, String path, List left, List right) throws DefinitionException, IOException, FHIRFormatError { List result = new ArrayList(); for (TypeRefComponent l : left) - checkAddTypeUnion(path, result, l); + checkAddTypeUnion(comp, res, path, result, l); for (TypeRefComponent r : right) - checkAddTypeUnion(path, result, r); + checkAddTypeUnion(comp, res, path, result, r); return result; } - private void checkAddTypeUnion(String path, List results, TypeRefComponent nw) throws DefinitionException, IOException, FHIRFormatError { - // TODO: fix -// boolean pfound = false; -// boolean tfound = false; -// nw = nw.copy(); -// if (nw.hasAggregation()) -// throw new DefinitionException("Aggregation not supported: "+path); -// for (TypeRefComponent ex : results) { -// if (Utilities.equals(ex.getWorkingCode(), nw.getWorkingCode())) { -// if (!ex.hasProfile() && !nw.hasProfile()) -// pfound = true; -// else if (!ex.hasProfile()) { -// pfound = true; -// } else if (!nw.hasProfile()) { -// pfound = true; -// ex.setProfile(null); -// } else { -// // both have profiles. Is one derived from the other? -// StructureDefinition sdex = context.fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue()); -// StructureDefinition sdnw = context.fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue()); -// if (sdex != null && sdnw != null) { -// if (sdex == sdnw) { -// pfound = true; -// } else if (derivesFrom(sdex, sdnw)) { -// ex.setProfile(nw.getProfile()); -// pfound = true; -// } else if (derivesFrom(sdnw, sdex)) { -// pfound = true; -// } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { -// ProfileComparison comp = compareProfiles(sdex, sdnw); -// if (comp.getSuperset() != null) { -// pfound = true; -// ex.addProfile("#"+comp.id); -// } -// } -// } -// } -// if (!ex.hasTargetProfile() && !nw.hasTargetProfile()) -// tfound = true; -// else if (!ex.hasTargetProfile()) { -// tfound = true; -// } else if (!nw.hasTargetProfile()) { -// tfound = true; -// ex.setTargetProfile(null); -// } else { -// // both have profiles. Is one derived from the other? -// StructureDefinition sdex = context.fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue()); -// StructureDefinition sdnw = context.fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue()); -// if (sdex != null && sdnw != null) { -// if (sdex == sdnw) { -// tfound = true; -// } else if (derivesFrom(sdex, sdnw)) { -// ex.setTargetProfile(nw.getTargetProfile()); -// tfound = true; -// } else if (derivesFrom(sdnw, sdex)) { -// tfound = true; -// } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { -// ProfileComparison comp = compareProfiles(sdex, sdnw); -// if (comp.getSuperset() != null) { -// tfound = true; -// ex.addTargetProfile("#"+comp.id); -// } -// } -// } -// } -// } -// } -// if (!tfound || !pfound) -// results.add(nw); + private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch res, String path, List results, TypeRefComponent nw) throws DefinitionException, IOException, FHIRFormatError { + boolean pfound = false; + boolean tfound = false; + nw = nw.copy(); + if (nw.hasAggregation()) + throw new DefinitionException("Aggregation not supported: "+path); + for (TypeRefComponent ex : results) { + if (Utilities.equals(ex.getWorkingCode(), nw.getWorkingCode())) { + if (!ex.hasProfile() && !nw.hasProfile()) + pfound = true; + else if (!ex.hasProfile()) { + pfound = true; + } else if (!nw.hasProfile()) { + pfound = true; + ex.setProfile(null); + } else { + // both have profiles. Is one derived from the other? + StructureDefinition sdex = session.getContext().fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue()); + StructureDefinition sdnw = session.getContext().fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue()); + if (sdex != null && sdnw != null) { + if (sdex == sdnw) { + pfound = true; + } else if (derivesFrom(sdex, sdnw)) { + ex.setProfile(nw.getProfile()); + pfound = true; + } else if (derivesFrom(sdnw, sdex)) { + pfound = true; + } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { + ProfileComparison compP = (ProfileComparison) session.compare(sdex, sdnw); + if (compP != null && compP.getUnion() != null) { // might be null if circular + pfound = true; + ex.addProfile("#"+compP.getId()); + } + } + } + } + if (!ex.hasTargetProfile() && !nw.hasTargetProfile()) + tfound = true; + else if (!ex.hasTargetProfile()) { + tfound = true; + } else if (!nw.hasTargetProfile()) { + tfound = true; + ex.setTargetProfile(null); + } else { + // both have profiles. Is one derived from the other? + StructureDefinition sdex = session.getContext().fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue()); + StructureDefinition sdnw = session.getContext().fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue()); + if (sdex != null && sdnw != null) { + if (sdex == sdnw) { + tfound = true; + } else if (derivesFrom(sdex, sdnw)) { + ex.setTargetProfile(nw.getTargetProfile()); + tfound = true; + } else if (derivesFrom(sdnw, sdex)) { + tfound = true; + } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { + ProfileComparison compP = (ProfileComparison) session.compare(sdex, sdnw); + if (compP.getUnion() != null) { + tfound = true; + ex.addTargetProfile("#"+compP.getId()); + } + } + } + } + } + } + if (!tfound || !pfound) + results.add(nw); } @@ -556,75 +539,74 @@ public class ProfileComparer extends CanonicalResourceComparer { private Collection intersectTypes(ProfileComparison comp, StructuralMatch res, ElementDefinition ed, String path, List left, List right) throws DefinitionException, IOException, FHIRFormatError { - // TODO: fix List result = new ArrayList(); -// for (TypeRefComponent l : left) { -// if (l.hasAggregation()) -// throw new DefinitionException("Aggregation not supported: "+path); -// boolean pfound = false; -// boolean tfound = false; -// TypeRefComponent c = l.copy(); -// for (TypeRefComponent r : right) { -// if (r.hasAggregation()) -// throw new DefinitionException("Aggregation not supported: "+path); -// if (!l.hasProfile() && !r.hasProfile()) { -// pfound = true; -// } else if (!r.hasProfile()) { -// pfound = true; -// } else if (!l.hasProfile()) { -// pfound = true; -// c.setProfile(r.getProfile()); -// } else { -// StructureDefinition sdl = resolveProfile(ed, outcome, path, l.getProfile().get(0).getValue(), outcome.leftName()); -// StructureDefinition sdr = resolveProfile(ed, outcome, path, r.getProfile().get(0).getValue(), outcome.rightName()); -// if (sdl != null && sdr != null) { -// if (sdl == sdr) { -// pfound = true; -// } else if (derivesFrom(sdl, sdr)) { -// pfound = true; -// } else if (derivesFrom(sdr, sdl)) { -// c.setProfile(r.getProfile()); -// pfound = true; -// } else if (sdl.getType().equals(sdr.getType())) { -// ProfileComparison comp = compareProfiles(sdl, sdr); -// if (comp.getSubset() != null) { -// pfound = true; -// c.addProfile("#"+comp.id); -// } -// } -// } -// } -// if (!l.hasTargetProfile() && !r.hasTargetProfile()) { -// tfound = true; -// } else if (!r.hasTargetProfile()) { -// tfound = true; -// } else if (!l.hasTargetProfile()) { -// tfound = true; -// c.setTargetProfile(r.getTargetProfile()); -// } else { -// StructureDefinition sdl = resolveProfile(ed, outcome, path, l.getTargetProfile().get(0).getValue(), outcome.leftName()); -// StructureDefinition sdr = resolveProfile(ed, outcome, path, r.getTargetProfile().get(0).getValue(), outcome.rightName()); -// if (sdl != null && sdr != null) { -// if (sdl == sdr) { -// tfound = true; -// } else if (derivesFrom(sdl, sdr)) { -// tfound = true; -// } else if (derivesFrom(sdr, sdl)) { -// c.setTargetProfile(r.getTargetProfile()); -// tfound = true; -// } else if (sdl.getType().equals(sdr.getType())) { -// ProfileComparison comp = compareProfiles(sdl, sdr); -// if (comp.getSubset() != null) { -// tfound = true; -// c.addTargetProfile("#"+comp.id); -// } -// } -// } -// } -// } -// if (pfound && tfound) -// result.add(c); -// } + for (TypeRefComponent l : left) { + if (l.hasAggregation()) + throw new DefinitionException("Aggregation not supported: "+path); + boolean pfound = false; + boolean tfound = false; + TypeRefComponent c = l.copy(); + for (TypeRefComponent r : right) { + if (r.hasAggregation()) + throw new DefinitionException("Aggregation not supported: "+path); + if (!l.hasProfile() && !r.hasProfile()) { + pfound = true; + } else if (!r.hasProfile()) { + pfound = true; + } else if (!l.hasProfile()) { + pfound = true; + c.setProfile(r.getProfile()); + } else { + StructureDefinition sdl = resolveProfile(comp, res, path, l.getProfile().get(0).getValue(), comp.getLeft().getName()); + StructureDefinition sdr = resolveProfile(comp, res, path, r.getProfile().get(0).getValue(), comp.getRight().getName()); + if (sdl != null && sdr != null) { + if (sdl == sdr) { + pfound = true; + } else if (derivesFrom(sdl, sdr)) { + pfound = true; + } else if (derivesFrom(sdr, sdl)) { + c.setProfile(r.getProfile()); + pfound = true; + } else if (sdl.getType().equals(sdr.getType())) { + ProfileComparison compP = (ProfileComparison) session.compare(sdl, sdr); + if (compP != null && compP.getIntersection() != null) { + pfound = true; + c.addProfile("#"+compP.getId()); + } + } + } + } + if (!l.hasTargetProfile() && !r.hasTargetProfile()) { + tfound = true; + } else if (!r.hasTargetProfile()) { + tfound = true; + } else if (!l.hasTargetProfile()) { + tfound = true; + c.setTargetProfile(r.getTargetProfile()); + } else { + StructureDefinition sdl = resolveProfile(comp, res, path, l.getTargetProfile().get(0).getValue(), comp.getLeft().getName()); + StructureDefinition sdr = resolveProfile(comp, res, path, r.getTargetProfile().get(0).getValue(), comp.getRight().getName()); + if (sdl != null && sdr != null) { + if (sdl == sdr) { + tfound = true; + } else if (derivesFrom(sdl, sdr)) { + tfound = true; + } else if (derivesFrom(sdr, sdl)) { + c.setTargetProfile(r.getTargetProfile()); + tfound = true; + } else if (sdl.getType().equals(sdr.getType())) { + ProfileComparison compP = (ProfileComparison) session.compare(sdl, sdr); + if (compP != null && compP.getIntersection() != null) { + tfound = true; + c.addTargetProfile("#"+compP.getId()); + } + } + } + } + } + if (pfound && tfound) + result.add(c); + } return result; } @@ -636,135 +618,101 @@ public class ProfileComparer extends CanonicalResourceComparer { } - private boolean compareBindings(ProfileComparison comp, StructuralMatch res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError { - // TODO: fix -// assert(lDef.hasBinding() || rDef.hasBinding()); -// if (!lDef.hasBinding()) { -// subset.setBinding(rDef.getBinding()); -// // technically, the super set is unbound, but that's not very useful - so we use the provided on as an example -// superset.setBinding(rDef.getBinding().copy()); -// superset.getBinding().setStrength(BindingStrength.EXAMPLE); -// return true; -// } -// if (!rDef.hasBinding()) { -// subset.setBinding(lDef.getBinding()); -// superset.setBinding(lDef.getBinding().copy()); -// superset.getBinding().setStrength(BindingStrength.EXAMPLE); -// return true; -// } -// ElementDefinitionBindingComponent left = lDef.getBinding(); -// ElementDefinitionBindingComponent right = rDef.getBinding(); -// if (Base.compareDeep(left, right, false)) { -// subset.setBinding(left); -// superset.setBinding(right); -// } -// -// // if they're both examples/preferred then: -// // subset: left wins if they're both the same -// // superset: -// if (isPreferredOrExample(left) && isPreferredOrExample(right)) { -// if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Example/preferred bindings differ at "+path+" using binding from "+outcome.rightName(), ValidationMessage.IssueSeverity.INFORMATION)); -// status(subset, ProfileUtilities.STATUS_HINT); -// subset.setBinding(right); -// superset.setBinding(unionBindings(superset, outcome, path, left, right)); -// } else { -// if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false) ) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Example/preferred bindings differ at "+path+" using binding from "+outcome.leftName(), ValidationMessage.IssueSeverity.INFORMATION)); -// status(subset, ProfileUtilities.STATUS_HINT); -// } -// subset.setBinding(left); -// superset.setBinding(unionBindings(superset, outcome, path, left, right)); -// } -// return true; -// } -// // if either of them are extensible/required, then it wins -// if (isPreferredOrExample(left)) { -// subset.setBinding(right); -// superset.setBinding(unionBindings(superset, outcome, path, left, right)); -// return true; -// } -// if (isPreferredOrExample(right)) { -// subset.setBinding(left); -// superset.setBinding(unionBindings(superset, outcome, path, left, right)); -// return true; -// } -// -// // ok, both are extensible or required. -// ElementDefinitionBindingComponent subBinding = new ElementDefinitionBindingComponent(); -// subset.setBinding(subBinding); -// ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent(); -// superset.setBinding(superBinding); -// subBinding.setDescription(mergeText(subset, outcome, path, "description", left.getDescription(), right.getDescription())); -// superBinding.setDescription(mergeText(subset, outcome, null, "description", left.getDescription(), right.getDescription())); -// if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED) -// subBinding.setStrength(BindingStrength.REQUIRED); -// else -// subBinding.setStrength(BindingStrength.EXTENSIBLE); -// if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE) -// superBinding.setStrength(BindingStrength.EXTENSIBLE); -// else -// superBinding.setStrength(BindingStrength.REQUIRED); -// -// if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { -// subBinding.setValueSet(left.getValueSet()); -// superBinding.setValueSet(left.getValueSet()); -// return true; -// } else if (!left.hasValueSet()) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "No left Value set at "+path, ValidationMessage.IssueSeverity.ERROR)); -// return true; -// } else if (!right.hasValueSet()) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "No right Value set at "+path, ValidationMessage.IssueSeverity.ERROR)); -// return true; -// } else { -// // ok, now we compare the value sets. This may be unresolvable. -// ValueSet lvs = resolveVS(outcome.left, left.getValueSet()); -// ValueSet rvs = resolveVS(outcome.right, right.getValueSet()); -// if (lvs == null) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, ValidationMessage.IssueSeverity.ERROR)); -// return true; -// } else if (rvs == null) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Unable to resolve right value set "+right.getValueSet().toString()+" at "+path, ValidationMessage.IssueSeverity.ERROR)); -// return true; -// } else { -// // first, we'll try to do it by definition -// ValueSet cvs = intersectByDefinition(lvs, rvs); -// if(cvs == null) { -// // if that didn't work, we'll do it by expansion -// ValueSetExpansionOutcome le; -// ValueSetExpansionOutcome re; -// try { -// le = context.expandVS(lvs, true, false); -// re = context.expandVS(rvs, true, false); -// if (le.getError() != null) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "The value set "+lvs.getUrl()+" could not be expanded", ValidationMessage.IssueSeverity.ERROR)); -// } else if (re.getError() != null) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "The value set "+rvs.getUrl()+" could not be expanded", ValidationMessage.IssueSeverity.ERROR)); -// } else if (!closed(le.getValueset())) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "The value set "+lvs.getUrl()+" is not closed, so can't be compased", ValidationMessage.IssueSeverity.ERROR)); -// } else if (!closed(re.getValueset())) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "The value set "+rvs.getUrl()+" is not closed, so can't be compased", ValidationMessage.IssueSeverity.ERROR)); -// } else { -// cvs = intersectByExpansion(path, le.getValueset(), re.getValueset()); -// if (!cvs.getCompose().hasInclude()) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "The value sets "+lvs.getUrl()+" and "+rvs.getUrl()+" do not intersect", ValidationMessage.IssueSeverity.ERROR)); -// status(subset, ProfileUtilities.STATUS_ERROR); -// return false; -// } -// } -// } catch (Exception e){ -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Unable to expand or process value sets "+lvs.getUrl()+" and "+rvs.getUrl()+": "+e.getMessage(), ValidationMessage.IssueSeverity.ERROR)); -// status(subset, ProfileUtilities.STATUS_ERROR); -// e.printStackTrace(); -// return false; -// } -// } -// if (cvs != null) { -// subBinding.setValueSet("#"+addValueSet(cvs)); -// superBinding.setValueSet("#"+addValueSet(unite(superset, outcome, path, lvs, rvs))); -// } -// } -// } + private boolean compareBindings(ProfileComparison comp, StructuralMatch res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException { + assert(lDef.hasBinding() || rDef.hasBinding()); + if (!lDef.hasBinding()) { + subset.setBinding(rDef.getBinding()); + // technically, the super set is unbound, but that's not very useful - so we use the provided on as an example + superset.setBinding(rDef.getBinding().copy()); + superset.getBinding().setStrength(BindingStrength.EXAMPLE); + return true; + } + if (!rDef.hasBinding()) { + subset.setBinding(lDef.getBinding()); + superset.setBinding(lDef.getBinding().copy()); + superset.getBinding().setStrength(BindingStrength.EXAMPLE); + return true; + } + ElementDefinitionBindingComponent left = lDef.getBinding(); + ElementDefinitionBindingComponent right = rDef.getBinding(); + if (Base.compareDeep(left, right, false)) { + subset.setBinding(left); + superset.setBinding(right); + } + + // if they're both examples/preferred then: + // subset: left wins if they're both the same + // superset: + if (isPreferredOrExample(left) && isPreferredOrExample(right)) { + if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { + vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getRight().getName(), path, comp.getMessages(), res.getMessages()); + subset.setBinding(right); + superset.setBinding(unionBindings(comp, res, path, left, right)); + } else { + if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false) ) { + vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getLeft().getName(), path, comp.getMessages(), res.getMessages()); + } + subset.setBinding(left); + superset.setBinding(unionBindings(comp, res, path, left, right)); + } + return true; + } + // if either of them are extensible/required, then it wins + if (isPreferredOrExample(left)) { + subset.setBinding(right); + superset.setBinding(unionBindings(comp, res, path, left, right)); + return true; + } + if (isPreferredOrExample(right)) { + subset.setBinding(left); + superset.setBinding(unionBindings(comp, res, path, left, right)); + return true; + } + + // ok, both are extensible or required. + ElementDefinitionBindingComponent subBinding = new ElementDefinitionBindingComponent(); + subset.setBinding(subBinding); + ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent(); + superset.setBinding(superBinding); + subBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription())); + superBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription())); + if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED) + subBinding.setStrength(BindingStrength.REQUIRED); + else + subBinding.setStrength(BindingStrength.EXTENSIBLE); + if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE) + superBinding.setStrength(BindingStrength.EXTENSIBLE); + else + superBinding.setStrength(BindingStrength.REQUIRED); + + if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { + subBinding.setValueSet(left.getValueSet()); + superBinding.setValueSet(left.getValueSet()); + return true; + } else if (!left.hasValueSet()) { + vm(IssueSeverity.ERROR, "No left Value set at "+path, path, comp.getMessages(), res.getMessages()); + return true; + } else if (!right.hasValueSet()) { + vm(IssueSeverity.ERROR, "No right Value set at "+path, path, comp.getMessages(), res.getMessages()); + return true; + } else { + // ok, now we compare the value sets. This may be unresolvable. + ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet()); + ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet()); + if (lvs == null) { + vm(IssueSeverity.ERROR, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages()); + return true; + } else if (rvs == null) { + vm(IssueSeverity.ERROR, "Unable to resolve right value set "+right.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages()); + return true; + } else { + ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs); + if (compP != null) { + subBinding.setValueSet(compP.getIntersection().getUrl()); + superBinding.setValueSet(compP.getUnion().getUrl()); + } + } + } return false; } @@ -783,32 +731,77 @@ public class ProfileComparer extends CanonicalResourceComparer { // we can't really know about constraints. We create warnings, and collate them private List unionConstraints(ProfileComparison comp, StructuralMatch res, String path, List left, List right) { - // TODO: fix List result = new ArrayList(); -// for (ElementDefinitionConstraintComponent l : left) { -// boolean found = false; -// for (ElementDefinitionConstraintComponent r : right) -// if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) -// found = true; -// if (!found) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "StructureDefinition "+outcome.leftName()+" has a constraint that is not found in "+outcome.rightName()+" and it is uncertain whether they are compatible ("+l.getXpath()+")", ValidationMessage.IssueSeverity.INFORMATION)); -// status(ed, ProfileUtilities.STATUS_WARNING); -// } -// result.add(l); -// } -// for (ElementDefinitionConstraintComponent r : right) { -// boolean found = false; -// for (ElementDefinitionConstraintComponent l : left) -// if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) -// found = true; -// if (!found) { -// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "StructureDefinition "+outcome.rightName()+" has a constraint that is not found in "+outcome.leftName()+" and it is uncertain whether they are compatible ("+r.getXpath()+")", ValidationMessage.IssueSeverity.INFORMATION)); -// status(ed, ProfileUtilities.STATUS_WARNING); -// result.add(r); -// } -// } + for (ElementDefinitionConstraintComponent l : left) { + boolean found = false; + for (ElementDefinitionConstraintComponent r : right) + if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) + found = true; + if (!found) { + vm(IssueSeverity.INFORMATION, "StructureDefinition "+comp.getLeft().getName()+" has a constraint that is removed in "+comp.getRight().getName()+" and it is uncertain whether they are compatible ("+l.getExpression()+")", path, comp.getMessages(), res.getMessages()); + } + result.add(l); + } + for (ElementDefinitionConstraintComponent r : right) { + boolean found = false; + for (ElementDefinitionConstraintComponent l : left) + if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) + found = true; + if (!found) { + vm(IssueSeverity.INFORMATION, "StructureDefinition "+comp.getRight().getName()+" has added constraint that is not found in "+comp.getLeft().getName()+" and it is uncertain whether they are compatible ("+r.getExpression()+")", path, comp.getMessages(), res.getMessages()); + } + } return result; } + private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch res, String path, String url, String name) { + StructureDefinition sd = session.getContext().fetchResource(StructureDefinition.class, url); + if (sd == null) { + ValidationMessage vm = vmI(IssueSeverity.WARNING, "Unable to resolve profile "+url+" in profile "+name, path); + } + return sd; + } + + + + private boolean isPreferredOrExample(ElementDefinitionBindingComponent binding) { + return binding.getStrength() == BindingStrength.EXAMPLE || binding.getStrength() == BindingStrength.PREFERRED; + } + + private ElementDefinitionBindingComponent unionBindings(ProfileComparison comp, StructuralMatch res, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right) throws FHIRFormatError, DefinitionException, IOException { + ElementDefinitionBindingComponent union = new ElementDefinitionBindingComponent(); + if (left.getStrength().compareTo(right.getStrength()) < 0) + union.setStrength(left.getStrength()); + else + union.setStrength(right.getStrength()); + union.setDescription(mergeText(comp, res, path, "binding.description", left.getDescription(), right.getDescription())); + if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) + union.setValueSet(left.getValueSet()); + else { + ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet()); + ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet()); + if (lvs != null && rvs != null) { + ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs); + if (compP != null) { + union.setValueSet(compP.getUnion().getUrl()); + } + } else if (lvs != null) { + union.setValueSet(lvs.getUrl()); + } else if (rvs != null) { + union.setValueSet(rvs.getUrl()); + } + } + return union; + } + + private ValueSet resolveVS(StructureDefinition ctxtLeft, String vsRef) { + if (vsRef == null) + return null; + return session.getContext().fetchResource(ValueSet.class, vsRef); + } + + + + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ResourceComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ResourceComparer.java index 7b2c163c5..c9653e8b3 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ResourceComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ResourceComparer.java @@ -2,6 +2,7 @@ package org.hl7.fhir.r5.comparison; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; import org.hl7.fhir.r5.context.IWorkerContext; @@ -18,12 +19,28 @@ import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; public class ResourceComparer { - public class ResourceCmparison { + public class ResourceComparison { + private String id; + protected List messages = new ArrayList<>(); + + public ResourceComparison() { + super(); + } public List getMessages() { return messages; } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + } public final static String COLOR_NO_ROW_LEFT = "#ffffb3"; @@ -33,11 +50,11 @@ public class ResourceComparer { public final static String COLOR_DIFFERENT = "#f0b3ff"; public final static String COLOR_ISSUE = "#ffad99"; - protected IWorkerContext context; + protected ComparisonSession session; - public ResourceComparer(IWorkerContext context) { + public ResourceComparer(ComparisonSession session) { super(); - this.context = context; + this.session = session; } public Cell missingCell(HierarchicalTableGenerator gen) { @@ -53,7 +70,7 @@ public class ResourceComparer { return c; } - public XhtmlNode renderErrors(ResourceCmparison csc) { + public XhtmlNode renderErrors(ResourceComparison csc) { XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); XhtmlNode tbl = div.table("grid"); for (ValidationMessage vm : csc.messages) { @@ -66,8 +83,17 @@ public class ResourceComparer { } - protected ValidationMessage vm(IssueSeverity level, String message, String path) { - return new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, message, level == IssueSeverity.NULL ? IssueSeverity.INFORMATION : level); + protected ValidationMessage vmI(IssueSeverity level, String message, String path) { + ValidationMessage vm = new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, message, level == IssueSeverity.NULL ? IssueSeverity.INFORMATION : level); + return vm; + } + + protected void vm(IssueSeverity level, String message, String path, List genMessages, List specMessages) { + ValidationMessage vm = new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, message, level == IssueSeverity.NULL ? IssueSeverity.INFORMATION : level); + genMessages.add(vm); + if (specMessages != null) { + specMessages.add(vm); + } } private String colorForLevel(IssueSeverity level) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ValueSetComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ValueSetComparer.java index 6bc7e68ab..ad2e50245 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ValueSetComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/ValueSetComparer.java @@ -72,9 +72,8 @@ public class ValueSetComparer extends CanonicalResourceComparer { } } - public ValueSetComparer(IWorkerContext context) { - super(context); - this.context = context; + public ValueSetComparer(ComparisonSession session) { + super(session); } public ValueSetComparison compare(ValueSet left, ValueSet right) { @@ -84,10 +83,10 @@ public class ValueSetComparer extends CanonicalResourceComparer { throw new DefinitionException("No ValueSet provided (right)"); ValueSetComparison res = new ValueSetComparison(left, right); + session.identify(res); ValueSet vs = new ValueSet(); res.setUnion(vs); - vs.setId(UUID.randomUUID().toString().toLowerCase()); - vs.setUrl("urn:uuid:"+vs.getId()); + session.identify(vs); vs.setName("Union"+left.getName()+"And"+right.getName()); vs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); vs.setStatus(left.getStatus()); @@ -95,8 +94,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ValueSet vs1 = new ValueSet(); res.setIntersection(vs1); - vs1.setId(UUID.randomUUID().toString().toLowerCase()); - vs1.setUrl("urn:uuid:"+vs1.getId()); + session.identify(vs1); vs1.setName("Intersection"+left.getName()+"And"+right.getName()); vs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); vs1.setStatus(left.getStatus()); @@ -123,7 +121,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ConceptSetComponent r = findInList(right.getInclude(), l, left.getInclude()); if (r == null) { union.getInclude().add(l); - res.getIncludes().getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed Include", "ValueSet.compose.include"))); + res.getIncludes().getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed Include", "ValueSet.compose.include"))); } else { matchR.add(r); ConceptSetComponent csM = new ConceptSetComponent(); @@ -138,7 +136,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (ConceptSetComponent r : right.getInclude()) { if (!matchR.contains(r)) { union.getInclude().add(r); - res.getIncludes().getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added Include", "ValueSet.compose.include"), r)); + res.getIncludes().getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added Include", "ValueSet.compose.include"), r)); } } @@ -148,7 +146,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ConceptSetComponent r = findInList(right.getExclude(), l, left.getExclude()); if (r == null) { union.getExclude().add(l); - res.getExcludes().getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed Exclude", "ValueSet.compose.exclude"))); + res.getExcludes().getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed Exclude", "ValueSet.compose.exclude"))); } else { matchR.add(r); ConceptSetComponent csM = new ConceptSetComponent(); @@ -163,7 +161,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (ConceptSetComponent r : right.getExclude()) { if (!matchR.contains(r)) { union.getExclude().add(r); - res.getExcludes().getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added Exclude", "ValueSet.compose.exclude"), r)); + res.getExcludes().getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added Exclude", "ValueSet.compose.exclude"), r)); } } } @@ -209,7 +207,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { CanonicalType r = findInList(right.getValueSet(), l, left.getValueSet()); if (r == null) { union.getValueSet().add(l); - combined.getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed ValueSet", "ValueSet.compose.include.valueSet"))); + combined.getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed ValueSet", "ValueSet.compose.include.valueSet"))); } else { matchVSR.add(r); if (l.getValue().equals(r.getValue())) { @@ -220,7 +218,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { } else { union.getValueSet().add(l); union.getValueSet().add(r); - StructuralMatch sm = new StructuralMatch(l, r, vm(IssueSeverity.INFORMATION, "Values are different", "ValueSet.compose.include.valueSet")); + StructuralMatch sm = new StructuralMatch(l, r, vmI(IssueSeverity.INFORMATION, "Values are different", "ValueSet.compose.include.valueSet")); combined.getChildren().add(sm); } } @@ -228,7 +226,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (CanonicalType r : right.getValueSet()) { if (!matchVSR.contains(r)) { union.getValueSet().add(r); - combined.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Add ValueSet", "ValueSet.compose.include.valueSet"), r)); + combined.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Add ValueSet", "ValueSet.compose.include.valueSet"), r)); } } @@ -237,7 +235,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ConceptReferenceComponent r = findInList(right.getConcept(), l, left.getConcept()); if (r == null) { union.getConcept().add(l); - combined.getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed this Concept", "ValueSet.compose.include.concept"))); + combined.getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed this Concept", "ValueSet.compose.include.concept"))); } else { matchCR.add(r); if (l.getCode().equals(r.getCode())) { @@ -251,7 +249,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { } else { union.getConcept().add(l); union.getConcept().add(r); - StructuralMatch sm = new StructuralMatch(l, r, vm(IssueSeverity.INFORMATION, "Concepts are different", "ValueSet.compose.include.concept")); + StructuralMatch sm = new StructuralMatch(l, r, vmI(IssueSeverity.INFORMATION, "Concepts are different", "ValueSet.compose.include.concept")); combined.getChildren().add(sm); compareConcepts(l, r, sm, null, null); } @@ -260,7 +258,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (ConceptReferenceComponent r : right.getConcept()) { if (!matchCR.contains(r)) { union.getConcept().add(r); - combined.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added this Concept", "ValueSet.compose.include.concept"), r)); + combined.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added this Concept", "ValueSet.compose.include.concept"), r)); } } @@ -269,7 +267,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ConceptSetFilterComponent r = findInList(right.getFilter(), l, left.getFilter()); if (r == null) { union.getFilter().add(l); - combined.getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed this item", "ValueSet.compose.include.filter"))); + combined.getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed this item", "ValueSet.compose.include.filter"))); } else { matchFR.add(r); if (l.getProperty().equals(r.getProperty()) && l.getOp().equals(r.getOp())) { @@ -283,7 +281,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { } else { union.getFilter().add(l); union.getFilter().add(r); - StructuralMatch sm = new StructuralMatch(l, r, vm(IssueSeverity.INFORMATION, "Codes are different", "ValueSet.compose.include.filter")); + StructuralMatch sm = new StructuralMatch(l, r, vmI(IssueSeverity.INFORMATION, "Codes are different", "ValueSet.compose.include.filter")); combined.getChildren().add(sm); compareFilters(l, r, sm, null, null); } @@ -292,44 +290,44 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (ConceptSetFilterComponent r : right.getFilter()) { if (!matchFR.contains(r)) { union.getFilter().add(r); - combined.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added this item", "ValueSet.compose.include.filter"), r)); + combined.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added this item", "ValueSet.compose.include.filter"), r)); } } } private void compareConcepts(ConceptReferenceComponent l, ConceptReferenceComponent r, StructuralMatch sm, ConceptReferenceComponent cu, ConceptReferenceComponent ci) { - sm.getChildren().add(new StructuralMatch(l.getCodeElement(), r.getCodeElement(), l.getCode().equals(r.getCode()) ? null : vm(IssueSeverity.INFORMATION, "Codes do not match", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getCodeElement(), r.getCodeElement(), l.getCode().equals(r.getCode()) ? null : vmI(IssueSeverity.INFORMATION, "Codes do not match", "ValueSet.compose.include.concept"))); if (ci != null) { ci.setCode(l.getCode()); cu.setCode(l.getCode()); } if (l.hasDisplay() && r.hasDisplay()) { - sm.getChildren().add(new StructuralMatch(l.getDisplayElement(), r.getDisplayElement(), l.getDisplay().equals(r.getDisplay()) ? null : vm(IssueSeverity.INFORMATION, "Displays do not match", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getDisplayElement(), r.getDisplayElement(), l.getDisplay().equals(r.getDisplay()) ? null : vmI(IssueSeverity.INFORMATION, "Displays do not match", "ValueSet.compose.include.concept"))); if (ci != null) { ci.setDisplay(r.getDisplay()); cu.setDisplay(r.getDisplay()); } } else if (l.hasDisplay()) { - sm.getChildren().add(new StructuralMatch(l.getDisplayElement(), null, vm(IssueSeverity.INFORMATION, "Display Removed", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getDisplayElement(), null, vmI(IssueSeverity.INFORMATION, "Display Removed", "ValueSet.compose.include.concept"))); if (ci != null) { ci.setDisplay(l.getDisplay()); cu.setDisplay(l.getDisplay()); } } else if (r.hasDisplay()) { - sm.getChildren().add(new StructuralMatch(null, r.getDisplayElement(), vm(IssueSeverity.INFORMATION, "Display added", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(null, r.getDisplayElement(), vmI(IssueSeverity.INFORMATION, "Display added", "ValueSet.compose.include.concept"))); if (ci != null) { ci.setDisplay(r.getDisplay()); cu.setDisplay(r.getDisplay()); } } else { - sm.getChildren().add(new StructuralMatch(null, null, vm(IssueSeverity.INFORMATION, "No Display", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(null, null, vmI(IssueSeverity.INFORMATION, "No Display", "ValueSet.compose.include.concept"))); } } private void compareFilters(ConceptSetFilterComponent l, ConceptSetFilterComponent r, StructuralMatch sm, ConceptSetFilterComponent cu, ConceptSetFilterComponent ci) { - sm.getChildren().add(new StructuralMatch(l.getPropertyElement(), r.getPropertyElement(), l.getProperty().equals(r.getProperty()) ? null : vm(IssueSeverity.INFORMATION, "Properties do not match", "ValueSet.compose.include.concept"))); - sm.getChildren().add(new StructuralMatch(l.getOpElement(), r.getOpElement(), l.getOp().equals(r.getOp()) ? null : vm(IssueSeverity.INFORMATION, "Filter Operations do not match", "ValueSet.compose.include.concept"))); - sm.getChildren().add(new StructuralMatch(l.getValueElement(), r.getValueElement(), l.getValue().equals(r.getValue()) ? null : vm(IssueSeverity.INFORMATION, "Values do not match", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getPropertyElement(), r.getPropertyElement(), l.getProperty().equals(r.getProperty()) ? null : vmI(IssueSeverity.INFORMATION, "Properties do not match", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getOpElement(), r.getOpElement(), l.getOp().equals(r.getOp()) ? null : vmI(IssueSeverity.INFORMATION, "Filter Operations do not match", "ValueSet.compose.include.concept"))); + sm.getChildren().add(new StructuralMatch(l.getValueElement(), r.getValueElement(), l.getValue().equals(r.getValue()) ? null : vmI(IssueSeverity.INFORMATION, "Values do not match", "ValueSet.compose.include.concept"))); if (ci != null) { ci.setProperty(l.getProperty()); ci.setOp(l.getOp()); @@ -386,7 +384,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { } private ValueSet expand(ValueSet vs, ValueSetComparison res, String name) { - ValueSetExpansionOutcome vse = context.expandVS(vs, true, false); + ValueSetExpansionOutcome vse =session.getContext().expandVS(vs, true, false); if (vse.getValueset() != null) { return vse.getValueset(); } else { @@ -401,7 +399,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { ValueSetExpansionContainsComponent r = findInList(right, l); if (r == null) { union.add(l); - combined.getChildren().add(new StructuralMatch(l, vm(IssueSeverity.INFORMATION, "Removed from expansion", path))); + combined.getChildren().add(new StructuralMatch(l, vmI(IssueSeverity.INFORMATION, "Removed from expansion", path))); } else { matchR.add(r); ValueSetExpansionContainsComponent ccU = merge(l, r); @@ -417,7 +415,7 @@ public class ValueSetComparer extends CanonicalResourceComparer { for (ValueSetExpansionContainsComponent r : right) { if (!matchR.contains(r)) { union.add(r); - combined.getChildren().add(new StructuralMatch(vm(IssueSeverity.INFORMATION, "Added to expansion", path), r)); + combined.getChildren().add(new StructuralMatch(vmI(IssueSeverity.INFORMATION, "Added to expansion", path), r)); } } } @@ -429,15 +427,15 @@ public class ValueSetComparer extends CanonicalResourceComparer { private void compareStrings(String path, List msgs, String left, String right, String name, IssueSeverity level, ValueSetComparison res) { if (!Utilities.noString(right)) { if (Utilities.noString(left)) { - msgs.add(vm(level, "Value for "+name+" added", path)); + msgs.add(vmI(level, "Value for "+name+" added", path)); } else if (!left.equals(right)) { if (level != IssueSeverity.NULL) { res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path+".name", "Changed value for "+name+": '"+left+"' vs '"+right+"'", level)); } - msgs.add(vm(level, name+" changed from left to right", path)); + msgs.add(vmI(level, name+" changed from left to right", path)); } } else if (!Utilities.noString(left)) { - msgs.add(vm(level, "Value for "+name+" removed", path)); + msgs.add(vmI(level, "Value for "+name+" removed", path)); } } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java index b462e1a0c..919ea6e05 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/PackageClientTests.java @@ -54,7 +54,7 @@ public class PackageClientTests { @Test public void testExists2() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); Assertions.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1")); Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2")); Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1")); @@ -62,7 +62,7 @@ public class PackageClientTests { @Test public void testSearch2() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); List matches = client.search("core", null, null, false); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -72,14 +72,14 @@ public class PackageClientTests { @Test public void testSearchNoMatches2() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); List matches = client.search("corezxxx", null, null, false); Assertions.assertTrue(matches.size() == 0); } @Test public void testVersions2() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); List matches = client.getVersions("Simplifier.Core.STU3"); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -89,7 +89,7 @@ public class PackageClientTests { @Test public void testVersions2A() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); List matches = client.getVersions("hl7.fhir.us.core"); for (PackageInfo pi : matches) { System.out.println(pi.toString()); @@ -99,7 +99,7 @@ public class PackageClientTests { @Test public void testVersionsNone2() throws IOException { - PackageClient client = new PackageClient("http://test.fhir.org/packages"); + PackageClient client = new PackageClient("http://packages2.fhir.org/packages"); List matches = client.getVersions("Simplifier.Core.STU3X"); Assertions.assertTrue(matches.size() == 0); } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java index 26e738343..34f5d0ab5 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/PackageCacheManager.java @@ -177,7 +177,7 @@ public class PackageCacheManager { } private static final String PRIMARY_SERVER = "http://packages.fhir.org"; - private static final String SECONDARY_SERVER = "http://test.fhir.org/packages"; + private static final String SECONDARY_SERVER = "http://packages2.fhir.org/packages"; // private static final String SECONDARY_SERVER = "http://local.fhir.org:960/packages"; public static final String PACKAGE_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+$"; public static final String PACKAGE_VERSION_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+\\#[a-z0-9\\-\\_]+(\\.[a-z0-9\\-\\_]+)*$"; diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java index 77f1abc7a..487e69ac8 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java @@ -17,6 +17,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.comparison.CodeSystemComparer; import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; +import org.hl7.fhir.r5.comparison.ComparisonSession; import org.hl7.fhir.r5.comparison.ValueSetComparer; import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; import org.hl7.fhir.r5.conformance.ProfileUtilities; @@ -136,9 +137,11 @@ public class ComparisonTests { System.out.println("---- " + name + " ----------------------------------------------------------------"); CanonicalResource left = load("left"); CanonicalResource right = load("right"); - + + ComparisonSession session = new ComparisonSession(context); + if (left instanceof CodeSystem && right instanceof CodeSystem) { - CodeSystemComparer cs = new CodeSystemComparer(context); + CodeSystemComparer cs = new CodeSystemComparer(session ); CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right); Assertions.assertTrue(csc.getUnion().getConcept().size() > csc.getIntersection().getConcept().size()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", name+"-union.json")), csc.getUnion()); @@ -150,7 +153,7 @@ public class ComparisonTests { TextFile.stringToFile(HEADER+hd("Messages")+xmle+BREAK+hd("Metadata")+xml1+BREAK+hd("Concepts")+xml2+FOOTER, Utilities.path("[tmp]", "comparison", name+".html")); checkOutcomes(csc.getMessages(), content); } else if (left instanceof ValueSet && right instanceof ValueSet) { - ValueSetComparer cs = new ValueSetComparer(context); + ValueSetComparer cs = new ValueSetComparer(session); ValueSetComparison csc = cs.compare((ValueSet) left, (ValueSet) right); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", name+"-union.json")), csc.getUnion()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", name+"-intersection.json")), csc.getIntersection());