Merge pull request #655 from hapifhir/gg-202111-conceptmap-rendering

Gg 202111 conceptmap rendering
This commit is contained in:
Grahame Grieve 2021-11-11 16:42:56 +11:00 committed by GitHub
commit cf440359aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 96 additions and 36 deletions

View File

@ -160,11 +160,24 @@ public class ConceptMapRenderer extends TerminologyRenderer {
addUnmapped(tbl, grp);
}
} else {
boolean hasRelationships = false;
for (int si = 0; si < grp.getElement().size(); si++) {
SourceElementComponent ccl = grp.getElement().get(si);
for (int ti = 0; ti < ccl.getTarget().size(); ti++) {
TargetElementComponent ccm = ccl.getTarget().get(ti);
if (ccm.hasRelationship()) {
hasRelationships = true;
}
}
}
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
XhtmlNode td;
tr.td().colspan(Integer.toString(1+sources.size())).b().tx("Source Concept Details");
tr.td().b().tx("Relationship");
if (hasRelationships) {
tr.td().b().tx("Relationship");
}
tr.td().colspan(Integer.toString(1+targets.size())).b().tx("Destination Concept Details");
if (comment) {
tr.td().b().tx("Comment");
@ -184,7 +197,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
tr.td().b().addText(getDescForConcept(s));
}
}
tr.td();
if (hasRelationships) {
tr.td();
}
if (targets.get("code").size() == 1) {
String url = targets.get("code").iterator().next();
renderCSDetailsLink(tr, url, true);
@ -238,23 +253,19 @@ public class ConceptMapRenderer extends TerminologyRenderer {
td.addText(ccl.getCode());
else
td.addText(grp.getSource()+" / "+ccl.getCode());
display = getDisplayForConcept(systemFromCanonical(grp.getSource()), versionFromCanonical(grp.getSource()), ccl.getCode());
display = ccl.hasDisplay() ? ccl.getDisplay() : getDisplayForConcept(systemFromCanonical(grp.getSource()), versionFromCanonical(grp.getSource()), ccl.getCode());
td = tr.td();
if (!first)
td.style("border-left-width: 0px; border-top-style: none");
else if (!last)
if (!last)
td.style("border-left-width: 0px; border-bottom-style: none");
else
td.style("border-left-width: 0px");
td.tx(display == null ? "" : display);
} else {
td = tr.td(); // for display
if (!first)
td.style("border-left-width: 0px; border-top-style: none");
else if (!last)
td.style("border-left-width: 0px; border-bottom-style: none");
if (!last)
td.style("border-left-width: 0px; border-top-style: none; border-bottom-style: none");
else
td.style("border-left-width: 0px");
td.style("border-top-style: none; border-left-width: 0px");
}
for (String s : sources.keySet()) {
if (!s.equals("code")) {
@ -268,14 +279,16 @@ public class ConceptMapRenderer extends TerminologyRenderer {
}
}
first = false;
if (!ccm.hasRelationship())
tr.td().tx(":"+"("+ConceptMapRelationship.EQUIVALENT.toCode()+")");
else {
if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
tr.td().ah(eqpath+"#"+code).tx(presentEquivalenceCode(code));
} else {
tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode()));
if (hasRelationships) {
if (!ccm.hasRelationship())
tr.td();
else {
if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) {
String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE);
tr.td().ah(eqpath+"#"+code).tx(presentEquivalenceCode(code));
} else {
tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode()));
}
}
}
td = tr.td().style("border-right-width: 0px");
@ -283,7 +296,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
td.addText(ccm.getCode());
else
td.addText(grp.getTarget()+" / "+ccm.getCode());
display = getDisplayForConcept(systemFromCanonical(grp.getTarget()), versionFromCanonical(grp.getTarget()), ccm.getCode());
display = ccm.hasDisplay() ? ccm.getDisplay() : getDisplayForConcept(systemFromCanonical(grp.getTarget()), versionFromCanonical(grp.getTarget()), ccm.getCode());
tr.td().style("border-left-width: 0px").tx(display == null ? "" : display);
for (String s : targets.keySet()) {

View File

@ -1320,7 +1320,7 @@ public class DataRenderer extends Renderer {
} else if (system.contains("|")) {
return system.substring(0, system.indexOf("|"));
} else {
return system;
return null;
}
}

View File

