001package org.hl7.fhir.r5.terminologies.client;
002
003import java.io.IOException;
004import java.util.HashMap;
005import java.util.HashSet;
006import java.util.Map;
007import java.util.Set;
008
009import org.hl7.fhir.r5.model.CanonicalResource;
010import org.hl7.fhir.r5.model.CapabilityStatement;
011import org.hl7.fhir.r5.model.TerminologyCapabilities;
012import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
013import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent;
014import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseCount;
015import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
016
017public class TerminologyClientContext {
018  public enum TerminologyClientContextUseType {
019    expand, validate, readVS, readCS
020  }
021  public class TerminologyClientContextUseCount {
022    private int expands;
023    private int validates;
024    private int readVS;
025    private int readCS;
026
027    public int getReadVS() {
028      return readVS;
029    }
030    public void setReadVS(int readVS) {
031      this.readVS = readVS;
032    }
033    public int getReadCS() {
034      return readCS;
035    }
036    public void setReadCS(int readCS) {
037      this.readCS = readCS;
038    }
039    public int getExpands() {
040      return expands;
041    }
042    public void setExpands(int expands) {
043      this.expands = expands;
044    }
045    public int getValidates() {
046      return validates;
047    }
048    public void setValidates(int validates) {
049      this.validates = validates;
050    }
051    
052  }
053
054  private ITerminologyClient client;
055  private boolean initialised = false;
056  private CapabilityStatement capabilitiesStatementQuick;
057  private TerminologyCapabilities txcaps;
058  private TerminologyCache txCache;
059  
060  private Map<String, TerminologyClientContextUseCount> useCounts = new HashMap<>();
061  private boolean isTxCaching;
062  private final Set<String> cached = new HashSet<>();
063  private boolean master;
064  private String cacheId;
065
066  protected TerminologyClientContext(ITerminologyClient client, String cacheId, boolean master) {
067    super();
068    this.client = client;
069    this.cacheId = cacheId;
070    this.master = master;
071  }
072
073  public Map<String, TerminologyClientContextUseCount> getUseCounts() {
074    return useCounts;
075  }
076
077  public boolean isMaster() {
078    return master;
079  }
080
081  public ITerminologyClient getClient() {
082    return client;
083  }
084
085  public void seeUse(Set<String> systems, TerminologyClientContextUseType useType) {
086    for (String s : systems) {
087      seeUse(s, useType);
088    }
089  }
090  
091  public void seeUse(String s, TerminologyClientContextUseType useType) {
092    TerminologyClientContextUseCount uc = useCounts.get(s);
093    if (uc == null) {
094      uc = new TerminologyClientContextUseCount();
095      useCounts.put(s,uc);
096    }
097    switch (useType) {
098    case expand:
099      uc.expands++;
100      break;
101    case readVS:
102      uc.readVS++;
103      break;
104    case readCS:
105      uc.readCS++;
106      break;
107    case validate:
108      uc.validates++;
109      break;
110    default:
111      break;
112    }
113  }
114
115  public TerminologyCapabilities getTxCapabilities() {
116    return txcaps;
117  }
118
119  public void setTxCapabilities(TerminologyCapabilities txcaps) {
120    this.txcaps = txcaps;
121  }
122
123  public Set<String> getCached() {
124    return cached;
125  }
126
127  public boolean alreadyCached(CanonicalResource cr) {
128    return cached.contains(cr.getVUrl());
129  }
130
131  public void addToCache(CanonicalResource cr) {
132    cached.add(cr.getVUrl());
133  }
134
135  public String getAddress() {
136    return client.getAddress();
137  }
138
139  public int getUseCount() {
140    return getClient().getUseCount();
141  }
142
143  public boolean isTxCaching() {
144    return isTxCaching;
145  }
146  
147  public void setTxCaching(boolean isTxCaching) {
148    this.isTxCaching = isTxCaching;
149  }
150
151  public boolean usingCache() {
152    return isTxCaching && cacheId != null;
153  }
154
155  public String getCacheId() {
156    return cacheId;
157  }
158
159  public TerminologyCache getTxCache() {
160    return txCache;
161  }
162
163  public void setTxCache(TerminologyCache txCache) {
164    this.txCache = txCache;
165  }
166
167  public void initialize() throws IOException {
168    if (!initialised) {
169      // we don't cache the quick CS - we want to know that the server is with us. 
170      capabilitiesStatementQuick =  client.getCapabilitiesStatementQuick();
171      if (txCache != null && txCache.hasTerminologyCapabilities(getAddress())) {
172        txcaps = txCache.getTerminologyCapabilities(getAddress());
173        if (txcaps.getSoftware().hasVersion() && !txcaps.getSoftware().getVersion().equals(capabilitiesStatementQuick.getSoftware().getVersion())) {
174          txcaps = null;
175        }
176      } 
177      if (txcaps == null) {
178        txcaps = client.getTerminologyCapabilities();
179        if (txCache != null) {
180          txCache.cacheTerminologyCapabilities(getAddress(), txcaps);
181        }
182      }
183      if (txcaps != null) {
184        for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) {
185          if ("cache-id".equals(t.getName())) {
186            setTxCaching(true);
187            break;
188          }
189        }
190      }
191      initialised = true;
192    }    
193  }
194
195  public boolean supportsSystem(String system) throws IOException {
196    initialize();
197    for (TerminologyCapabilitiesCodeSystemComponent tccs : txcaps.getCodeSystem()) {
198      if (system.equals(tccs.getUri())) {
199        return true;
200      }
201    }
202    return false;
203  }
204
205  @Override
206  public String toString() {
207    return client.getAddress();
208  }
209  
210  
211}