001package org.hl7.fhir.common.hapi.validation.support;
002
003import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
004import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
005import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
006import ca.uhn.fhir.context.FhirContext;
007import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
008import ca.uhn.fhir.context.support.IValidationSupport;
009import ca.uhn.fhir.context.support.TranslateConceptResult;
010import ca.uhn.fhir.context.support.TranslateConceptResults;
011import ca.uhn.fhir.util.ParametersUtil;
012import org.apache.commons.lang3.StringUtils;
013import org.hl7.fhir.instance.model.api.IBase;
014import org.hl7.fhir.instance.model.api.IBaseCoding;
015import org.hl7.fhir.instance.model.api.IBaseParameters;
016import org.hl7.fhir.instance.model.api.IPrimitiveType;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Objects;
021import java.util.Optional;
022
023public final class RemoteTerminologyUtil {
024        private RemoteTerminologyUtil() {}
025
026        public static IBaseParameters buildTranslateInputParameters(
027                        FhirContext fhirContext, IValidationSupport.TranslateCodeRequest theRequest) {
028                IBaseParameters params = ParametersUtil.newInstance(fhirContext);
029                if (!StringUtils.isEmpty(theRequest.getConceptMapUrl())) {
030                        ParametersUtil.addParameterToParametersUri(fhirContext, params, "url", theRequest.getConceptMapUrl());
031                }
032                if (!StringUtils.isEmpty(theRequest.getConceptMapVersion())) {
033                        ParametersUtil.addParameterToParametersString(
034                                        fhirContext, params, "conceptMapVersion", theRequest.getConceptMapVersion());
035                }
036                if (theRequest.getCodings() != null) {
037                        addCodingsToTranslateParameters(fhirContext, theRequest.getCodings(), params);
038                }
039                if (!StringUtils.isEmpty(theRequest.getSourceValueSetUrl())) {
040                        ParametersUtil.addParameterToParametersUri(
041                                        fhirContext, params, "source", theRequest.getSourceValueSetUrl());
042                }
043                if (!StringUtils.isEmpty(theRequest.getTargetValueSetUrl())) {
044                        ParametersUtil.addParameterToParametersUri(
045                                        fhirContext, params, "target", theRequest.getTargetValueSetUrl());
046                }
047                if (!StringUtils.isEmpty(theRequest.getTargetSystemUrl())) {
048                        ParametersUtil.addParameterToParametersUri(
049                                        fhirContext, params, "targetsystem", theRequest.getTargetSystemUrl());
050                }
051                if (theRequest.isReverse()) {
052                        ParametersUtil.addParameterToParametersBoolean(fhirContext, params, "reverse", theRequest.isReverse());
053                }
054
055                return params;
056        }
057
058        public static void addCodingsToTranslateParameters(
059                        FhirContext fhirContext, List<IBaseCoding> theCodings, IBaseParameters theParams) {
060                BaseRuntimeElementCompositeDefinition<?> codeableConceptDef = (BaseRuntimeElementCompositeDefinition<?>)
061                                Objects.requireNonNull(fhirContext.getElementDefinition("CodeableConcept"));
062                BaseRuntimeChildDefinition codings = codeableConceptDef.getChildByName("coding");
063                BaseRuntimeElementCompositeDefinition<?> codingDef = (BaseRuntimeElementCompositeDefinition<?>)
064                                Objects.requireNonNull(fhirContext.getElementDefinition("Coding"));
065                BaseRuntimeChildDefinition codingSystemChild = codingDef.getChildByName("system");
066                BaseRuntimeChildDefinition codingCodeChild = codingDef.getChildByName("code");
067                BaseRuntimeElementDefinition<IPrimitiveType<?>> systemDef =
068                                (RuntimePrimitiveDatatypeDefinition) fhirContext.getElementDefinition("uri");
069                BaseRuntimeElementDefinition<IPrimitiveType<?>> codeDef =
070                                (RuntimePrimitiveDatatypeDefinition) fhirContext.getElementDefinition("code");
071
072                IBase codeableConcept = codeableConceptDef.newInstance();
073
074                for (IBaseCoding aCoding : theCodings) {
075                        IBaseCoding newCoding = (IBaseCoding) codingDef.newInstance();
076
077                        IPrimitiveType<?> newSystem = systemDef.newInstance(aCoding.getSystem());
078                        codingSystemChild.getMutator().addValue(newCoding, newSystem);
079                        IPrimitiveType<?> newCode = codeDef.newInstance(aCoding.getCode());
080                        codingCodeChild.getMutator().addValue(newCoding, newCode);
081
082                        codings.getMutator().addValue(codeableConcept, newCoding);
083                }
084
085                ParametersUtil.addParameterToParameters(fhirContext, theParams, "codeableConcept", codeableConcept);
086        }
087
088        public static TranslateConceptResults translateOutcomeToResults(FhirContext fhirContext, IBaseParameters outcome) {
089                Optional<String> result = ParametersUtil.getNamedParameterValueAsString(fhirContext, outcome, "result");
090                Optional<String> message = ParametersUtil.getNamedParameterValueAsString(fhirContext, outcome, "message");
091                List<IBase> matches = ParametersUtil.getNamedParameters(fhirContext, outcome, "match");
092
093                TranslateConceptResults retVal = new TranslateConceptResults();
094                if (result.isPresent()) {
095                        retVal.setResult(Boolean.parseBoolean(result.get()));
096                }
097                if (message.isPresent()) {
098                        retVal.setMessage(message.get());
099                }
100                if (!matches.isEmpty()) {
101                        retVal.setResults(matchesToTranslateConceptResults(fhirContext, matches));
102                }
103
104                return retVal;
105        }
106
107        private static List<TranslateConceptResult> matchesToTranslateConceptResults(
108                        FhirContext fhirContext, List<IBase> theMatches) {
109                List<TranslateConceptResult> resultList = new ArrayList();
110                for (IBase m : theMatches) {
111                        TranslateConceptResult match = new TranslateConceptResult();
112                        String equivalence = ParametersUtil.getParameterPartValueAsString(fhirContext, m, "equivalence");
113                        Optional<IBase> concept = ParametersUtil.getParameterPartValue(fhirContext, m, "concept");
114                        String source = ParametersUtil.getParameterPartValueAsString(fhirContext, m, "source");
115
116                        if (StringUtils.isNotBlank(equivalence)) {
117                                match.setEquivalence(equivalence);
118                        }
119
120                        if (concept.isPresent()) {
121                                IBaseCoding matchedCoding = (IBaseCoding) concept.get();
122                                match.setSystem(matchedCoding.getSystem());
123                                match.setCode(matchedCoding.getCode());
124                                match.setDisplay(matchedCoding.getDisplay());
125
126                                if (StringUtils.isNotBlank(source)) {
127                                        match.setConceptMapUrl(source);
128                                }
129
130                                resultList.add(match);
131                        }
132                }
133                return resultList;
134        }
135}