001package ca.uhn.fhir.jpa.provider.dstu3;
002
003/*
004 * #%L
005 * HAPI FHIR JPA Server
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.context.support.TranslateConceptResults;
025import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoConceptMap;
026import ca.uhn.fhir.jpa.api.model.TranslationRequest;
027import ca.uhn.fhir.jpa.model.util.JpaConstants;
028import ca.uhn.fhir.jpa.term.TermConceptMappingSvcImpl;
029import ca.uhn.fhir.rest.annotation.IdParam;
030import ca.uhn.fhir.rest.annotation.Operation;
031import ca.uhn.fhir.rest.annotation.OperationParam;
032import ca.uhn.fhir.rest.api.server.RequestDetails;
033import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
034import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
035import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40;
036import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
037import org.hl7.fhir.dstu3.model.BooleanType;
038import org.hl7.fhir.dstu3.model.CodeType;
039import org.hl7.fhir.dstu3.model.CodeableConcept;
040import org.hl7.fhir.dstu3.model.Coding;
041import org.hl7.fhir.dstu3.model.ConceptMap;
042import org.hl7.fhir.dstu3.model.IdType;
043import org.hl7.fhir.dstu3.model.Parameters;
044import org.hl7.fhir.dstu3.model.StringType;
045import org.hl7.fhir.dstu3.model.UriType;
046import org.hl7.fhir.exceptions.FHIRException;
047
048import javax.servlet.http.HttpServletRequest;
049
050public class BaseJpaResourceProviderConceptMapDstu3 extends JpaResourceProviderDstu3<ConceptMap> {
051        @Operation(name = JpaConstants.OPERATION_TRANSLATE, idempotent = true, returnParameters = {
052                @OperationParam(name = "result", type = BooleanType.class, min = 1, max = 1),
053                @OperationParam(name = "message", type = StringType.class, min = 0, max = 1),
054        })
055        public Parameters translate(
056                HttpServletRequest theServletRequest,
057                @IdParam(optional = true) IdType theId,
058                @OperationParam(name = "url", min = 0, max = 1) UriType theUrl,
059                @OperationParam(name = "conceptMapVersion", min = 0, max = 1) StringType theConceptMapVersion,
060                @OperationParam(name = "code", min = 0, max = 1) CodeType theSourceCode,
061                @OperationParam(name = "system", min = 0, max = 1) UriType theSourceCodeSystem,
062                @OperationParam(name = "version", min = 0, max = 1) StringType theSourceCodeSystemVersion,
063                @OperationParam(name = "source", min = 0, max = 1) UriType theSourceValueSet,
064                @OperationParam(name = "coding", min = 0, max = 1) Coding theSourceCoding,
065                @OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConcept theSourceCodeableConcept,
066                @OperationParam(name = "target", min = 0, max = 1) UriType theTargetValueSet,
067                @OperationParam(name = "targetsystem", min = 0, max = 1) UriType theTargetCodeSystem,
068                @OperationParam(name = "reverse", min = 0, max = 1) BooleanType theReverse,
069                RequestDetails theRequestDetails
070        ) {
071                boolean haveUrl = theUrl != null
072                        && theUrl.hasValue();
073                boolean haveConceptMapVersion = theConceptMapVersion != null
074                        && theConceptMapVersion.hasValue();
075                boolean haveSourceCode = theSourceCode != null
076                        && theSourceCode.hasValue();
077                boolean haveSourceCodeSystem = theSourceCodeSystem != null
078                        && theSourceCodeSystem.hasValue();
079                boolean haveSourceCodeSystemVersion = theSourceCodeSystemVersion != null
080                        && theSourceCodeSystemVersion.hasValue();
081                boolean haveSourceValueSet = theSourceValueSet != null
082                        && theSourceValueSet.hasValue();
083                boolean haveSourceCoding = theSourceCoding != null
084                        && theSourceCoding.hasCode();
085                boolean haveSourceCodeableConcept = theSourceCodeableConcept != null
086                        && theSourceCodeableConcept.hasCoding()
087                        && theSourceCodeableConcept.getCodingFirstRep().hasCode();
088                boolean haveTargetValueSet = theTargetValueSet != null
089                        && theTargetValueSet.hasValue();
090                boolean haveTargetCodeSystem = theTargetCodeSystem != null
091                        && theTargetCodeSystem.hasValue();
092                boolean haveReverse = theReverse != null;
093                boolean haveId = theId != null && theId.hasIdPart();
094
095                // <editor-fold desc="Filters">
096                if ((!haveSourceCode && !haveSourceCoding && !haveSourceCodeableConcept)
097                        || moreThanOneTrue(haveSourceCode, haveSourceCoding, haveSourceCodeableConcept)) {
098                        throw new InvalidRequestException(Msg.code(1149) + "One (and only one) of the in parameters (code, coding, codeableConcept) must be provided, to identify the code that is to be translated.");
099                }
100
101                TranslationRequest translationRequest = new TranslationRequest();
102                try {
103
104                        if (haveUrl) {
105                                translationRequest.setUrl((org.hl7.fhir.r4.model.UriType) VersionConvertorFactory_30_40.convertType(theUrl, new BaseAdvisor_30_40(false)));
106                        }
107
108                        if (haveConceptMapVersion) {
109                                translationRequest.setConceptMapVersion((org.hl7.fhir.r4.model.StringType) VersionConvertorFactory_30_40.convertType(theConceptMapVersion, new BaseAdvisor_30_40(false)));
110                        }
111
112                        // Convert from DSTU3 to R4
113                        if (haveSourceCode) {
114                                translationRequest.getCodeableConcept().addCoding().setCodeElement((org.hl7.fhir.r4.model.CodeType) VersionConvertorFactory_30_40.convertType(theSourceCode, new BaseAdvisor_30_40(false)));
115
116                                if (haveSourceCodeSystem) {
117                                        translationRequest.getCodeableConcept().getCodingFirstRep().setSystemElement((org.hl7.fhir.r4.model.UriType) VersionConvertorFactory_30_40.convertType(theSourceCodeSystem, new BaseAdvisor_30_40(false)));
118                                }
119
120                                if (haveSourceCodeSystemVersion) {
121                                        translationRequest.getCodeableConcept().getCodingFirstRep().setVersionElement((org.hl7.fhir.r4.model.StringType) VersionConvertorFactory_30_40.convertType(theSourceCodeSystemVersion, new BaseAdvisor_30_40(false)));
122                                }
123                        } else if (haveSourceCoding) {
124                                translationRequest.getCodeableConcept().addCoding((org.hl7.fhir.r4.model.Coding) VersionConvertorFactory_30_40.convertType(theSourceCoding, new BaseAdvisor_30_40(false)));
125                        } else {
126                                translationRequest.setCodeableConcept((org.hl7.fhir.r4.model.CodeableConcept) VersionConvertorFactory_30_40.convertType(theSourceCodeableConcept, new BaseAdvisor_30_40(false)));
127                        }
128
129                        if (haveSourceValueSet) {
130                                translationRequest.setSource((org.hl7.fhir.r4.model.UriType) VersionConvertorFactory_30_40.convertType(theSourceValueSet, new BaseAdvisor_30_40(false)));
131                        }
132
133                        if (haveTargetValueSet) {
134                                translationRequest.setTarget((org.hl7.fhir.r4.model.UriType) VersionConvertorFactory_30_40.convertType(theTargetValueSet, new BaseAdvisor_30_40(false)));
135                        }
136
137                        if (haveTargetCodeSystem) {
138                                translationRequest.setTargetSystem((org.hl7.fhir.r4.model.UriType) VersionConvertorFactory_30_40.convertType(theTargetCodeSystem, new BaseAdvisor_30_40(false)));
139                        }
140
141                        if (haveReverse) {
142                                translationRequest.setReverse((org.hl7.fhir.r4.model.BooleanType) VersionConvertorFactory_30_40.convertType(theReverse, new BaseAdvisor_30_40(false)));
143                        }
144
145                        if (haveId) {
146                                translationRequest.setResourceId(theId.getIdPartAsLong());
147                        }
148                } catch (FHIRException fe) {
149                        throw new InternalErrorException(Msg.code(1150) + fe);
150                }
151
152                startRequest(theServletRequest);
153                try {
154                        IFhirResourceDaoConceptMap<ConceptMap> dao = (IFhirResourceDaoConceptMap<ConceptMap>) getDao();
155                        TranslateConceptResults result = dao.translate(translationRequest, theRequestDetails);
156
157                        // Convert from R4 to DSTU3
158                        return (Parameters) VersionConvertorFactory_30_40.convertResource(TermConceptMappingSvcImpl.toParameters(result), new BaseAdvisor_30_40(false));
159                } catch (FHIRException fe) {
160                        throw new InternalErrorException(Msg.code(1151) + fe);
161                } finally {
162                        endRequest(theServletRequest);
163                }
164        }
165
166        private static boolean moreThanOneTrue(boolean... theBooleans) {
167                boolean haveOne = false;
168                for (boolean next : theBooleans) {
169                        if (next) {
170                                if (haveOne) {
171                                        return true;
172                                } else {
173                                        haveOne = true;
174                                }
175                        }
176                }
177                return false;
178        }
179}