Work on comparison and rendering for showing differences properly
This commit is contained in:
parent
ebc755bc2a
commit
ced8a36f37
|
@ -232,6 +232,10 @@ public abstract class CanonicalResourceComparer extends ResourceComparer {
|
|||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public boolean noUpdates() {
|
||||
return !(changedMetadata.noteable() || changedDefinitions.noteable() || !changedContent.noteable() || !changedContentInterpretation.noteable());
|
||||
}
|
||||
}
|
||||
|
||||
public CanonicalResourceComparer(ComparisonSession session) {
|
||||
|
|
|
@ -33,8 +33,8 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
|
|||
|
||||
public class CodeSystemComparison extends CanonicalResourceComparison<CodeSystem> {
|
||||
|
||||
private StructuralMatch<PropertyComponent> properties;
|
||||
private StructuralMatch<CodeSystemFilterComponent> filters;
|
||||
private StructuralMatch<PropertyComponent> properties = new StructuralMatch<PropertyComponent>();
|
||||
private StructuralMatch<CodeSystemFilterComponent> filters = new StructuralMatch<CodeSystemFilterComponent>();
|
||||
private StructuralMatch<ConceptDefinitionComponent> combined;
|
||||
private Map<String, String> propMap = new HashMap<>(); // right to left; left retains it's name
|
||||
public CodeSystemComparison(CodeSystem left, CodeSystem right) {
|
||||
|
|
|
@ -115,6 +115,7 @@ public class ComparisonSession {
|
|||
return csc;
|
||||
}
|
||||
} else if (left != null) {
|
||||
VersionComparisonAnnotation.markDeleted(null, forVersion, left.fhirType(), left); // todo: waht?
|
||||
String key = key(left.getUrl(), left.getVersion(), left.getUrl(), left.getVersion());
|
||||
if (compares.containsKey(key)) {
|
||||
return compares.get(key);
|
||||
|
@ -123,6 +124,7 @@ public class ComparisonSession {
|
|||
compares.put(key, csc);
|
||||
return csc;
|
||||
} else {
|
||||
VersionComparisonAnnotation.markAdded(right, forVersion);
|
||||
String key = key(right.getUrl(), right.getVersion(), right.getUrl(), right.getVersion());
|
||||
if (compares.containsKey(key)) {
|
||||
return compares.get(key);
|
||||
|
|
|
@ -173,7 +173,7 @@ public class ProfileComparer extends CanonicalResourceComparer implements Profil
|
|||
res.combined = sm;
|
||||
ln = new DefinitionNavigator(session.getContextLeft(), left, true);
|
||||
rn = new DefinitionNavigator(session.getContextRight(), right, true);
|
||||
ch = compareDiff(ln.path(), null, ln, rn) || ch;
|
||||
ch = compareDiff(ln.path(), null, ln, rn, res) || ch;
|
||||
// we don't preserve the differences - we only want the annotations
|
||||
}
|
||||
res.updateDefinitionsState(ch);
|
||||
|
@ -389,7 +389,7 @@ public class ProfileComparer extends CanonicalResourceComparer implements Profil
|
|||
}
|
||||
|
||||
|
||||
private boolean compareDiff(String path, String sliceName, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, FHIRFormatError, IOException {
|
||||
private boolean compareDiff(String path, String sliceName, DefinitionNavigator left, DefinitionNavigator right, ProfileComparison res) throws DefinitionException, FHIRFormatError, IOException {
|
||||
assert(path != null);
|
||||
assert(left != null);
|
||||
assert(right != null);
|
||||
|
@ -414,7 +414,7 @@ public class ProfileComparer extends CanonicalResourceComparer implements Profil
|
|||
def = comparePrimitivesWithTracking("max", left.current().getMaxElement(), right.current().getMaxElement(), null, IssueSeverity.INFORMATION, null, right.current(), session.getForVersion()) || def;
|
||||
|
||||
// add the children
|
||||
def = compareDiffChildren(path, left, right) || def;
|
||||
def = compareDiffChildren(path, left, right, right.current(), res) || def;
|
||||
//
|
||||
// // now process the slices
|
||||
// if (left.current().hasSlicing() || right.current().hasSlicing()) {
|
||||
|
@ -478,31 +478,26 @@ public class ProfileComparer extends CanonicalResourceComparer implements Profil
|
|||
}
|
||||
|
||||
|
||||
private boolean compareDiffChildren(String path, DefinitionNavigator left, DefinitionNavigator right) throws DefinitionException, IOException, FHIRFormatError {
|
||||
private boolean compareDiffChildren(String path, DefinitionNavigator left, DefinitionNavigator right, Base parent, ProfileComparison res) throws DefinitionException, IOException, FHIRFormatError {
|
||||
boolean def = false;
|
||||
|
||||
List<DefinitionNavigator> lc = left.children();
|
||||
List<DefinitionNavigator> rc = right.children();
|
||||
// it's possible that one of these profiles walks into a data type and the other doesn't
|
||||
// if it does, we have to load the children for that data into the profile that doesn't
|
||||
// walk into it
|
||||
if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0), left.getStructure()))
|
||||
lc = left.childrenFromType(right.current().getType().get(0), right.getStructure());
|
||||
if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0), right.getStructure()))
|
||||
rc = right.childrenFromType(left.current().getType().get(0), left.getStructure());
|
||||
|
||||
|
||||
List<DefinitionNavigator> matchR = new ArrayList<>();
|
||||
for (DefinitionNavigator l : lc) {
|
||||
DefinitionNavigator r = findInList(rc, l);
|
||||
if (r == null) {
|
||||
// todo
|
||||
VersionComparisonAnnotation.markDeleted(parent, session.getForVersion(), "element", l.current());
|
||||
res.updateContentState(true);
|
||||
} else {
|
||||
def = compareDiff(l.path(), null, l, r) || def;
|
||||
def = compareDiff(l.path(), null, l, r, res) || def;
|
||||
}
|
||||
}
|
||||
for (DefinitionNavigator r : rc) {
|
||||
if (!matchR.contains(r)) {
|
||||
// todo
|
||||
VersionComparisonAnnotation.markAdded(r.current(), session.getForVersion());
|
||||
res.updateContentState(true);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
|
|
|
@ -142,7 +142,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
|
||||
def = compareCompose(left.getCompose(), right.getCompose(), res, res.getUnion().getCompose(), res.getIntersection().getCompose()) || def;
|
||||
res.updateDefinitionsState(def);
|
||||
compareExpansions(left, right, res);
|
||||
// compareExpansions(left, right, res);
|
||||
VersionComparisonAnnotation.annotate(right, session.getForVersion(), res);
|
||||
return res;
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
intersection.getInclude().add(csI);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
||||
res.getIncludes().getChildren().add(sm);
|
||||
def = compareDefinitions(l, r, sm, csM, csI, res) || def;
|
||||
def = compareDefinitions("ValueSet.compose.exclude["+right.getInclude().indexOf(r)+"]", l, r, sm, csM, csI, res) || def;
|
||||
}
|
||||
}
|
||||
for (ConceptSetComponent r : right.getInclude()) {
|
||||
|
@ -194,7 +194,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
intersection.getExclude().add(csI);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
||||
res.getExcludes().getChildren().add(sm);
|
||||
def = compareDefinitions(l, r, sm, csM, csI, res) || def;
|
||||
def = compareDefinitions("ValueSet.compose.exclude["+right.getExclude().indexOf(r)+"]", l, r, sm, csM, csI, res) || def;
|
||||
}
|
||||
}
|
||||
for (ConceptSetComponent r : right.getExclude()) {
|
||||
|
@ -241,7 +241,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
}
|
||||
|
||||
|
||||
private boolean compareDefinitions(ConceptSetComponent left, ConceptSetComponent right, StructuralMatch<Element> combined, ConceptSetComponent union, ConceptSetComponent intersection, ValueSetComparison res) {
|
||||
private boolean compareDefinitions(String path, ConceptSetComponent left, ConceptSetComponent right, StructuralMatch<Element> combined, ConceptSetComponent union, ConceptSetComponent intersection, ValueSetComparison res) {
|
||||
boolean def = false;
|
||||
// system must match, but the rest might not. we're going to do the full comparison whatever, so the outcome looks consistent to the user
|
||||
List<CanonicalType> matchVSR = new ArrayList<>();
|
||||
|
@ -250,7 +250,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (r == null) {
|
||||
union.getValueSet().add(l);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed ValueSet", "ValueSet.compose.include.valueSet")));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.ERROR, "Removed ValueSet", "ValueSet.compose.include.valueSet")));
|
||||
if (session.isAnnotate()) {
|
||||
VersionComparisonAnnotation.markDeleted(right, session.getForVersion(), "valueset", l);
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
union.getValueSet().add(l);
|
||||
union.getValueSet().add(r);
|
||||
res.updateContentState(true);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Values are different", "ValueSet.compose.include.valueSet"));
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.WARNING, "Values are different", "ValueSet.compose.include.valueSet"));
|
||||
combined.getChildren().add(sm);
|
||||
if (session.isAnnotate()) {
|
||||
VersionComparisonAnnotation.markChanged(r, session.getForVersion());
|
||||
|
@ -279,7 +279,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (!matchVSR.contains(r)) {
|
||||
union.getValueSet().add(r);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.INFORMATION, "Add ValueSet", "ValueSet.compose.include.valueSet"), r));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.ERROR, "Add ValueSet", "ValueSet.compose.include.valueSet"), r));
|
||||
VersionComparisonAnnotation.markAdded(r, session.getForVersion());
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,8 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (r == null) {
|
||||
union.getConcept().add(l);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed this Concept", "ValueSet.compose.include.concept")));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.ERROR, "Removed this Concept", "ValueSet.compose.include.concept")));
|
||||
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, "Code "+l.getCode()+" removed", IssueSeverity.ERROR));
|
||||
VersionComparisonAnnotation.markDeleted(right, session.getForVersion(), "concept", l);
|
||||
} else {
|
||||
matchCR.add(r);
|
||||
|
@ -301,15 +302,15 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
intersection.getConcept().add(ci);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r);
|
||||
combined.getChildren().add(sm);
|
||||
def = compareConcepts(l, r, sm, cu, ci) || def;
|
||||
def = compareConcepts(path+".concept["+right.getConcept().indexOf(r)+"]", l, r, sm, cu, ci, res) || def;
|
||||
} else {
|
||||
// not that it's possible to get here?
|
||||
union.getConcept().add(l);
|
||||
union.getConcept().add(r);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Concepts are different", "ValueSet.compose.include.concept"));
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.WARNING, "Concepts are different", "ValueSet.compose.include.concept"));
|
||||
combined.getChildren().add(sm);
|
||||
res.updateContentState(true);
|
||||
compareConcepts(l, r, sm, null, null);
|
||||
compareConcepts(path+".concept["+right.getConcept().indexOf(r)+"]", l, r, sm, null, null, res);
|
||||
VersionComparisonAnnotation.markChanged(r, session.getForVersion());
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +319,8 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (!matchCR.contains(r)) {
|
||||
union.getConcept().add(r);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.INFORMATION, "Added this Concept", "ValueSet.compose.include.concept"), r));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.ERROR, "Added this Concept", "ValueSet.compose.include.concept"), r));
|
||||
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, "Code "+r.getCode()+" added", IssueSeverity.ERROR));
|
||||
VersionComparisonAnnotation.markAdded(r, session.getForVersion());
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +331,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (r == null) {
|
||||
union.getFilter().add(l);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.INFORMATION, "Removed this item", "ValueSet.compose.include.filter")));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(l, vmI(IssueSeverity.ERROR, "Removed this item", "ValueSet.compose.include.filter")));
|
||||
VersionComparisonAnnotation.markDeleted(right, session.getForVersion(), "filter", l);
|
||||
} else {
|
||||
matchFR.add(r);
|
||||
|
@ -347,7 +349,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
} else {
|
||||
union.getFilter().add(l);
|
||||
union.getFilter().add(r);
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.INFORMATION, "Codes are different", "ValueSet.compose.include.filter"));
|
||||
StructuralMatch<Element> sm = new StructuralMatch<Element>(l, r, vmI(IssueSeverity.WARNING, "Codes are different", "ValueSet.compose.include.filter"));
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(sm);
|
||||
compareFilters(l, r, sm, null, null);
|
||||
|
@ -358,14 +360,14 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (!matchFR.contains(r)) {
|
||||
union.getFilter().add(r);
|
||||
res.updateContentState(true);
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.INFORMATION, "Added this item", "ValueSet.compose.include.filter"), r));
|
||||
combined.getChildren().add(new StructuralMatch<Element>(vmI(IssueSeverity.ERROR, "Added this item", "ValueSet.compose.include.filter"), r));
|
||||
VersionComparisonAnnotation.markAdded(r, session.getForVersion());
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
private boolean compareConcepts(ConceptReferenceComponent l, ConceptReferenceComponent r, StructuralMatch<Element> sm, ConceptReferenceComponent cu, ConceptReferenceComponent ci) {
|
||||
private boolean compareConcepts(String path, ConceptReferenceComponent l, ConceptReferenceComponent r, StructuralMatch<Element> sm, ConceptReferenceComponent cu, ConceptReferenceComponent ci, ValueSetComparison res) {
|
||||
boolean def = false;
|
||||
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) {
|
||||
|
@ -379,7 +381,13 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
cu.setDisplay(r.getDisplay());
|
||||
}
|
||||
def = !l.getDisplay().equals(r.getDisplay());
|
||||
if (def) {
|
||||
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, "Code "+l.getCode()+" display changed from '"+l.getDisplay()+"' to '"+r.getDisplay()+"'", IssueSeverity.WARNING));
|
||||
VersionComparisonAnnotation.markChanged(r.getDisplayElement(), session.getForVersion());
|
||||
}
|
||||
} else if (l.hasDisplay()) {
|
||||
VersionComparisonAnnotation.markDeleted(r, session.getForVersion(), "display", l.getDisplayElement());
|
||||
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, "Code "+l.getCode()+" display '"+l.getDisplay()+"' removed", IssueSeverity.WARNING));
|
||||
sm.getChildren().add(new StructuralMatch<Element>(l.getDisplayElement(), null, vmI(IssueSeverity.INFORMATION, "Display Removed", "ValueSet.compose.include.concept")));
|
||||
if (ci != null) {
|
||||
ci.setDisplay(l.getDisplay());
|
||||
|
@ -387,6 +395,8 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
}
|
||||
def = true;
|
||||
} else if (r.hasDisplay()) {
|
||||
VersionComparisonAnnotation.markAdded(r.getDisplayElement(), session.getForVersion());
|
||||
res.getMessages().add(new ValidationMessage(Source.ProfileComparer, IssueType.INFORMATIONAL, path, "Code "+l.getCode()+" display '"+r.getDisplay()+"' added", IssueSeverity.WARNING));
|
||||
sm.getChildren().add(new StructuralMatch<Element>(null, r.getDisplayElement(), vmI(IssueSeverity.INFORMATION, "Display added", "ValueSet.compose.include.concept")));
|
||||
if (ci != null) {
|
||||
ci.setDisplay(r.getDisplay());
|
||||
|
|
|
@ -9,13 +9,17 @@ import org.hl7.fhir.r5.comparison.CanonicalResourceComparer.CanonicalResourceCom
|
|||
import org.hl7.fhir.r5.comparison.CanonicalResourceComparer.ChangeAnalysisState;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class VersionComparisonAnnotation {
|
||||
|
||||
public enum AnotationType {
|
||||
NoChange, Added, Changed, Deleted;
|
||||
NoChange, Added, Changed, ChildrenDeleted, Deleted;
|
||||
}
|
||||
|
||||
public static final String USER_DATA_NAME = "version-annotation";
|
||||
|
@ -37,7 +41,7 @@ public class VersionComparisonAnnotation {
|
|||
|
||||
public static void annotate(Base base, String version, CanonicalResourceComparison<? extends CanonicalResource> comp) {
|
||||
if (version != null) {
|
||||
VersionComparisonAnnotation vca = new VersionComparisonAnnotation(comp.noChange() ? AnotationType.NoChange : AnotationType.Added, version);
|
||||
VersionComparisonAnnotation vca = new VersionComparisonAnnotation(comp.noUpdates() ? AnotationType.NoChange : AnotationType.Changed, version);
|
||||
vca.comp = comp;
|
||||
base.setUserData(USER_DATA_NAME, vca);
|
||||
}
|
||||
|
@ -57,13 +61,13 @@ public class VersionComparisonAnnotation {
|
|||
}
|
||||
|
||||
public static void markDeleted(Base parent, String version, String name, Base other) {
|
||||
if (version != null) {
|
||||
if (version != null && other != null) {
|
||||
VersionComparisonAnnotation vca = null;
|
||||
if (parent.hasUserData(USER_DATA_NAME)) {
|
||||
vca = (VersionComparisonAnnotation) parent.getUserData(USER_DATA_NAME);
|
||||
assert vca.type != AnotationType.Added;
|
||||
} else {
|
||||
vca = new VersionComparisonAnnotation(AnotationType.Changed, version);
|
||||
vca = new VersionComparisonAnnotation(AnotationType.ChildrenDeleted, version);
|
||||
parent.setUserData(USER_DATA_NAME, vca);
|
||||
}
|
||||
if (vca.deletedChildren == null) {
|
||||
|
@ -103,13 +107,13 @@ public class VersionComparisonAnnotation {
|
|||
return spanOuter;
|
||||
case Changed:
|
||||
spanOuter = x.span("border: solid 1px #dddddd; margin: 2px; padding: 2px", null);
|
||||
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been changed since "+version);
|
||||
spanInner.img("icon-change-edit.png", "icon");
|
||||
spanInner.tx(" Changed:");
|
||||
return spanOuter;
|
||||
case Deleted:
|
||||
spanOuter = x.span("border: solid 1px #dddddd; margin: 2px; padding: 2px", null);
|
||||
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been removed since "+version);
|
||||
spanInner.img("icon-change-remove.png", "icon");
|
||||
spanInner.tx(" Removed:");
|
||||
return spanOuter.strikethrough();
|
||||
|
@ -137,13 +141,13 @@ public class VersionComparisonAnnotation {
|
|||
return divOuter;
|
||||
case Changed:
|
||||
divOuter = x.div("border: solid 1px #dddddd; margin: 2px; padding: 2px");
|
||||
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been changed since "+version);
|
||||
spanInner.img("icon-change-edit.png", "icon");
|
||||
spanInner.tx(" Changed:");
|
||||
return divOuter;
|
||||
case Deleted:
|
||||
divOuter = x.div("border: solid 1px #dddddd; margin: 2px; padding: 2px");
|
||||
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been removed since "+version);
|
||||
spanInner.img("icon-change-remove.png", "icon");
|
||||
spanInner.tx(" Removed:");
|
||||
return divOuter.strikethrough();
|
||||
|
@ -151,6 +155,51 @@ public class VersionComparisonAnnotation {
|
|||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static XhtmlNode renderRow(Base b, XhtmlNode tbl, XhtmlNode tr) {
|
||||
if (b.hasUserData(USER_DATA_NAME)) {
|
||||
VersionComparisonAnnotation self = (VersionComparisonAnnotation) b.getUserData(USER_DATA_NAME);
|
||||
return self.renderRow(tbl, tr);
|
||||
} else {
|
||||
return tr.td();
|
||||
}
|
||||
}
|
||||
|
||||
private XhtmlNode renderRow(XhtmlNode tbl, XhtmlNode tr) {
|
||||
switch (type) {
|
||||
case Added:
|
||||
if (tbl.isClass("grid")) {
|
||||
tr.style("border: solid 1px #dddddd; margin: 2px; padding: 2px");
|
||||
}
|
||||
XhtmlNode td = tr.td();
|
||||
XhtmlNode span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This row of content has been added since "+version);
|
||||
span.img("icon-change-add.png", "icon");
|
||||
span.tx(" Added:");
|
||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "holder");
|
||||
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This row of content has been added since "+version).tx(" ");
|
||||
tr.styleCells(x);
|
||||
return td;
|
||||
case Changed:
|
||||
td = tr.td();
|
||||
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This row of content has been changed since "+version);
|
||||
span.img("icon-change-edit.png", "icon");
|
||||
span.tx(" Changed:");
|
||||
return td;
|
||||
case Deleted:
|
||||
tr.style("text-decoration: line-through");
|
||||
td = tr.td();
|
||||
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been removed since "+version);
|
||||
span.img("icon-change-remove.png", "icon");
|
||||
span.tx(" Removed:");
|
||||
x = new XhtmlNode(NodeType.Element, "holder");
|
||||
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px; text-decoration: none", "This row of content has been added since "+version).tx(" ");
|
||||
tr.styleCells(x);
|
||||
return td;
|
||||
default:
|
||||
return tr.td();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasDeleted(Base base, String... names) {
|
||||
boolean result = false;
|
||||
|
@ -178,6 +227,18 @@ public class VersionComparisonAnnotation {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static Base getDeletedItem(Base base, String name) {
|
||||
List<Base> result = new ArrayList<>();
|
||||
if (base.hasUserData(USER_DATA_NAME)) {
|
||||
VersionComparisonAnnotation self = (VersionComparisonAnnotation) base.getUserData(USER_DATA_NAME);
|
||||
if (self.deletedChildren != null && self.deletedChildren.containsKey(name)) {
|
||||
result.addAll(self.deletedChildren.get(name));
|
||||
}
|
||||
}
|
||||
return result.isEmpty() ? null : result.get(0);
|
||||
}
|
||||
|
||||
|
||||
public static CanonicalResourceComparison<? extends CanonicalResource> artifactComparison(Base base) {
|
||||
if (base.hasUserData(USER_DATA_NAME)) {
|
||||
VersionComparisonAnnotation self = (VersionComparisonAnnotation) base.getUserData(USER_DATA_NAME);
|
||||
|
@ -186,5 +247,34 @@ public class VersionComparisonAnnotation {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void renderSummary(Base base, XhtmlNode x, String version) {
|
||||
if (base.hasUserData(USER_DATA_NAME)) {
|
||||
VersionComparisonAnnotation self = (VersionComparisonAnnotation) base.getUserData(USER_DATA_NAME);
|
||||
switch (self.type) {
|
||||
case Added:
|
||||
XhtmlNode spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner.img("icon-change-add.png", "icon");
|
||||
spanInner.tx(" Added");
|
||||
return;
|
||||
case Changed:
|
||||
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner.img("icon-change-edit.png", "icon");
|
||||
spanInner.tx(" Changed");
|
||||
return;
|
||||
case Deleted:
|
||||
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", "This content has been added since "+version);
|
||||
spanInner.img("icon-change-remove.png", "icon");
|
||||
spanInner.tx(" Removed");
|
||||
return;
|
||||
default:
|
||||
x.span("color: #eeeeee").tx("n/c");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
x.span("color: #eeeeee").tx("--");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -398,7 +398,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
tr.setAttribute("style", "background-color: #ffeeee");
|
||||
}
|
||||
|
||||
XhtmlNode td = tr.td();
|
||||
XhtmlNode td = VersionComparisonAnnotation.renderRow(c, t, tr);
|
||||
if (hasHierarchy) {
|
||||
td.addText(Integer.toString(level+1));
|
||||
td = tr.td();
|
||||
|
@ -407,9 +407,9 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
}
|
||||
String link = isSupplement ? getLinkForCode(cs.getSupplements(), null, c.getCode()) : null;
|
||||
if (link != null) {
|
||||
td.ah(link).attribute("style", "white-space:nowrap").addText(c.getCode());
|
||||
td.ah(link).style( "white-space:nowrap").addText(c.getCode());
|
||||
} else {
|
||||
VersionComparisonAnnotation.render(c, td.attribute("style", "white-space:nowrap")).addText(c.getCode());
|
||||
td.style("white-space:nowrap").addText(c.getCode());
|
||||
}
|
||||
XhtmlNode a;
|
||||
if (c.hasCodeElement()) {
|
||||
|
@ -579,7 +579,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
td = tr.td();
|
||||
String s = Utilities.padLeft("", '\u00A0', (level+1)*2);
|
||||
td.addText(s);
|
||||
td.attribute("style", "white-space:nowrap");
|
||||
td.style("white-space:nowrap");
|
||||
a = td.ah("#"+cs.getId()+"-" + Utilities.nmtokenize(cc.getCode()));
|
||||
a.addText(cc.getCode());
|
||||
if (hasDisplay) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,7 @@ import org.hl7.fhir.r5.model.Extension;
|
|||
import org.hl7.fhir.r5.model.ExtensionHelper;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent;
|
||||
|
@ -57,6 +58,7 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
|||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.ibm.icu.impl.locale.StringTokenIterator;
|
||||
|
||||
public class ValueSetRenderer extends TerminologyRenderer {
|
||||
|
||||
|
@ -1175,50 +1177,10 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
hasExtensions = true;
|
||||
addMapHeaders(addTableHeaderRowStandard(t, false, true, hasDefinition, hasComments, false, false, null, langs, designations, doDesignations), maps);
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
XhtmlNode tr = t.tr();
|
||||
XhtmlNode td = tr.td();
|
||||
ConceptDefinitionComponent cc = definitions == null ? null : definitions.get(c.getCode());
|
||||
addCodeToTable(false, inc.getSystem(), c.getCode(), c.hasDisplay()? c.getDisplay() : cc != null ? cc.getDisplay() : "", td);
|
||||
|
||||
td = tr.td();
|
||||
if (!Utilities.noString(c.getDisplay()))
|
||||
td.addText(c.getDisplay());
|
||||
else if (cc != null && !Utilities.noString(cc.getDisplay()))
|
||||
td.addText(cc.getDisplay());
|
||||
|
||||
if (hasDefinition) {
|
||||
td = tr.td();
|
||||
if (ExtensionHelper.hasExtension(c, ToolingExtensions.EXT_DEFINITION)) {
|
||||
smartAddText(td, ToolingExtensions.readStringExtension(c, ToolingExtensions.EXT_DEFINITION));
|
||||
} else if (cc != null && !Utilities.noString(cc.getDefinition())) {
|
||||
smartAddText(td, cc.getDefinition());
|
||||
}
|
||||
}
|
||||
if (hasComments) {
|
||||
td = tr.td();
|
||||
if (ExtensionHelper.hasExtension(c, ToolingExtensions.EXT_VS_COMMENT)) {
|
||||
smartAddText(td, "Note: "+ToolingExtensions.readStringExtension(c, ToolingExtensions.EXT_VS_COMMENT));
|
||||
}
|
||||
}
|
||||
if (doDesignations) {
|
||||
addDesignationsToRow(c, designations, tr);
|
||||
addLangaugesToRow(c, langs, tr);
|
||||
}
|
||||
for (UsedConceptMap m : maps) {
|
||||
td = tr.td();
|
||||
List<TargetElementComponentWrapper> mappings = findMappingsForCode(c.getCode(), m.getMap());
|
||||
boolean first = true;
|
||||
for (TargetElementComponentWrapper mapping : mappings) {
|
||||
if (!first)
|
||||
td.br();
|
||||
first = false;
|
||||
XhtmlNode span = td.span(null, mapping.comp.getRelationship().toString());
|
||||
span.addText(getCharForRelationship(mapping.comp));
|
||||
addRefToCode(td, mapping.group.getTarget(), m.getLink(), mapping.comp.getCode());
|
||||
if (!Utilities.noString(mapping.comp.getComment()))
|
||||
td.i().tx("("+mapping.comp.getComment()+")");
|
||||
}
|
||||
}
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, c);
|
||||
}
|
||||
for (Base b : VersionComparisonAnnotation.getDeleted(inc, "concept" )) {
|
||||
renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, (ConceptReferenceComponent) b);
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 0) {
|
||||
|
@ -1306,6 +1268,58 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
return hasExtensions;
|
||||
}
|
||||
|
||||
private void renderConcept(ConceptSetComponent inc, List<String> langs, boolean doDesignations,
|
||||
List<UsedConceptMap> maps, Map<String, String> designations, Map<String, ConceptDefinitionComponent> definitions,
|
||||
XhtmlNode t, boolean hasComments, boolean hasDefinition, ConceptReferenceComponent c) {
|
||||
XhtmlNode tr = t.tr();
|
||||
XhtmlNode td = VersionComparisonAnnotation.renderRow(c, t, tr);
|
||||
ConceptDefinitionComponent cc = definitions == null ? null : definitions.get(c.getCode());
|
||||
addCodeToTable(false, inc.getSystem(), c.getCode(), c.hasDisplay()? c.getDisplay() : cc != null ? cc.getDisplay() : "", td);
|
||||
|
||||
td = tr.td();
|
||||
if (!Utilities.noString(c.getDisplay()))
|
||||
VersionComparisonAnnotation.render(c.getDisplayElement(), td).addText(c.getDisplay());
|
||||
else if (VersionComparisonAnnotation.hasDeleted(c, "display")) {
|
||||
StringType d = (StringType) VersionComparisonAnnotation.getDeletedItem(c, "display");
|
||||
VersionComparisonAnnotation.render(d, td).addText(d.primitiveValue());
|
||||
} else if (cc != null && !Utilities.noString(cc.getDisplay()))
|
||||
td.style("color: #cccccc").addText(cc.getDisplay());
|
||||
|
||||
if (hasDefinition) {
|
||||
td = tr.td();
|
||||
if (ExtensionHelper.hasExtension(c, ToolingExtensions.EXT_DEFINITION)) {
|
||||
smartAddText(td, ToolingExtensions.readStringExtension(c, ToolingExtensions.EXT_DEFINITION));
|
||||
} else if (cc != null && !Utilities.noString(cc.getDefinition())) {
|
||||
smartAddText(td, cc.getDefinition());
|
||||
}
|
||||
}
|
||||
if (hasComments) {
|
||||
td = tr.td();
|
||||
if (ExtensionHelper.hasExtension(c, ToolingExtensions.EXT_VS_COMMENT)) {
|
||||
smartAddText(td, "Note: "+ToolingExtensions.readStringExtension(c, ToolingExtensions.EXT_VS_COMMENT));
|
||||
}
|
||||
}
|
||||
if (doDesignations) {
|
||||
addDesignationsToRow(c, designations, tr);
|
||||
addLangaugesToRow(c, langs, tr);
|
||||
}
|
||||
for (UsedConceptMap m : maps) {
|
||||
td = tr.td();
|
||||
List<TargetElementComponentWrapper> mappings = findMappingsForCode(c.getCode(), m.getMap());
|
||||
boolean first = true;
|
||||
for (TargetElementComponentWrapper mapping : mappings) {
|
||||
if (!first)
|
||||
td.br();
|
||||
first = false;
|
||||
XhtmlNode span = td.span(null, mapping.comp.getRelationship().toString());
|
||||
span.addText(getCharForRelationship(mapping.comp));
|
||||
addRefToCode(td, mapping.group.getTarget(), m.getLink(), mapping.comp.getCode());
|
||||
if (!Utilities.noString(mapping.comp.getComment()))
|
||||
td.i().tx("("+mapping.comp.getComment()+")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addDesignationsToRow(ConceptReferenceComponent c, Map<String, String> designations, XhtmlNode tr) {
|
||||
for (String url : designations.keySet()) {
|
||||
String d = null;
|
||||
|
|
|
@ -79,6 +79,7 @@ public class RenderingContext {
|
|||
SUMMARY, // 5 cells: tree/name | flags | cardinality | type | details
|
||||
BINDINGS, // tree/name + column for each kind of binding found, cells are lists of bindings
|
||||
OBLIGATIONS, // tree/name + column for each actor that has obligations
|
||||
DATA_DICT, // detailed element view
|
||||
}
|
||||
|
||||
public enum ExampleScenarioRendererMode {
|
||||
|
@ -132,6 +133,7 @@ public class RenderingContext {
|
|||
LINKS
|
||||
}
|
||||
|
||||
|
||||
public enum KnownLinkType {
|
||||
SELF, // absolute link to where the content is to be found (only used in a few circumstances when making external references to tools)
|
||||
SPEC, // version specific link to core specification
|
||||
|
|
|
@ -138,8 +138,8 @@ public class DefinitionNavigator {
|
|||
if (nameMap.containsKey(path)) {
|
||||
DefinitionNavigator master = nameMap.get(path);
|
||||
ElementDefinition cm = master.current();
|
||||
if (!cm.hasSlicing())
|
||||
throw new DefinitionException("Found slices with no slicing details at "+dn.current().getPath());
|
||||
// if (!cm.hasSlicing())
|
||||
// throw new DefinitionException("Found slices with no slicing details at "+dn.current().getPath());
|
||||
if (master.slices == null)
|
||||
master.slices = new ArrayList<DefinitionNavigator>();
|
||||
master.slices.add(dn);
|
||||
|
|
Loading…
Reference in New Issue