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}