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