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(FhirContext fhirContext, IValidationSupport.TranslateCodeRequest theRequest) {
027                IBaseParameters params = ParametersUtil.newInstance(fhirContext);
028                if (!StringUtils.isEmpty(theRequest.getConceptMapUrl())) {
029                        ParametersUtil.addParameterToParametersUri(fhirContext, params, "url", theRequest.getConceptMapUrl());
030                }
031                if (!StringUtils.isEmpty(theRequest.getConceptMapVersion())) {
032                        ParametersUtil.addParameterToParametersString(fhirContext, params, "conceptMapVersion", theRequest.getConceptMapVersion());
033                }
034                if (theRequest.getCodings() != null) {
035                        addCodingsToTranslateParameters(fhirContext, theRequest.getCodings(), params);
036                }
037                if (!StringUtils.isEmpty(theRequest.getSourceValueSetUrl())) {
038                        ParametersUtil.addParameterToParametersUri(fhirContext, params, "source", theRequest.getSourceValueSetUrl());
039                }
040                if (!StringUtils.isEmpty(theRequest.getTargetValueSetUrl())) {
041                        ParametersUtil.addParameterToParametersUri(fhirContext, params, "target", theRequest.getTargetValueSetUrl());
042                }
043                if (!StringUtils.isEmpty(theRequest.getTargetSystemUrl())) {
044                        ParametersUtil.addParameterToParametersUri(fhirContext, params, "targetsystem", theRequest.getTargetSystemUrl());
045                }
046                if (theRequest.isReverse()) {
047                        ParametersUtil.addParameterToParametersBoolean(fhirContext, params, "reverse", theRequest.isReverse());
048                }
049
050                return params;
051        }
052
053        public static void addCodingsToTranslateParameters(FhirContext fhirContext, List<IBaseCoding> theCodings, IBaseParameters theParams) {
054                BaseRuntimeElementCompositeDefinition<?> codeableConceptDef = (BaseRuntimeElementCompositeDefinition<?>) Objects.requireNonNull(fhirContext.getElementDefinition("CodeableConcept"));
055                BaseRuntimeChildDefinition codings = codeableConceptDef.getChildByName("coding");
056                BaseRuntimeElementCompositeDefinition<?> codingDef = (BaseRuntimeElementCompositeDefinition<?>) Objects.requireNonNull(fhirContext.getElementDefinition("Coding"));
057                BaseRuntimeChildDefinition codingSystemChild = codingDef.getChildByName("system");
058                BaseRuntimeChildDefinition codingCodeChild = codingDef.getChildByName("code");
059                BaseRuntimeElementDefinition<IPrimitiveType<?>> systemDef = (RuntimePrimitiveDatatypeDefinition) fhirContext.getElementDefinition("uri");
060                BaseRuntimeElementDefinition<IPrimitiveType<?>> codeDef = (RuntimePrimitiveDatatypeDefinition) fhirContext.getElementDefinition("code");
061
062                IBase codeableConcept = codeableConceptDef.newInstance();
063
064                for (IBaseCoding aCoding : theCodings) {
065                        IBaseCoding newCoding = (IBaseCoding) codingDef.newInstance();
066
067                        IPrimitiveType<?> newSystem = systemDef.newInstance(aCoding.getSystem());
068                        codingSystemChild.getMutator().addValue(newCoding, newSystem);
069                        IPrimitiveType<?> newCode = codeDef.newInstance(aCoding.getCode());
070                        codingCodeChild.getMutator().addValue(newCoding, newCode);
071
072                        codings.getMutator().addValue(codeableConcept, newCoding);
073                }
074
075                ParametersUtil.addParameterToParameters(fhirContext, theParams, "codeableConcept", codeableConcept);
076        }
077
078        public static TranslateConceptResults translateOutcomeToResults(FhirContext fhirContext, IBaseParameters outcome) {
079                Optional<String> result = ParametersUtil.getNamedParameterValueAsString(fhirContext, outcome, "result");
080                Optional<String> message = ParametersUtil.getNamedParameterValueAsString(fhirContext, outcome, "message");
081                List<IBase> matches = ParametersUtil.getNamedParameters(fhirContext, outcome, "match");
082
083                TranslateConceptResults retVal = new TranslateConceptResults();
084                if (result.isPresent()) {
085                        retVal.setResult(Boolean.parseBoolean(result.get()));
086                }
087                if (message.isPresent()) {
088                        retVal.setMessage(message.get());
089                }
090                if (!matches.isEmpty()) {
091                        retVal.setResults(matchesToTranslateConceptResults(fhirContext, matches));
092                }
093
094                return retVal;
095        }
096
097        private static List<TranslateConceptResult> matchesToTranslateConceptResults(FhirContext fhirContext, List<IBase> theMatches) {
098                List<TranslateConceptResult> resultList = new ArrayList();
099                for (IBase m : theMatches) {
100                        TranslateConceptResult match = new TranslateConceptResult();
101                        String equivalence = ParametersUtil.getParameterPartValueAsString(fhirContext, m, "equivalence");
102                        Optional<IBase> concept = ParametersUtil.getParameterPartValue(fhirContext, m, "concept");
103                        String source = ParametersUtil.getParameterPartValueAsString(fhirContext, m, "source");
104
105                        if (StringUtils.isNotBlank(equivalence)) {
106                                match.setEquivalence(equivalence);
107                        }
108
109                        if (concept.isPresent()) {
110                                IBaseCoding matchedCoding = (IBaseCoding) concept.get();
111                                match.setSystem(matchedCoding.getSystem());
112                                match.setCode(matchedCoding.getCode());
113                                match.setDisplay(matchedCoding.getDisplay());
114
115                                if (StringUtils.isNotBlank(source)) {
116                                        match.setConceptMapUrl(source);
117                                }
118
119                                resultList.add(match);
120                        }
121                }
122                return resultList;
123        }
124}