
001package org.hl7.fhir.r5.renderers.mappings; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import org.hl7.fhir.r5.fhirpath.ExpressionNode; 007import org.hl7.fhir.r5.fhirpath.FHIRPathEngine; 008import org.hl7.fhir.r5.fhirpath.TypeDetails; 009import org.hl7.fhir.r5.fhirpath.ExpressionNode.Function; 010import org.hl7.fhir.r5.fhirpath.ExpressionNode.Kind; 011import org.hl7.fhir.r5.fhirpath.ExpressionNode.Operation; 012import org.hl7.fhir.r5.model.Base; 013import org.hl7.fhir.r5.model.ElementDefinition; 014import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent; 015import org.hl7.fhir.r5.model.StructureDefinition; 016import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; 017import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.Column; 018import org.hl7.fhir.r5.renderers.utils.RenderingContext; 019import org.hl7.fhir.utilities.SourceLocation; 020import org.hl7.fhir.utilities.xhtml.XhtmlNode; 021 022public class StructureDefinitionMappingProvider extends ModelMappingProvider { 023 024 private StructureDefinition sd; 025 private StructureDefinitionMappingComponent map; 026 private FHIRPathEngine fpe; 027 028 public StructureDefinitionMappingProvider(RenderingContext context, StructureDefinition dest, boolean reverse, StructureDefinition sd, StructureDefinitionMappingComponent map, FHIRPathEngine fpe) { 029 super(context, dest, reverse); 030 this.sd = sd; 031 this.map = map; 032 this.fpe = fpe; 033 } 034 035 @Override 036 public Column makeColumn(String id) { 037 return new Column(id, map.getName(), dest == null ? "??" : dest.present(), null); 038 } 039 040 @Override 041 public void render(ElementDefinition element, XhtmlNode div) { 042 if (reverse) { 043 List<ElementDefinition> sources = new ArrayList<>(); 044 for (ElementDefinition ed : dest.getSnapshot().getElement()) { 045 ElementDefinitionMappingComponent m = null; 046 for (ElementDefinitionMappingComponent t : ed.getMapping()) { 047 if (t.hasIdentity() && t.getIdentity().equals(map.getIdentity())) { 048 m = t; 049 } 050 } 051 if (m != null) { 052 String[] maps = (m.getMap() == null ? "" : m.getMap()).split("\\,"); 053 for (String s : maps) { 054 String tgt = processMap(s); 055 if (tgt != null && tgt.equals(element.getId()) || tgt.equals(element.getPath())) { 056 sources.add(ed); 057 } 058 } 059 } 060 } 061 if (sources.size() == 1) { 062 renderElementLink(div, sources.get(0)); 063 } else { 064 XhtmlNode ul = div.ul(); 065 for (ElementDefinition ed : sources) { 066 renderElementLink(ul.li(), ed); 067 } 068 } 069 } else { 070 ElementDefinitionMappingComponent m = null; 071 for (ElementDefinitionMappingComponent t : element.getMapping()) { 072 if (t.hasIdentity() && t.getIdentity().equals(map.getIdentity())) { 073 m = t; 074 } 075 } 076 boolean complex = false; 077 if (m != null) { 078 String[] maps = (m.getMap() == null ? "" : m.getMap()).split("\\,"); 079 if (maps.length == 1) { 080 renderMap(div, maps[0]); 081 } else { 082 complex = true; 083 XhtmlNode ul = div.ul(); 084 for (String s : maps) { 085 renderMap(ul.li(), s); 086 } 087 } 088 if (m.hasComment()) { 089 if (!complex) { 090 div.br(); 091 } 092 div.i().tx(m.getComment()); 093 } 094 } 095 } 096 } 097 098 private String processMap(String s) { 099 if (s.contains(":")) { 100 String l = s.substring(0, s.indexOf(":")); 101 return l; 102 } else { 103 try { 104 ExpressionNode exp = fpe.parse(s); 105 stripFunctions(exp); 106 return exp.toString(); 107 } catch (Exception e) { 108 return null; 109 } 110 } 111 } 112 113 private void renderElementLink(XhtmlNode div, ElementDefinition ed) { 114 div.ah(ref()+"#"+ed.getId()).tx(ed.getPath()); 115 } 116 117 private void renderMap(XhtmlNode x, String s) { 118 // the approved syntax is id: fhirPath, or it's just rendered directly 119 if (s.contains(":")) { 120 String l = s.substring(0, s.indexOf(":")); 121 String r = s.substring(s.indexOf(":")+1); 122 if (dest != null && dest.getSnapshot().getElementById(l) != null) { 123 x.ah(ref()+"#"+l, l).tx(r); 124 } else { 125 x.tx(r); 126 } 127 } else { 128 try { 129 ExpressionNode exp = fpe.parse(s); 130 stripFunctions(exp); 131 String p = exp.toString(); 132 if (dest.getSnapshot().getElementById(p) != null) { 133 x.ah(ref()+"#"+p, p).tx(s); 134 } else { 135 x.tx(s); 136 } 137 } catch (Exception e) { 138 x.tx(s); 139 } 140 } 141 } 142 143 private void stripFunctions(ExpressionNode exp) { 144 while (exp.getInner() != null && exp.getInner().getKind() == Kind.Function) { 145 exp.setInner(exp.getInner().getInner()); 146 } 147 if (exp.getInner() != null) { 148 stripFunctions(exp.getInner()); 149 } 150 } 151}