001package ca.uhn.fhir.jpa.dao.dstu3;
002
003/*-
004 * #%L
005 * HAPI FHIR Storage api
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.context.FhirContext;
025import ca.uhn.fhir.jpa.dao.ITransactionProcessorVersionAdapter;
026import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
027import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
028import ca.uhn.fhir.util.BundleUtil;
029import org.hl7.fhir.dstu3.model.Bundle;
030import org.hl7.fhir.dstu3.model.OperationOutcome;
031import org.hl7.fhir.dstu3.model.Resource;
032import org.hl7.fhir.exceptions.FHIRException;
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;
038
039import static org.apache.commons.lang3.StringUtils.isBlank;
040
041public class TransactionProcessorVersionAdapterDstu3 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(BaseServerResponseException theCaughtEx, Bundle.BundleEntryComponent theEntry) {
072                OperationOutcome oo = new OperationOutcome();
073                oo.addIssue()
074                        .setSeverity(OperationOutcome.IssueSeverity.ERROR)
075                        .setDiagnostics(theCaughtEx.getMessage())
076                        .setCode(OperationOutcome.IssueType.EXCEPTION);
077                theEntry.getResponse().setOutcome(oo);
078        }
079
080        @Override
081        public Bundle createBundle(String theBundleType) {
082                Bundle resp = new Bundle();
083                try {
084                        resp.setType(Bundle.BundleType.fromCode(theBundleType));
085                } catch (FHIRException theE) {
086                        throw new InternalErrorException(Msg.code(548) + "Unknown bundle type: " + theBundleType);
087                }
088                return resp;
089        }
090
091        @Override
092        public List<Bundle.BundleEntryComponent> getEntries(Bundle theRequest) {
093                return theRequest.getEntry();
094        }
095
096        @Override
097        public void addEntry(Bundle theBundle, Bundle.BundleEntryComponent theEntry) {
098                theBundle.addEntry(theEntry);
099        }
100
101        @Override
102        public Bundle.BundleEntryComponent addEntry(Bundle theBundle) {
103                return theBundle.addEntry();
104        }
105
106        @Override
107        public String getEntryRequestVerb(FhirContext theContext, Bundle.BundleEntryComponent theEntry) {
108                String retVal = null;
109                Bundle.HTTPVerb value = theEntry.getRequest().getMethodElement().getValue();
110                if (value != null) {
111                        retVal = value.toCode();
112                }
113
114                /*
115                 * This is a workaround for the fact that PATCH isn't a valid constant for
116                 * DSTU3 Bundle.entry.request.method (it was added in R4)
117                 */
118                if (isBlank(retVal)) {
119                        Resource resource = theEntry.getResource();
120                        boolean isPatch = BundleUtil.isDstu3TransactionPatch(theContext, resource);
121
122                        if (isPatch) {
123                                retVal = "PATCH";
124                        }
125                }
126                return retVal;
127        }
128
129        @Override
130        public String getFullUrl(Bundle.BundleEntryComponent theEntry) {
131                return theEntry.getFullUrl();
132        }
133
134        @Override
135        public void setFullUrl(Bundle.BundleEntryComponent theEntry, String theFullUrl) {
136                theEntry.setFullUrl(theFullUrl);
137        }
138
139        @Override
140        public String getEntryIfNoneExist(Bundle.BundleEntryComponent theEntry) {
141                return theEntry.getRequest().getIfNoneExist();
142        }
143
144        @Override
145        public String getEntryRequestUrl(Bundle.BundleEntryComponent theEntry) {
146                return theEntry.getRequest().getUrl();
147        }
148
149        @Override
150        public void setResponseLocation(Bundle.BundleEntryComponent theEntry, String theResponseLocation) {
151                theEntry.getResponse().setLocation(theResponseLocation);
152        }
153
154        @Override
155        public void setResponseETag(Bundle.BundleEntryComponent theEntry, String theEtag) {
156                theEntry.getResponse().setEtag(theEtag);
157        }
158
159        @Override
160        public String getEntryRequestIfMatch(Bundle.BundleEntryComponent theEntry) {
161                return theEntry.getRequest().getIfMatch();
162        }
163
164        @Override
165        public String getEntryRequestIfNoneExist(Bundle.BundleEntryComponent theEntry) {
166                return theEntry.getRequest().getIfNoneExist();
167        }
168
169        @Override
170        public String getEntryRequestIfNoneMatch(Bundle.BundleEntryComponent theEntry) {
171                return theEntry.getRequest().getIfNoneMatch();
172        }
173
174        @Override
175        public void setResponseOutcome(Bundle.BundleEntryComponent theEntry, IBaseOperationOutcome theOperationOutcome) {
176                theEntry.getResponse().setOutcome((Resource) theOperationOutcome);
177        }
178
179        @Override
180        public void setRequestVerb(Bundle.BundleEntryComponent theEntry, String theVerb) {
181                theEntry.getRequest().setMethod(Bundle.HTTPVerb.fromCode(theVerb));
182        }
183
184        @Override
185        public void setRequestUrl(Bundle.BundleEntryComponent theEntry, String theUrl) {
186                theEntry.getRequest().setUrl(theUrl);
187        }
188
189}