001package ca.uhn.fhir.rest.api;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
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.util.CoverageIgnore;
024import org.apache.commons.lang3.Validate;
025import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
026import org.hl7.fhir.instance.model.api.IBaseResource;
027import org.hl7.fhir.instance.model.api.IIdType;
028
029import java.util.ArrayList;
030import java.util.Collection;
031import java.util.List;
032import java.util.Map;
033
034public class MethodOutcome {
035
036        private Boolean myCreated;
037        private IIdType myId;
038        private IBaseOperationOutcome myOperationOutcome;
039        private IBaseResource myResource;
040        private Map<String, List<String>> myResponseHeaders;
041        private Collection<Runnable> myResourceViewCallbacks;
042        private int myResponseStatusCode;
043
044        /**
045         * Constructor
046         */
047        public MethodOutcome() {
048                super();
049        }
050
051        /**
052         * Constructor
053         *
054         * @param theId      The ID of the created/updated resource
055         * @param theCreated If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called
056         *                   whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
057         */
058        @CoverageIgnore
059        public MethodOutcome(IIdType theId, Boolean theCreated) {
060                myId = theId;
061                myCreated = theCreated;
062        }
063
064        /**
065         * Constructor
066         *
067         * @param theId                   The ID of the created/updated resource
068         * @param theBaseOperationOutcome The operation outcome to return with the response (or null for none)
069         */
070        public MethodOutcome(IIdType theId, IBaseOperationOutcome theBaseOperationOutcome) {
071                myId = theId;
072                myOperationOutcome = theBaseOperationOutcome;
073        }
074
075        /**
076         * Constructor
077         *
078         * @param theId                   The ID of the created/updated resource
079         * @param theBaseOperationOutcome The operation outcome to return with the response (or null for none)
080         * @param theCreated              If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called
081         *                                whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
082         */
083        public MethodOutcome(IIdType theId, IBaseOperationOutcome theBaseOperationOutcome, Boolean theCreated) {
084                myId = theId;
085                myOperationOutcome = theBaseOperationOutcome;
086                myCreated = theCreated;
087        }
088
089        /**
090         * Constructor
091         *
092         * @param theId The ID of the created/updated resource
093         */
094        public MethodOutcome(IIdType theId) {
095                myId = theId;
096        }
097
098        /**
099         * Constructor
100         *
101         * @param theOperationOutcome The operation outcome resource to return
102         */
103        public MethodOutcome(IBaseOperationOutcome theOperationOutcome) {
104                myOperationOutcome = theOperationOutcome;
105        }
106
107        /**
108         * This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are
109         * returned to client instances, if the server has responded with an HTTP 201 Created.
110         */
111        public Boolean getCreated() {
112                return myCreated;
113        }
114
115        /**
116         * If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called whether the
117         * result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
118         * <p>
119         * Users of HAPI should only interact with this method in Server applications
120         * </p>
121         *
122         * @param theCreated If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called
123         *                   whether the result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist.
124         * @return Returns a reference to <code>this</code> for easy method chaining
125         */
126        public MethodOutcome setCreated(Boolean theCreated) {
127                myCreated = theCreated;
128                return this;
129        }
130
131        public IIdType getId() {
132                return myId;
133        }
134
135        /**
136         * @param theId The ID of the created/updated resource
137         * @return Returns a reference to <code>this</code> for easy method chaining
138         */
139        public MethodOutcome setId(IIdType theId) {
140                myId = theId;
141                return this;
142        }
143
144        /**
145         * Returns the {@link IBaseOperationOutcome} resource to return to the client or <code>null</code> if none.
146         *
147         * @return This method <b>will return null</b>, unlike many methods in the API.
148         */
149        public IBaseOperationOutcome getOperationOutcome() {
150                return myOperationOutcome;
151        }
152
153        /**
154         * Sets the {@link IBaseOperationOutcome} resource to return to the client. Set to <code>null</code> (which is the default) if none.
155         *
156         * @return Returns a reference to <code>this</code> for easy method chaining
157         */
158        public MethodOutcome setOperationOutcome(IBaseOperationOutcome theBaseOperationOutcome) {
159                myOperationOutcome = theBaseOperationOutcome;
160                return this;
161        }
162
163        /**
164         * <b>From a client response:</b> If the method returned an actual resource body (e.g. a create/update with
165         * "Prefer: return=representation") this field will be populated with the
166         * resource itself.
167         */
168        public IBaseResource getResource() {
169                return myResource;
170        }
171
172        /**
173         * <b>In a server response</b>: This field may be populated in server code with the final resource for operations
174         * where a resource body is being created/updated. E.g. for an update method, this field could be populated with
175         * the resource after the update is applied, with the new version ID, lastUpdate time, etc.
176         * <p>
177         * This field is optional, but if it is populated the server will return the resource body if requested to
178         * do so via the HTTP Prefer header.
179         * </p>
180         *
181         * @return Returns a reference to <code>this</code> for easy method chaining
182         * @see #registerResourceViewCallback(Runnable) to register a callback that should be invoked by the framework before the resource is shown/returned to a client
183         */
184        public MethodOutcome setResource(IBaseResource theResource) {
185                myResource = theResource;
186                return this;
187        }
188
189        /**
190         * Gets the headers for the HTTP response
191         */
192        public Map<String, List<String>> getResponseHeaders() {
193                return myResponseHeaders;
194        }
195
196        /**
197         * Sets the headers for the HTTP response
198         */
199        public void setResponseHeaders(Map<String, List<String>> theResponseHeaders) {
200                myResponseHeaders = theResponseHeaders;
201        }
202
203        /**
204         * Registers a callback to be invoked before the resource in this object gets
205         * returned to the client. Note that this is an experimental API and may change.
206         *
207         * @param theCallback The callback
208         * @since 4.0.0
209         */
210        public void registerResourceViewCallback(Runnable theCallback) {
211                Validate.notNull(theCallback, "theCallback must not be null");
212
213                if (myResourceViewCallbacks == null) {
214                        myResourceViewCallbacks = new ArrayList<>(2);
215                }
216                myResourceViewCallbacks.add(theCallback);
217        }
218
219        /**
220         * Fires callbacks registered to {@link #registerResourceViewCallback(Runnable)} and then
221         * clears the list of registered callbacks.
222         *
223         * @since 4.0.0
224         */
225        public void fireResourceViewCallbacks() {
226                if (myResourceViewCallbacks != null) {
227                        myResourceViewCallbacks.forEach(t -> t.run());
228                        myResourceViewCallbacks.clear();
229                }
230        }
231
232        public void setCreatedUsingStatusCode(int theResponseStatusCode) {
233                if (theResponseStatusCode == Constants.STATUS_HTTP_201_CREATED) {
234                        setCreated(true);
235                }
236        }
237
238        protected boolean hasResource() {
239                return myResource != null;
240        }
241
242        public void setStatusCode(int theResponseStatusCode) {
243                myResponseStatusCode = theResponseStatusCode;
244        }
245
246        public int getResponseStatusCode() {
247                return myResponseStatusCode;
248        }
249}