package org.hl7.fhir.dstu2016may.terminologies; import java.util.List; import org.hl7.fhir.dstu2016may.model.CodeSystem; import org.hl7.fhir.dstu2016may.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.dstu2016may.model.UriType; import org.hl7.fhir.dstu2016may.model.ValueSet; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.dstu2016may.utils.EOperationOutcome; import org.hl7.fhir.dstu2016may.utils.IWorkerContext; import org.hl7.fhir.dstu2016may.utils.IWorkerContext.ValidationResult; public class ValueSetCheckerSimple implements ValueSetChecker { private ValueSet valueset; private ValueSetExpanderFactory factory; private IWorkerContext context; public ValueSetCheckerSimple(ValueSet source, ValueSetExpanderFactory factory, IWorkerContext context) { this.valueset = source; this.factory = factory; this.context = context; } @Override public boolean codeInValueSet(String system, String code) throws EOperationOutcome, Exception { if (valueset.hasCompose()) { boolean ok = false; for (UriType uri : valueset.getCompose().getImport()) { ok = ok || inImport(uri.getValue(), system, code); } for (ConceptSetComponent vsi : valueset.getCompose().getInclude()) { ok = ok || inComponent(vsi, system, code); } for (ConceptSetComponent vsi : valueset.getCompose().getExclude()) { ok = ok && !inComponent(vsi, system, code); } } return false; } private boolean inImport(String uri, String system, String code) throws EOperationOutcome, Exception { ValueSet vs = context.fetchResource(ValueSet.class, uri); if (vs == null) return false ; // we can't tell return codeInExpansion(factory.getExpander().expand(vs), system, code); } private boolean codeInExpansion(ValueSetExpansionOutcome vso, String system, String code) throws EOperationOutcome, Exception { if (vso.getService() != null) { return vso.getService().codeInValueSet(system, code); } else { for (ValueSetExpansionContainsComponent c : vso.getValueset().getExpansion().getContains()) { if (code.equals(c.getCode()) && (system == null || system.equals(c.getSystem()))) return true; if (codeinExpansion(c, system, code)) return true; } } return false; } private boolean codeinExpansion(ValueSetExpansionContainsComponent cnt, String system, String code) { for (ValueSetExpansionContainsComponent c : cnt.getContains()) { if (code.equals(c.getCode()) && system.equals(c.getSystem().toString())) return true; if (codeinExpansion(c, system, code)) return true; } return false; } private boolean inComponent(ConceptSetComponent vsi, String system, String code) { if (!vsi.getSystem().equals(system)) return false; // whether we know the system or not, we'll accept the stated codes at face value for (ConceptReferenceComponent cc : vsi.getConcept()) if (cc.getCode().equals(code)) { return true; } CodeSystem def = context.fetchCodeSystem(system); if (def != null) { if (!def.getCaseSensitive()) { // well, ok, it's not case sensitive - we'll check that too now for (ConceptReferenceComponent cc : vsi.getConcept()) if (cc.getCode().equalsIgnoreCase(code)) { return false; } } if (vsi.getConcept().isEmpty() && vsi.getFilter().isEmpty()) { return codeInDefine(def.getConcept(), code, def.getCaseSensitive()); } for (ConceptSetFilterComponent f: vsi.getFilter()) throw new Error("not done yet: "+f.getValue()); return false; } else if (context.supportsSystem(system)) { ValidationResult vv = context.validateCode(system, code, null, vsi); return vv.isOk(); } else // we don't know this system, and can't resolve it return false; } private boolean codeInDefine(List<ConceptDefinitionComponent> concepts, String code, boolean caseSensitive) { for (ConceptDefinitionComponent c : concepts) { if (caseSensitive && code.equals(c.getCode())) return true; if (!caseSensitive && code.equalsIgnoreCase(c.getCode())) return true; if (codeInDefine(c.getConcept(), code, caseSensitive)) return true; } return false; } }