update to use new secondary package server

This commit is contained in:
Grahame Grieve 2020-05-10 08:15:40 +10:00
parent 0bf1dedf1e
commit d203b17c7d
9 changed files with 569 additions and 451 deletions

View File

@ -32,7 +32,7 @@ import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Title;
public abstract class CanonicalResourceComparer extends ResourceComparer { public abstract class CanonicalResourceComparer extends ResourceComparer {
public class CanonicalResourceComparison<T extends CanonicalResource> extends ResourceCmparison { public class CanonicalResourceComparison<T extends CanonicalResource> extends ResourceComparison {
protected T left; protected T left;
protected T right; protected T right;
@ -91,8 +91,8 @@ public abstract class CanonicalResourceComparer extends ResourceComparer {
} }
public CanonicalResourceComparer(IWorkerContext context) { public CanonicalResourceComparer(ComparisonSession session) {
super(context); super(session);
} }
protected void compareMetadata(CanonicalResource left, CanonicalResource right, Map<String, StructuralMatch<String>> comp, CanonicalResourceComparison<? extends CanonicalResource> res) { protected void compareMetadata(CanonicalResource left, CanonicalResource right, Map<String, StructuralMatch<String>> comp, CanonicalResourceComparison<? extends CanonicalResource> res) {
@ -115,19 +115,19 @@ public abstract class CanonicalResourceComparer extends ResourceComparer {
if (l.isEmpty() && r.isEmpty()) { if (l.isEmpty() && r.isEmpty()) {
match = new StructuralMatch<>(null, null, null); match = new StructuralMatch<>(null, null, null);
} else if (l.isEmpty()) { } 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()) { } 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()) { } 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()) { } 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()) { } 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())) { } else if (l.getValue().equals(r.getValue())) {
match = new StructuralMatch<>(l.primitiveValue(), r.primitiveValue(), null); match = new StructuralMatch<>(l.primitiveValue(), r.primitiveValue(), null);
} else { } 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) { 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)); res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, fhirType()+"."+name, "Values for "+name+" differ: '"+l.primitiveValue()+"' vs '"+r.primitiveValue()+"'", level));
} }

View File

@ -54,9 +54,8 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
private CodeSystem right; private CodeSystem right;
public CodeSystemComparer(IWorkerContext context) { public CodeSystemComparer(ComparisonSession session) {
super(context); super(session);
this.context = context;
} }
public CodeSystemComparison compare(CodeSystem left, CodeSystem right) { public CodeSystemComparison compare(CodeSystem left, CodeSystem right) {
@ -67,10 +66,10 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
CodeSystemComparison res = new CodeSystemComparison(left, right); CodeSystemComparison res = new CodeSystemComparison(left, right);
session.identify(res);
CodeSystem cs = new CodeSystem(); CodeSystem cs = new CodeSystem();
res.setUnion(cs); res.setUnion(cs);
cs.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(cs);
cs.setUrl("urn:uuid:"+cs.getId());
cs.setName("Union"+left.getName()+"And"+right.getName()); cs.setName("Union"+left.getName()+"And"+right.getName());
cs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); cs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle());
cs.setStatus(left.getStatus()); cs.setStatus(left.getStatus());
@ -90,8 +89,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
CodeSystem cs1 = new CodeSystem(); CodeSystem cs1 = new CodeSystem();
res.setIntersection(cs1); res.setIntersection(cs1);
cs1.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(cs1);
cs1.setUrl("urn:uuid:"+cs1.getId());
cs1.setName("Intersection"+left.getName()+"And"+right.getName()); cs1.setName("Intersection"+left.getName()+"And"+right.getName());
cs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); cs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle());
cs1.setStatus(left.getStatus()); cs1.setStatus(left.getStatus());
@ -144,7 +142,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
ConceptDefinitionComponent r = findInList(right, l); ConceptDefinitionComponent r = findInList(right, l);
if (r == null) { if (r == null) {
union.add(l); union.add(l);
combined.getChildren().add(new StructuralMatch<CodeSystem.ConceptDefinitionComponent>(l, vm(IssueSeverity.INFORMATION, "Removed this concept", path))); combined.getChildren().add(new StructuralMatch<CodeSystem.ConceptDefinitionComponent>(l, vmI(IssueSeverity.INFORMATION, "Removed this concept", path)));
} else { } else {
matchR.add(r); matchR.add(r);
ConceptDefinitionComponent cdM = merge(l, r, csU.getProperty(), res); ConceptDefinitionComponent cdM = merge(l, r, csU.getProperty(), res);
@ -160,7 +158,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
for (ConceptDefinitionComponent r : right) { for (ConceptDefinitionComponent r : right) {
if (!matchR.contains(r)) { if (!matchR.contains(r)) {
union.add(r); union.add(r);
combined.getChildren().add(new StructuralMatch<CodeSystem.ConceptDefinitionComponent>(vm(IssueSeverity.INFORMATION, "Added this concept", path), r)); combined.getChildren().add(new StructuralMatch<CodeSystem.ConceptDefinitionComponent>(vmI(IssueSeverity.INFORMATION, "Added this concept", path), r));
} }
} }
} }
@ -182,15 +180,15 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
private void compareStrings(String path, List<ValidationMessage> msgs, String left, String right, String name, IssueSeverity level, CodeSystemComparison res) { private void compareStrings(String path, List<ValidationMessage> msgs, String left, String right, String name, IssueSeverity level, CodeSystemComparison res) {
if (!Utilities.noString(right)) { if (!Utilities.noString(right)) {
if (Utilities.noString(left)) { 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)) { } else if (!left.equals(right)) {
if (level != IssueSeverity.NULL) { if (level != IssueSeverity.NULL) {
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path+"."+name, "Changed value for "+name+": '"+left+"' vs '"+right+"'", level)); 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)) { } else if (!Utilities.noString(left)) {
msgs.add(vm(level, "Value for "+name+" removed", path)); msgs.add(vmI(level, "Value for "+name+" removed", path));
} }
} }

View File

@ -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<String, ResourceComparison> 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);
}
}

View File

