
001/*- 002 * #%L 003 * HAPI FHIR Storage api 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.api.svc; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; 025import ca.uhn.fhir.jpa.api.model.PersistentIdToForcedIdMap; 026import ca.uhn.fhir.jpa.model.cross.IResourceLookup; 027import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; 028import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; 029import org.hl7.fhir.instance.model.api.IAnyResource; 030import org.hl7.fhir.instance.model.api.IBaseResource; 031import org.hl7.fhir.instance.model.api.IIdType; 032 033import javax.annotation.Nonnull; 034import javax.annotation.Nullable; 035import java.util.Date; 036import java.util.List; 037import java.util.Map; 038import java.util.Optional; 039import java.util.Set; 040 041/** 042 * This interface is used to translate between {@link IResourcePersistentId} 043 * and actual resource IDs. 044 */ 045public interface IIdHelperService<T extends IResourcePersistentId> { 046 047 /** 048 * Given a collection of resource IDs (resource type + id), resolves the internal persistent IDs. 049 * <p> 050 * This implementation will always try to use a cache for performance, meaning that it can resolve resources that 051 * are deleted (but note that forced IDs can't change, so the cache can't return incorrect results) 052 * 053 * @param theOnlyForcedIds If <code>true</code>, resources which are not existing forced IDs will not be resolved 054 */ 055 @Nonnull 056 List<T> resolveResourcePersistentIdsWithCache(@Nonnull RequestPartitionId theRequestPartitionId, List<IIdType> theIds, boolean theOnlyForcedIds); 057 058 /** 059 * Given a resource type and ID, determines the internal persistent ID for the resource. 060 * 061 * @throws ResourceNotFoundException If the ID can not be found 062 */ 063 @Nonnull 064 T resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId); 065 066 /** 067 * Given a resource type and ID, determines the internal persistent ID for a resource. 068 * Optionally filters out deleted resources. 069 * 070 * @throws ResourceNotFoundException If the ID can not be found 071 */ 072 @Nonnull 073 T resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theId, boolean theExcludeDeleted); 074 075 /** 076 * Returns a mapping of Id -> IResourcePersistentId. 077 * If any resource is not found, it will throw ResourceNotFound exception 078 * (and no map will be returned) 079 */ 080 @Nonnull 081 Map<String, T> resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, List<String> theIds); 082 083 /** 084 * Returns a mapping of Id -> IResourcePersistentId. 085 * If any resource is not found, it will throw ResourceNotFound exception (and no map will be returned) 086 * Optionally filters out deleted resources. 087 */ 088 @Nonnull 089 Map<String, T> resolveResourcePersistentIds(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, List<String> theIds, boolean theExcludeDeleted); 090 091 /** 092 * Given a persistent ID, returns the associated resource ID 093 */ 094 @Nonnull 095 IIdType translatePidIdToForcedId(FhirContext theCtx, String theResourceType, T theId); 096 097 /** 098 * Given a forced ID, convert it to it's Long value. Since you are allowed to use string IDs for resources, we need to 099 * convert those to the underlying Long values that are stored, for lookup and comparison purposes. 100 * 101 * @throws ResourceNotFoundException If the ID can not be found 102 */ 103 @Nonnull 104 IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId) throws ResourceNotFoundException; 105 106 /** 107 * Given a forced ID, convert it to it's Long value. Since you are allowed to use string IDs for resources, we need to 108 * convert those to the underlying Long values that are stored, for lookup and comparison purposes. 109 * Optionally filters out deleted resources. 110 * 111 * @throws ResourceNotFoundException If the ID can not be found 112 */ 113 @Nonnull 114 IResourceLookup resolveResourceIdentity(@Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, String theResourceId, boolean theExcludeDeleted) throws ResourceNotFoundException; 115 116 /** 117 * Returns true if the given resource ID should be stored in a forced ID. Under default config 118 * (meaning client ID strategy is {@link JpaStorageSettings.ClientIdStrategyEnum#ALPHANUMERIC}) 119 * this will return true if the ID has any non-digit characters. 120 * <p> 121 * In {@link JpaStorageSettings.ClientIdStrategyEnum#ANY} mode it will always return true. 122 */ 123 boolean idRequiresForcedId(String theId); 124 125 /** 126 * Given a collection of resource IDs (resource type + id), resolves the internal persistent IDs. 127 * <p> 128 * This implementation will always try to use a cache for performance, meaning that it can resolve resources that 129 * are deleted (but note that forced IDs can't change, so the cache can't return incorrect results) 130 */ 131 @Nonnull 132 List<T> resolveResourcePersistentIdsWithCache(RequestPartitionId theRequestPartitionId, List<IIdType> theIds); 133 134 Optional<String> translatePidIdToForcedIdWithCache(T theResourcePersistentId); 135 136 PersistentIdToForcedIdMap<T> translatePidsToForcedIds(Set<T> theResourceIds); 137 138 /** 139 * Pre-cache a PID-to-Resource-ID mapping for later retrieval by {@link #translatePidsToForcedIds(Set)} and related methods 140 */ 141 void addResolvedPidToForcedId(T theResourcePersistentId, @Nonnull RequestPartitionId theRequestPartitionId, String theResourceType, @Nullable String theForcedId, @Nullable Date theDeletedAt); 142 143 @Nonnull 144 List<T> getPidsOrThrowException(RequestPartitionId theRequestPartitionId, List<IIdType> theIds); 145 146 @Nullable 147 T getPidOrNull(RequestPartitionId theRequestPartitionId, IBaseResource theResource); 148 149 @Nonnull 150 T getPidOrThrowException(RequestPartitionId theRequestPartitionId, IIdType theId); 151 152 @Nonnull 153 T getPidOrThrowException(@Nonnull IAnyResource theResource); 154 155 IIdType resourceIdFromPidOrThrowException(T thePid, String theResourceType); 156 157 /** 158 * Given a set of PIDs, return a set of public FHIR Resource IDs. 159 * This function will resolve a forced ID if it resolves, and if it fails to resolve to a forced it, will just return the pid 160 * Example: 161 * Let's say we have Patient/1(pid == 1), Patient/pat1 (pid == 2), Patient/3 (pid == 3), their pids would resolve as follows: 162 * <p> 163 * [1,2,3] -> ["1","pat1","3"] 164 * 165 * @param thePids The Set of pids you would like to resolve to external FHIR Resource IDs. 166 * @return A Set of strings representing the FHIR IDs of the pids. 167 */ 168 Set<String> translatePidsToFhirResourceIds(Set<T> thePids); 169 170 T newPid(Object thePid); 171 172 T newPidFromStringIdAndResourceName(String thePid, String theResourceType); 173}