001package org.hl7.fhir.r4.terminologies;
002
003import org.hl7.fhir.exceptions.FHIRException;
004import org.hl7.fhir.r4.context.SimpleWorkerContext;
005import org.hl7.fhir.r4.model.Coding;
006import org.hl7.fhir.r4.model.ConceptMap;
007import org.hl7.fhir.r4.model.ConceptMap.ConceptMapGroupComponent;
008import org.hl7.fhir.r4.model.ConceptMap.SourceElementComponent;
009import org.hl7.fhir.r4.model.ConceptMap.TargetElementComponent;
010import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
011
012public class ConceptMapEngine {
013
014  private SimpleWorkerContext context;
015
016  public ConceptMapEngine(SimpleWorkerContext context) {
017    this.context = context;
018  }
019
020  public Coding translate(Coding source, String url) throws FHIRException {
021    ConceptMap cm = context.fetchResource(ConceptMap.class, url);
022    if (cm == null)
023      throw new FHIRException("Unable to find ConceptMap '"+url+"'");
024    if (source.hasSystem()) 
025      return translateBySystem(cm, source.getSystem(), source.getCode());
026    else
027      return translateByJustCode(cm, source.getCode());
028  }
029
030  private Coding translateByJustCode(ConceptMap cm, String code) throws FHIRException {
031    SourceElementComponent ct = null;
032    ConceptMapGroupComponent cg = null;
033    for (ConceptMapGroupComponent g : cm.getGroup()) {
034      for (SourceElementComponent e : g.getElement()) {
035        if (code.equals(e.getCode())) {
036          if (e != null)
037            throw new FHIRException("Unable to process translate "+code+" because multiple candidate matches were found in concept map "+cm.getUrl());
038          ct = e;
039          cg = g;
040        }
041      }
042    }
043    if (ct == null)
044      return null;
045    TargetElementComponent tt = null;
046    for (TargetElementComponent t : ct.getTarget()) {
047      if (!t.hasDependsOn() && !t.hasProduct() && isOkEquivalence(t.getEquivalence())) {
048        if (tt != null)
049          throw new FHIRException("Unable to process translate "+code+" because multiple targets were found in concept map "+cm.getUrl());
050        tt = t;       
051      }
052    }
053    if (tt == null)
054      return null;
055    return new Coding().setSystem(cg.getTarget()).setVersion(cg.getTargetVersion()).setCode(tt.getCode()).setDisplay(tt.getDisplay());
056  }
057
058  private boolean isOkEquivalence(ConceptMapEquivalence equivalence) {
059    return equivalence != null && equivalence != ConceptMapEquivalence.DISJOINT && equivalence != ConceptMapEquivalence.UNMATCHED;
060  }
061
062  private Coding translateBySystem(ConceptMap cm, String system, String code) {
063    throw new Error("Not done yet");
064  }
065
066}