@ -290,7 +290,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasAnswerValueSet()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Value Set: ", null));
if (i.getAnswerValueSet().startsWith("#")) {
if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
if (vs == null) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
@ -469,7 +469,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasAnswerValueSet()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Value Set: ", null));
if (i.getAnswerValueSet().startsWith("#")) {
if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
if (vs == null) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
@ -703,7 +703,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
}
if (i.hasAnswerValueSet()) {
XhtmlNode ans = item(ul, "Answers");
if (i.getAnswerValueSet().startsWith("#")) {
if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
if (vs == null) {
ans.tx(i.getAnswerValueSet());
@ -792,7 +792,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
private void listOptions(Questionnaire q, QuestionnaireItemComponent i, XhtmlNode select) {
if (i.hasAnswerValueSet()) {
ValueSet vs = null;
if (i.getAnswerValueSet().startsWith("#")) {
if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) {
vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1));
if (vs != null && !vs.hasUrl()) {
vs = vs.copy();

View File

@ -104,7 +104,7 @@ public class TerminologyCacheManager {
Utilities.createDirectory(path);
} else {
Utilities.createDirectory(Utilities.getDirectoryForFile(path));
TextFile.streamToFile(zipIn, path);
TextFile.streamToFileNoClose(zipIn, path);
}
}
}
@ -154,6 +154,8 @@ public class TerminologyCacheManager {
String url = "https://tx.fhir.org/post/tx-cache/"+ghOrg+"/"+ghRepo+"/"+ghBranch+".zip";
System.out.println("Sending tx-cache to "+url+" ("+Utilities.describeSize(bs.toByteArray().length)+")");
SimpleHTTPClient http = new SimpleHTTPClient();
http.setUsername(token.substring(0, token.indexOf(':')));
http.setPassword(token.substring(token.indexOf(':')+1));
HTTPResult res = http.put(url, "application/zip", bs.toByteArray(), null); // accept doesn't matter
if (res.getCode() >= 300) {
System.out.println("sending cache failed: "+res.getCode());

View File

@ -166,14 +166,23 @@ public class TextFile {
if (input== null) {
return null;
}
// Define a size if you have an idea of it.
ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
byte[] read = new byte[512]; // Your buffer size.
byte[] read = new byte[512];
for (int i; -1 != (i = input.read(read)); r.write(read, 0, i));
input.close();
return r.toByteArray();
}
public static byte[] streamToBytesNoClose(InputStream input) throws IOException {
if (input== null) {
return null;
}
ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
byte[] read = new byte[512];
for (int i; -1 != (i = input.read(read)); r.write(read, 0, i));
return r.toByteArray();
}
public static void bytesToFile(byte[] bytes, String path) throws IOException {
File file = new CSFile(path);
OutputStream sw = new FileOutputStream(file);
@ -231,4 +240,9 @@ public class TextFile {
byte[] cnt = streamToBytes(stream);
bytesToFile(cnt, filename);
}
public static void streamToFileNoClose(InputStream stream, String filename) throws IOException {
byte[] cnt = streamToBytesNoClose(stream);
bytesToFile(cnt, filename);
}
}

View File

@ -32,6 +32,7 @@ public class I18nConstants {
public static final String BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = "BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES";
public static final String BUNDLE_BUNDLE_ENTRY_NOTFOUND = "Bundle_BUNDLE_Entry_NotFound";
public static final String BUNDLE_BUNDLE_ENTRY_ORPHAN = "Bundle_BUNDLE_Entry_Orphan";
public static final String BUNDLE_BUNDLE_ENTRY_REVERSE = "BUNDLE_BUNDLE_ENTRY_REVERSE";
public static final String BUNDLE_BUNDLE_ENTRY_TYPE = "Bundle_BUNDLE_Entry_Type";
public static final String BUNDLE_BUNDLE_ENTRY_TYPE2 = "Bundle_BUNDLE_Entry_Type2";
public static final String BUNDLE_BUNDLE_ENTRY_TYPE3 = "Bundle_BUNDLE_Entry_Type3";

View File

@ -11,6 +11,7 @@ BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED = Except for transactions and batches, each
Bundle_BUNDLE_Entry_NoProfile = No profile found for contained resource of type ''{0}''
Bundle_BUNDLE_Entry_NotFound = Can''t find ''{0}'' in the bundle ({1})
Bundle_BUNDLE_Entry_Orphan = Entry {0} isn''t reachable by traversing from first Bundle entry
BUNDLE_BUNDLE_ENTRY_REVERSE = Entry {0} isn''t reachable by traversing forwards from first Bundle entry, and isn''t a resource type that is typically used that way - check this is not missed somewhere
Bundle_BUNDLE_Entry_Type = The type ''{0}'' is not valid - no resources allowed here (allowed = {1})
Bundle_BUNDLE_Entry_Type2 = The type ''{0}'' is not valid - must be {1} (allowed = {2})
Bundle_BUNDLE_Entry_Type3 = The type ''{0}'' is not valid - must be one of {1}

View File

@ -396,20 +396,30 @@ public class BundleValidator extends BaseValidator{
private void checkAllInterlinked(List<ValidationMessage> errors, List<Element> entries, NodeStack stack, Element bundle, boolean isError) {
List<EntrySummary> entryList = new ArrayList<>();
int i = 0;
for (Element entry : entries) {
Element r = entry.getNamedChild(RESOURCE);
if (r != null) {
entryList.add(new EntrySummary(entry, r));
EntrySummary e = new EntrySummary(i, entry, r);
entryList.add(e);
System.out.println("Found entry "+e.dbg());
}
i++;
}
for (EntrySummary e : entryList) {
Set<String> references = findReferences(e.getEntry());
for (String ref : references) {
Element tgt = resolveInBundle(entries, ref, e.getEntry().getChildValue(FULL_URL), e.getResource().fhirType(), e.getResource().getIdBase());
if (tgt != null) {
EntrySummary t = entryForTarget(entryList, tgt);
if (t != null) {
e.getTargets().add(t);
if (t != null ) {
if (t != e) {
System.out.println("Entry "+e.getIndex()+" refers to "+t.getIndex()+" by ref '"+ref+"'");
e.getTargets().add(t);
} else {
System.out.println("Entry "+e.getIndex()+" refers to itself by '"+ref+"'");
}
}
}
}
@ -422,6 +432,7 @@ public class BundleValidator extends BaseValidator{
foundRevLinks = false;
for (EntrySummary e : entryList) {
if (!visited.contains(e)) {
System.out.println("Not visited "+e.getIndex()+" - check for reverse links");
boolean add = false;
for (EntrySummary t : e.getTargets()) {
if (visited.contains(t)) {
@ -429,6 +440,10 @@ public class BundleValidator extends BaseValidator{
}
}
if (add) {
warning(errors, IssueType.INFORMATIONAL, e.getEntry().line(), e.getEntry().col(),
stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), isExpectedToBeReverse(e.getResource().fhirType()),
I18nConstants.BUNDLE_BUNDLE_ENTRY_REVERSE, (e.getEntry().getChildValue(FULL_URL) != null ? "'" + e.getEntry().getChildValue(FULL_URL) + "'" : ""));
System.out.println("Found reverse links for "+e.getIndex());
foundRevLinks = true;
visitLinked(visited, e);
}
@ -436,7 +451,7 @@ public class BundleValidator extends BaseValidator{
}
} while (foundRevLinks);
int i = 0;
i = 0;
for (EntrySummary e : entryList) {
Element entry = e.getEntry();
if (isError) {
@ -450,6 +465,10 @@ public class BundleValidator extends BaseValidator{
private boolean isExpectedToBeReverse(String fhirType) {
return Utilities.existsInList(fhirType, "Provenance");
}
private String uriRegexForVersion() {
if (VersionUtilities.isR3Ver(context.getVersion()))
return URI_REGEX3;

View File

@ -10,6 +10,7 @@ public class EntrySummary {
Element entry;
Element resource;
List<EntrySummary> targets = new ArrayList<>();
private int index;
public Element getEntry() {
return entry;
@ -38,8 +39,17 @@ public class EntrySummary {
return this;
}
public EntrySummary(Element entry, Element resource) {
this.entry = entry;
this.resource = resource;
public EntrySummary(int i, Element entry, Element resource) {
this.index = i;
this.entry = entry;
this.resource = resource;
}
public String dbg() {
return ""+index+"="+ entry.getChildValue("fullUrl")+" | "+resource.getIdBase() + "("+resource.fhirType()+")";
}
public String getIndex() {
return Integer.toString(index);
}
}

View File

@ -19,7 +19,7 @@
<properties>
<hapi_fhir_version>5.1.0</hapi_fhir_version>
<validator_test_case_version>1.1.73-SNAPSHOT</validator_test_case_version>
<validator_test_case_version>1.1.73</validator_test_case_version>
<junit_jupiter_version>5.7.1</junit_jupiter_version>
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
<maven_surefire_version>3.0.0-M4</maven_surefire_version>