001/*-
002 * #%L
003 * HAPI FHIR JPA Server - Master Data Management
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.mdm.config;
021
022import ca.uhn.fhir.context.ConfigurationException;
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.i18n.Msg;
025import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
026import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
027import ca.uhn.fhir.jpa.subscription.channel.api.ChannelProducerSettings;
028import ca.uhn.fhir.jpa.subscription.channel.subscription.IChannelNamer;
029import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader;
030import ca.uhn.fhir.mdm.api.IMdmSettings;
031import ca.uhn.fhir.mdm.api.MdmConstants;
032import ca.uhn.fhir.mdm.log.Logs;
033import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
034import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
035import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
036import ca.uhn.fhir.util.HapiExtensions;
037import org.hl7.fhir.instance.model.api.IBaseResource;
038import org.hl7.fhir.r4.model.BooleanType;
039import org.hl7.fhir.r4.model.Subscription;
040import org.slf4j.Logger;
041import org.springframework.beans.factory.annotation.Autowired;
042import org.springframework.stereotype.Service;
043
044import java.util.List;
045import java.util.stream.Collectors;
046
047@Service
048public class MdmSubscriptionLoader {
049
050        public static final String MDM_SUBSCIPRION_ID_PREFIX = "mdm-";
051        private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
052
053        @Autowired
054        public FhirContext myFhirContext;
055
056        @Autowired
057        public DaoRegistry myDaoRegistry;
058
059        @Autowired
060        IChannelNamer myChannelNamer;
061
062        @Autowired
063        private SubscriptionLoader mySubscriptionLoader;
064
065        @Autowired
066        private IMdmSettings myMdmSettings;
067
068        private IFhirResourceDao<IBaseResource> mySubscriptionDao;
069
070        public synchronized void daoUpdateMdmSubscriptions() {
071                List<IBaseResource> subscriptions;
072                List<String> mdmResourceTypes = myMdmSettings.getMdmRules().getMdmTypes();
073                switch (myFhirContext.getVersion().getVersion()) {
074                        case DSTU3:
075                                subscriptions = mdmResourceTypes.stream()
076                                                .map(resourceType ->
077                                                                buildMdmSubscriptionDstu3(MDM_SUBSCIPRION_ID_PREFIX + resourceType, resourceType + "?"))
078                                                .collect(Collectors.toList());
079                                break;
080                        case R4:
081                                subscriptions = mdmResourceTypes.stream()
082                                                .map(resourceType ->
083                                                                buildMdmSubscriptionR4(MDM_SUBSCIPRION_ID_PREFIX + resourceType, resourceType + "?"))
084                                                .collect(Collectors.toList());
085                                break;
086                        default:
087                                throw new ConfigurationException(Msg.code(736) + "MDM not supported for FHIR version "
088                                                + myFhirContext.getVersion().getVersion());
089                }
090
091                mySubscriptionDao = myDaoRegistry.getResourceDao("Subscription");
092                for (IBaseResource subscription : subscriptions) {
093                        updateIfNotPresent(subscription);
094                }
095                // After loading all the subscriptions, sync the subscriptions to the registry.
096                if (subscriptions != null && subscriptions.size() > 0) {
097                        mySubscriptionLoader.syncDatabaseToCache();
098                }
099        }
100
101        synchronized void updateIfNotPresent(IBaseResource theSubscription) {
102                try {
103                        mySubscriptionDao.read(theSubscription.getIdElement(), SystemRequestDetails.forAllPartitions());
104                } catch (ResourceNotFoundException | ResourceGoneException e) {
105                        ourLog.info("Creating subscription " + theSubscription.getIdElement());
106                        mySubscriptionDao.update(theSubscription, SystemRequestDetails.forAllPartitions());
107                }
108        }
109
110        private org.hl7.fhir.dstu3.model.Subscription buildMdmSubscriptionDstu3(String theId, String theCriteria) {
111                org.hl7.fhir.dstu3.model.Subscription retval = new org.hl7.fhir.dstu3.model.Subscription();
112                retval.setId(theId);
113                retval.setReason("MDM");
114                retval.setStatus(org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus.REQUESTED);
115                retval.setCriteria(theCriteria);
116                retval.getMeta()
117                                .addTag()
118                                .setSystem(MdmConstants.SYSTEM_MDM_MANAGED)
119                                .setCode(MdmConstants.CODE_HAPI_MDM_MANAGED);
120                retval.addExtension()
121                                .setUrl(HapiExtensions.EXTENSION_SUBSCRIPTION_CROSS_PARTITION)
122                                .setValue(new org.hl7.fhir.dstu3.model.BooleanType().setValue(true));
123                org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelComponent channel = retval.getChannel();
124                channel.setType(org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType.MESSAGE);
125                channel.setEndpoint("channel:"
126                                + myChannelNamer.getChannelName(IMdmSettings.EMPI_CHANNEL_NAME, new ChannelProducerSettings()));
127                channel.setPayload("application/json");
128                return retval;
129        }
130
131        private Subscription buildMdmSubscriptionR4(String theId, String theCriteria) {
132                Subscription retval = new Subscription();
133                retval.setId(theId);
134                retval.setReason("MDM");
135                retval.setStatus(Subscription.SubscriptionStatus.REQUESTED);
136                retval.setCriteria(theCriteria);
137                retval.getMeta()
138                                .addTag()
139                                .setSystem(MdmConstants.SYSTEM_MDM_MANAGED)
140                                .setCode(MdmConstants.CODE_HAPI_MDM_MANAGED);
141                retval.addExtension()
142                                .setUrl(HapiExtensions.EXTENSION_SUBSCRIPTION_CROSS_PARTITION)
143                                .setValue(new BooleanType().setValue(true));
144                Subscription.SubscriptionChannelComponent channel = retval.getChannel();
145                channel.setType(Subscription.SubscriptionChannelType.MESSAGE);
146                channel.setEndpoint("channel:"
147                                + myChannelNamer.getChannelName(IMdmSettings.EMPI_CHANNEL_NAME, new ChannelProducerSettings()));
148                channel.setPayload("application/json");
149                return retval;
150        }
151}