001package org.hl7.fhir.r5.renderers; 002 003import java.io.IOException; 004import java.io.UnsupportedEncodingException; 005import java.util.Collection; 006import java.util.HashMap; 007import java.util.HashSet; 008import java.util.List; 009import java.util.Map; 010import java.util.Set; 011 012import org.hl7.fhir.exceptions.DefinitionException; 013import org.hl7.fhir.exceptions.FHIRException; 014import org.hl7.fhir.exceptions.FHIRFormatError; 015import org.hl7.fhir.r5.model.CodeSystem; 016import org.hl7.fhir.r5.model.ConceptMap; 017import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent; 018import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent; 019import org.hl7.fhir.r5.model.DataType; 020import org.hl7.fhir.r5.model.Enumeration; 021import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship; 022import org.hl7.fhir.r5.model.IdType; 023import org.hl7.fhir.r5.model.OperationDefinition; 024import org.hl7.fhir.r5.model.Resource; 025import org.hl7.fhir.r5.model.StringType; 026import org.hl7.fhir.r5.model.StructureDefinition; 027import org.hl7.fhir.r5.model.StructureMap; 028import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupComponent; 029import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupInputComponent; 030import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleComponent; 031import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleDependentComponent; 032import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleSourceComponent; 033import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleTargetComponent; 034import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleTargetParameterComponent; 035import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent; 036import org.hl7.fhir.r5.model.StructureMap.StructureMapTargetListMode; 037import org.hl7.fhir.r5.model.StructureMap.StructureMapTransform; 038import org.hl7.fhir.r5.model.UriType; 039import org.hl7.fhir.r5.renderers.utils.RenderingContext; 040import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; 041import org.hl7.fhir.r5.utils.EOperationOutcome; 042import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; 043import org.hl7.fhir.utilities.Utilities; 044import org.hl7.fhir.utilities.VersionUtilities; 045import org.hl7.fhir.utilities.xhtml.XhtmlNode; 046 047public class StructureMapRenderer extends TerminologyRenderer { 048 049 public StructureMapRenderer(RenderingContext context) { 050 super(context); 051 } 052 053 @Override 054 public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { 055 if (r.isDirect()) { 056 renderResourceTechDetails(r, x); 057 genSummaryTable(status, x, (StructureMap) r.getBase()); 058 renderMap(status, x.pre("fml"), (StructureMap) r.getBase()); 059 } else { 060 // the intention is to change this in the future 061 x.para().tx("StructureMapRenderer only renders native resources directly"); 062 } 063 } 064 065 066 @Override 067 public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { 068 return canonicalTitle(r); 069 } 070 071 072 073 private static final String COLOR_COMMENT = "green"; 074 private static final String COLOR_METADATA = "#cc00cc"; 075 private static final String COLOR_CONST = "blue"; 076 private static final String COLOR_VARIABLE = "maroon"; 077 private static final String COLOR_SYNTAX = "navy"; 078 private static final boolean MULTIPLE_TARGETS_ONELINE = true; 079 private static final String COLOR_SPECIAL = "#b36b00"; 080 081 public void renderMap(RenderingStatus status, XhtmlNode x, StructureMap map) { 082 083 x.tx("\r\n"); 084 if (VersionUtilities.isR5Plus(context.getContext().getVersion())) { 085 renderMetadata(x, "url", map.getUrlElement()); 086 renderMetadata(x, "name", map.getNameElement()); 087 renderMetadata(x, "title", map.getTitleElement()); 088 renderMetadata(x, "status", map.getStatusElement()); 089 x.tx("\r\n"); 090 } else { 091 x.b().tx("map"); 092 x.color(COLOR_SYNTAX).tx(" \""); 093 x.tx(map.getUrl()); 094 x.color(COLOR_SYNTAX).tx("\" = \""); 095 x.tx(Utilities.escapeJson(map.getName())); 096 x.color(COLOR_SYNTAX).tx("\"\r\n\r\n"); 097 if (map.getDescription() != null) { 098 renderMultilineDoco(x, map.getDescription(), 0, null); 099 x.tx("\r\n"); 100 } 101 } 102 renderConceptMaps(x, map); 103 renderUses(x, map); 104 renderImports(x, map); 105 for (StructureMapGroupComponent g : map.getGroup()) 106 renderGroup(x, g); 107 } 108 109 private void renderMetadata(XhtmlNode x, String name, DataType value) { 110 if (!value.isEmpty()) { 111 renderMetadata(x, name, value, null); 112 } 113 } 114 115 private void renderMetadata(XhtmlNode x, String name, DataType value, String def) { 116 String v = value.primitiveValue(); 117 if (def == null || !def.equals(v)) { 118 XhtmlNode c = x.color(COLOR_METADATA); 119 c.tx("/// "); 120 c.b().tx(name); 121 c.tx(" = "); 122 if (Utilities.existsInList(v, "true", "false") || Utilities.isDecimal(v, true)) { 123 x.color(COLOR_CONST).tx(v); 124 } else { 125 x.color(COLOR_CONST).tx("'"+v+"'"); 126 } 127 x.tx("\r\n"); 128 } 129 } 130 131 private void renderConceptMaps(XhtmlNode x,StructureMap map) { 132 for (Resource r : map.getContained()) { 133 if (r instanceof ConceptMap) { 134 produceConceptMap(x, (ConceptMap) r); 135 } 136 } 137 } 138 139 private void produceConceptMap(XhtmlNode x,ConceptMap cm) { 140 if (cm.hasFormatCommentPre()) { 141 renderMultilineDoco(x, cm.getFormatCommentsPre(), 0, null); 142 } 143 x.b().tx("conceptmap"); 144 x.color(COLOR_SYNTAX).tx(" \""); 145 x.tx(cm.getId()); 146 x.color(COLOR_SYNTAX).tx("\" {\r\n"); 147 Map<String, String> prefixesSrc = new HashMap<String, String>(); 148 Map<String, String> prefixesTgt = new HashMap<String, String>(); 149 char prefix = 's'; 150 for (ConceptMapGroupComponent cg : cm.getGroup()) { 151 if (!prefixesSrc.containsKey(cg.getSource())) { 152 prefixesSrc.put(cg.getSource(), String.valueOf(prefix)); 153 x.b().tx(" prefix "); 154 x.tx(""+prefix); 155 x.color(COLOR_SYNTAX).tx(" = \""); 156 CodeSystem cs = context.getContext().fetchResource(CodeSystem.class, cg.getSource()); 157 if (cs != null && cs.hasWebPath()) { 158 x.ah(context.prefixLocalHref(cs.getWebPath()), cs.present()).tx(cg.getSource()); 159 } else { 160 x.tx(cg.getSource()); 161 } 162 x.color(COLOR_SYNTAX).tx("\"\r\n"); 163 prefix++; 164 } 165 if (!prefixesTgt.containsKey(cg.getTarget())) { 166 prefixesTgt.put(cg.getTarget(), String.valueOf(prefix)); 167 x.b().tx(" prefix "); 168 x.tx(""+prefix); 169 x.color(COLOR_SYNTAX).tx(" = \""); 170 CodeSystem cs = context.getContext().fetchResource(CodeSystem.class, cg.getTarget()); 171 if (cs != null && cs.hasWebPath()) { 172 x.ah(context.prefixLocalHref(cs.getWebPath()), cs.present()).tx(cg.getTarget()); 173 } else { 174 x.tx(""+cg.getTarget()); 175 } 176 x.color(COLOR_SYNTAX).tx("\"\r\n"); 177 prefix++; 178 } 179 } 180 x.tx("\r\n"); 181 for (ConceptMapGroupComponent cg : cm.getGroup()) { 182 if (cg.hasUnmapped()) { 183 x.b().tx(" unmapped for "); 184 x.tx(prefixesSrc.get(cg.getSource())); 185 x.color(COLOR_SYNTAX).tx(" = "); 186 x.tx(cg.getUnmapped().getMode().toCode()); 187 x.tx("\r\n"); 188 } 189 } 190 191 for (ConceptMapGroupComponent cg : cm.getGroup()) { 192 if (cg.hasFormatCommentPre()) { 193 renderMultilineDoco(x, cg.getFormatCommentsPre(), 2, prefixesSrc.values()); 194 } 195 for (SourceElementComponent ce : cg.getElement()) { 196 if (ce.hasFormatCommentPre()) { 197 renderMultilineDoco(x, ce.getFormatCommentsPre(), 2, prefixesSrc.values()); 198 } 199 200 x.tx(" "); 201 x.tx(prefixesSrc.get(cg.getSource())); 202 x.color(COLOR_SYNTAX).tx(":"); 203 if (Utilities.isToken(ce.getCode())) { 204 x.tx(ce.getCode()); 205 } else { 206 x.tx("\""); 207 x.tx(ce.getCode()); 208 x.tx("\""); 209 } 210 x.tx(" "); 211 x.b().tx(getChar(ce.getTargetFirstRep().getRelationship())); 212 x.tx(" "); 213 x.tx(prefixesTgt.get(cg.getTarget())); 214 x.color(COLOR_SYNTAX).tx(":"); 215 if (Utilities.isToken(ce.getTargetFirstRep().getCode())) { 216 x.tx(ce.getTargetFirstRep().getCode()); 217 } else { 218 x.color(COLOR_SYNTAX).tx("\""); 219 x.tx(ce.getTargetFirstRep().getCode()); 220 x.color(COLOR_SYNTAX).tx("\""); 221 } 222 x.tx("\r\n"); 223 if (ce.hasFormatCommentPost()) { 224 renderMultilineDoco(x, ce.getFormatCommentsPost(), 2, prefixesSrc.values()); 225 } 226 } 227 if (cg.hasFormatCommentPost()) { 228 renderMultilineDoco(x, cg.getFormatCommentsPost(), 2, prefixesSrc.values()); 229 } 230 } 231 if (cm.hasFormatCommentPost()) { 232 renderMultilineDoco(x, cm.getFormatCommentsPost(), 2, prefixesSrc.values()); 233 } 234 x.color(COLOR_SYNTAX).tx("}\r\n\r\n"); 235 } 236 237 private String getChar(ConceptMapRelationship relationship) { 238 switch (relationship) { 239 case RELATEDTO: 240 return "-"; 241 case EQUIVALENT: 242 return "=="; 243 case NOTRELATEDTO: 244 return "!="; 245 case SOURCEISNARROWERTHANTARGET: 246 return "<="; 247 case SOURCEISBROADERTHANTARGET: 248 return ">="; 249 default: 250 return "??"; 251 } 252 } 253 254 private void renderUses(XhtmlNode x,StructureMap map) { 255 for (StructureMapStructureComponent s : map.getStructure()) { 256 x.b().tx("uses"); 257 x.color(COLOR_SYNTAX).tx(" \""); 258 StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, s.getUrl()); 259 if (sd != null && sd.hasWebPath()) { 260 x.ah(context.prefixLocalHref(sd.getWebPath()), sd.present()).tx(s.getUrl()); 261 } else { 262 x.tx(s.getUrl()); 263 } 264 x.color(COLOR_SYNTAX).tx("\" "); 265 if (s.hasAlias()) { 266 x.b().tx("alias "); 267 x.tx(s.getAlias()); 268 x.tx(" "); 269 } 270 x.b().tx("as "); 271 x.b().tx(s.getMode().toCode()); 272 renderDoco(x, s.getDocumentation(), false, null); 273 x.tx("\r\n"); 274 } 275 if (map.hasStructure()) 276 x.tx("\r\n"); 277 } 278 279 private void renderImports(XhtmlNode x,StructureMap map) { 280 for (UriType s : map.getImport()) { 281 x.b().tx("imports"); 282 x.color(COLOR_SYNTAX).tx(" \""); 283 StructureMap m = context.getContext().fetchResource(StructureMap.class, s.getValue()); 284 if (m != null) { 285 x.ah(context.prefixLocalHref(m.getWebPath()), m.present()).tx(s.getValue()); 286 } else { 287 x.tx(s.getValue()); 288 } 289 x.color(COLOR_SYNTAX).tx("\"\r\n"); 290 } 291 if (map.hasImport()) 292 x.tx("\r\n"); 293 } 294 295 private void renderGroup(XhtmlNode x,StructureMapGroupComponent g) { 296 Collection<String> tokens = scanVariables(g, null); 297 if (g.hasFormatCommentPre()) { 298 renderMultilineDoco(x, g.getFormatCommentsPre(), 0, tokens); 299 } 300 if (g.hasDocumentation()) { 301 renderMultilineDoco(x, g.getDocumentation(), 0, tokens); 302 } 303 x.b().tx("group "); 304 x.tx(g.getName()); 305 x.color(COLOR_SYNTAX).tx("("); 306 boolean first = true; 307 for (StructureMapGroupInputComponent gi : g.getInput()) { 308 if (first) 309 first = false; 310 else 311 x.tx(", "); 312 x.b().tx(gi.getMode().toCode()); 313 x.tx(" "); 314 x.color(COLOR_VARIABLE).tx(gi.getName()); 315 if (gi.hasType()) { 316 x.color(COLOR_SYNTAX).tx(" : "); 317 x.tx(gi.getType()); 318 } 319 } 320 x.color(COLOR_SYNTAX).tx(")"); 321 if (g.hasExtends()) { 322 x.b().tx(" extends "); 323 String ref = resolveRuleReference(g.getExtendsElement()); 324 if (ref != null) { 325 x.ah(context.prefixLocalHref(ref)).tx(g.getExtends()); 326 } else { 327 x.tx(g.getExtends()); 328 } 329 } 330 331 if (g.hasTypeMode()) { 332 switch (g.getTypeMode()) { 333 case TYPES: 334 x.b().tx(" <<types>>"); 335 break; 336 case TYPEANDTYPES: 337 x.b().tx(" <<type+>>"); 338 break; 339 default: // NONE, NULL 340 } 341 } 342 x.color(COLOR_SYNTAX).tx(" {\r\n"); 343 for (StructureMapGroupRuleComponent r : g.getRule()) { 344 renderRule(x, g, r, 2); 345 } 346 if (g.hasFormatCommentPost()) { 347 renderMultilineDoco(x, g.getFormatCommentsPost(), 0, scanVariables(g, null)); 348 } 349 x.color(COLOR_SYNTAX).tx("}\r\n\r\n"); 350 } 351 352 private String resolveRuleReference(IdType idType) { 353 return null; 354 } 355 356 private void renderRule(XhtmlNode x, StructureMapGroupComponent g, StructureMapGroupRuleComponent r, int indent) { 357 Collection<String> tokens = scanVariables(g, r); 358 if (r.hasFormatCommentPre()) { 359 renderMultilineDoco(x, r.getFormatCommentsPre(), indent, tokens); 360 } 361 for (int i = 0; i < indent; i++) 362 x.tx(" "); 363 boolean canBeAbbreviated = checkisSimple(r); 364 { 365 boolean first = true; 366 for (StructureMapGroupRuleSourceComponent rs : r.getSource()) { 367 if (first) 368 first = false; 369 else 370 x.color(COLOR_SYNTAX).tx(", "); 371 renderSource(x, rs, canBeAbbreviated); 372 } 373 } 374 if (r.getTarget().size() > 1) { 375 x.color(COLOR_SYNTAX).b().tx(" -> "); 376 boolean first = true; 377 for (StructureMapGroupRuleTargetComponent rt : r.getTarget()) { 378 if (first) 379 first = false; 380 else 381 x.color(COLOR_SYNTAX).tx(", "); 382 if (MULTIPLE_TARGETS_ONELINE) 383 x.tx(" "); 384 else { 385 x.tx("\r\n"); 386 for (int i = 0; i < indent + 4; i++) 387 x.tx(" "); 388 } 389 renderTarget(x, rt, false); 390 } 391 } else if (r.hasTarget()) { 392 x.color(COLOR_SYNTAX).b().tx(" -> "); 393 renderTarget(x, r.getTarget().get(0), canBeAbbreviated); 394 } 395 if (r.hasRule()) { 396 x.b().tx(" then"); 397 x.color(COLOR_SYNTAX).tx(" {\r\n"); 398 for (StructureMapGroupRuleComponent ir : r.getRule()) { 399 renderRule(x, g, ir, indent + 2); 400 } 401 for (int i = 0; i < indent; i++) 402 x.tx(" "); 403 x.color(COLOR_SYNTAX).tx("}"); 404 } else { 405 if (r.hasDependent() && !canBeAbbreviated) { 406 x.b().tx(" then "); 407 boolean first = true; 408 for (StructureMapGroupRuleDependentComponent rd : r.getDependent()) { 409 if (first) 410 first = false; 411 else 412 x.color(COLOR_SYNTAX).tx(", "); 413 String ref = resolveRuleReference(rd.getNameElement()); 414 if (ref != null) { 415 x.ah(context.prefixLocalHref(ref)).tx(rd.getName()); 416 } else { 417 x.tx(rd.getName()); 418 } 419 x.color(COLOR_SYNTAX).tx("("); 420 boolean ifirst = true; 421 for (StructureMapGroupRuleTargetParameterComponent rdp : rd.getParameter()) { 422 if (ifirst) 423 ifirst = false; 424 else 425 x.color(COLOR_SYNTAX).tx(", "); 426 renderTransformParam(x, rdp); 427 } 428 x.color(COLOR_SYNTAX).tx(")"); 429 } 430 } 431 } 432 if (r.hasName()) { 433 String n = ntail(r.getName()); 434 if (!n.startsWith("\"")) 435 n = "\"" + n + "\""; 436 if (!matchesName(n, r.getSource())) { 437 x.tx(" "); 438 x.i().tx(n); 439 } 440 } 441 x.color(COLOR_SYNTAX).tx(";"); 442 if (r.hasDocumentation()) { 443 renderDoco(x, r.getDocumentation(), false, null); 444 } 445 x.tx("\r\n"); 446 if (r.hasFormatCommentPost()) { 447 renderMultilineDoco(x, r.getFormatCommentsPost(), indent, tokens); 448 } 449 } 450 451 private Collection<String> scanVariables(StructureMapGroupComponent g, StructureMapGroupRuleComponent r) { 452 Set<String> res = new HashSet<>(); 453 for (StructureMapGroupInputComponent input : g.getInput()) { 454 res.add(input.getName()); 455 } 456 if (r != null) { 457 for (StructureMapGroupRuleSourceComponent src : r.getSource()) { 458 if (src.hasVariable()) { 459 res.add(src.getVariable()); 460 } 461 } 462 } 463 return res; 464 } 465 466 private boolean matchesName(String n, List<StructureMapGroupRuleSourceComponent> source) { 467 if (source.size() != 1) 468 return false; 469 if (!source.get(0).hasElement()) 470 return false; 471 String s = source.get(0).getElement(); 472 if (n.equals(s) || n.equals("\"" + s + "\"")) 473 return true; 474 if (source.get(0).hasType()) { 475 s = source.get(0).getElement() + Utilities.capitalize(source.get(0).getType()); 476 return n.equals(s) || n.equals("\"" + s + "\""); 477 } 478 return false; 479 } 480 481 private String ntail(String name) { 482 if (name == null) 483 return null; 484 if (name.startsWith("\"")) { 485 name = name.substring(1); 486 name = name.substring(0, name.length() - 1); 487 } 488 return "\"" + (name.contains(".") ? name.substring(name.lastIndexOf(".") + 1) : name) + "\""; 489 } 490 491 private boolean checkisSimple(StructureMapGroupRuleComponent r) { 492 return 493 (r.getSource().size() == 1 && r.getSourceFirstRep().hasElement() && r.getSourceFirstRep().hasVariable()) && 494 (r.getTarget().size() == 1 && r.getTargetFirstRep().hasVariable() && (r.getTargetFirstRep().getTransform() == null || r.getTargetFirstRep().getTransform() == StructureMapTransform.CREATE) && r.getTargetFirstRep().getParameter().size() == 0) && 495 (r.getDependent().size() == 0 || (r.getDependent().size() == 1 && StructureMapUtilities.DEF_GROUP_NAME.equals(r.getDependentFirstRep().getName()))) && (r.getRule().size() == 0); 496 } 497 498 private void renderSource(XhtmlNode x,StructureMapGroupRuleSourceComponent rs, boolean abbreviate) { 499 x.tx(rs.getContext()); 500 if (rs.getContext().equals("@search")) { 501 x.color(COLOR_SYNTAX).tx("("); 502 x.tx(rs.getElement()); 503 x.color(COLOR_SYNTAX).tx(")"); 504 } else if (rs.hasElement()) { 505 x.tx("."); 506 x.tx(rs.getElement()); 507 } 508 if (rs.hasType()) { 509 x.color(COLOR_SYNTAX).tx(" : "); 510 x.tx(rs.getType()); 511 if (rs.hasMin()) { 512 x.tx(" "); 513 x.tx(rs.getMin()); 514 x.color(COLOR_SYNTAX).tx(".."); 515 x.tx(rs.getMax()); 516 } 517 } 518 519 if (rs.hasListMode()) { 520 x.tx(" "); 521 x.tx(rs.getListMode().toCode()); 522 } 523 if (rs.hasDefaultValue()) { 524 x.b().tx(" default "); 525 x.tx("\"" + Utilities.escapeJson(rs.getDefaultValue()) + "\""); 526 } 527 if (!abbreviate && rs.hasVariable()) { 528 x.b().tx(" as "); 529 x.color(COLOR_VARIABLE).tx(rs.getVariable()); 530 } 531 if (rs.hasCondition()) { 532 x.b().tx(" where "); 533 x.tx(rs.getCondition()); 534 } 535 if (rs.hasCheck()) { 536 x.b().tx(" check "); 537 x.tx(rs.getCheck()); 538 } 539 if (rs.hasLogMessage()) { 540 x.b().tx(" log "); 541 x.tx(rs.getLogMessage()); 542 } 543 } 544 545 private void renderTarget(XhtmlNode x,StructureMapGroupRuleTargetComponent rt, boolean abbreviate) { 546 if (rt.hasContext()) { 547 x.tx(rt.getContext()); 548 if (rt.hasElement()) { 549 x.tx("."); 550 x.tx(rt.getElement()); 551 } 552 } 553 if (!abbreviate && rt.hasTransform()) { 554 if (rt.hasContext()) 555 x.tx(" = "); 556 if (rt.getTransform() == StructureMapTransform.COPY && rt.getParameter().size() == 1) { 557 renderTransformParam(x, rt.getParameter().get(0)); 558 } else if (rt.getTransform() == StructureMapTransform.EVALUATE && rt.getParameter().size() == 1) { 559 x.color(COLOR_SYNTAX).tx("("); 560 x.tx(((StringType) rt.getParameter().get(0).getValue()).asStringValue()); 561 x.color(COLOR_SYNTAX).tx(")"); 562 } else if (rt.getTransform() == StructureMapTransform.EVALUATE && rt.getParameter().size() == 2) { 563 x.tx(rt.getTransform().toCode()); 564 x.color(COLOR_SYNTAX).tx("("); 565 x.tx(((IdType) rt.getParameter().get(0).getValue()).asStringValue()); 566 x.color(COLOR_SYNTAX).tx(", "); 567 x.tx(((StringType) rt.getParameter().get(1).getValue()).asStringValue()); 568 x.color(COLOR_SYNTAX).tx(")"); 569 } else { 570 x.b().tx(rt.getTransform().toCode()); 571 x.color(COLOR_SYNTAX).tx("("); 572 boolean first = true; 573 for (StructureMapGroupRuleTargetParameterComponent rtp : rt.getParameter()) { 574 if (first) 575 first = false; 576 else 577 x.color(COLOR_SYNTAX).tx(", "); 578 renderTransformParam(x, rtp); 579 } 580 x.color(COLOR_SYNTAX).tx(")"); 581 } 582 } 583 if (!abbreviate && rt.hasVariable()) { 584 x.b().tx(" as "); 585 x.color(COLOR_VARIABLE).tx(rt.getVariable()); 586 } 587 for (Enumeration<StructureMapTargetListMode> lm : rt.getListMode()) { 588 x.tx(" "); 589 x.b().tx(lm.getValue().toCode()); 590 if (lm.getValue() == StructureMapTargetListMode.SHARE) { 591 x.tx(" "); 592 x.b().tx(rt.getListRuleId()); 593 } 594 } 595 } 596 597 598 private void renderTransformParam(XhtmlNode x,StructureMapGroupRuleTargetParameterComponent rtp) { 599 try { 600 if (rtp.hasValueBooleanType()) 601 x.color(COLOR_CONST).tx(rtp.getValueBooleanType().asStringValue()); 602 else if (rtp.hasValueDecimalType()) 603 x.color(COLOR_CONST).tx(rtp.getValueDecimalType().asStringValue()); 604 else if (rtp.hasValueIdType()) 605 x.color(COLOR_VARIABLE).tx(rtp.getValueIdType().asStringValue()); 606 else if (rtp.hasValueIntegerType()) 607 x.color(COLOR_CONST).tx(rtp.getValueIntegerType().asStringValue()); 608 else 609 x.color(COLOR_CONST).tx("'" + Utilities.escapeJava(rtp.getValueStringType().asStringValue()) + "'"); 610 } catch (FHIRException e) { 611 e.printStackTrace(); 612 x.tx("error!"); 613 } 614 } 615 616 private void renderDoco(XhtmlNode x,String doco, boolean startLine, Collection<String> tokens) { 617 if (Utilities.noString(doco)) 618 return; 619 if (!startLine) { 620 x.tx(" "); 621 } 622 boolean isClause = false; 623 String t = doco.trim().replace(" ", ""); 624 if (tokens != null) { 625 for (String s : tokens) { 626 if (t.startsWith(s+":") || t.startsWith(s+".") || t.startsWith(s+"->")) { 627 isClause = true; 628 break; 629 } 630 } 631 } 632 if (isClause) { 633 XhtmlNode s= x.color(COLOR_SPECIAL); 634 s.setAttribute("title", formatPhrase(RenderingContext.MAP_DEFAULT_COMMENT)); 635 s.tx("// "); 636 s.tx(doco.replace("\r\n", " ").replace("\r", " ").replace("\n", " ")); 637 } else { 638 x.color(COLOR_SYNTAX).tx("// "); 639 x.color(COLOR_COMMENT).tx(doco.replace("\r\n", " ").replace("\r", " ").replace("\n", " ")); 640 } 641 } 642 643 private void renderMultilineDoco(XhtmlNode x,String doco, int indent, Collection<String> tokens) { 644 if (Utilities.noString(doco)) 645 return; 646 String[] lines = doco.split("\\r?\\n"); 647 for (String line : lines) { 648 for (int i = 0; i < indent; i++) 649 x.tx(" "); 650 renderDoco(x, line, true, tokens); 651 x.tx("\r\n"); 652 } 653 } 654 655 private void renderMultilineDoco(XhtmlNode x, List<String> doco, int indent, Collection<String> tokens) { 656 for (String line : doco) { 657 for (int i = 0; i < indent; i++) 658 x.tx(" "); 659 renderDoco(x, line, true, tokens); 660 x.tx("\r\n"); 661 } 662 } 663 664 665 public void describe(XhtmlNode x, OperationDefinition opd) { 666 x.tx(display(opd)); 667 } 668 669 public String display(OperationDefinition opd) { 670 return opd.present(); 671 } 672 673 @Override 674 public String display(Resource r) throws UnsupportedEncodingException, IOException { 675 return ((StructureMap) r).present(); 676 } 677 678}