
001/*- 002 * #%L 003 * HAPI FHIR Storage api 004 * %% 005 * Copyright (C) 2014 - 2025 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.dao.dstu3; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.jpa.dao.ITransactionProcessorVersionAdapter; 025import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; 026import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 027import ca.uhn.fhir.util.BundleUtil; 028import org.hl7.fhir.dstu3.model.Bundle; 029import org.hl7.fhir.dstu3.model.OperationOutcome; 030import org.hl7.fhir.dstu3.model.Resource; 031import org.hl7.fhir.exceptions.FHIRException; 032import org.hl7.fhir.instance.model.api.IBaseExtension; 033import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; 034import org.hl7.fhir.instance.model.api.IBaseResource; 035 036import java.util.Date; 037import java.util.List; 038import java.util.Optional; 039 040import static org.apache.commons.lang3.StringUtils.isBlank; 041 042public class TransactionProcessorVersionAdapterDstu3 043 implements ITransactionProcessorVersionAdapter<Bundle, Bundle.BundleEntryComponent> { 044 @Override 045 public void setResponseStatus(Bundle.BundleEntryComponent theBundleEntry, String theStatus) { 046 theBundleEntry.getResponse().setStatus(theStatus); 047 } 048 049 @Override 050 public void setResponseLastModified(Bundle.BundleEntryComponent theBundleEntry, Date theLastModified) { 051 theBundleEntry.getResponse().setLastModified(theLastModified); 052 } 053 054 @Override 055 public void setResource(Bundle.BundleEntryComponent theBundleEntry, IBaseResource theResource) { 056 theBundleEntry.setResource((Resource) theResource); 057 } 058 059 @Override 060 public IBaseResource getResource(Bundle.BundleEntryComponent theBundleEntry) { 061 return theBundleEntry.getResource(); 062 } 063 064 @Override 065 public String getBundleType(Bundle theRequest) { 066 if (theRequest.getType() == null) { 067 return null; 068 } 069 return theRequest.getTypeElement().getValue().toCode(); 070 } 071 072 @Override 073 public void populateEntryWithOperationOutcome( 074 BaseServerResponseException theCaughtEx, Bundle.BundleEntryComponent theEntry) { 075 OperationOutcome oo = new OperationOutcome(); 076 oo.addIssue() 077 .setSeverity(OperationOutcome.IssueSeverity.ERROR) 078 .setDiagnostics(theCaughtEx.getMessage()) 079 .setCode(OperationOutcome.IssueType.EXCEPTION); 080 theEntry.getResponse().setOutcome(oo); 081 } 082 083 @Override 084 public Bundle createBundle(String theBundleType) { 085 Bundle resp = new Bundle(); 086 try { 087 resp.setType(Bundle.BundleType.fromCode(theBundleType)); 088 } catch (FHIRException theE) { 089 throw new InternalErrorException(Msg.code(548) + "Unknown bundle type: " + theBundleType); 090 } 091 return resp; 092 } 093 094 @Override 095 public List<Bundle.BundleEntryComponent> getEntries(Bundle theRequest) { 096 return theRequest.getEntry(); 097 } 098 099 @Override 100 public void addEntry(Bundle theBundle, Bundle.BundleEntryComponent theEntry) { 101 theBundle.addEntry(theEntry); 102 } 103 104 @Override 105 public Bundle.BundleEntryComponent addEntry(Bundle theBundle) { 106 return theBundle.addEntry(); 107 } 108 109 @Override 110 public String getEntryRequestVerb(FhirContext theContext, Bundle.BundleEntryComponent theEntry) { 111 String retVal = null; 112 Bundle.HTTPVerb value = theEntry.getRequest().getMethodElement().getValue(); 113 if (value != null) { 114 retVal = value.toCode(); 115 } 116 117 /* 118 * This is a workaround for the fact that PATCH isn't a valid constant for 119 * DSTU3 Bundle.entry.request.method (it was added in R4) 120 */ 121 if (isBlank(retVal)) { 122 Resource resource = theEntry.getResource(); 123 boolean isPatch = BundleUtil.isDstu3TransactionPatch(theContext, resource); 124 125 if (isPatch) { 126 retVal = "PATCH"; 127 } 128 } 129 return retVal; 130 } 131 132 @Override 133 public String getFullUrl(Bundle.BundleEntryComponent theEntry) { 134 return theEntry.getFullUrl(); 135 } 136 137 @Override 138 public void setFullUrl(Bundle.BundleEntryComponent theEntry, String theFullUrl) { 139 theEntry.setFullUrl(theFullUrl); 140 } 141 142 @Override 143 public String getEntryIfNoneExist(Bundle.BundleEntryComponent theEntry) { 144 return theEntry.getRequest().getIfNoneExist(); 145 } 146 147 @Override 148 public String getEntryRequestUrl(Bundle.BundleEntryComponent theEntry) { 149 return theEntry.getRequest().getUrl(); 150 } 151 152 @Override 153 public void setResponseLocation(Bundle.BundleEntryComponent theEntry, String theResponseLocation) { 154 theEntry.getResponse().setLocation(theResponseLocation); 155 } 156 157 @Override 158 public void setResponseETag(Bundle.BundleEntryComponent theEntry, String theEtag) { 159 theEntry.getResponse().setEtag(theEtag); 160 } 161 162 @Override 163 public String getEntryRequestIfMatch(Bundle.BundleEntryComponent theEntry) { 164 return theEntry.getRequest().getIfMatch(); 165 } 166 167 @Override 168 public String getEntryRequestIfNoneExist(Bundle.BundleEntryComponent theEntry) { 169 return theEntry.getRequest().getIfNoneExist(); 170 } 171 172 @Override 173 public String getEntryRequestIfNoneMatch(Bundle.BundleEntryComponent theEntry) { 174 return theEntry.getRequest().getIfNoneMatch(); 175 } 176 177 @Override 178 public void setResponseOutcome(Bundle.BundleEntryComponent theEntry, IBaseOperationOutcome theOperationOutcome) { 179 theEntry.getResponse().setOutcome((Resource) theOperationOutcome); 180 } 181 182 @Override 183 public void setRequestVerb(Bundle.BundleEntryComponent theEntry, String theVerb) { 184 theEntry.getRequest().setMethod(Bundle.HTTPVerb.fromCode(theVerb)); 185 } 186 187 @Override 188 public void setRequestUrl(Bundle.BundleEntryComponent theEntry, String theUrl) { 189 theEntry.getRequest().setUrl(theUrl); 190 } 191 192 @Override 193 public Optional<IBaseExtension<?, ?>> getEntryRequestExtensionByUrl( 194 Bundle.BundleEntryComponent theEntry, String theUrl) { 195 return Optional.ofNullable(theEntry.getRequest().getExtensionByUrl(theUrl)); 196 } 197}