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 static boolean canUseCacheId; 055 056 private ITerminologyClient client; 057 private boolean initialised = false; 058 private CapabilityStatement capabilitiesStatementQuick; 059 private TerminologyCapabilities txcaps; 060 private TerminologyCache txCache; 061 062 private Map<String, TerminologyClientContextUseCount> useCounts = new HashMap<>(); 063 private boolean isTxCaching; 064 private final Set<String> cached = new HashSet<>(); 065 private boolean master; 066 private String cacheId; 067 068 protected TerminologyClientContext(ITerminologyClient client, String cacheId, boolean master) { 069 super(); 070 this.client = client; 071 this.cacheId = cacheId; 072 this.master = master; 073 } 074 075 public Map<String, TerminologyClientContextUseCount> getUseCounts() { 076 return useCounts; 077 } 078 079 public boolean isMaster() { 080 return master; 081 } 082 083 public ITerminologyClient getClient() { 084 return client; 085 } 086 087 public void seeUse(Set<String> systems, TerminologyClientContextUseType useType) { 088 for (String s : systems) { 089 seeUse(s, useType); 090 } 091 } 092 093 public void seeUse(String s, TerminologyClientContextUseType useType) { 094 TerminologyClientContextUseCount uc = useCounts.get(s); 095 if (uc == null) { 096 uc = new TerminologyClientContextUseCount(); 097 useCounts.put(s,uc); 098 } 099 switch (useType) { 100 case expand: 101 uc.expands++; 102 break; 103 case readVS: 104 uc.readVS++; 105 break; 106 case readCS: 107 uc.readCS++; 108 break; 109 case validate: 110 uc.validates++; 111 break; 112 default: 113 break; 114 } 115 } 116 117 public TerminologyCapabilities getTxCapabilities() { 118 return txcaps; 119 } 120 121 public void setTxCapabilities(TerminologyCapabilities txcaps) { 122 this.txcaps = txcaps; 123 } 124 125 public Set<String> getCached() { 126 return cached; 127 } 128 129 public boolean alreadyCached(CanonicalResource cr) { 130 return cached.contains(cr.getVUrl()); 131 } 132 133 public void addToCache(CanonicalResource cr) { 134 cached.add(cr.getVUrl()); 135 } 136 137 public String getAddress() { 138 return client.getAddress(); 139 } 140 141 public int getUseCount() { 142 return getClient().getUseCount(); 143 } 144 145 public boolean isTxCaching() { 146 return isTxCaching; 147 } 148 149 public void setTxCaching(boolean isTxCaching) { 150 this.isTxCaching = isTxCaching; 151 } 152 153 public boolean usingCache() { 154 return isTxCaching && cacheId != null; 155 } 156 157 public String getCacheId() { 158 return cacheId; 159 } 160 161 public TerminologyCache getTxCache() { 162 return txCache; 163 } 164 165 public void setTxCache(TerminologyCache txCache) { 166 this.txCache = txCache; 167 } 168 169 public void initialize() throws IOException { 170 if (!initialised) { 171 // we don't cache the quick CS - we want to know that the server is with us. 172 capabilitiesStatementQuick = client.getCapabilitiesStatementQuick(); 173 if (txCache != null && txCache.hasTerminologyCapabilities(getAddress())) { 174 txcaps = txCache.getTerminologyCapabilities(getAddress()); 175 if (txcaps.getSoftware().hasVersion() && !txcaps.getSoftware().getVersion().equals(capabilitiesStatementQuick.getSoftware().getVersion())) { 176 txcaps = null; 177 } 178 } 179 if (txcaps == null) { 180 txcaps = client.getTerminologyCapabilities(); 181 if (txCache != null) { 182 txCache.cacheTerminologyCapabilities(getAddress(), txcaps); 183 } 184 } 185 if (txcaps != null && TerminologyClientContext.canUseCacheId) { 186 for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) { 187 if ("cache-id".equals(t.getName())) { 188 setTxCaching(true); 189 break; 190 } 191 } 192 } 193 initialised = true; 194 } 195 } 196 197 public boolean supportsSystem(String system) throws IOException { 198 initialize(); 199 for (TerminologyCapabilitiesCodeSystemComponent tccs : txcaps.getCodeSystem()) { 200 if (system.equals(tccs.getUri())) { 201 return true; 202 } 203 } 204 return false; 205 } 206 207 @Override 208 public String toString() { 209 return client.getAddress(); 210 } 211 212 public static boolean isCanUseCacheId() { 213 return canUseCacheId; 214 } 215 216 public static void setCanUseCacheId(boolean canUseCacheId) { 217 TerminologyClientContext.canUseCacheId = canUseCacheId; 218 } 219 220}