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