001package org.hl7.fhir.r5.renderers.utils; 002 003import org.hl7.fhir.r5.model.Bundle; 004import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; 005import org.hl7.fhir.r5.model.DomainResource; 006import org.hl7.fhir.r5.model.Parameters; 007import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; 008import org.hl7.fhir.r5.model.Resource; 009import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; 010import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceReferenceKind; 011import org.w3c.dom.Element; 012 013public class Resolver { 014 015 016 public interface IReferenceResolver { 017 ResourceWithReference resolve(RenderingContext context, String url); 018 019 // returns null if contained resource is inlined 020 String urlForContained(RenderingContext context, String containingType, String containingId, String containedType, String containedId); 021 022 /** 023 * returns the correct literal URL for the specified logical uri 024 * @param context 025 * @param value 026 * @return 027 */ 028 String resolveUri(RenderingContext context, String uri); 029 } 030 031 public static class ResourceContext { 032 private ResourceContext container; 033 034 Resource resource; 035 org.hl7.fhir.r5.elementmodel.Element element; 036 037 public ResourceContext(ResourceContext container, Resource dr) { 038 super(); 039 this.container = container; 040 this.resource = dr; 041 } 042 043 public ResourceContext(ResourceContext container, org.hl7.fhir.r5.elementmodel.Element dr) { 044 super(); 045 this.container = container; 046 this.element = dr; 047 } 048 049 050// public ResourceContext(Object bundle, Element doc) { 051// // TODO Auto-generated constructor stub 052// } 053 054// public Bundle getBundleResource() { 055// return containerResource; 056// } 057 058 059 public ResourceContext(ResourceContext container, ResourceWrapper rw) { 060 super(); 061 this.container = container; 062 // todo: howto do this better? 063 064 if (rw instanceof DirectWrappers.ResourceWrapperDirect) { 065 this.resource = ((DirectWrappers.ResourceWrapperDirect) rw).getResource(); 066 } else if (rw instanceof ElementWrappers.ResourceWrapperMetaElement) { 067 this.element = ((ElementWrappers.ResourceWrapperMetaElement) rw).getElement(); 068 } else { 069 // this is not supported for now... throw new Error("Not supported yet"); 070 } 071 } 072 073 public ResourceContext getContainer() { 074 return container; 075 } 076 077 public void setContainer(ResourceContext container) { 078 this.container = container; 079 } 080 081 // public org.hl7.fhir.r5.elementmodel.Element getBundleElement() { 082// return containerElement; 083// } 084// 085 public Resource getResource() { 086 return resource; 087 } 088 089 public org.hl7.fhir.r5.elementmodel.Element getElement() { 090 return element; 091 } 092 093 public BundleEntryComponent resolve(String value) { 094 if (value.startsWith("#")) { 095 if (resource instanceof DomainResource) { 096 DomainResource dr = (DomainResource) resource; 097 for (Resource r : dr.getContained()) { 098 if (r.getId().equals(value.substring(1))) { 099 BundleEntryComponent be = new BundleEntryComponent(); 100 be.setResource(r); 101 return be; 102 } 103 } 104 } 105 return null; 106 } 107 108 if (resource instanceof Bundle) { 109 Bundle b = (Bundle) resource; 110 for (BundleEntryComponent be : b.getEntry()) { 111 if (be.hasFullUrl() && be.getFullUrl().equals(value)) 112 return be; 113 if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId())) 114 return be; 115 } 116 } 117 118 if (resource instanceof Parameters) { 119 Parameters pp = (Parameters) resource; 120 for (ParametersParameterComponent p : pp.getParameter()) { 121 if (p.getResource() != null && value.equals(p.getResource().fhirType()+"/"+p.getResource().getId())) { 122 BundleEntryComponent be = new BundleEntryComponent(); 123 be.setResource(p.getResource()); 124 return be; 125 126 } 127 } 128 } 129 130 return container != null ? container.resolve(value) : null; 131 } 132 133 public org.hl7.fhir.r5.elementmodel.Element resolveElement(String value, String version) { 134 if (value.startsWith("#")) { 135 if (element != null) { 136 for (org.hl7.fhir.r5.elementmodel.Element r : element.getChildrenByName("contained")) { 137 if (r.getChildValue("id").equals(value.substring(1))) 138 return r; 139 } 140 } 141 return null; 142 } 143 if (element != null) { 144 if (element.fhirType().equals("Bundle")) { 145 for (org.hl7.fhir.r5.elementmodel.Element be : element.getChildren("entry")) { 146 org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource"); 147 if (res != null) { 148 if (value.equals(be.getChildValue("fullUrl"))) { 149 if (checkVersion(version, res)) { 150 return be; 151 } 152 } 153 if (value.equals(res.fhirType()+"/"+res.getChildValue("id"))) { 154 if (checkVersion(version, res)) { 155 return be; 156 } 157 } 158 } 159 } 160 } 161 if (element.fhirType().equals("Parameters")) { 162 for (org.hl7.fhir.r5.elementmodel.Element p : element.getChildren("parameter")) { 163 org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource"); 164 if (res != null && value.equals(res.fhirType()+"/"+res.getChildValue("id"))) { 165 if (checkVersion(version, res)) { 166 return p; 167 } 168 } 169 } 170 } 171 } 172 return container != null ? container.resolveElement(value, version) : null; 173 } 174 175 private boolean checkVersion(String version, org.hl7.fhir.r5.elementmodel.Element res) { 176 if (version == null) { 177 return true; 178 } else if (!res.hasChild("meta")) { 179 return false; 180 } else { 181 org.hl7.fhir.r5.elementmodel.Element meta = res.getNamedChild("meta"); 182 return version.equals(meta.getChildValue("version")); 183 } 184 } 185 } 186 187 188 public enum ResourceReferenceKind { 189 CONTAINED, BUNDLE, EXTERNAL, UNKNOWN 190 191 } 192 193 public static class ResourceWithReference { 194 195 private ResourceReferenceKind kind; 196 private String reference; 197 private ResourceWrapper resource; 198 199 public ResourceWithReference(ResourceReferenceKind kind, String reference, ResourceWrapper resource) { 200 super(); 201 this.kind = kind; 202 this.reference = reference; 203 this.resource = resource; 204 } 205 206 public ResourceReferenceKind getKind() { 207 return kind; 208 } 209 210 public String getReference() { 211 return reference; 212 } 213 214 public ResourceWrapper getResource() { 215 return resource; 216 } 217 } 218 219 220 221}