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