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}