001package ca.uhn.fhir.jpa.provider.r4;
002
003import ca.uhn.fhir.context.FhirContext;
004import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
005import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
006import ca.uhn.fhir.model.primitive.IdDt;
007import ca.uhn.fhir.rest.param.StringParam;
008import ca.uhn.fhir.rest.param.TokenOrListParam;
009import ca.uhn.fhir.util.ParametersUtil;
010import com.google.common.collect.Lists;
011import org.hl7.fhir.instance.model.api.IBaseParameters;
012import org.hl7.fhir.instance.model.api.IBaseResource;
013import org.hl7.fhir.r4.model.CodeableConcept;
014import org.hl7.fhir.r4.model.Coding;
015import org.hl7.fhir.r4.model.Coverage;
016import org.hl7.fhir.r4.model.Identifier;
017import org.hl7.fhir.r4.model.Parameters;
018import org.hl7.fhir.r4.model.Patient;
019import org.hl7.fhir.r4.model.Reference;
020import org.springframework.beans.factory.annotation.Autowired;
021
022import java.util.List;
023import java.util.Optional;
024
025import static ca.uhn.fhir.rest.api.Constants.PARAM_MEMBER_PATIENT;
026import static ca.uhn.fhir.rest.api.Constants.PARAM_NEW_COVERAGE;
027
028/*
029 * #%L
030 * HAPI FHIR JPA Server
031 * %%
032 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
033 * %%
034 * Licensed under the Apache License, Version 2.0 (the "License");
035 * you may not use this file except in compliance with the License.
036 * You may obtain a copy of the License at
037 *
038 *      http://www.apache.org/licenses/LICENSE-2.0
039 *
040 * Unless required by applicable law or agreed to in writing, software
041 * distributed under the License is distributed on an "AS IS" BASIS,
042 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
043 * See the License for the specific language governing permissions and
044 * limitations under the License.
045 * #L%
046 */
047
048public class MemberMatcherR4Helper {
049
050        private static final String OUT_COVERAGE_IDENTIFIER_CODE_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0203";
051        private static final String OUT_COVERAGE_IDENTIFIER_CODE = "UMB";
052        private static final String OUT_COVERAGE_IDENTIFIER_TEXT = "Member Number";
053        private static final String COVERAGE_TYPE = "Coverage";
054
055        private final FhirContext myFhirContext;
056
057        @Autowired
058        private IFhirResourceDao<Coverage> myCoverageDao;
059
060        @Autowired
061        private IFhirResourceDao<Patient> myPatientDao;
062
063
064        public MemberMatcherR4Helper(FhirContext theContext) {
065                myFhirContext = theContext;
066        }
067
068        /**
069         * Find Coverage matching the received member (Patient) by coverage id or by coverage identifier
070         * Matching by member patient demographics is not supported.
071         */
072        public Optional<Coverage> findMatchingCoverage(Coverage theCoverageToMatch) {
073                // search by received old coverage id
074                List<IBaseResource> foundCoverages = findCoverageByCoverageId(theCoverageToMatch);
075                if (foundCoverages.size() == 1 && isCoverage(foundCoverages.get(0))) {
076                        return Optional.of( (Coverage) foundCoverages.get(0) );
077                }
078
079                // search by received old coverage identifier
080                foundCoverages = findCoverageByCoverageIdentifier(theCoverageToMatch);
081                if (foundCoverages.size() == 1 && isCoverage(foundCoverages.get(0))) {
082                        return Optional.of( (Coverage) foundCoverages.get(0) );
083                }
084
085                return Optional.empty();
086        }
087
088
089        private List<IBaseResource> findCoverageByCoverageIdentifier(Coverage theCoverageToMatch) {
090                TokenOrListParam identifierParam = new TokenOrListParam();
091                for (Identifier identifier : theCoverageToMatch.getIdentifier()) {
092                        identifierParam.add(identifier.getSystem(), identifier.getValue());
093                }
094
095                SearchParameterMap paramMap = new SearchParameterMap()
096                        .add("identifier", identifierParam);
097                ca.uhn.fhir.rest.api.server.IBundleProvider retVal = myCoverageDao.search(paramMap);
098
099                return retVal.getAllResources();
100        }
101
102
103        private boolean isCoverage(IBaseResource theIBaseResource) {
104                return theIBaseResource.fhirType().equals(COVERAGE_TYPE);
105        }
106
107
108        private List<IBaseResource> findCoverageByCoverageId(Coverage theCoverageToMatch) {
109                SearchParameterMap paramMap = new SearchParameterMap()
110                        .add("_id", new StringParam(theCoverageToMatch.getId()));
111                ca.uhn.fhir.rest.api.server.IBundleProvider retVal = myCoverageDao.search(paramMap);
112
113                return retVal.getAllResources();
114        }
115
116
117        public Parameters buildSuccessReturnParameters(Patient theMemberPatient, Coverage theCoverage) {
118                IBaseParameters parameters = ParametersUtil.newInstance(myFhirContext);
119                ParametersUtil.addParameterToParameters(myFhirContext, parameters, PARAM_MEMBER_PATIENT, theMemberPatient);
120                ParametersUtil.addParameterToParameters(myFhirContext, parameters, PARAM_NEW_COVERAGE, theCoverage);
121                return (Parameters) parameters;
122        }
123
124
125        public void addMemberIdentifierToMemberPatient(Patient theMemberPatient, Identifier theNewIdentifier) {
126                Coding coding = new Coding()
127                        .setSystem(OUT_COVERAGE_IDENTIFIER_CODE_SYSTEM)
128                        .setCode(OUT_COVERAGE_IDENTIFIER_CODE)
129                        .setDisplay(OUT_COVERAGE_IDENTIFIER_TEXT)
130                        .setUserSelected(false);
131
132                CodeableConcept concept = new CodeableConcept()
133                        .setCoding(Lists.newArrayList(coding))
134                        .setText(OUT_COVERAGE_IDENTIFIER_TEXT);
135
136                Identifier newIdentifier = new Identifier()
137                        .setUse(Identifier.IdentifierUse.USUAL)
138                        .setType(concept)
139                        .setSystem(theNewIdentifier.getSystem())
140                        .setValue(theNewIdentifier.getValue());
141
142                theMemberPatient.addIdentifier(newIdentifier);
143        }
144
145
146        public Optional<Patient> getBeneficiaryPatient(Coverage theCoverage) {
147                if (theCoverage.getBeneficiaryTarget() == null && theCoverage.getBeneficiary() == null) {
148                        return Optional.empty();
149                }
150
151                if (theCoverage.getBeneficiaryTarget() != null
152                                && ! theCoverage.getBeneficiaryTarget().getIdentifier().isEmpty()) {
153                        return Optional.of(theCoverage.getBeneficiaryTarget());
154                }
155
156                Reference beneficiaryRef = theCoverage.getBeneficiary();
157                if (beneficiaryRef == null) {
158                        return Optional.empty();
159                }
160
161                if (beneficiaryRef.getResource() != null) {
162                        return Optional.of((Patient) beneficiaryRef.getResource());
163                }
164
165                if (beneficiaryRef.getReference() == null) {
166                        return Optional.empty();
167                }
168
169                Patient beneficiary = myPatientDao.read(new IdDt(beneficiaryRef.getReference()));
170                return Optional.ofNullable(beneficiary);
171        }
172}