001package org.hl7.fhir.dstu2016may.terminologies; 002 003import java.util.List; 004 005import org.hl7.fhir.dstu2016may.model.CodeSystem; 006import org.hl7.fhir.dstu2016may.model.CodeSystem.ConceptDefinitionComponent; 007import org.hl7.fhir.dstu2016may.model.UriType; 008import org.hl7.fhir.dstu2016may.model.ValueSet; 009import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptReferenceComponent; 010import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; 011import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetFilterComponent; 012import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionContainsComponent; 013import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpander.ValueSetExpansionOutcome; 014import org.hl7.fhir.dstu2016may.utils.EOperationOutcome; 015import org.hl7.fhir.dstu2016may.utils.IWorkerContext; 016import org.hl7.fhir.dstu2016may.utils.IWorkerContext.ValidationResult; 017 018public class ValueSetCheckerSimple implements ValueSetChecker { 019 020 private ValueSet valueset; 021 private ValueSetExpanderFactory factory; 022 private IWorkerContext context; 023 024 public ValueSetCheckerSimple(ValueSet source, ValueSetExpanderFactory factory, IWorkerContext context) { 025 this.valueset = source; 026 this.factory = factory; 027 this.context = context; 028 } 029 030 @Override 031 public boolean codeInValueSet(String system, String code) throws EOperationOutcome, Exception { 032 033 if (valueset.hasCompose()) { 034 boolean ok = false; 035 for (UriType uri : valueset.getCompose().getImport()) { 036 ok = ok || inImport(uri.getValue(), system, code); 037 } 038 for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) { 039 ok = ok || inComponent(vsi, system, code); 040 } 041 for (ConceptSetComponent vsi : valueset.getCompose().getExclude()) { 042 ok = ok && !inComponent(vsi, system, code); 043 } 044 } 045 046 return false; 047 } 048 049 private boolean inImport(String uri, String system, String code) throws EOperationOutcome, Exception { 050 ValueSet vs = context.fetchResource(ValueSet.class, uri); 051 if (vs == null) 052 return false ; // we can't tell 053 return codeInExpansion(factory.getExpander().expand(vs), system, code); 054 } 055 056 private boolean codeInExpansion(ValueSetExpansionOutcome vso, String system, String code) throws EOperationOutcome, Exception { 057 if (vso.getService() != null) { 058 return vso.getService().codeInValueSet(system, code); 059 } else { 060 for (ValueSetExpansionContainsComponent c : vso.getValueset().getExpansion().getContains()) { 061 if (code.equals(c.getCode()) && (system == null || system.equals(c.getSystem()))) 062 return true; 063 if (codeinExpansion(c, system, code)) 064 return true; 065 } 066 } 067 return false; 068 } 069 070 private boolean codeinExpansion(ValueSetExpansionContainsComponent cnt, String system, String code) { 071 for (ValueSetExpansionContainsComponent c : cnt.getContains()) { 072 if (code.equals(c.getCode()) && system.equals(c.getSystem().toString())) 073 return true; 074 if (codeinExpansion(c, system, code)) 075 return true; 076 } 077 return false; 078 } 079 080 081 private boolean inComponent(ConceptSetComponent vsi, String system, String code) { 082 if (!vsi.getSystem().equals(system)) 083 return false; 084 // whether we know the system or not, we'll accept the stated codes at face value 085 for (ConceptReferenceComponent cc : vsi.getConcept()) 086 if (cc.getCode().equals(code)) { 087 return true; 088 } 089 090 CodeSystem def = context.fetchCodeSystem(system); 091 if (def != null) { 092 if (!def.getCaseSensitive()) { 093 // well, ok, it's not case sensitive - we'll check that too now 094 for (ConceptReferenceComponent cc : vsi.getConcept()) 095 if (cc.getCode().equalsIgnoreCase(code)) { 096 return false; 097 } 098 } 099 if (vsi.getConcept().isEmpty() && vsi.getFilter().isEmpty()) { 100 return codeInDefine(def.getConcept(), code, def.getCaseSensitive()); 101 } 102 for (ConceptSetFilterComponent f: vsi.getFilter()) 103 throw new Error("not done yet: "+f.getValue()); 104 105 return false; 106 } else if (context.supportsSystem(system)) { 107 ValidationResult vv = context.validateCode(system, code, null, vsi); 108 return vv.isOk(); 109 } else 110 // we don't know this system, and can't resolve it 111 return false; 112 } 113 114 private boolean codeInDefine(List<ConceptDefinitionComponent> concepts, String code, boolean caseSensitive) { 115 for (ConceptDefinitionComponent c : concepts) { 116 if (caseSensitive && code.equals(c.getCode())) 117 return true; 118 if (!caseSensitive && code.equalsIgnoreCase(c.getCode())) 119 return true; 120 if (codeInDefine(c.getConcept(), code, caseSensitive)) 121 return true; 122 } 123 return false; 124 } 125 126}