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}