ConceptMap utilities
This commit is contained in:
parent
7ba1511748
commit
0076a2206d
|
@ -300,7 +300,6 @@ public class NpmPackageVersionConverter {
|
||||||
}
|
}
|
||||||
throw new Error("Unknown version " + currentVersion + " -> " + version);
|
throw new Error("Unknown version " + currentVersion + " -> " + version);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
|
||||||
errors.add("Error converting " + n + ": " + ex.getMessage());
|
errors.add("Error converting " + n + ": " + ex.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -336,6 +335,7 @@ public class NpmPackageVersionConverter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void convertResourceR5(Resource res) {
|
private void convertResourceR5(Resource res) {
|
||||||
if (res instanceof ImplementationGuide) {
|
if (res instanceof ImplementationGuide) {
|
||||||
ImplementationGuide ig = (ImplementationGuide) res;
|
ImplementationGuide ig = (ImplementationGuide) res;
|
||||||
|
|
|
@ -629,5 +629,9 @@ public class Coding extends DataType implements IBaseCoding, ICompositeType, ICo
|
||||||
}
|
}
|
||||||
// end addition
|
// end addition
|
||||||
|
|
||||||
|
public String getVersionedSystem() {
|
||||||
|
return hasVersion() ? getSystem()+"|"+getVersion() : getSystem();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1785,6 +1785,7 @@ public class ConceptMap extends MetadataResource {
|
||||||
}
|
}
|
||||||
return addElement().setCode(code);
|
return addElement().setCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Block()
|
@Block()
|
||||||
|
@ -2273,6 +2274,21 @@ public class ConceptMap extends MetadataResource {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasTargetCode(String code) {
|
||||||
|
for (TargetElementComponent tgt : getTarget()) {
|
||||||
|
if (code.equals(tgt.getCode())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TargetElementComponent addTarget(String code, ConceptMapRelationship relationship) {
|
||||||
|
TargetElementComponent tgt = addTarget();
|
||||||
|
tgt.setCode(code);
|
||||||
|
tgt.setRelationship(relationship);
|
||||||
|
return tgt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Block()
|
@Block()
|
||||||
|
@ -8590,7 +8606,31 @@ public class ConceptMap extends MetadataResource {
|
||||||
private String tail(String uri) {
|
private String tail(String uri) {
|
||||||
return uri.contains("/") ? uri.substring(uri.lastIndexOf("/")+1) : uri;
|
return uri.contains("/") ? uri.substring(uri.lastIndexOf("/")+1) : uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConceptMapGroupComponent getGroup(String su, String tu) {
|
||||||
|
for (ConceptMapGroupComponent g : getGroup()) {
|
||||||
|
if (su.equals(g.getSource()) && tu.equals(g.getTarget())) {
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConceptMapGroupComponent forceGroup(String su, String tu) {
|
||||||
|
for (ConceptMapGroupComponent g : getGroup()) {
|
||||||
|
if (su.equals(g.getSource()) && tu.equals(g.getTarget())) {
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConceptMapGroupComponent g = addGroup();
|
||||||
|
g.setSource(su);
|
||||||
|
g.setTarget(tu);
|
||||||
|
return g;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// end addition
|
// end addition
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,92 +322,131 @@ public class ConceptMapUtilities {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkReciprocal(ConceptMap left, ConceptMap right, List<String> issues) {
|
public static boolean checkReciprocal(ConceptMap left, ConceptMap right, List<String> issues, boolean makeChanges) {
|
||||||
|
boolean changed = 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());
|
||||||
}
|
}
|
||||||
if (!Base.compareDeep(left.getSourceScope(), right.getTargetScope(), true)) {
|
if (!Base.compareDeep(left.getSourceScope(), right.getTargetScope(), true)) {
|
||||||
issues.add("scopes are not reciprocal: "+left.getSourceScope()+" vs "+right.getTargetScope());
|
issues.add("scopes are not reciprocal: "+left.getSourceScope()+" vs "+right.getTargetScope());
|
||||||
}
|
}
|
||||||
if (left.getGroup().size() != right.getGroup().size()) {
|
|
||||||
issues.add("group count mismatch: "+left.getGroup().size()+" vs "+right.getGroup().size());
|
|
||||||
}
|
|
||||||
for (ConceptMapGroupComponent gl : left.getGroup()) {
|
for (ConceptMapGroupComponent gl : left.getGroup()) {
|
||||||
ConceptMapGroupComponent gr = findMatchingGroup(right.getGroup(), gl.getTarget(), gl.getSource());
|
ConceptMapGroupComponent gr = findMatchingGroup(right.getGroup(), gl.getTarget(), gl.getSource());
|
||||||
if (gr == null) {
|
if (gr == null) {
|
||||||
issues.add("left maps from "+gl.getSource()+" to "+gl.getTarget()+" but right has no matching reverse map");
|
for (SourceElementComponent e : gl.getElement()) {
|
||||||
|
for (TargetElementComponent t : e.getTarget()) {
|
||||||
|
if (t.getRelationship() != ConceptMapRelationship.NOTRELATEDTO) {
|
||||||
|
if (makeChanges) {
|
||||||
|
changed = true;
|
||||||
|
right.forceGroup(gl.getTarget(), gl.getSource()).getOrAddElement(t.getCode()).addTarget(e.getCode(), inverse(t.getRelationship()));
|
||||||
|
} else {
|
||||||
|
issues.add("left maps from "+gl.getSource()+"#"+e.getCode()+" to "+gl.getTarget()+"#"+t.getCode()+" but right has no matching reverse map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (SourceElementComponent srcL : gl.getElement()) {
|
for (SourceElementComponent srcL : gl.getElement()) {
|
||||||
if (!"CHECK!".equals(srcL.getCode())) {
|
if (!srcL.getNoMap()) {
|
||||||
if (!srcL.getNoMap()) {
|
for (TargetElementComponent tgtL : srcL.getTarget()) {
|
||||||
for (TargetElementComponent tgtL : srcL.getTarget()) {
|
List<ElementMappingPair> pairs = getMappings(gr, tgtL.getCode(), srcL.getCode());
|
||||||
List<ElementMappingPair> pairs = getMappings(gr, tgtL.getCode(), srcL.getCode());
|
if (tgtL.getRelationship() == null) {
|
||||||
switch (tgtL.getRelationship()) {
|
issues.add("Left map has relationship "+srcL.getCode()+" with no relationship");
|
||||||
case EQUIVALENT:
|
} else switch (tgtL.getRelationship()) {
|
||||||
if (pairs.isEmpty()) {
|
case EQUIVALENT:
|
||||||
|
if (pairs.isEmpty()) {
|
||||||
|
if (makeChanges) {
|
||||||
|
changed = true;
|
||||||
|
gr.getOrAddElement(tgtL.getCode()).addTarget(srcL.getCode(), ConceptMapRelationship.EQUIVALENT);
|
||||||
|
} else {
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but there's no reverse relationship");
|
issues.add("Left map says that "+srcL.getCode()+" is equivalent to "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
case RELATEDTO:
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT) {
|
||||||
if (pairs.isEmpty()) {
|
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 there's no reverse relationship");
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is related to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case SOURCEISBROADERTHANTARGET:
|
|
||||||
if (pairs.isEmpty()) {
|
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is broader than "+tgtL.getCode()+" but there's no reverse relationship");
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SOURCEISNARROWERTHANTARGET:
|
|
||||||
if (pairs.isEmpty()) {
|
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is narrower than "+tgtL.getCode()+" but there's no reverse relationship");
|
|
||||||
} else for (ElementMappingPair pair : pairs) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NOTRELATEDTO:
|
|
||||||
for (ElementMappingPair pair : pairs) {
|
|
||||||
if (pair.tgt.getRelationship() != ConceptMapRelationship.NOTRELATEDTO) {
|
|
||||||
issues.add("Left map says that "+srcL.getCode()+" is not related to "+tgtL.getCode()+" but a reverse relationship exists with type "+pair.tgt.getRelationship().toCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
} else {
|
case RELATEDTO:
|
||||||
for (SourceElementComponent srcR : gr.getElement()) {
|
if (pairs.isEmpty()) {
|
||||||
for (TargetElementComponent tgtR : srcR.getTarget()) {
|
issues.add("Left map says that "+srcL.getCode()+" is related to "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
if (srcL.getCode().equals(tgtR.getCode())) {
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
issues.add("Left map says that there is no relationship for "+srcL.getCode()+" but right map has a "+tgtR.getRelationship().toCode()+" mapping to it from "+srcR.getCode());
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.EQUIVALENT && pair.tgt.getRelationship() != ConceptMapRelationship.RELATEDTO) {
|
||||||
|
issues.add("Left map says that "+srcL.getCode()+" is related to "+tgtL.getCode()+" but the reverse relationship has type "+pair.tgt.getRelationship().toCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case SOURCEISBROADERTHANTARGET:
|
||||||
|
if (pairs.isEmpty()) {
|
||||||
|
issues.add("Left map says that "+srcL.getCode()+" is broader than "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOURCEISNARROWERTHANTARGET:
|
||||||
|
if (pairs.isEmpty()) {
|
||||||
|
issues.add("Left map says that "+srcL.getCode()+" is narrower than "+tgtL.getCode()+" but there's no reverse relationship");
|
||||||
|
} else for (ElementMappingPair pair : pairs) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTRELATEDTO:
|
||||||
|
for (ElementMappingPair pair : pairs) {
|
||||||
|
if (pair.tgt.getRelationship() != ConceptMapRelationship.NOTRELATEDTO) {
|
||||||
|
issues.add("Left map says that "+srcL.getCode()+" is not related to "+tgtL.getCode()+" but a reverse relationship exists with type "+pair.tgt.getRelationship().toCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (SourceElementComponent srcR : gr.getElement()) {
|
||||||
|
for (TargetElementComponent tgtR : srcR.getTarget()) {
|
||||||
|
if (srcL.getCode().equals(tgtR.getCode())) {
|
||||||
|
issues.add("Left map says that there is no relationship for "+srcL.getCode()+" but right map has a "+tgtR.getRelationship().toCode()+" mapping to it from "+srcR.getCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ConceptMapGroupComponent gr : right.getGroup()) {
|
||||||
|
ConceptMapGroupComponent gl = findMatchingGroup(left.getGroup(), gr.getTarget(), gr.getSource());
|
||||||
|
if (gl == null) {
|
||||||
|
for (SourceElementComponent e : gr.getElement()) {
|
||||||
|
for (TargetElementComponent t : e.getTarget()) {
|
||||||
|
if (t.getRelationship() != ConceptMapRelationship.NOTRELATEDTO) {
|
||||||
|
if (makeChanges) {
|
||||||
|
changed = true;
|
||||||
|
left.forceGroup(gr.getTarget(), gr.getSource()).getOrAddElement(t.getCode()).addTarget(e.getCode(), inverse(t.getRelationship()));
|
||||||
|
} else {
|
||||||
|
issues.add("left maps from "+gr.getSource()+"#"+e.getCode()+" to "+gr.getTarget()+"#"+t.getCode()+" but right has no matching reverse map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (SourceElementComponent srcR : gr.getElement()) {
|
for (SourceElementComponent srcR : gr.getElement()) {
|
||||||
if (!"CHECK!".equals(srcR.getCode())) {
|
if (!"CHECK!".equals(srcR.getCode())) {
|
||||||
if (!srcR.getNoMap()) {
|
if (!srcR.getNoMap()) {
|
||||||
for (TargetElementComponent tgtR : srcR.getTarget()) {
|
for (TargetElementComponent tgtR : srcR.getTarget()) {
|
||||||
List<ElementMappingPair> pairs = getMappings(gl, tgtR.getCode(), srcR.getCode());
|
List<ElementMappingPair> pairs = getMappings(gl, tgtR.getCode(), srcR.getCode());
|
||||||
switch (tgtR.getRelationship()) {
|
if (tgtR.getRelationship() == null) {
|
||||||
|
issues.add("Right map has relationship "+srcR.getCode()+" with no relationship");
|
||||||
|
} else switch (tgtR.getRelationship()) {
|
||||||
case EQUIVALENT:
|
case EQUIVALENT:
|
||||||
if (pairs.isEmpty()) {
|
if (pairs.isEmpty()) {
|
||||||
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but there's no reverse relationship");
|
if (makeChanges) {
|
||||||
|
changed = true;
|
||||||
|
gl.getOrAddElement(tgtR.getCode()).addTarget(srcR.getCode(), ConceptMapRelationship.EQUIVALENT);
|
||||||
|
} else {
|
||||||
|
issues.add("Right map says that "+srcR.getCode()+" is equivalent to "+tgtR.getCode()+" but there's no reverse relationship");
|
||||||
|
}
|
||||||
} 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());
|
||||||
|
@ -463,6 +502,27 @@ public class ConceptMapUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ConceptMapRelationship inverse(ConceptMapRelationship relationship) {
|
||||||
|
switch (relationship) {
|
||||||
|
case EQUIVALENT: return ConceptMapRelationship.EQUIVALENT;
|
||||||
|
case RELATEDTO: return ConceptMapRelationship.RELATEDTO;
|
||||||
|
case SOURCEISBROADERTHANTARGET: return ConceptMapRelationship.SOURCEISNARROWERTHANTARGET;
|
||||||
|
case SOURCEISNARROWERTHANTARGET: return ConceptMapRelationship.SOURCEISBROADERTHANTARGET;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasActualMappings(ConceptMapGroupComponent gr) {
|
||||||
|
for (SourceElementComponent e : gr.getElement()) {
|
||||||
|
for (TargetElementComponent tgt : e.getTarget()) {
|
||||||
|
if (tgt.getRelationship() != ConceptMapRelationship.NOTRELATEDTO) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,28 +583,34 @@ public class ConceptMapUtilities {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> listCodesWithNoMappings(Set<String> set, ConceptMap map) {
|
public static Set<Coding> listCodesWithNoMappings(Set<Coding> codes, ConceptMap map) {
|
||||||
Set<String> res = new HashSet<>();
|
Set<Coding> res = new HashSet<>();
|
||||||
for (String s : set) {
|
for (Coding c : codes) {
|
||||||
if (s != null) {
|
if (c != null && c.hasCode()) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (ConceptMapGroupComponent grp : map.getGroup()) {
|
for (ConceptMapGroupComponent grp : map.getGroup()) {
|
||||||
for (SourceElementComponent src : grp.getElement()) {
|
if (matchesCoding(grp, c)) {
|
||||||
if (s.equals(src.getCode())) {
|
for (SourceElementComponent src : grp.getElement()) {
|
||||||
for (TargetElementComponent tgt : src.getTarget()) {
|
if (c.getCode().equals(src.getCode())) {
|
||||||
if (tgt.getRelationship() == ConceptMapRelationship.RELATEDTO || tgt.getRelationship() == ConceptMapRelationship.EQUIVALENT || tgt.getRelationship() == ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
for (TargetElementComponent tgt : src.getTarget()) {
|
||||||
found = true;
|
if (tgt.getRelationship() == ConceptMapRelationship.RELATEDTO || tgt.getRelationship() == ConceptMapRelationship.EQUIVALENT || tgt.getRelationship() == ConceptMapRelationship.SOURCEISNARROWERTHANTARGET) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
res.add(s);
|
res.add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean matchesCoding(ConceptMapGroupComponent grp, Coding code) {
|
||||||
|
return code.getSystem().equals(grp.getSource()) || (code.getSystem()+"|"+code.getVersion()).equals(grp.getSource());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue