All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hl7.fhir.r5.terminologies.client.TerminologyClientContext Maven / Gradle / Ivy

package org.hl7.fhir.r5.terminologies.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseCount;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.ENoDump;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.VersionUtilities;

@MarkedToMoveToAdjunctPackage
public class TerminologyClientContext {
  
  public enum TerminologyClientContextUseType {
    expand, validate, readVS, readCS
  }
  public class TerminologyClientContextUseCount {
    private int expands;
    private int validates;
    private int readVS;
    private int readCS;

    public int getReadVS() {
      return readVS;
    }
    public void setReadVS(int readVS) {
      this.readVS = readVS;
    }
    public int getReadCS() {
      return readCS;
    }
    public void setReadCS(int readCS) {
      this.readCS = readCS;
    }
    public int getExpands() {
      return expands;
    }
    public void setExpands(int expands) {
      this.expands = expands;
    }
    public int getValidates() {
      return validates;
    }
    public void setValidates(int validates) {
      this.validates = validates;
    }
  }

  private static final String MIN_TEST_VERSION = "1.6.0";
  private static boolean allowNonConformantServers = false;
  private static boolean canAllowNonConformantServers = false;

  private static boolean canUseCacheId;

  private ITerminologyClient client;
  private boolean initialised = false;
  private CapabilityStatement capabilitiesStatement;
  private TerminologyCapabilities txcaps;
  private TerminologyCache txCache;
  
  private Map useCounts = new HashMap<>();
  private boolean isTxCaching;
  private final Set cached = new HashSet<>();
  private boolean master;
  private String cacheId;

  protected TerminologyClientContext(ITerminologyClient client, String cacheId, boolean master) {
    super();
    this.client = client;
    this.cacheId = cacheId;
    this.master = master;
  }

  public Map getUseCounts() {
    return useCounts;
  }

  public boolean isMaster() {
    return master;
  }

  public ITerminologyClient getClient() {
    return client;
  }

  public void seeUse(Set systems, TerminologyClientContextUseType useType) {
    if (systems != null) {
      for (String s : systems) {
        seeUse(s, useType);
      }
    }
  }
  
  public void seeUse(String s, TerminologyClientContextUseType useType) {
    TerminologyClientContextUseCount uc = useCounts.get(s);
    if (uc == null) {
      uc = new TerminologyClientContextUseCount();
      useCounts.put(s,uc);
    }
    switch (useType) {
    case expand:
      uc.expands++;
      break;
    case readVS:
      uc.readVS++;
      break;
    case readCS:
      uc.readCS++;
      break;
    case validate:
      uc.validates++;
      break;
    default:
      break;
    }
  }

  public TerminologyCapabilities getTxCapabilities() {
    return txcaps;
  }

  public void setTxCapabilities(TerminologyCapabilities txcaps) {
    this.txcaps = txcaps;
  }

  public Set getCached() {
    return cached;
  }

  public boolean alreadyCached(CanonicalResource cr) {
    return cached.contains(cr.getVUrl());
  }

  public void addToCache(CanonicalResource cr) {
    cached.add(cr.getVUrl());
  }

  public String getAddress() {
    return client.getAddress();
  }

  public int getUseCount() {
    return getClient().getUseCount();
  }

  public boolean isTxCaching() {
    return isTxCaching;
  }
  
  public void setTxCaching(boolean isTxCaching) {
    this.isTxCaching = isTxCaching;
  }

  public boolean usingCache() {
    return isTxCaching && cacheId != null;
  }

  public String getCacheId() {
    return cacheId;
  }

  public TerminologyCache getTxCache() {
    return txCache;
  }

  public void setTxCache(TerminologyCache txCache) {
    this.txCache = txCache;
  }

  public void initialize() throws IOException {
    if (!initialised) {
      // we don't cache the quick CS - we want to know that the server is with us. 
      capabilitiesStatement = client.getCapabilitiesStatement();
      checkFeature();
      if (txCache != null && txCache.hasTerminologyCapabilities(getAddress())) {
        txcaps = txCache.getTerminologyCapabilities(getAddress());
        if (txcaps.getSoftware().hasVersion() && !txcaps.getSoftware().getVersion().equals(capabilitiesStatement.getSoftware().getVersion())) {
          txcaps = null;
        }
      } 
      if (txcaps == null) {
        txcaps = client.getTerminologyCapabilities();
        if (txCache != null) {
          txCache.cacheTerminologyCapabilities(getAddress(), txcaps);
        }
      }
      if (txcaps != null && TerminologyClientContext.canUseCacheId) {
        for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) {
          if ("cache-id".equals(t.getName())) {
            setTxCaching(true);
            break;
          }
        }
      }
      initialised = true;
    }    
  }

  private void checkFeature() {
    if (!allowNonConformantServers && capabilitiesStatement != null) {
      String testVersion = null;
      boolean csParams = false;

      for (Extension t : capabilitiesStatement.getExtension()) {
        if (ToolingExtensions.EXT_FEATURE.equals(t.getUrl())) {
          String defn = t.getExtensionString("definition");
          if (ToolingExtensions.FEATURE_TX_TEST_VERSION.equals(defn)) {
            testVersion = t.getExtensionString("value");
          } else if (ToolingExtensions.FEATURE_TX_CS_PARAMS.equals(defn)) {
            csParams = "true".equals(t.getExtensionString("value"));
          } 
        }
      }

      if (testVersion == null) {
        if (canAllowNonConformantServers) {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use with this software (it does not pass the required tests).\r\nIf you wish to use this server, add the parameter -authorise-non-conformant-tx-servers to the command line parameters");
        } else {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use with this software (it does not pass the required tests)");
        }
      } else if (!VersionUtilities.isThisOrLater(MIN_TEST_VERSION, testVersion)) {
        if (canAllowNonConformantServers) {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use with this software as it is too old (test version = "+testVersion+").\r\nIf you wish to use this server, add the parameter -authorise-non-conformant-tx-servers to the command line parameters");
        } else {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use with this software as it is too old (test version = "+testVersion+")");          
        }
      } else if (!csParams) {
        if (canAllowNonConformantServers) {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use as it does not accept code systems in the tx-resource parameter.\r\nIf you wish to use this server, add the parameter -authorise-non-conformant-tx-servers to the command line parameters");
        } else {
          throw new ENoDump("The terminology server "+client.getAddress()+" is not approved for use as it does not accept code systems in the tx-resource parameter");          
        }
      } else {
        // all good
      }
    }
  }

  public boolean supportsSystem(String system) throws IOException {
    initialize();
    for (TerminologyCapabilitiesCodeSystemComponent tccs : txcaps.getCodeSystem()) {
      if (system.equals(tccs.getUri())) {
        return true;
      }
    }
    return false;
  }

  @Override
  public String toString() {
    return client.getAddress();
  }

  public static boolean isCanUseCacheId() {
    return canUseCacheId;
  }

  public static void setCanUseCacheId(boolean canUseCacheId) {
    TerminologyClientContext.canUseCacheId = canUseCacheId;
  }

  public String getHost() {
    try {
      URL uri = new URL(getAddress());
      return uri.getHost();
    } catch (MalformedURLException e) {
      return getAddress();
    }
  }

  public static boolean isAllowNonConformantServers() {
    return allowNonConformantServers;
  }

  public static void setAllowNonConformantServers(boolean allowNonConformantServers) {
    TerminologyClientContext.allowNonConformantServers = allowNonConformantServers;
  }

  public static boolean isCanAllowNonConformantServers() {
    return canAllowNonConformantServers;
  }

  public static void setCanAllowNonConformantServers(boolean canAllowNonConformantServers) {
    TerminologyClientContext.canAllowNonConformantServers = canAllowNonConformantServers;
  }
  
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy