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