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