@ -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.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; 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.Base;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.IntegerType; 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.StringType;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; 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.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.utils.DefinitionNavigator; import org.hl7.fhir.r5.utils.DefinitionNavigator;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
public class ProfileComparer extends CanonicalResourceComparer { public class ProfileComparer extends CanonicalResourceComparer {
private static final int BOTH_NULL = 0;
private static final int EITHER_NULL = 1;
public class ProfileComparison extends CanonicalResourceComparison<StructureDefinition> { public class ProfileComparison extends CanonicalResourceComparison<StructureDefinition> {
private StructuralMatch<ElementDefinition> combined; private StructuralMatch<ElementDefinition> combined;
@ -63,8 +63,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
} }
} }
public ProfileComparer(IWorkerContext context) { public ProfileComparer(ComparisonSession session) {
super(context); super(session);
} }
@Override @Override
@ -77,10 +77,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
check(right, "right"); check(right, "right");
ProfileComparison res = new ProfileComparison(left, right); ProfileComparison res = new ProfileComparison(left, right);
session.identify(res);
StructureDefinition sd = new StructureDefinition(); StructureDefinition sd = new StructureDefinition();
res.setUnion(sd); res.setUnion(sd);
sd.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(sd);
sd.setUrl("urn:uuid:"+sd.getId());
sd.setName("Union"+left.getName()+"And"+right.getName()); sd.setName("Union"+left.getName()+"And"+right.getName());
sd.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); sd.setTitle("Union of "+left.getTitle()+" And "+right.getTitle());
sd.setStatus(left.getStatus()); sd.setStatus(left.getStatus());
@ -88,8 +88,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
StructureDefinition sd1 = new StructureDefinition(); StructureDefinition sd1 = new StructureDefinition();
res.setIntersection(sd1); res.setIntersection(sd1);
sd1.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(sd1);
sd1.setUrl("urn:uuid:"+sd1.getId());
sd1.setName("Intersection"+left.getName()+"And"+right.getName()); sd1.setName("Intersection"+left.getName()+"And"+right.getName());
sd1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); sd1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle());
sd1.setStatus(left.getStatus()); sd1.setStatus(left.getStatus());
@ -103,10 +102,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
comparePrimitives("baseDefinition", left.getBaseDefinitionElement(), right.getBaseDefinitionElement(), res.getMetadata(), IssueSeverity.ERROR, res); comparePrimitives("baseDefinition", left.getBaseDefinitionElement(), right.getBaseDefinitionElement(), res.getMetadata(), IssueSeverity.ERROR, res);
if (left.getType().equals(right.getType())) { if (left.getType().equals(right.getType())) {
DefinitionNavigator ln = new DefinitionNavigator(context, left); DefinitionNavigator ln = new DefinitionNavigator(session.getContext(), left);
DefinitionNavigator rn = new DefinitionNavigator(context, right); DefinitionNavigator rn = new DefinitionNavigator(session.getContext(), right);
// StructuralMatch<ElementDefinition> res = new StructuralMatch<ElementDefinition>(left.current(), right.current()); StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(ln.current(), rn.current());
// compareElements(res, res.getCombined(), ln.path(), null, ln, rn, sd, sd1); compareElements(res, sm, ln.path(), null, ln, rn);
} }
return res; return res;
} }
@ -131,10 +130,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
assert(left.path().equals(right.path())); assert(left.path().equals(right.path()));
// not allowed to be different: // not allowed to be different:
ruleCompares(comp, res, left.current().getDefaultValue(), right.current().getDefaultValue(), path+".defaultValue[x]", BOTH_NULL); ruleEqual(comp, res, left.current().getDefaultValue(), right.current().getDefaultValue(), "defaultValue", path);
ruleEqual(comp, res, path, left.current().getMeaningWhenMissing(), right.current().getMeaningWhenMissing(), "meaningWhenMissing Must be the same", true); ruleEqual(comp, res, left.current().getMeaningWhenMissingElement(), right.current().getMeaningWhenMissingElement(), "meaningWhenMissing", path);
ruleEqual(comp, res, left.current().getIsModifier(), right.current().getIsModifier(), path, "isModifier"); ruleEqual(comp, res, left.current().getIsModifierElement(), right.current().getIsModifierElement(), "isModifier", path);
ruleEqual(comp, res, left.current().getIsSummary(), right.current().getIsSummary(), path, "isSummary"); 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 // we ignore slicing right now - we're going to clone the root one anyway, and then think about clones
// simple stuff // simple stuff
@ -173,7 +172,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
subset.setMax(intersectMax(left.current().getMax(), right.current().getMax())); 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)); 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())); 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)); rule(comp, res, !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]> // <fixed[x]><!-- ?? 0..1 * Value must be exactly this --></fixed[x]>
@ -268,7 +267,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
DefinitionNavigator r = findInList(rc, l); DefinitionNavigator r = findInList(rc, l);
if (r == null) { if (r == null) {
comp.getUnion().getSnapshot().getElement().add(l.current().copy()); comp.getUnion().getSnapshot().getElement().add(l.current().copy());
res.getChildren().add(new StructuralMatch<ElementDefinition>(l.current(), vm(IssueSeverity.INFORMATION, "Removed this element", path))); res.getChildren().add(new StructuralMatch<ElementDefinition>(l.current(), vmI(IssueSeverity.INFORMATION, "Removed this element", path)));
} else { } else {
matchR.add(r); matchR.add(r);
StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(l.current(), r.current()); StructuralMatch<ElementDefinition> sm = new StructuralMatch<ElementDefinition>(l.current(), r.current());
@ -279,88 +278,73 @@ public class ProfileComparer extends CanonicalResourceComparer {
for (DefinitionNavigator r : rc) { for (DefinitionNavigator r : rc) {
if (!matchR.contains(r)) { if (!matchR.contains(r)) {
comp.getUnion().getSnapshot().getElement().add(r.current().copy()); comp.getUnion().getSnapshot().getElement().add(r.current().copy());
res.getChildren().add(new StructuralMatch<ElementDefinition>(vm(IssueSeverity.INFORMATION, "Added this element", path), r.current())); res.getChildren().add(new StructuralMatch<ElementDefinition>(vmI(IssueSeverity.INFORMATION, "Added this element", path), r.current()));
} }
} }
} }
private DefinitionNavigator findInList(List<DefinitionNavigator> rc, DefinitionNavigator l) { private DefinitionNavigator findInList(List<DefinitionNavigator> rc, DefinitionNavigator l) {
// TODO: fix for (DefinitionNavigator t : rc) {
if (t.current().getPath().equals(l.current().getPath())) {
return t;
}
}
return null; return null;
} }
private boolean ruleCompares(ProfileComparison comp, StructuralMatch<ElementDefinition> res, DataType vLeft, DataType vRight, String path, int nullStatus) throws IOException { private void ruleEqual(ProfileComparison comp, StructuralMatch<ElementDefinition> res, DataType vLeft, DataType vRight, String name, String path) throws IOException {
// TODO: fix if (vLeft == null && vRight == null) {
// if (vLeft == null && vRight == null && nullStatus == BOTH_NULL) // nothing
// return true; } else if (vLeft == null) {
// if (vLeft == null && vRight == null) { vm(IssueSeverity.ERROR, "Added "+name, path, comp.getMessages(), res.getMessages());
// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Must be the same and not null (null/null)", ValidationMessage.IssueSeverity.ERROR)); } else if (vRight == null) {
// status(ed, ProfileUtilities.STATUS_ERROR); vm(IssueSeverity.ERROR, "Removed "+name, path, comp.getMessages(), res.getMessages());
// } } else if (Base.compareDeep(vLeft, vRight, false)) {
// if (vLeft == null && nullStatus == EITHER_NULL) vm(IssueSeverity.ERROR, name+" be the same ("+toString(vLeft)+"/"+toString(vRight)+")", path, comp.getMessages(), res.getMessages());
// return true; }
// if (vRight == null && nullStatus == EITHER_NULL) }
// return true;
// if (vLeft == null || vRight == null || !Base.compareDeep(vLeft, vRight, false)) { private String toString(DataType val) throws IOException {
// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "Must be the same ("+toString(vLeft)+"/"+toString(vRight)+")", ValidationMessage.IssueSeverity.ERROR)); if (val instanceof PrimitiveType)
// status(ed, ProfileUtilities.STATUS_ERROR); return "\"" + ((PrimitiveType) val).getValueAsString()+"\"";
// }
return true; 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<ElementDefinition> res, boolean test, String path, String message) { private boolean rule(ProfileComparison comp, StructuralMatch<ElementDefinition> res, boolean test, String path, String message) {
// TODO: fix if (!test) {
// if (!test) { vm(IssueSeverity.ERROR, message, path, comp.getMessages(), res.getMessages());
// messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, message, ValidationMessage.IssueSeverity.ERROR)); }
// status(ed, ProfileUtilities.STATUS_ERROR);
// }
return test; return test;
} }
private String mergeText(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, String name, String left, String right) {
private boolean ruleEqual(ProfileComparison comp, StructuralMatch<ElementDefinition> res, boolean vLeft, boolean vRight, String path, String elementName) { if (left == null && right == null)
// TODO: fix return null;
// if (vLeft != vRight) { if (left == null)
// res.getMessages().add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, elementName+" must be the same ("+vLeft+"/"+vRight+")", ValidationMessage.IssueSeverity.ERROR)); return right;
// status(ed, ProfileUtilities.STATUS_ERROR); if (right == null)
// } return left;
return true; 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());
} }
private boolean ruleEqual(ProfileComparison comp, StructuralMatch<ElementDefinition> 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<ElementDefinition> 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+":<br/>\""+Utilities.escapeXml(left)+"\"<br/>\""+Utilities.escapeXml(right)+"\"", ValidationMessage.IssueSeverity.INFORMATION));
// status(ed, ProfileUtilities.STATUS_HINT);
// }
return "left: "+left+"; right: "+right; return "left: "+left+"; right: "+right;
} }
@ -467,84 +451,83 @@ public class ProfileComparer extends CanonicalResourceComparer {
} }
private Collection<? extends TypeRefComponent> unionTypes(String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError { private Collection<? extends TypeRefComponent> unionTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>(); List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
for (TypeRefComponent l : left) for (TypeRefComponent l : left)
checkAddTypeUnion(path, result, l); checkAddTypeUnion(comp, res, path, result, l);
for (TypeRefComponent r : right) for (TypeRefComponent r : right)
checkAddTypeUnion(path, result, r); checkAddTypeUnion(comp, res, path, result, r);
return result; return result;
} }
private void checkAddTypeUnion(String path, List<TypeRefComponent> results, TypeRefComponent nw) throws DefinitionException, IOException, FHIRFormatError { private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<TypeRefComponent> results, TypeRefComponent nw) throws DefinitionException, IOException, FHIRFormatError {
// TODO: fix boolean pfound = false;
// boolean pfound = false; boolean tfound = false;
// boolean tfound = false; nw = nw.copy();
// nw = nw.copy(); if (nw.hasAggregation())
// if (nw.hasAggregation()) throw new DefinitionException("Aggregation not supported: "+path);
// throw new DefinitionException("Aggregation not supported: "+path); for (TypeRefComponent ex : results) {
// for (TypeRefComponent ex : results) { if (Utilities.equals(ex.getWorkingCode(), nw.getWorkingCode())) {
// if (Utilities.equals(ex.getWorkingCode(), nw.getWorkingCode())) { if (!ex.hasProfile() && !nw.hasProfile())
// if (!ex.hasProfile() && !nw.hasProfile()) pfound = true;
// pfound = true; else if (!ex.hasProfile()) {
// else if (!ex.hasProfile()) { pfound = true;
// pfound = true; } else if (!nw.hasProfile()) {
// } else if (!nw.hasProfile()) { pfound = true;
// pfound = true; ex.setProfile(null);
// ex.setProfile(null); } else {
// } else { // both have profiles. Is one derived from the other?
// // both have profiles. Is one derived from the other? StructureDefinition sdex = session.getContext().fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue());
// StructureDefinition sdex = context.fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue()); StructureDefinition sdnw = session.getContext().fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue());
// StructureDefinition sdnw = context.fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue()); if (sdex != null && sdnw != null) {
// if (sdex != null && sdnw != null) { if (sdex == sdnw) {
// if (sdex == sdnw) { pfound = true;
// pfound = true; } else if (derivesFrom(sdex, sdnw)) {
// } else if (derivesFrom(sdex, sdnw)) { ex.setProfile(nw.getProfile());
// ex.setProfile(nw.getProfile()); pfound = true;
// pfound = true; } else if (derivesFrom(sdnw, sdex)) {
// } else if (derivesFrom(sdnw, sdex)) { pfound = true;
// pfound = true; } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) {
// } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { ProfileComparison compP = (ProfileComparison) session.compare(sdex, sdnw);
// ProfileComparison comp = compareProfiles(sdex, sdnw); if (compP != null && compP.getUnion() != null) { // might be null if circular
// if (comp.getSuperset() != null) { pfound = true;
// pfound = true; ex.addProfile("#"+compP.getId());
// ex.addProfile("#"+comp.id); }
// } }
// } }
// } }
// } if (!ex.hasTargetProfile() && !nw.hasTargetProfile())
// if (!ex.hasTargetProfile() && !nw.hasTargetProfile()) tfound = true;
// tfound = true; else if (!ex.hasTargetProfile()) {
// else if (!ex.hasTargetProfile()) { tfound = true;
// tfound = true; } else if (!nw.hasTargetProfile()) {
// } else if (!nw.hasTargetProfile()) { tfound = true;
// tfound = true; ex.setTargetProfile(null);
// ex.setTargetProfile(null); } else {
// } else { // both have profiles. Is one derived from the other?
// // both have profiles. Is one derived from the other? StructureDefinition sdex = session.getContext().fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue());
// StructureDefinition sdex = context.fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue()); StructureDefinition sdnw = session.getContext().fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue());
// StructureDefinition sdnw = context.fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue()); if (sdex != null && sdnw != null) {
// if (sdex != null && sdnw != null) { if (sdex == sdnw) {
// if (sdex == sdnw) { tfound = true;
// tfound = true; } else if (derivesFrom(sdex, sdnw)) {
// } else if (derivesFrom(sdex, sdnw)) { ex.setTargetProfile(nw.getTargetProfile());
// ex.setTargetProfile(nw.getTargetProfile()); tfound = true;
// tfound = true; } else if (derivesFrom(sdnw, sdex)) {
// } else if (derivesFrom(sdnw, sdex)) { tfound = true;
// tfound = true; } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) {
// } else if (sdnw.getSnapshot().getElement().get(0).getPath().equals(sdex.getSnapshot().getElement().get(0).getPath())) { ProfileComparison compP = (ProfileComparison) session.compare(sdex, sdnw);
// ProfileComparison comp = compareProfiles(sdex, sdnw); if (compP.getUnion() != null) {
// if (comp.getSuperset() != null) { tfound = true;
// tfound = true; ex.addTargetProfile("#"+compP.getId());
// ex.addTargetProfile("#"+comp.id); }
// } }
// } }
// } }
// } }
// } }
// } if (!tfound || !pfound)
// if (!tfound || !pfound) results.add(nw);
// results.add(nw);
} }
@ -556,75 +539,74 @@ public class ProfileComparer extends CanonicalResourceComparer {
private Collection<? extends TypeRefComponent> intersectTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition ed, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError { private Collection<? extends TypeRefComponent> intersectTypes(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition ed, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError {
// TODO: fix
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>(); List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
// for (TypeRefComponent l : left) { for (TypeRefComponent l : left) {
// if (l.hasAggregation()) if (l.hasAggregation())
// throw new DefinitionException("Aggregation not supported: "+path); throw new DefinitionException("Aggregation not supported: "+path);
// boolean pfound = false; boolean pfound = false;
// boolean tfound = false; boolean tfound = false;
// TypeRefComponent c = l.copy(); TypeRefComponent c = l.copy();
// for (TypeRefComponent r : right) { for (TypeRefComponent r : right) {
// if (r.hasAggregation()) if (r.hasAggregation())
// throw new DefinitionException("Aggregation not supported: "+path); throw new DefinitionException("Aggregation not supported: "+path);
// if (!l.hasProfile() && !r.hasProfile()) { if (!l.hasProfile() && !r.hasProfile()) {
// pfound = true; pfound = true;
// } else if (!r.hasProfile()) { } else if (!r.hasProfile()) {
// pfound = true; pfound = true;
// } else if (!l.hasProfile()) { } else if (!l.hasProfile()) {
// pfound = true; pfound = true;
// c.setProfile(r.getProfile()); c.setProfile(r.getProfile());
// } else { } else {
// StructureDefinition sdl = resolveProfile(ed, outcome, path, l.getProfile().get(0).getValue(), outcome.leftName()); StructureDefinition sdl = resolveProfile(comp, res, path, l.getProfile().get(0).getValue(), comp.getLeft().getName());
// StructureDefinition sdr = resolveProfile(ed, outcome, path, r.getProfile().get(0).getValue(), outcome.rightName()); StructureDefinition sdr = resolveProfile(comp, res, path, r.getProfile().get(0).getValue(), comp.getRight().getName());
// if (sdl != null && sdr != null) { if (sdl != null && sdr != null) {
// if (sdl == sdr) { if (sdl == sdr) {
// pfound = true; pfound = true;
// } else if (derivesFrom(sdl, sdr)) { } else if (derivesFrom(sdl, sdr)) {
// pfound = true; pfound = true;
// } else if (derivesFrom(sdr, sdl)) { } else if (derivesFrom(sdr, sdl)) {
// c.setProfile(r.getProfile()); c.setProfile(r.getProfile());
// pfound = true; pfound = true;
// } else if (sdl.getType().equals(sdr.getType())) { } else if (sdl.getType().equals(sdr.getType())) {
// ProfileComparison comp = compareProfiles(sdl, sdr); ProfileComparison compP = (ProfileComparison) session.compare(sdl, sdr);
// if (comp.getSubset() != null) { if (compP != null && compP.getIntersection() != null) {
// pfound = true; pfound = true;
// c.addProfile("#"+comp.id); c.addProfile("#"+compP.getId());
// } }
// } }
// } }
// } }
// if (!l.hasTargetProfile() && !r.hasTargetProfile()) { if (!l.hasTargetProfile() && !r.hasTargetProfile()) {
// tfound = true; tfound = true;
// } else if (!r.hasTargetProfile()) { } else if (!r.hasTargetProfile()) {
// tfound = true; tfound = true;
// } else if (!l.hasTargetProfile()) { } else if (!l.hasTargetProfile()) {
// tfound = true; tfound = true;
// c.setTargetProfile(r.getTargetProfile()); c.setTargetProfile(r.getTargetProfile());
// } else { } else {
// StructureDefinition sdl = resolveProfile(ed, outcome, path, l.getTargetProfile().get(0).getValue(), outcome.leftName()); StructureDefinition sdl = resolveProfile(comp, res, path, l.getTargetProfile().get(0).getValue(), comp.getLeft().getName());
// StructureDefinition sdr = resolveProfile(ed, outcome, path, r.getTargetProfile().get(0).getValue(), outcome.rightName()); StructureDefinition sdr = resolveProfile(comp, res, path, r.getTargetProfile().get(0).getValue(), comp.getRight().getName());
// if (sdl != null && sdr != null) { if (sdl != null && sdr != null) {
// if (sdl == sdr) { if (sdl == sdr) {
// tfound = true; tfound = true;
// } else if (derivesFrom(sdl, sdr)) { } else if (derivesFrom(sdl, sdr)) {
// tfound = true; tfound = true;
// } else if (derivesFrom(sdr, sdl)) { } else if (derivesFrom(sdr, sdl)) {
// c.setTargetProfile(r.getTargetProfile()); c.setTargetProfile(r.getTargetProfile());
// tfound = true; tfound = true;
// } else if (sdl.getType().equals(sdr.getType())) { } else if (sdl.getType().equals(sdr.getType())) {
// ProfileComparison comp = compareProfiles(sdl, sdr); ProfileComparison compP = (ProfileComparison) session.compare(sdl, sdr);
// if (comp.getSubset() != null) { if (compP != null && compP.getIntersection() != null) {
// tfound = true; tfound = true;
// c.addTargetProfile("#"+comp.id); c.addTargetProfile("#"+compP.getId());
// } }
// } }
// } }
// } }
// } }
// if (pfound && tfound) if (pfound && tfound)
// result.add(c); result.add(c);
// } }
return result; return result;
} }
@ -636,135 +618,101 @@ public class ProfileComparer extends CanonicalResourceComparer {
} }
private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError { private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinition> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException {
// TODO: fix assert(lDef.hasBinding() || rDef.hasBinding());
// assert(lDef.hasBinding() || rDef.hasBinding()); if (!lDef.hasBinding()) {
// if (!lDef.hasBinding()) { subset.setBinding(rDef.getBinding());
// 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
// // 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.setBinding(rDef.getBinding().copy()); superset.getBinding().setStrength(BindingStrength.EXAMPLE);
// superset.getBinding().setStrength(BindingStrength.EXAMPLE); return true;
// return true; }
// } if (!rDef.hasBinding()) {
// if (!rDef.hasBinding()) { subset.setBinding(lDef.getBinding());
// subset.setBinding(lDef.getBinding()); superset.setBinding(lDef.getBinding().copy());
// superset.setBinding(lDef.getBinding().copy()); superset.getBinding().setStrength(BindingStrength.EXAMPLE);
// superset.getBinding().setStrength(BindingStrength.EXAMPLE); return true;
// return true; }
// } ElementDefinitionBindingComponent left = lDef.getBinding();
// ElementDefinitionBindingComponent left = lDef.getBinding(); ElementDefinitionBindingComponent right = rDef.getBinding();
// ElementDefinitionBindingComponent right = rDef.getBinding(); if (Base.compareDeep(left, right, false)) {
// if (Base.compareDeep(left, right, false)) { subset.setBinding(left);
// subset.setBinding(left); superset.setBinding(right);
// superset.setBinding(right); }
// }
// // if they're both examples/preferred then:
// // if they're both examples/preferred then: // subset: left wins if they're both the same
// // subset: left wins if they're both the same // superset:
// // superset: if (isPreferredOrExample(left) && isPreferredOrExample(right)) {
// if (isPreferredOrExample(left) && isPreferredOrExample(right)) { if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
// 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());
// 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)); subset.setBinding(right);
// status(subset, ProfileUtilities.STATUS_HINT); superset.setBinding(unionBindings(comp, res, path, left, right));
// subset.setBinding(right); } else {
// superset.setBinding(unionBindings(superset, outcome, path, left, right)); if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false) ) {
// } else { vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getLeft().getName(), path, comp.getMessages(), res.getMessages());
// 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)); subset.setBinding(left);
// status(subset, ProfileUtilities.STATUS_HINT); superset.setBinding(unionBindings(comp, res, path, left, right));
// } }
// subset.setBinding(left); return true;
// superset.setBinding(unionBindings(superset, outcome, path, left, right)); }
// } // if either of them are extensible/required, then it wins
// return true; if (isPreferredOrExample(left)) {
// } subset.setBinding(right);
// // if either of them are extensible/required, then it wins superset.setBinding(unionBindings(comp, res, path, left, right));
// if (isPreferredOrExample(left)) { return true;
// subset.setBinding(right); }
// superset.setBinding(unionBindings(superset, outcome, path, left, right)); if (isPreferredOrExample(right)) {
// return true; subset.setBinding(left);
// } superset.setBinding(unionBindings(comp, res, path, left, right));
// if (isPreferredOrExample(right)) { return true;
// 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);
// // ok, both are extensible or required. ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent();
// ElementDefinitionBindingComponent subBinding = new ElementDefinitionBindingComponent(); superset.setBinding(superBinding);
// subset.setBinding(subBinding); subBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription()));
// ElementDefinitionBindingComponent superBinding = new ElementDefinitionBindingComponent(); superBinding.setDescription(mergeText(comp, res, path, "description", left.getDescription(), right.getDescription()));
// superset.setBinding(superBinding); if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED)
// subBinding.setDescription(mergeText(subset, outcome, path, "description", left.getDescription(), right.getDescription())); subBinding.setStrength(BindingStrength.REQUIRED);
// superBinding.setDescription(mergeText(subset, outcome, null, "description", left.getDescription(), right.getDescription())); else
// if (left.getStrength() == BindingStrength.REQUIRED || right.getStrength() == BindingStrength.REQUIRED) subBinding.setStrength(BindingStrength.EXTENSIBLE);
// subBinding.setStrength(BindingStrength.REQUIRED); if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE)
// else superBinding.setStrength(BindingStrength.EXTENSIBLE);
// subBinding.setStrength(BindingStrength.EXTENSIBLE); else
// if (left.getStrength() == BindingStrength.EXTENSIBLE || right.getStrength() == BindingStrength.EXTENSIBLE) superBinding.setStrength(BindingStrength.REQUIRED);
// superBinding.setStrength(BindingStrength.EXTENSIBLE);
// else if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
// superBinding.setStrength(BindingStrength.REQUIRED); subBinding.setValueSet(left.getValueSet());
// superBinding.setValueSet(left.getValueSet());
// if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { return true;
// subBinding.setValueSet(left.getValueSet()); } else if (!left.hasValueSet()) {
// superBinding.setValueSet(left.getValueSet()); vm(IssueSeverity.ERROR, "No left Value set at "+path, path, comp.getMessages(), res.getMessages());
// return true; return true;
// } else if (!left.hasValueSet()) { } else if (!right.hasValueSet()) {
// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "No left Value set at "+path, ValidationMessage.IssueSeverity.ERROR)); vm(IssueSeverity.ERROR, "No right Value set at "+path, path, comp.getMessages(), res.getMessages());
// return true; return true;
// } else if (!right.hasValueSet()) { } else {
// outcome.messages.add(new ValidationMessage(Source.ProfileComparer, ValidationMessage.IssueType.STRUCTURE, path, "No right Value set at "+path, ValidationMessage.IssueSeverity.ERROR)); // ok, now we compare the value sets. This may be unresolvable.
// return true; ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet());
// } else { ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet());
// // ok, now we compare the value sets. This may be unresolvable. if (lvs == null) {
// ValueSet lvs = resolveVS(outcome.left, left.getValueSet()); vm(IssueSeverity.ERROR, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages());
// ValueSet rvs = resolveVS(outcome.right, right.getValueSet()); return true;
// if (lvs == null) { } else if (rvs == 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)); vm(IssueSeverity.ERROR, "Unable to resolve right value set "+right.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages());
// return true; return true;
// } else if (rvs == null) { } else {
// 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)); ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs);
// return true; if (compP != null) {
// } else { subBinding.setValueSet(compP.getIntersection().getUrl());
// // first, we'll try to do it by definition superBinding.setValueSet(compP.getUnion().getUrl());
// 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)));
// }
// }
// }
return false; return false;
} }
@ -783,32 +731,77 @@ public class ProfileComparer extends CanonicalResourceComparer {
// we can't really know about constraints. We create warnings, and collate them // we can't really know about constraints. We create warnings, and collate them
private List<ElementDefinitionConstraintComponent> unionConstraints(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<ElementDefinitionConstraintComponent> left, List<ElementDefinitionConstraintComponent> right) { private List<ElementDefinitionConstraintComponent> unionConstraints(ProfileComparison comp, StructuralMatch<ElementDefinition> res, String path, List<ElementDefinitionConstraintComponent> left, List<ElementDefinitionConstraintComponent> right) {
// TODO: fix
List<ElementDefinitionConstraintComponent> result = new ArrayList<ElementDefinitionConstraintComponent>(); List<ElementDefinitionConstraintComponent> result = new ArrayList<ElementDefinitionConstraintComponent>();
// for (ElementDefinitionConstraintComponent l : left) { for (ElementDefinitionConstraintComponent l : left) {
// boolean found = false; boolean found = false;
// for (ElementDefinitionConstraintComponent r : right) for (ElementDefinitionConstraintComponent r : right)
// if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity()))
// found = true; found = true;
// if (!found) { 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)); 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());
// status(ed, ProfileUtilities.STATUS_WARNING); }
// } result.add(l);
// result.add(l); }
// } for (ElementDefinitionConstraintComponent r : right) {
// for (ElementDefinitionConstraintComponent r : right) { boolean found = false;
// boolean found = false; for (ElementDefinitionConstraintComponent l : left)
// for (ElementDefinitionConstraintComponent l : left) if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity()))
// if (Utilities.equals(r.getId(), l.getId()) || (Utilities.equals(r.getXpath(), l.getXpath()) && r.getSeverity() == l.getSeverity())) found = true;
// found = true; if (!found) {
// 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());
// 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);
// }
// }
return result; return result;
} }
private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinition> 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<ElementDefinition> 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);
}
} }

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.r5.comparison;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
@ -18,12 +19,28 @@ import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
public class ResourceComparer { public class ResourceComparer {
public class ResourceCmparison { public class ResourceComparison {
private String id;
protected List<ValidationMessage> messages = new ArrayList<>(); protected List<ValidationMessage> messages = new ArrayList<>();
public ResourceComparison() {
super();
}
public List<ValidationMessage> getMessages() { public List<ValidationMessage> getMessages() {
return messages; return messages;
} }
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
} }
public final static String COLOR_NO_ROW_LEFT = "#ffffb3"; 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_DIFFERENT = "#f0b3ff";
public final static String COLOR_ISSUE = "#ffad99"; public final static String COLOR_ISSUE = "#ffad99";
protected IWorkerContext context; protected ComparisonSession session;
public ResourceComparer(IWorkerContext context) { public ResourceComparer(ComparisonSession session) {
super(); super();
this.context = context; this.session = session;
} }
public Cell missingCell(HierarchicalTableGenerator gen) { public Cell missingCell(HierarchicalTableGenerator gen) {
@ -53,7 +70,7 @@ public class ResourceComparer {
return c; return c;
} }
public XhtmlNode renderErrors(ResourceCmparison csc) { public XhtmlNode renderErrors(ResourceComparison csc) {
XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
XhtmlNode tbl = div.table("grid"); XhtmlNode tbl = div.table("grid");
for (ValidationMessage vm : csc.messages) { for (ValidationMessage vm : csc.messages) {
@ -66,8 +83,17 @@ public class ResourceComparer {
} }
protected ValidationMessage vm(IssueSeverity level, String message, String path) { protected ValidationMessage vmI(IssueSeverity level, String message, String path) {
return new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, message, level == IssueSeverity.NULL ? IssueSeverity.INFORMATION : level); 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<ValidationMessage> genMessages, List<ValidationMessage> 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) { private String colorForLevel(IssueSeverity level) {

View File

@ -72,9 +72,8 @@ public class ValueSetComparer extends CanonicalResourceComparer {
} }
} }
public ValueSetComparer(IWorkerContext context) { public ValueSetComparer(ComparisonSession session) {
super(context); super(session);
this.context = context;
} }
public ValueSetComparison compare(ValueSet left, ValueSet right) { public ValueSetComparison compare(ValueSet left, ValueSet right) {
@ -84,10 +83,10 @@ public class ValueSetComparer extends CanonicalResourceComparer {
throw new DefinitionException("No ValueSet provided (right)"); throw new DefinitionException("No ValueSet provided (right)");
ValueSetComparison res = new ValueSetComparison(left, right); ValueSetComparison res = new ValueSetComparison(left, right);
session.identify(res);
ValueSet vs = new ValueSet(); ValueSet vs = new ValueSet();
res.setUnion(vs); res.setUnion(vs);
vs.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(vs);
vs.setUrl("urn:uuid:"+vs.getId());
vs.setName("Union"+left.getName()+"And"+right.getName()); vs.setName("Union"+left.getName()+"And"+right.getName());
vs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle()); vs.setTitle("Union of "+left.getTitle()+" And "+right.getTitle());
vs.setStatus(left.getStatus()); vs.setStatus(left.getStatus());
@ -95,8 +94,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
ValueSet vs1 = new ValueSet(); ValueSet vs1 = new ValueSet();
res.setIntersection(vs1); res.setIntersection(vs1);
vs1.setId(UUID.randomUUID().toString().toLowerCase()); session.identify(vs1);
vs1.setUrl("urn:uuid:"+vs1.getId());
vs1.setName("Intersection"+left.getName()+"And"+right.getName()); vs1.setName("Intersection"+left.getName()+"And"+right.getName());
vs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle()); vs1.setTitle("Intersection of "+left.getTitle()+" And "+right.getTitle());
vs1.setStatus(left.getStatus()); vs1.setStatus(left.getStatus());
@ -123,7 +121,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
ConceptSetComponent r = findInList(right.getInclude(), l, left.getInclude()); ConceptSetComponent r = findInList(right.getInclude(), l, left.getInclude());
if (r == null) { if (r == null) {
union.getInclude().add(l); union.getInclude().add(l);
res.getIncludes().getChildren().add(new StructuralMatch<Element>(l, vm(IssueSeverity.INFORMATION, "Removed Include", "ValueSet.compose.include"))); res.getIncludes().getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed Include", "ValueSet.compose.include")));
} else { } else {
matchR.add(r); matchR.add(r);
ConceptSetComponent csM = new ConceptSetComponent(); ConceptSetComponent csM = new ConceptSetComponent();
@ -138,7 +136,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (ConceptSetComponent r : right.getInclude()) { for (ConceptSetComponent r : right.getInclude()) {
if (!matchR.contains(r)) { if (!matchR.contains(r)) {
union.getInclude().add(r); union.getInclude().add(r);
res.getIncludes().getChildren().add(new StructuralMatch<Element>(vm(IssueSeverity.INFORMATION, "Added Include", "ValueSet.compose.include"), r)); res.getIncludes().getChildren().add(new StructuralMatch<Element>(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()); ConceptSetComponent r = findInList(right.getExclude(), l, left.getExclude());
if (r == null) { if (r == null) {
union.getExclude().add(l); union.getExclude().add(l);
res.getExcludes().getChildren().add(new StructuralMatch<Element>(l, vm(IssueSeverity.INFORMATION, "Removed Exclude", "ValueSet.compose.exclude"))); res.getExcludes().getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed Exclude", "ValueSet.compose.exclude")));
} else { } else {
matchR.add(r); matchR.add(r);
ConceptSetComponent csM = new ConceptSetComponent(); ConceptSetComponent csM = new ConceptSetComponent();
@ -163,7 +161,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (ConceptSetComponent r : right.getExclude()) { for (ConceptSetComponent r : right.getExclude()) {
if (!matchR.contains(r)) { if (!matchR.contains(r)) {
union.getExclude().add(r); union.getExclude().add(r);
res.getExcludes().getChildren().add(new StructuralMatch<Element>(vm(IssueSeverity.INFORMATION, "Added Exclude", "ValueSet.compose.exclude"), r)); res.getExcludes().getChildren().add(new StructuralMatch<Element>(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()); CanonicalType r = findInList(right.getValueSet(), l, left.getValueSet());
if (r == null) { if (r == null) {
union.getValueSet().add(l); union.getValueSet().add(l);
combined.getChildren().add(new StructuralMatch<Element>(l, vm(IssueSeverity.INFORMATION, "Removed ValueSet", "ValueSet.compose.include.valueSet"))); combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed ValueSet", "ValueSet.compose.include.valueSet")));
} else { } else {
matchVSR.add(r); matchVSR.add(r);
if (l.getValue().equals(r.getValue())) { if (l.getValue().equals(r.getValue())) {
@ -220,7 +218,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
} else { } else {
union.getValueSet().add(l); union.getValueSet().add(l);
union.getValueSet().add(r); union.getValueSet().add(r);
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vm(IssueSeverity.INFORMATION, "Values are different", "ValueSet.compose.include.valueSet")); StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Values are different", "ValueSet.compose.include.valueSet"));
combined.getChildren().add(sm); combined.getChildren().add(sm);
} }
} }
@ -228,7 +226,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (CanonicalType r : right.getValueSet()) { for (CanonicalType r : right.getValueSet()) {
if (!matchVSR.contains(r)) { if (!matchVSR.contains(r)) {
union.getValueSet().add(r); union.getValueSet().add(r);
combined.getChildren().add(new StructuralMatch<Element>(vm(IssueSeverity.INFORMATION, "Add ValueSet", "ValueSet.compose.include.valueSet"), r)); combined.getChildren().add(new StructuralMatch<Element>(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()); ConceptReferenceComponent r = findInList(right.getConcept(), l, left.getConcept());
if (r == null) { if (r == null) {
union.getConcept().add(l); union.getConcept().add(l);
combined.getChildren().add(new StructuralMatch<Element>(l, vm(IssueSeverity.INFORMATION, "Removed this Concept", "ValueSet.compose.include.concept"))); combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed this Concept", "ValueSet.compose.include.concept")));
} else { } else {
matchCR.add(r); matchCR.add(r);
if (l.getCode().equals(r.getCode())) { if (l.getCode().equals(r.getCode())) {
@ -251,7 +249,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
} else { } else {
union.getConcept().add(l); union.getConcept().add(l);
union.getConcept().add(r); union.getConcept().add(r);
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vm(IssueSeverity.INFORMATION, "Concepts are different", "ValueSet.compose.include.concept")); StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Concepts are different", "ValueSet.compose.include.concept"));
combined.getChildren().add(sm); combined.getChildren().add(sm);
compareConcepts(l, r, sm, null, null); compareConcepts(l, r, sm, null, null);
} }
@ -260,7 +258,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (ConceptReferenceComponent r : right.getConcept()) { for (ConceptReferenceComponent r : right.getConcept()) {
if (!matchCR.contains(r)) { if (!matchCR.contains(r)) {
union.getConcept().add(r); union.getConcept().add(r);
combined.getChildren().add(new StructuralMatch<Element>(vm(IssueSeverity.INFORMATION, "Added this Concept", "ValueSet.compose.include.concept"), r)); combined.getChildren().add(new StructuralMatch<Element>(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()); ConceptSetFilterComponent r = findInList(right.getFilter(), l, left.getFilter());
if (r == null) { if (r == null) {
union.getFilter().add(l); union.getFilter().add(l);
combined.getChildren().add(new StructuralMatch<Element>(l, vm(IssueSeverity.INFORMATION, "Removed this item", "ValueSet.compose.include.filter"))); combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed this item", "ValueSet.compose.include.filter")));
} else { } else {
matchFR.add(r); matchFR.add(r);
if (l.getProperty().equals(r.getProperty()) && l.getOp().equals(r.getOp())) { if (l.getProperty().equals(r.getProperty()) && l.getOp().equals(r.getOp())) {
@ -283,7 +281,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
} else { } else {
union.getFilter().add(l); union.getFilter().add(l);
union.getFilter().add(r); union.getFilter().add(r);
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vm(IssueSeverity.INFORMATION, "Codes are different", "ValueSet.compose.include.filter")); StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Codes are different", "ValueSet.compose.include.filter"));
combined.getChildren().add(sm); combined.getChildren().add(sm);
compareFilters(l, r, sm, null, null); compareFilters(l, r, sm, null, null);
} }
@ -292,44 +290,44 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (ConceptSetFilterComponent r : right.getFilter()) { for (ConceptSetFilterComponent r : right.getFilter()) {
if (!matchFR.contains(r)) { if (!matchFR.contains(r)) {
union.getFilter().add(r); union.getFilter().add(r);
combined.getChildren().add(new StructuralMatch<Element>(vm(IssueSeverity.INFORMATION, "Added this item", "ValueSet.compose.include.filter"), r)); combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.INFORMATION, "Added this item", "ValueSet.compose.include.filter"), r));
} }
} }
} }
private void compareConcepts(ConceptReferenceComponent l, ConceptReferenceComponent r, StructuralMatch<Element> sm, ConceptReferenceComponent cu, ConceptReferenceComponent ci) { private void compareConcepts(ConceptReferenceComponent l, ConceptReferenceComponent r, StructuralMatch<Element> sm, ConceptReferenceComponent cu, ConceptReferenceComponent ci) {
sm.getChildren().add(new StructuralMatch<Element>(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<Element>(l.getCodeElement(), r.getCodeElement(), l.getCode().equals(r.getCode()) ? null : vmI(IssueSeverity.INFORMATION, "Codes do not match", "ValueSet.compose.include.concept")));
if (ci != null) { if (ci != null) {
ci.setCode(l.getCode()); ci.setCode(l.getCode());
cu.setCode(l.getCode()); cu.setCode(l.getCode());
} }
if (l.hasDisplay() && r.hasDisplay()) { if (l.hasDisplay() && r.hasDisplay()) {
sm.getChildren().add(new StructuralMatch<Element>(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<Element>(l.getDisplayElement(), r.getDisplayElement(), l.getDisplay().equals(r.getDisplay()) ? null : vmI(IssueSeverity.INFORMATION, "Displays do not match", "ValueSet.compose.include.concept")));
if (ci != null) { if (ci != null) {
ci.setDisplay(r.getDisplay()); ci.setDisplay(r.getDisplay());
cu.setDisplay(r.getDisplay()); cu.setDisplay(r.getDisplay());
} }
} else if (l.hasDisplay()) { } else if (l.hasDisplay()) {
sm.getChildren().add(new StructuralMatch<Element>(l.getDisplayElement(), null, vm(IssueSeverity.INFORMATION, "Display Removed", "ValueSet.compose.include.concept"))); sm.getChildren().add(new StructuralMatch<Element>(l.getDisplayElement(), null, vmI(IssueSeverity.INFORMATION, "Display Removed", "ValueSet.compose.include.concept")));
if (ci != null) { if (ci != null) {
ci.setDisplay(l.getDisplay()); ci.setDisplay(l.getDisplay());
cu.setDisplay(l.getDisplay()); cu.setDisplay(l.getDisplay());
} }
} else if (r.hasDisplay()) { } else if (r.hasDisplay()) {
sm.getChildren().add(new StructuralMatch<Element>(null, r.getDisplayElement(), vm(IssueSeverity.INFORMATION, "Display added", "ValueSet.compose.include.concept"))); sm.getChildren().add(new StructuralMatch<Element>(null, r.getDisplayElement(), vmI(IssueSeverity.INFORMATION, "Display added", "ValueSet.compose.include.concept")));
if (ci != null) { if (ci != null) {
ci.setDisplay(r.getDisplay()); ci.setDisplay(r.getDisplay());
cu.setDisplay(r.getDisplay()); cu.setDisplay(r.getDisplay());
} }
} else { } else {
sm.getChildren().add(new StructuralMatch<Element>(null, null, vm(IssueSeverity.INFORMATION, "No Display", "ValueSet.compose.include.concept"))); sm.getChildren().add(new StructuralMatch<Element>(null, null, vmI(IssueSeverity.INFORMATION, "No Display", "ValueSet.compose.include.concept")));
} }
} }
private void compareFilters(ConceptSetFilterComponent l, ConceptSetFilterComponent r, StructuralMatch<Element> sm, ConceptSetFilterComponent cu, ConceptSetFilterComponent ci) { private void compareFilters(ConceptSetFilterComponent l, ConceptSetFilterComponent r, StructuralMatch<Element> sm, ConceptSetFilterComponent cu, ConceptSetFilterComponent ci) {
sm.getChildren().add(new StructuralMatch<Element>(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<Element>(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<Element>(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<Element>(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<Element>(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<Element>(l.getValueElement(), r.getValueElement(), l.getValue().equals(r.getValue()) ? null : vmI(IssueSeverity.INFORMATION, "Values do not match", "ValueSet.compose.include.concept")));
if (ci != null) { if (ci != null) {
ci.setProperty(l.getProperty()); ci.setProperty(l.getProperty());
ci.setOp(l.getOp()); ci.setOp(l.getOp());
@ -386,7 +384,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
} }
private ValueSet expand(ValueSet vs, ValueSetComparison res, String name) { 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) { if (vse.getValueset() != null) {
return vse.getValueset(); return vse.getValueset();
} else { } else {
@ -401,7 +399,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
ValueSetExpansionContainsComponent r = findInList(right, l); ValueSetExpansionContainsComponent r = findInList(right, l);
if (r == null) { if (r == null) {
union.add(l); union.add(l);
combined.getChildren().add(new StructuralMatch<ValueSetExpansionContainsComponent>(l, vm(IssueSeverity.INFORMATION, "Removed from expansion", path))); combined.getChildren().add(new StructuralMatch<ValueSetExpansionContainsComponent>(l, vmI(IssueSeverity.INFORMATION, "Removed from expansion", path)));
} else { } else {
matchR.add(r); matchR.add(r);
ValueSetExpansionContainsComponent ccU = merge(l, r); ValueSetExpansionContainsComponent ccU = merge(l, r);
@ -417,7 +415,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
for (ValueSetExpansionContainsComponent r : right) { for (ValueSetExpansionContainsComponent r : right) {
if (!matchR.contains(r)) { if (!matchR.contains(r)) {
union.add(r); union.add(r);
combined.getChildren().add(new StructuralMatch<ValueSetExpansionContainsComponent>(vm(IssueSeverity.INFORMATION, "Added to expansion", path), r)); combined.getChildren().add(new StructuralMatch<ValueSetExpansionContainsComponent>(vmI(IssueSeverity.INFORMATION, "Added to expansion", path), r));
} }
} }
} }
@ -429,15 +427,15 @@ public class ValueSetComparer extends CanonicalResourceComparer {
private void compareStrings(String path, List<ValidationMessage> msgs, String left, String right, String name, IssueSeverity level, ValueSetComparison res) { private void compareStrings(String path, List<ValidationMessage> msgs, String left, String right, String name, IssueSeverity level, ValueSetComparison res) {
if (!Utilities.noString(right)) { if (!Utilities.noString(right)) {
if (Utilities.noString(left)) { 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)) { } else if (!left.equals(right)) {
if (level != IssueSeverity.NULL) { if (level != IssueSeverity.NULL) {
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path+".name", "Changed value for "+name+": '"+left+"' vs '"+right+"'", level)); 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)) { } else if (!Utilities.noString(left)) {
msgs.add(vm(level, "Value for "+name+" removed", path)); msgs.add(vmI(level, "Value for "+name+" removed", path));
} }
} }

View File

@ -54,7 +54,7 @@ public class PackageClientTests {
@Test @Test
public void testExists2() throws IOException { 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", "4.0.1"));
Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2")); Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1")); Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
@ -62,7 +62,7 @@ public class PackageClientTests {
@Test @Test
public void testSearch2() throws IOException { public void testSearch2() throws IOException {
PackageClient client = new PackageClient("http://test.fhir.org/packages"); PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.search("core", null, null, false); List<PackageInfo> matches = client.search("core", null, null, false);
for (PackageInfo pi : matches) { for (PackageInfo pi : matches) {
System.out.println(pi.toString()); System.out.println(pi.toString());
@ -72,14 +72,14 @@ public class PackageClientTests {
@Test @Test
public void testSearchNoMatches2() throws IOException { public void testSearchNoMatches2() throws IOException {
PackageClient client = new PackageClient("http://test.fhir.org/packages"); PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.search("corezxxx", null, null, false); List<PackageInfo> matches = client.search("corezxxx", null, null, false);
Assertions.assertTrue(matches.size() == 0); Assertions.assertTrue(matches.size() == 0);
} }
@Test @Test
public void testVersions2() throws IOException { public void testVersions2() throws IOException {
PackageClient client = new PackageClient("http://test.fhir.org/packages"); PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3"); List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3");
for (PackageInfo pi : matches) { for (PackageInfo pi : matches) {
System.out.println(pi.toString()); System.out.println(pi.toString());
@ -89,7 +89,7 @@ public class PackageClientTests {
@Test @Test
public void testVersions2A() throws IOException { public void testVersions2A() throws IOException {
PackageClient client = new PackageClient("http://test.fhir.org/packages"); PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("hl7.fhir.us.core"); List<PackageInfo> matches = client.getVersions("hl7.fhir.us.core");
for (PackageInfo pi : matches) { for (PackageInfo pi : matches) {
System.out.println(pi.toString()); System.out.println(pi.toString());
@ -99,7 +99,7 @@ public class PackageClientTests {
@Test @Test
public void testVersionsNone2() throws IOException { public void testVersionsNone2() throws IOException {
PackageClient client = new PackageClient("http://test.fhir.org/packages"); PackageClient client = new PackageClient("http://packages2.fhir.org/packages");
List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X"); List<PackageInfo> matches = client.getVersions("Simplifier.Core.STU3X");
Assertions.assertTrue(matches.size() == 0); Assertions.assertTrue(matches.size() == 0);
} }

View File

@ -177,7 +177,7 @@ public class PackageCacheManager {
} }
private static final String PRIMARY_SERVER = "http://packages.fhir.org"; 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"; // 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_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\\-\\_]+)*$"; public static final String PACKAGE_VERSION_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+\\#[a-z0-9\\-\\_]+(\\.[a-z0-9\\-\\_]+)*$";

View File

@ -17,6 +17,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r5.comparison.CodeSystemComparer; import org.hl7.fhir.r5.comparison.CodeSystemComparer;
import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; 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;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
@ -137,8 +138,10 @@ public class ComparisonTests {
CanonicalResource left = load("left"); CanonicalResource left = load("left");
CanonicalResource right = load("right"); CanonicalResource right = load("right");
ComparisonSession session = new ComparisonSession(context);
if (left instanceof CodeSystem && right instanceof CodeSystem) { 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); CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right);
Assertions.assertTrue(csc.getUnion().getConcept().size() > csc.getIntersection().getConcept().size()); 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()); 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")); 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); checkOutcomes(csc.getMessages(), content);
} else if (left instanceof ValueSet && right instanceof ValueSet) { } 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); 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+"-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()); new org.hl7.fhir.r5.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "comparison", name+"-intersection.json")), csc.getIntersection());