001package ca.uhn.fhir.jpa.mdm.config;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server - Master Data Management
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.context.ConfigurationException;
024import ca.uhn.fhir.context.FhirContext;
025import ca.uhn.fhir.i18n.Msg;
026import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
027import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
028import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
029import ca.uhn.fhir.jpa.subscription.channel.api.ChannelProducerSettings;
030import ca.uhn.fhir.jpa.subscription.channel.subscription.IChannelNamer;
031import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader;
032import ca.uhn.fhir.mdm.api.IMdmSettings;
033import ca.uhn.fhir.mdm.api.MdmConstants;
034import ca.uhn.fhir.mdm.log.Logs;
035import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
036import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
037import ca.uhn.fhir.util.HapiExtensions;
038import org.hl7.fhir.instance.model.api.IBaseResource;
039import org.hl7.fhir.r4.model.BooleanType;
040import org.hl7.fhir.r4.model.Subscription;
041import org.slf4j.Logger;
042import org.springframework.beans.factory.annotation.Autowired;
043import org.springframework.stereotype.Service;
044
045import java.util.List;
046import java.util.stream.Collectors;
047
048@Service
049public class MdmSubscriptionLoader {
050
051        public static final String MDM_SUBSCIPRION_ID_PREFIX = "mdm-";
052        private static final Logger ourLog = Logs.getMdmTroubleshootingLog();
053        @Autowired
054        public FhirContext myFhirContext;
055        @Autowired
056        public DaoRegistry myDaoRegistry;
057        @Autowired
058        IChannelNamer myChannelNamer;
059        @Autowired
060        private SubscriptionLoader mySubscriptionLoader;
061        @Autowired
062        private IMdmSettings myMdmSettings;
063
064        private IFhirResourceDao<IBaseResource> mySubscriptionDao;
065
066        synchronized public void daoUpdateMdmSubscriptions() {
067                List<IBaseResource> subscriptions;
068                List<String> mdmResourceTypes = myMdmSettings.getMdmRules().getMdmTypes();
069                switch (myFhirContext.getVersion().getVersion()) {
070                        case DSTU3:
071                                subscriptions = mdmResourceTypes
072                                        .stream()
073                                        .map(resourceType -> buildMdmSubscriptionDstu3(MDM_SUBSCIPRION_ID_PREFIX + resourceType, resourceType + "?"))
074                                        .collect(Collectors.toList());
075                                break;
076                        case R4:
077                                subscriptions = mdmResourceTypes
078                                        .stream()
079                                        .map(resourceType -> buildMdmSubscriptionR4(MDM_SUBSCIPRION_ID_PREFIX + resourceType, resourceType + "?"))
080                                        .collect(Collectors.toList());
081                                break;
082                        default:
083                                throw new ConfigurationException(Msg.code(736) + "MDM not supported for FHIR version " + myFhirContext.getVersion().getVersion());
084                }
085
086                mySubscriptionDao = myDaoRegistry.getResourceDao("Subscription");
087                for (IBaseResource subscription : subscriptions) {
088                        updateIfNotPresent(subscription);
089                }
090                //After loading all the subscriptions, sync the subscriptions to the registry.
091                if (subscriptions != null && subscriptions.size() > 0) {
092                        mySubscriptionLoader.syncSubscriptions();
093                }
094        }
095
096        synchronized void updateIfNotPresent(IBaseResource theSubscription) {
097                try {
098                        mySubscriptionDao.read(theSubscription.getIdElement(), SystemRequestDetails.forAllPartitions());
099                } catch (ResourceNotFoundException | ResourceGoneException e) {
100                        ourLog.info("Creating subscription " + theSubscription.getIdElement());
101                        mySubscriptionDao.update(theSubscription, SystemRequestDetails.forAllPartitions());
102                }
103        }
104
105        private org.hl7.fhir.dstu3.model.Subscription buildMdmSubscriptionDstu3(String theId, String theCriteria) {
106                org.hl7.fhir.dstu3.model.Subscription retval = new org.hl7.fhir.dstu3.model.Subscription();
107                retval.setId(theId);
108                retval.setReason("MDM");
109                retval.setStatus(org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus.REQUESTED);
110                retval.setCriteria(theCriteria);
111                retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED);
112                retval.addExtension().setUrl(HapiExtensions.EXTENSION_SUBSCRIPTION_CROSS_PARTITION).setValue(new org.hl7.fhir.dstu3.model.BooleanType().setValue(true));
113                org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelComponent channel = retval.getChannel();
114                channel.setType(org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType.MESSAGE);
115                channel.setEndpoint("channel:" + myChannelNamer.getChannelName(IMdmSettings.EMPI_CHANNEL_NAME, new ChannelProducerSettings()));
116                channel.setPayload("application/json");
117                return retval;
118        }
119
120        private Subscription buildMdmSubscriptionR4(String theId, String theCriteria) {
121                Subscription retval = new Subscription();
122                retval.setId(theId);
123                retval.setReason("MDM");
124                retval.setStatus(Subscription.SubscriptionStatus.REQUESTED);
125                retval.setCriteria(theCriteria);
126                retval.getMeta().addTag().setSystem(MdmConstants.SYSTEM_MDM_MANAGED).setCode(MdmConstants.CODE_HAPI_MDM_MANAGED);
127                retval.addExtension().setUrl(HapiExtensions.EXTENSION_SUBSCRIPTION_CROSS_PARTITION).setValue(new BooleanType().setValue(true));
128                Subscription.SubscriptionChannelComponent channel = retval.getChannel();
129                channel.setType(Subscription.SubscriptionChannelType.MESSAGE);
130                channel.setEndpoint("channel:" + myChannelNamer.getChannelName(IMdmSettings.EMPI_CHANNEL_NAME, new ChannelProducerSettings()));
131                channel.setPayload("application/json");
132                return retval;
133        }
134}