More improvements to ConceptMap Infrastructure
This commit is contained in:
parent
7fb2b1ea00
commit
a3fb1457a0
|
@ -39,8 +39,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IConceptMapInformationProvider {
|
public interface IMultiMapRendererAdvisor {
|
||||||
public List<Coding> getMembers(String uri);
|
public List<Coding> getMembers(String uri);
|
||||||
|
public boolean describeMap(ConceptMap map, XhtmlNode x);
|
||||||
public String getLink(String system, String code);
|
public String getLink(String system, String code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,11 +724,11 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XhtmlNode renderMultipleMaps(String start, List<ConceptMap> maps, IConceptMapInformationProvider linker, RenderMultiRowSortPolicy sort) {
|
public static XhtmlNode renderMultipleMaps(String start, String startLink, List<ConceptMap> maps, IMultiMapRendererAdvisor advisor, RenderMultiRowSortPolicy sort) {
|
||||||
// 1+1 column for each provided map
|
// 1+1 column for each provided map
|
||||||
List<MultipleMappingRow> rowSets = new ArrayList<>();
|
List<MultipleMappingRow> rowSets = new ArrayList<>();
|
||||||
for (int i = 0; i < maps.size(); i++) {
|
for (int i = 0; i < maps.size(); i++) {
|
||||||
populateRows(rowSets, maps.get(i), i, linker);
|
populateRows(rowSets, maps.get(i), i, advisor);
|
||||||
}
|
}
|
||||||
collateRows(rowSets);
|
collateRows(rowSets);
|
||||||
if (sort != RenderMultiRowSortPolicy.UNSORTED) {
|
if (sort != RenderMultiRowSortPolicy.UNSORTED) {
|
||||||
|
@ -736,16 +737,19 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
|
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
|
||||||
XhtmlNode tbl = div.table("none").style("text-align: left; border-spacing: 0; padding: 5px");
|
XhtmlNode tbl = div.table("none").style("text-align: left; border-spacing: 0; padding: 5px");
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
styleCell(tr.td(), false, true, 5).b().tx(start);
|
styleCell(tr.td(), false, true, 5).b().ahOrNot(startLink).tx(start);
|
||||||
for (ConceptMap map : maps) {
|
for (ConceptMap map : maps) {
|
||||||
if (map.hasWebPath()) {
|
XhtmlNode td = styleCell(tr.td(), false, true, 5).colspan(2);
|
||||||
styleCell(tr.td(), false, true, 5).colspan(2).b().ah(map.getWebPath(), map.getVersionedUrl()).tx(map.present());
|
if (!advisor.describeMap(map, td)) {
|
||||||
} else {
|
if (map.hasWebPath()) {
|
||||||
styleCell(tr.td(), false, true, 5).colspan(2).b().tx(map.present());
|
td.b().ah(map.getWebPath(), map.getVersionedUrl()).tx(map.present());
|
||||||
|
} else {
|
||||||
|
td.b().tx(map.present());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (MultipleMappingRow row : rowSets) {
|
for (MultipleMappingRow row : rowSets) {
|
||||||
renderMultiRow(tbl, row, maps, linker);
|
renderMultiRow(tbl, row, maps, advisor);
|
||||||
}
|
}
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +769,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
rowSets.removeAll(toDelete);
|
rowSets.removeAll(toDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderMultiRow(XhtmlNode tbl, MultipleMappingRow rows, List<ConceptMap> maps, IConceptMapInformationProvider linker) {
|
private static void renderMultiRow(XhtmlNode tbl, MultipleMappingRow rows, List<ConceptMap> maps, IMultiMapRendererAdvisor advisor) {
|
||||||
int rowCounter = 0;
|
int rowCounter = 0;
|
||||||
for (MultipleMappingRowItem row : rows.rowSets) {
|
for (MultipleMappingRowItem row : rows.rowSets) {
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
|
@ -787,7 +791,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
if (cell.code == null) {
|
if (cell.code == null) {
|
||||||
styleCell(tr.td(), rowCounter == 0, true, 5).rowspan(c).style("background-color: #eeeeee");
|
styleCell(tr.td(), rowCounter == 0, true, 5).rowspan(c).style("background-color: #eeeeee");
|
||||||
} else {
|
} else {
|
||||||
String link = linker.getLink(cell.system, cell.code);
|
String link = advisor.getLink(cell.system, cell.code);
|
||||||
XhtmlNode x = null;
|
XhtmlNode x = null;
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
x = styleCell(tr.td(), rowCounter == 0, true, 5).attributeNN("title", cell.display).rowspan(c).ah(link);
|
x = styleCell(tr.td(), rowCounter == 0, true, 5).attributeNN("title", cell.display).rowspan(c).ah(link);
|
||||||
|
@ -835,7 +839,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
if (cell.code == null) {
|
if (cell.code == null) {
|
||||||
styleCell(tr.td(), rowCounter == 0, true, 5).rowspan(c).style("background-color: #eeeeee");
|
styleCell(tr.td(), rowCounter == 0, true, 5).rowspan(c).style("background-color: #eeeeee");
|
||||||
} else {
|
} else {
|
||||||
String link = linker.getLink(cell.system, cell.code);
|
String link = advisor.getLink(cell.system, cell.code);
|
||||||
XhtmlNode x = null;
|
XhtmlNode x = null;
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
x = styleCell(tr.td(), rowCounter == 0, true, 5).attributeNN("title", cell.display).rowspan(c).ah(link);
|
x = styleCell(tr.td(), rowCounter == 0, true, 5).attributeNN("title", cell.display).rowspan(c).ah(link);
|
||||||
|
@ -868,10 +872,10 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
return td;
|
return td;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void populateRows(List<MultipleMappingRow> rowSets, ConceptMap map, int i, IConceptMapInformationProvider linker) {
|
private static void populateRows(List<MultipleMappingRow> rowSets, ConceptMap map, int i, IMultiMapRendererAdvisor advisor) {
|
||||||
// if we can resolve the value set, we create entries for it
|
// if we can resolve the value set, we create entries for it
|
||||||
if (map.hasSourceScope()) {
|
if (map.hasSourceScope()) {
|
||||||
List<Coding> codings = linker.getMembers(map.getSourceScope().primitiveValue());
|
List<Coding> codings = advisor.getMembers(map.getSourceScope().primitiveValue());
|
||||||
if (codings != null) {
|
if (codings != null) {
|
||||||
for (Coding c : codings) {
|
for (Coding c : codings) {
|
||||||
MultipleMappingRow row = i == 0 ? null : findExistingRowBySource(rowSets, c.getSystem(), c.getCode(), i);
|
MultipleMappingRow row = i == 0 ? null : findExistingRowBySource(rowSets, c.getSystem(), c.getCode(), i);
|
||||||
|
@ -931,7 +935,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (map.hasTargetScope()) {
|
if (map.hasTargetScope()) {
|
||||||
List<Coding> codings = linker.getMembers(map.getTargetScope().primitiveValue());
|
List<Coding> codings = advisor.getMembers(map.getTargetScope().primitiveValue());
|
||||||
if (codings != null) {
|
if (codings != null) {
|
||||||
for (Coding c : codings) {
|
for (Coding c : codings) {
|
||||||
MultipleMappingRow row = findExistingRowByTarget(rowSets, c.getSystem(), c.getCode(), i);
|
MultipleMappingRow row = findExistingRowByTarget(rowSets, c.getSystem(), c.getCode(), i);
|
||||||
|
|
|
@ -4,8 +4,10 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.r5.model.Base;
|
import org.hl7.fhir.r5.model.Base;
|
||||||
import org.hl7.fhir.r5.model.CanonicalType;
|
import org.hl7.fhir.r5.model.CanonicalType;
|
||||||
|
@ -321,7 +323,6 @@ public class ConceptMapUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkReciprocal(ConceptMap left, ConceptMap right, List<String> issues) {
|
public static boolean checkReciprocal(ConceptMap left, ConceptMap right, List<String> issues) {
|
||||||
boolean altered = false;
|
|
||||||
if (!Base.compareDeep(left.getTargetScope(), right.getSourceScope(), true)) {
|
if (!Base.compareDeep(left.getTargetScope(), right.getSourceScope(), true)) {
|
||||||
issues.add("scopes are not reciprocal: "+left.getTargetScope()+" vs "+right.getSourceScope());
|
issues.add("scopes are not reciprocal: "+left.getTargetScope()+" vs "+right.getSourceScope());
|
||||||
}
|
}
|
||||||
|
@ -344,8 +345,7 @@ public class ConceptMapUtilities {
|
||||||
switch (tgtL.getRelationship()) {
|
switch (tgtL.getRelationship()) {
|
||||||
case EQUIVALENT:
|
case EQUIVALENT:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gr.getOrAddElement(tgtL.getCode()).addTarget().setCode(srcL.getCode()).setRelationship(ConceptMapRelationship.EQUIVALENT);
|
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT) {
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -354,18 +354,16 @@ public class ConceptMapUtilities {
|
||||||
break;
|
break;
|
||||||
case RELATEDTO:
|
case RELATEDTO:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gr.getOrAddElement(tgtL.getCode()).addTarget().setCode(srcL.getCode()).setRelationship(ConceptMapRelationship.RELATEDTO);
|
issues.add("Left map says that "+srcL.getCode()+" is related to "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Left map says that "+srcL.getCode()+" is related to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SOURCEISBROADERTHANTARGET:
|
case SOURCEISBROADERTHANTARGET:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gr.getOrAddElement(tgtL.getCode()).addTarget().setCode(srcL.getCode()).setRelationship(ConceptMapRelationship.SOURCEISNARROWERTHANTARGET);
|
issues.add("Left map says that "+srcL.getCode()+" is broader than "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is broader than "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Left map says that "+srcL.getCode()+" is broader than "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -374,8 +372,7 @@ public class ConceptMapUtilities {
|
||||||
break;
|
break;
|
||||||
case SOURCEISNARROWERTHANTARGET:
|
case SOURCEISNARROWERTHANTARGET:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gr.getOrAddElement(tgtL.getCode()).addTarget().setCode(srcL.getCode()).setRelationship(ConceptMapRelationship.SOURCEISBROADERTHANTARGET);
|
issues.add("Left map says that "+srcL.getCode()+" is narrower than "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISBROADERTHANTARGET) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISBROADERTHANTARGET) {
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is narrower than "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Left map says that "+srcL.getCode()+" is narrower than "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -410,8 +407,7 @@ public class ConceptMapUtilities {
|
||||||
switch (tgtR.getRelationship()) {
|
switch (tgtR.getRelationship()) {
|
||||||
case EQUIVALENT:
|
case EQUIVALENT:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gl.getOrAddElement(tgtR.getCode()).addTarget().setCode(srcR.getCode()).setRelationship(ConceptMapRelationship.EQUIVALENT);
|
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT) {
|
||||||
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -420,8 +416,7 @@ public class ConceptMapUtilities {
|
||||||
break;
|
break;
|
||||||
case RELATEDTO:
|
case RELATEDTO:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gl.getOrAddElement(tgtR.getCode()).addTarget().setCode(srcR.getCode()).setRelationship(ConceptMapRelationship.RELATEDTO);
|
issues.add("Right map says that "+srcR.getCode()+" is related to "+tgtR.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
||||||
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -430,8 +425,7 @@ public class ConceptMapUtilities {
|
||||||
break;
|
break;
|
||||||
case SOURCEISBROADERTHANTARGET:
|
case SOURCEISBROADERTHANTARGET:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gl.getOrAddElement(tgtR.getCode()).addTarget().setCode(srcR.getCode()).setRelationship(ConceptMapRelationship.SOURCEISNARROWERTHANTARGET);
|
issues.add("Right map says that "+srcR.getCode()+" is broader than "+tgtR.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
||||||
issues.add("Right map says that "+srcR.getCode()+" is broader than "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Right map says that "+srcR.getCode()+" is broader than "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -440,8 +434,7 @@ public class ConceptMapUtilities {
|
||||||
break;
|
break;
|
||||||
case SOURCEISNARROWERTHANTARGET:
|
case SOURCEISNARROWERTHANTARGET:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
gl.getOrAddElement(tgtR.getCode()).addTarget().setCode(srcR.getCode()).setRelationship(ConceptMapRelationship.SOURCEISBROADERTHANTARGET);
|
issues.add("Right map says that "+srcR.getCode()+" is narrower than "+tgtR.getCode()+" but there's no reverse relationship");
|
||||||
altered = true;
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISBROADERTHANTARGET) {
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.SOURCEISBROADERTHANTARGET) {
|
||||||
issues.add("Right map says that "+srcR.getCode()+" is narrower than "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
issues.add("Right map says that "+srcR.getCode()+" is narrower than "+tgtR.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
|
@ -470,7 +463,7 @@ public class ConceptMapUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return altered;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ElementMappingPair> getMappings(ConceptMapGroupComponent g, String source, String target) {
|
private static List<ElementMappingPair> getMappings(ConceptMapGroupComponent g, String source, String target) {
|
||||||
|
@ -530,4 +523,28 @@ public class ConceptMapUtilities {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Set<String> listCodesWithNoMappings(Set<String> set, ConceptMap map) {
|
||||||
|
Set<String> res = new HashSet<>();
|
||||||
|
for (String s : set) {
|
||||||
|
if (s != null) {
|
||||||
|
boolean found = false;
|
||||||
|
for (ConceptMapGroupComponent grp : map.getGroup()) {
|
||||||
|
for (SourceElementComponent src : grp.getElement()) {
|
||||||
|
if (s.equals(src.getCode())) {
|
||||||
|
for (TargetElementComponent tgt : src.getTarget()) {
|
||||||
|
if (tgt.getRelationship() == ConceptMapRelationship.RELATEDTO || tgt.getRelationship() == ConceptMapRelationship.EQUIVALENT || tgt.getRelationship() == ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
res.add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue