001package org.hl7.fhir.instance.utils;
002
003import java.net.URISyntaxException;
004import java.util.ArrayList;
005import java.util.Calendar;
006import java.util.Date;
007import java.util.HashMap;
008import java.util.List;
009import java.util.Map;
010
011import org.hl7.fhir.instance.client.FeedFormat;
012import org.hl7.fhir.instance.client.IFHIRClient;
013import org.hl7.fhir.instance.client.ResourceFormat;
014import org.hl7.fhir.instance.model.Bundle;
015import org.hl7.fhir.instance.model.ConceptMap;
016import org.hl7.fhir.instance.model.Conformance;
017import org.hl7.fhir.instance.model.DataElement;
018import org.hl7.fhir.instance.model.ElementDefinition.TypeRefComponent;
019import org.hl7.fhir.instance.model.OperationOutcome;
020import org.hl7.fhir.instance.model.Parameters;
021import org.hl7.fhir.instance.model.Questionnaire;
022import org.hl7.fhir.instance.model.Resource;
023import org.hl7.fhir.instance.model.SearchParameter;
024import org.hl7.fhir.instance.model.StructureDefinition;
025import org.hl7.fhir.instance.model.ValueSet;
026import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent;
027import org.hl7.fhir.instance.model.ValueSet.ConceptSetComponent;
028import org.hl7.fhir.instance.model.ValueSet.ValueSetExpansionComponent;
029import org.hl7.fhir.instance.terminologies.ITerminologyServices;
030import org.hl7.fhir.instance.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
031
032/*
033 *  private static Map<String, StructureDefinition> loadProfiles() throws Exception {
034 HashMap<String, StructureDefinition> result = new HashMap<String, StructureDefinition>();
035 Bundle feed = new XmlParser().parseGeneral(new FileInputStream(PROFILES)).getFeed();
036 for (AtomEntry<? extends Resource> e : feed.getEntryList()) {
037 if (e.getReference() instanceof StructureDefinition) {
038 result.put(e.getId(), (StructureDefinition) e.getReference());
039 }
040 }
041 return result;
042 }
043 private static final String TEST_PROFILE = "C:\\work\\org.hl7.fhir\\build\\publish\\namespace.profile.xml";
044 private static final String PROFILES = "C:\\work\\org.hl7.fhir\\build\\publish\\profiles-resources.xml";
045 igtodo - things to add: 
046 - version
047 - list of resource names
048 */
049public class WorkerContext implements NameResolver {
050
051  private ITerminologyServices terminologyServices = new NullTerminologyServices();
052  private IFHIRClient client = new NullClient();
053  private Map<String, ValueSet> codeSystems = new HashMap<String, ValueSet>();
054  private Map<String, DataElement> dataElements = new HashMap<String, DataElement>();
055  private Map<String, ValueSet> valueSets = new HashMap<String, ValueSet>();
056  private Map<String, ConceptMap> maps = new HashMap<String, ConceptMap>();
057  private Map<String, StructureDefinition> profiles = new HashMap<String, StructureDefinition>();
058  private Map<String, SearchParameter> searchParameters = new HashMap<String, SearchParameter>();
059  private Map<String, StructureDefinition> extensionDefinitions = new HashMap<String, StructureDefinition>();
060  private String version;
061  private List<String> resourceNames = new ArrayList<String>();
062  private Map<String, Questionnaire> questionnaires = new HashMap<String, Questionnaire>();
063
064  public WorkerContext() {
065    super();
066  }
067
068  public WorkerContext(ITerminologyServices conceptLocator, IFHIRClient client, Map<String, ValueSet> codeSystems,
069      Map<String, ValueSet> valueSets, Map<String, ConceptMap> maps, Map<String, StructureDefinition> profiles) {
070    super();
071    if (conceptLocator != null)
072      this.terminologyServices = conceptLocator;
073    if (client != null)
074      this.client = client;
075    if (codeSystems != null)
076      this.codeSystems = codeSystems;
077    if (valueSets != null)
078      this.valueSets = valueSets;
079    if (maps != null)
080      this.maps = maps;
081    if (profiles != null)
082      this.profiles = profiles;
083  }
084
085  public ITerminologyServices getTerminologyServices() {
086    return terminologyServices;
087  }
088
089  public boolean hasClient() {
090    return !(client == null || client instanceof NullClient);
091  }
092
093  public IFHIRClient getClient() {
094    return client;
095  }
096
097  public Map<String, ValueSet> getCodeSystems() {
098    return codeSystems;
099  }
100
101  public Map<String, DataElement> getDataElements() {
102    return dataElements;
103  }
104
105  public Map<String, ValueSet> getValueSets() {
106    return valueSets;
107  }
108
109  public Map<String, ConceptMap> getMaps() {
110    return maps;
111  }
112
113  public StructureDefinition getProfile(String theId) {
114    return profiles.get(theId);
115  }
116
117  /**
118   * @deprecated Use {@link #getProfile(String)} instead
119   */
120  @Deprecated
121  public Map<String, StructureDefinition> getProfiles() {
122    return profiles;
123  }
124
125  public Map<String, StructureDefinition> getExtensionDefinitions() {
126    return extensionDefinitions;
127  }
128
129  public Map<String, Questionnaire> getQuestionnaires() {
130    return questionnaires;
131  }
132
133  public WorkerContext setTerminologyServices(ITerminologyServices terminologyServices) {
134    this.terminologyServices = terminologyServices;
135    return this;
136  }
137
138  public WorkerContext clone(IFHIRClient altClient) {
139    WorkerContext res = new WorkerContext(terminologyServices, null, codeSystems, valueSets, maps, profiles);
140    res.extensionDefinitions.putAll(extensionDefinitions);
141    res.version = version;
142    res.client = altClient;
143    return res;
144  }
145
146  public void seeExtensionDefinition(String url, StructureDefinition ed) throws Exception {
147    if (extensionDefinitions.get(ed.getUrl()) != null)
148      throw new Exception("duplicate extension definition: " + ed.getUrl());
149    extensionDefinitions.put(ed.getId(), ed);
150    extensionDefinitions.put(url, ed);
151    extensionDefinitions.put(ed.getUrl(), ed);
152  }
153
154  public void seeQuestionnaire(String url, Questionnaire theQuestionnaire) throws Exception {
155    if (questionnaires.get(theQuestionnaire.getId()) != null)
156      throw new Exception("duplicate extension definition: "+theQuestionnaire.getId());
157    questionnaires.put(theQuestionnaire.getId(), theQuestionnaire);
158    questionnaires.put(url, theQuestionnaire);
159  }
160
161  public void seeValueSet(String url, ValueSet vs) throws Exception {
162    if (valueSets.containsKey(vs.getUrl()))
163      throw new Exception("Duplicate Profile "+vs.getUrl());
164    valueSets.put(vs.getId(), vs);
165    valueSets.put(url, vs);
166    valueSets.put(vs.getUrl(), vs);
167     if (vs.hasCodeSystem()) {
168       codeSystems.put(vs.getCodeSystem().getSystem().toString(), vs);
169    }
170  }
171
172  public void seeProfile(String url, StructureDefinition p) {
173    if (profiles.containsKey(p.getUrl()))
174      throw new IllegalArgumentException("Duplicate Profile "+p.getUrl());
175    profiles.put(p.getId(), p);
176    profiles.put(url, p);
177    profiles.put(p.getUrl(), p);
178  }
179
180  public class NullClient implements IFHIRClient {
181
182    @Override
183    public VersionInfo getVersions() {
184      throw new Error("call to NullClient");
185    }
186
187    @Override
188    public IFHIRClient initialize(String baseServiceUrl) throws URISyntaxException {
189      throw new Error("call to NullClient");
190    }
191
192    @Override
193    public void initialize(String baseServiceUrl, int recordCount) throws URISyntaxException {
194      throw new Error("call to NullClient");
195    }
196
197    @Override
198    public void setPreferredResourceFormat(ResourceFormat resourceFormat) {
199      throw new Error("call to NullClient");
200    }
201
202    @Override
203    public String getPreferredResourceFormat() {
204      throw new Error("call to NullClient");
205    }
206
207    @Override
208    public void setPreferredFeedFormat(FeedFormat feedFormat) {
209      throw new Error("call to NullClient");
210    }
211
212    @Override
213    public String getPreferredFeedFormat() {
214      throw new Error("call to NullClient");
215    }
216
217    @Override
218    public int getMaximumRecordCount() {
219      throw new Error("call to NullClient");
220    }
221
222    @Override
223    public void setMaximumRecordCount(int recordCount) {
224      throw new Error("call to NullClient");
225    }
226
227    @Override
228    public Conformance getConformanceStatement() {
229      throw new Error("call to NullClient");
230    }
231
232    @Override
233    public Conformance getConformanceStatement(boolean useOptionsVerb) {
234      throw new Error("call to NullClient");
235    }
236
237    @Override
238    public <T extends Resource> T read(Class<T> resource, String id) {
239      throw new Error("call to NullClient");
240    }
241
242    @Override
243    public <T extends Resource> T vread(Class<T> resource, String id, String versionid) {
244      throw new Error("call to NullClient");
245    }
246
247    @Override
248    public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) {
249      throw new Error("call to NullClient");
250    }
251
252    @Override
253    public <T extends Resource> boolean delete(Class<T> resourceClass, String id) {
254      throw new Error("call to NullClient");
255    }
256
257    @Override
258    public <T extends Resource> OperationOutcome create(Class<T> resourceClass, T resource) {
259      throw new Error("call to NullClient");
260    }
261
262    @Override
263    public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass, String id) {
264      throw new Error("call to NullClient");
265    }
266
267    @Override
268    public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass, String id) {
269      throw new Error("call to NullClient");
270    }
271
272    @Override
273    public <T extends Resource> Bundle history(Class<T> resource, String id) {
274      throw new Error("call to NullClient");
275    }
276
277    @Override
278    public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass) {
279      throw new Error("call to NullClient");
280    }
281
282    @Override
283    public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass) {
284      throw new Error("call to NullClient");
285    }
286
287    @Override
288    public <T extends Resource> Bundle history(Class<T> resourceClass) {
289      throw new Error("call to NullClient");
290    }
291
292    @Override
293    public <T extends Resource> Bundle history(Calendar lastUpdate) {
294      throw new Error("call to NullClient");
295    }
296
297    @Override
298    public <T extends Resource> Bundle history(Date lastUpdate) {
299      throw new Error("call to NullClient");
300    }
301
302    @Override
303    public <T extends Resource> Bundle history() {
304      throw new Error("call to NullClient");
305    }
306
307    @Override
308    public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) {
309      throw new Error("call to NullClient");
310    }
311
312    @Override
313    public <T extends Resource> Bundle search(Class<T> resourceClass, Map<String, String> params) {
314      throw new Error("call to NullClient");
315    }
316
317    @Override
318    public <T extends Resource> Bundle searchPost(Class<T> resourceClass, T resource, Map<String, String> params) {
319      throw new Error("call to NullClient");
320    }
321
322    @Override
323    public Bundle transaction(Bundle batch) {
324      throw new Error("call to NullClient");
325    }
326
327    @Override
328    public Bundle fetchFeed(String url) {
329      throw new Error("call to NullClient");
330    }
331
332    @Override
333    public ValueSet expandValueset(ValueSet source) throws Exception {
334      throw new Error("call to NullClient");
335    }
336
337    @Override
338    public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
339      throw new Error("call to NullClient");
340    }
341
342    @Override
343    public Conformance getConformanceStatementQuick() {
344      throw new Error("call to NullClient");
345    }
346
347    @Override
348    public Conformance getConformanceStatementQuick(boolean useOptionsVerb) {
349      throw new Error("call to NullClient");
350    }
351
352    @Override
353    public String getAddress() {
354      throw new Error("call to NullClient");
355    }
356
357  }
358
359  public StructureDefinition getExtensionStructure(StructureDefinition context, String url) throws Exception {
360    if (url.startsWith("#")) {
361      throw new Error("Contained extensions not done yet");
362    } else {
363      if (url.contains("#"))
364        url = url.substring(0, url.indexOf("#"));
365      StructureDefinition res = extensionDefinitions.get(url);
366      if (res == null)
367        res = profiles.get(url);
368      if (res == null)
369        return null;
370      if (res.getSnapshot() == null || res.getSnapshot().getElement().isEmpty())
371        throw new Exception("no snapshot on extension for url " + url);
372      return res;
373    }
374  }
375
376  public class NullTerminologyServices implements ITerminologyServices {
377
378    @Override
379    public boolean supportsSystem(String system) {
380      return false;
381    }
382
383    @Override
384    public ConceptDefinitionComponent getCodeDefinition(String system, String code) {
385      throw new Error("call to NullTerminologyServices");
386    }
387
388    @Override
389    public ValidationResult validateCode(String system, String code, String display) {
390      throw new Error("call to NullTerminologyServices");
391    }
392
393    @Override
394    public ValueSetExpansionComponent expandVS(ConceptSetComponent inc) throws Exception {
395      throw new Error("call to NullTerminologyServices");
396    }
397
398    @Override
399    public boolean checkVS(ConceptSetComponent vsi, String system, String code) {
400      throw new Error("call to NullTerminologyServices");
401    }
402
403    @Override
404    public boolean verifiesSystem(String system) {
405      return false;
406    }
407
408    @Override
409    public ValueSetExpansionOutcome expand(ValueSet vs) {
410      throw new Error("call to NullTerminologyServices");
411    }
412
413  }
414
415  public String getVersion() {
416    return version;
417  }
418
419  public void setVersion(String version) {
420    this.version = version;
421  }
422
423  @Override
424  public boolean isResource(String name) {
425    if (resourceNames.contains(name))
426      return true;
427    StructureDefinition sd = profiles.get("http://hl7.org/fhir/StructureDefinition/" + name);
428    return sd != null && (sd.getBase().endsWith("Resource") || sd.getBase().endsWith("DomainResource"));
429  }
430
431  public List<String> getResourceNames() {
432    return resourceNames;
433  }
434
435  public StructureDefinition getTypeStructure(TypeRefComponent type) {
436    if (type.hasProfile())
437      return profiles.get(type.getProfile().get(0).getValue());
438    else
439      return profiles.get(type.getCode());
440  }
441
442  public Map<String, SearchParameter> getSearchParameters() {
443    return searchParameters;
444  }
445
446}