001package org.hl7.fhir.r5.renderers; 002 003import java.io.IOException; 004import java.util.ArrayList; 005import java.util.Collections; 006import java.util.List; 007import java.util.Map; 008 009import org.hl7.fhir.exceptions.DefinitionException; 010import org.hl7.fhir.exceptions.FHIRFormatError; 011import org.hl7.fhir.r5.model.CodeSystem; 012import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode; 013import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent; 014import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 015import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent; 016import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent; 017import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent; 018import org.hl7.fhir.r5.model.Coding; 019import org.hl7.fhir.r5.model.Enumeration; 020import org.hl7.fhir.r5.model.Extension; 021import org.hl7.fhir.r5.model.Resource; 022import org.hl7.fhir.r5.renderers.utils.RenderingContext; 023import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; 024import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; 025import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; 026import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator; 027import org.hl7.fhir.r5.utils.ToolingExtensions; 028import org.hl7.fhir.utilities.LoincLinker; 029import org.hl7.fhir.utilities.Utilities; 030import org.hl7.fhir.utilities.xhtml.XhtmlNode; 031 032public class CodeSystemRenderer extends TerminologyRenderer { 033 034 public CodeSystemRenderer(RenderingContext context) { 035 super(context); 036 } 037 038 public CodeSystemRenderer(RenderingContext context, ResourceContext rcontext) { 039 super(context, rcontext); 040 } 041 042 043 public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { 044 return render(x, (CodeSystem) dr); 045 } 046 047 public boolean render(XhtmlNode x, CodeSystem cs) throws FHIRFormatError, DefinitionException, IOException { 048 boolean hasExtensions = false; 049 050 if (context.isHeader()) { 051 XhtmlNode h = x.h2(); 052 h.addText(cs.hasTitle() ? cs.getTitle() : cs.getName()); 053 addMarkdown(x, cs.getDescription()); 054 if (cs.hasCopyright()) 055 generateCopyright(x, cs ); 056 } 057 058 boolean props = generateProperties(x, cs); 059 generateFilters(x, cs); 060 List<UsedConceptMap> maps = new ArrayList<UsedConceptMap>(); 061 hasExtensions = generateCodeSystemContent(x, cs, hasExtensions, maps, props); 062 063 return hasExtensions; 064 } 065 066 public void describe(XhtmlNode x, CodeSystem cs) { 067 x.tx(display(cs)); 068 } 069 070 public String display(CodeSystem cs) { 071 return cs.present(); 072 } 073 074 private void generateFilters(XhtmlNode x, CodeSystem cs) { 075 if (cs.hasFilter()) { 076 x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Filters", getContext().getLang())); 077 XhtmlNode tbl = x.table("grid"); 078 XhtmlNode tr = tbl.tr(); 079 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Code", getContext().getLang())); 080 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Description", getContext().getLang())); 081 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "operator", getContext().getLang())); 082 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Value", getContext().getLang())); 083 for (CodeSystemFilterComponent f : cs.getFilter()) { 084 tr = tbl.tr(); 085 tr.td().tx(f.getCode()); 086 tr.td().tx(f.getDescription()); 087 XhtmlNode td = tr.td(); 088 for (Enumeration<org.hl7.fhir.r5.model.Enumerations.FilterOperator> t : f.getOperator()) 089 td.tx(t.asStringValue()+" "); 090 tr.td().tx(f.getValue()); 091 } 092 } 093 } 094 095 private boolean generateProperties(XhtmlNode x, CodeSystem cs) { 096 if (cs.hasProperty()) { 097 boolean hasRendered = false; 098 boolean hasURI = false; 099 boolean hasDescription = false; 100 for (PropertyComponent p : cs.getProperty()) { 101 hasRendered = hasRendered || !p.getCode().equals(ToolingExtensions.getPresentation(p, p.getCodeElement())); 102 hasURI = hasURI || p.hasUri(); 103 hasDescription = hasDescription || p.hasDescription(); 104 } 105 106 x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Properties", getContext().getLang())); 107 x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "This code system defines the following properties for its concepts", getContext().getLang())); 108 XhtmlNode tbl = x.table("grid"); 109 XhtmlNode tr = tbl.tr(); 110 if (hasRendered) { 111 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Name", getContext().getLang())); 112 } 113 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Code", getContext().getLang())); 114 if (hasURI) { 115 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "URI", getContext().getLang())); 116 } 117 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Type", getContext().getLang())); 118 if (hasDescription) { 119 tr.td().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Description", getContext().getLang())); 120 } 121 for (PropertyComponent p : cs.getProperty()) { 122 tr = tbl.tr(); 123 if (hasRendered) { 124 tr.td().tx(ToolingExtensions.getPresentation(p, p.getCodeElement())); 125 } 126 tr.td().tx(p.getCode()); 127 if (hasURI) { 128 tr.td().tx(p.getUri()); 129 } 130 tr.td().tx(p.hasType() ? p.getType().toCode() : ""); 131 if (hasDescription) { 132 tr.td().tx(p.getDescription()); 133 } 134 } 135 return true; 136 } else { 137 return false; 138 } 139 } 140 141 private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps, boolean props) throws FHIRFormatError, DefinitionException, IOException { 142 if (props) { 143 x.para().b().tx(getContext().getWorker().translator().translate("xhtml-gen-cs", "Concepts", getContext().getLang())); 144 } 145 XhtmlNode p = x.para(); 146 p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), "This code system ")); 147 p.code().tx(cs.getUrl()); 148 if (cs.getContent() == CodeSystemContentMode.COMPLETE) 149 p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines the following codes")+":"); 150 else if (cs.getContent() == CodeSystemContentMode.EXAMPLE) 151 p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines some example codes")+":"); 152 else if (cs.getContent() == CodeSystemContentMode.FRAGMENT ) 153 p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines many codes, of which the following are a subset")+":"); 154 else if (cs.getContent() == CodeSystemContentMode.NOTPRESENT ) { 155 p.tx(getContext().getWorker().translator().translateAndFormat("xhtml-gen-cs", getContext().getLang(), " defines many codes, but they are not represented here")); 156 return false; 157 } 158 XhtmlNode t = x.table( "codes"); 159 boolean definitions = false; 160 boolean commentS = false; 161 boolean deprecated = false; 162 boolean display = false; 163 boolean hierarchy = false; 164 boolean version = false; 165 boolean ignoreStatus = false; 166 boolean isSupplement = cs.getContent() == CodeSystemContentMode.SUPPLEMENT; 167 List<PropertyComponent> properties = new ArrayList<>(); 168 for (PropertyComponent cp : cs.getProperty()) { 169 if (showPropertyInTable(cp)) { 170 boolean exists = false; 171 for (ConceptDefinitionComponent c : cs.getConcept()) { 172 exists = exists || conceptsHaveProperty(c, cp); 173 } 174 if (exists) { 175 properties.add(cp); 176 if ("status".equals(cp.getCode())) { 177 ignoreStatus = true; 178 } 179 } 180 } 181 } 182 for (ConceptDefinitionComponent c : cs.getConcept()) { 183 commentS = commentS || conceptsHaveComments(c); 184 deprecated = deprecated || conceptsHaveDeprecated(cs, c, ignoreStatus); 185 display = display || conceptsHaveDisplay(c); 186 version = version || conceptsHaveVersion(c); 187 hierarchy = hierarchy || c.hasConcept(); 188 definitions = definitions || conceptsHaveDefinition(c); 189 } 190 CodeSystemNavigator csNav = new CodeSystemNavigator(cs); 191 hierarchy = hierarchy || csNav.isRestructure(); 192 193 List<String> langs = new ArrayList<>(); 194 addCopyColumn(addMapHeaders(addTableHeaderRowStandard(t, hierarchy, display, definitions, commentS, version, deprecated, properties, null, null, false), maps)); 195 for (ConceptDefinitionComponent c : csNav.getConcepts(null)) { 196 hasExtensions = addDefineRowToTable(t, c, 0, hierarchy, display, definitions, commentS, version, deprecated, maps, cs.getUrl(), cs, properties, csNav, langs, isSupplement) || hasExtensions; 197 } 198 if (langs.size() > 0) { 199 Collections.sort(langs); 200 x.para().b().tx("Additional Language Displays"); 201 t = x.table( "codes"); 202 XhtmlNode tr = t.tr(); 203 tr.td().b().tx("Code"); 204 for (String lang : langs) 205 tr.td().b().addText(describeLang(lang)); 206 for (ConceptDefinitionComponent c : cs.getConcept()) { 207 addLanguageRow(c, t, langs); 208 } 209 } 210 return hasExtensions; 211 } 212 213 private void addCopyColumn(XhtmlNode tr) { 214 if (context.isCopyButton()) { 215 tr.td().b().tx("Copy"); 216 } 217 218 } 219 220 private boolean conceptsHaveDefinition(ConceptDefinitionComponent c) { 221 if (c.hasDefinition()) { 222 return true; 223 } 224 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 225 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) { 226 return true; 227 } 228 } 229 for (ConceptDefinitionComponent g : c.getConcept()) { 230 if (conceptsHaveDefinition(g)) { 231 return true; 232 } 233 } 234 return false; 235 } 236 237 private boolean conceptsHaveProperty(ConceptDefinitionComponent c, PropertyComponent cp) { 238 if (CodeSystemUtilities.hasProperty(c, cp.getCode())) 239 return true; 240 for (ConceptDefinitionComponent g : c.getConcept()) 241 if (conceptsHaveProperty(g, cp)) 242 return true; 243 return false; 244 245 } 246 247 private boolean showPropertyInTable(PropertyComponent cp) { 248 if (cp.hasCode()) { 249 if (cp.hasExtension(ToolingExtensions.EXT_RENDERED_VALUE)) { 250 return true; 251 } 252 if (cp.getCodeElement().hasExtension(ToolingExtensions.EXT_RENDERED_VALUE)) { 253 return true; 254 } 255 String uri = cp.getUri(); 256 if (Utilities.noString(uri)){ 257 return true; // do we always want to render properties in this case? Not sure... 258 } 259 String code = null; 260 if (uri.contains("#")) { 261 code = uri.substring(uri.indexOf("#")+1); 262 uri = uri.substring(0, uri.indexOf("#")); 263 } 264 if (Utilities.existsInList(uri, "http://hl7.org/fhir/concept-properties") || context.getCodeSystemPropList().contains(uri)) { 265 return true; 266 }; 267 CodeSystem cs = getContext().getWorker().fetchCodeSystem(uri); 268 if (cs == null) { 269 return false; 270 } 271 return code == null ? false : CodeSystemUtilities.hasCode(cs, code); 272 } 273 return false; 274 } 275 276 277 private int countConcepts(List<ConceptDefinitionComponent> list) { 278 int count = list.size(); 279 for (ConceptDefinitionComponent c : list) 280 if (c.hasConcept()) 281 count = count + countConcepts(c.getConcept()); 282 return count; 283 } 284 285 private boolean conceptsHaveComments(ConceptDefinitionComponent c) { 286 if (ToolingExtensions.hasCSComment(c)) 287 return true; 288 for (ConceptDefinitionComponent g : c.getConcept()) 289 if (conceptsHaveComments(g)) 290 return true; 291 return false; 292 } 293 294 private boolean conceptsHaveDisplay(ConceptDefinitionComponent c) { 295 if (c.hasDisplay() && !c.getDisplay().equals(c.getCode())) 296 return true; 297 for (ConceptDefinitionComponent g : c.getConcept()) 298 if (conceptsHaveDisplay(g)) 299 return true; 300 return false; 301 } 302 303 private boolean conceptsHaveVersion(ConceptDefinitionComponent c) { 304 if (c.hasUserData("cs.version.notes")) 305 return true; 306 for (ConceptDefinitionComponent g : c.getConcept()) 307 if (conceptsHaveVersion(g)) 308 return true; 309 return false; 310 } 311 312 private boolean conceptsHaveDeprecated(CodeSystem cs, ConceptDefinitionComponent c, boolean ignoreStatus) { 313 if (CodeSystemUtilities.isDeprecated(cs, c, ignoreStatus)) 314 return true; 315 for (ConceptDefinitionComponent g : c.getConcept()) 316 if (conceptsHaveDeprecated(cs, g, ignoreStatus)) 317 return true; 318 return false; 319 } 320 321 322 323 private boolean addDefineRowToTable(XhtmlNode t, ConceptDefinitionComponent c, int level, boolean hasHierarchy, boolean hasDisplay, boolean hasDefinitions, boolean comment, boolean version, boolean deprecated, List<UsedConceptMap> maps, String system, CodeSystem cs, List<PropertyComponent> properties, CodeSystemNavigator csNav, List<String> langs, boolean isSupplement) throws FHIRFormatError, DefinitionException, IOException { 324 boolean hasExtensions = false; 325 XhtmlNode tr = t.tr(); 326 boolean notCurrent = CodeSystemUtilities.isNotCurrent(cs, c); 327 if (notCurrent) { 328 tr.setAttribute("style", "background-color: #ffeeee"); 329 } 330 331 XhtmlNode td = tr.td(); 332 if (hasHierarchy) { 333 td.addText(Integer.toString(level+1)); 334 td = tr.td(); 335 String s = Utilities.padLeft("", '\u00A0', level*2); 336 td.addText(s); 337 } 338 String link = isSupplement ? getLinkForCode(cs.getSupplements(), null, c.getCode()) : null; 339 if (link != null) { 340 td.ah(link).attribute("style", "white-space:nowrap").addText(c.getCode()); 341 } else { 342 td.attribute("style", "white-space:nowrap").addText(c.getCode()); 343 } 344 XhtmlNode a; 345 if (c.hasCodeElement()) { 346 td.an(cs.getId()+"-" + Utilities.nmtokenize(c.getCode())); 347 } 348 349 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 350 if (cd.hasLanguage() && !langs.contains(cd.getLanguage()) && (!cs.hasLanguage() || !cs.getLanguage().equals(cd.getLanguage()))) { 351 langs.add(cd.getLanguage()); 352 } 353 354 } 355 356 if (hasDisplay) { 357 td = tr.td(); 358 renderDisplayName(c, cs, td); 359 } 360 if (hasDefinitions) { 361 td = tr.td(); 362 if (c != null && 363 c.hasDefinitionElement()) { 364 if (getContext().getLang() == null) { 365 if (hasMarkdownInDefinitions(cs)) 366 addMarkdown(td, c.getDefinition()); 367 else 368 td.addText(c.getDefinition()); 369 } else if (getContext().getLang().equals("*")) { 370 boolean sl = false; 371 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) 372 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) 373 sl = true; 374 td.addText((sl ? cs.getLanguage("en")+": " : "")+c.getDefinition()); 375 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 376 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) { 377 td.br(); 378 td.addText(cd.getLanguage()+": "+cd.getValue()); 379 } 380 } 381 } else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) { 382 td.addText(c.getDefinition()); 383 } else { 384 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 385 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) { 386 td.addText(cd.getValue()); 387 } 388 } 389 } 390 } 391 } 392 if (deprecated) { 393 td = tr.td(); 394 Boolean b = CodeSystemUtilities.isDeprecated(cs, c, false); 395 if (b != null && b) { 396 smartAddText(td, getContext().getWorker().translator().translate("xhtml-gen-cs", "Deprecated", getContext().getLang())); 397 hasExtensions = true; 398 if (ToolingExtensions.hasExtension(c, ToolingExtensions.EXT_REPLACED_BY)) { 399 Coding cc = (Coding) ToolingExtensions.getExtension(c, ToolingExtensions.EXT_REPLACED_BY).getValue(); 400 td.tx(" (replaced by "); 401 String url = getCodingReference(cc, system); 402 if (url != null) { 403 td.ah(url).addText(cc.getCode()); 404 td.tx(": "+cc.getDisplay()+")"); 405 } else 406 td.addText(cc.getCode()+" '"+cc.getDisplay()+"' in "+cc.getSystem()+")"); 407 } else { 408 Extension ext = c.getExtensionByUrl(ToolingExtensions.EXT_STANDARDS_STATUS); 409 if (ext != null) { 410 ext = ext.getValue().getExtensionByUrl(ToolingExtensions.EXT_STANDARDS_STATUS_REASON); 411 if (ext != null) { 412 addMarkdown(td, ext.getValue().primitiveValue()); 413 } 414 } 415 } 416 } 417 } 418 if (comment) { 419 td = tr.td(); 420 Extension ext = c.getExtensionByUrl(ToolingExtensions.EXT_CS_COMMENT); 421 if (ext != null) { 422 hasExtensions = true; 423 String bc = ext.hasValue() ? ext.getValue().primitiveValue() : null; 424 Map<String, String> translations = ToolingExtensions.getLanguageTranslations(ext.getValue()); 425 426 if (getContext().getLang() == null) { 427 if (bc != null) 428 td.addText(bc); 429 } else if (getContext().getLang().equals("*")) { 430 boolean sl = false; 431 for (String l : translations.keySet()) 432 if (bc == null || !bc.equalsIgnoreCase(translations.get(l))) 433 sl = true; 434 if (bc != null) { 435 td.addText((sl ? cs.getLanguage("en")+": " : "")+bc); 436 } 437 for (String l : translations.keySet()) { 438 if (bc == null || !bc.equalsIgnoreCase(translations.get(l))) { 439 if (!td.getChildNodes().isEmpty()) 440 td.br(); 441 td.addText(l+": "+translations.get(l)); 442 } 443 } 444 } else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) { 445 if (bc != null) 446 td.addText(bc); 447 } else { 448 if (bc != null) 449 translations.put(cs.getLanguage("en"), bc); 450 for (String l : translations.keySet()) { 451 if (l.equals(getContext().getLang())) { 452 td.addText(translations.get(l)); 453 } 454 } 455 } 456 } 457 } 458 if (version) { 459 td = tr.td(); 460 if (c.hasUserData("cs.version.notes")) 461 td.addText(c.getUserString("cs.version.notes")); 462 } 463 if (properties != null) { 464 for (PropertyComponent pc : properties) { 465 td = tr.td(); 466 boolean first = true; 467 List<ConceptPropertyComponent> pcvl = CodeSystemUtilities.getPropertyValues(c, pc.getCode()); 468 for (ConceptPropertyComponent pcv : pcvl) { 469 if (pcv.hasValue()) { 470 if (first) first = false; else td.addText(", "); 471 if (pcv.hasValueCoding()) { 472 td.addText(pcv.getValueCoding().getCode()); 473 } else if (pcv.hasValueStringType() && Utilities.isAbsoluteUrlLinkable(pcv.getValue().primitiveValue())) { 474 td.ah(pcv.getValue().primitiveValue()).tx(pcv.getValue().primitiveValue()); 475 } else { 476 td.addText(pcv.getValue().primitiveValue()); 477 } 478 } 479 } 480 } 481 } 482 483 for (UsedConceptMap m : maps) { 484 td = tr.td(); 485 List<TargetElementComponentWrapper> mappings = findMappingsForCode(c.getCode(), m.getMap()); 486 boolean first = true; 487 for (TargetElementComponentWrapper mapping : mappings) { 488 if (!first) 489 td.br(); 490 first = false; 491 XhtmlNode span = td.span(null, mapping.comp.hasRelationship() ? mapping.comp.getRelationship().toCode() : ""); 492 span.addText(getCharForRelationship(mapping.comp)); 493 a = td.ah(getContext().getLink(KnownLinkType.SPEC)+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode())); 494 a.addText(mapping.comp.getCode()); 495 if (!Utilities.noString(mapping.comp.getComment())) 496 td.i().tx("("+mapping.comp.getComment()+")"); 497 } 498 } 499 List<ConceptDefinitionComponent> ocl = csNav.getOtherChildren(c); 500 for (ConceptDefinitionComponent cc : csNav.getConcepts(c)) { 501 hasExtensions = addDefineRowToTable(t, cc, level+1, hasHierarchy, hasDisplay, hasDefinitions, comment, version, deprecated, maps, system, cs, properties, csNav, langs, isSupplement) || hasExtensions; 502 } 503 for (ConceptDefinitionComponent cc : ocl) { 504 tr = t.tr(); 505 td = tr.td(); 506 td.addText(Integer.toString(level+2)); 507 td = tr.td(); 508 String s = Utilities.padLeft("", '\u00A0', (level+1)*2); 509 td.addText(s); 510 td.attribute("style", "white-space:nowrap"); 511 a = td.ah("#"+cs.getId()+"-" + Utilities.nmtokenize(cc.getCode())); 512 a.addText(cc.getCode()); 513 if (hasDisplay) { 514 td = tr.td(); 515 renderDisplayName(cc, cs, td); 516 } 517 int w = 1 + (deprecated ? 1 : 0) + (comment ? 1 : 0) + (version ? 1 : 0) + maps.size(); 518 if (properties != null) { 519 w = w + properties.size(); 520 } 521 td = tr.td().colspan(Integer.toString(w)); 522 } 523 if (context.isCopyButton()) { 524 td = tr.td(); 525 clipboard(td, "icon_clipboard_x.png", "XML", "<system value=\""+Utilities.escapeXml(cs.getUrl())+"\">\n"+(cs.getVersionNeeded() ? "<version value=\""+Utilities.escapeXml(cs.getVersion())+"\">\n" : "")+"<code value=\""+Utilities.escapeXml(c.getCode())+"\">\n<display value=\""+Utilities.escapeXml(c.getDisplay())+"\">\n"); 526 td.nbsp(); 527 clipboard(td, "icon_clipboard_j.png", "JSON", "\"system\" : \""+Utilities.escapeXml(cs.getUrl())+"\",\n"+(cs.getVersionNeeded() ? "\"version\" : \""+Utilities.escapeXml(cs.getVersion())+"\",\n" : "")+"\"code\" : \""+Utilities.escapeXml(c.getCode())+"\",\n\"display\" : \""+Utilities.escapeXml(c.getDisplay())+"\"\n"); 528 } 529 return hasExtensions; 530 } 531 532 private boolean hasMarkdownInDefinitions(CodeSystem cs) { 533 return ToolingExtensions.readBoolExtension(cs, "http://hl7.org/fhir/StructureDefinition/codesystem-use-markdown"); 534 } 535 536 537 public void renderDisplayName(ConceptDefinitionComponent c, CodeSystem cs, XhtmlNode td) { 538 if (c.hasDisplayElement()) { 539 if (getContext().getLang() == null) { 540 td.addText(c.getDisplay()); 541 } else if (getContext().getLang().equals("*")) { 542 boolean sl = false; 543 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) 544 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue())) 545 sl = true; 546 td.addText((sl ? cs.getLanguage("en")+": " : "")+c.getDisplay()); 547 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 548 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue())) { 549 td.br(); 550 td.addText(cd.getLanguage()+": "+cd.getValue()); 551 } 552 } 553 } else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) { 554 td.addText(c.getDisplay()); 555 } else { 556 for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) { 557 if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) { 558 td.addText(cd.getValue()); 559 } 560 } 561 } 562 } 563 } 564 565 private String getCodingReference(Coding cc, String system) { 566 if (cc.getSystem().equals(system)) 567 return "#"+cc.getCode(); 568 if (cc.getSystem().equals("http://snomed.info/sct")) 569 return "http://snomed.info/sct/"+cc.getCode(); 570 if (cc.getSystem().equals("http://loinc.org")) 571 return LoincLinker.getLinkForCode(cc.getCode()); 572 return null; 573 } 574 575 576 private void addLanguageRow(ConceptDefinitionComponent c, XhtmlNode t, List<String> langs) { 577 XhtmlNode tr = t.tr(); 578 tr.td().addText(c.getCode()); 579 for (String lang : langs) { 580 ConceptDefinitionDesignationComponent d = null; 581 for (ConceptDefinitionDesignationComponent designation : c.getDesignation()) { 582 if (designation.hasLanguage()) { 583 if (lang.equals(designation.getLanguage())) 584 d = designation; 585 } 586 } 587 tr.td().addText(d == null ? "" : d.getValue()); 588 } 589 } 590 591}