001package ca.uhn.fhir.rest.method;
002
003import java.io.IOException;
004import java.io.InputStream;
005import java.io.Reader;
006import java.io.UnsupportedEncodingException;
007
008/*
009 * #%L
010 * HAPI FHIR - Core Library
011 * %%
012 * Copyright (C) 2014 - 2016 University Health Network
013 * %%
014 * Licensed under the Apache License, Version 2.0 (the "License");
015 * you may not use this file except in compliance with the License.
016 * You may obtain a copy of the License at
017 * 
018 *      http://www.apache.org/licenses/LICENSE-2.0
019 * 
020 * Unless required by applicable law or agreed to in writing, software
021 * distributed under the License is distributed on an "AS IS" BASIS,
022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
023 * See the License for the specific language governing permissions and
024 * limitations under the License.
025 * #L%
026 */
027
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.HashMap;
031import java.util.List;
032import java.util.Map;
033
034import org.hl7.fhir.instance.model.api.IIdType;
035
036import ca.uhn.fhir.rest.api.RequestTypeEnum;
037import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
038import ca.uhn.fhir.rest.server.IRestfulResponse;
039import ca.uhn.fhir.rest.server.IRestfulServerDefaults;
040
041public abstract class RequestDetails {
042
043        private byte[] myRequestContents;
044        private String myCompartmentName;
045        private String myCompleteUrl;
046        private String myFhirServerBase;
047        private IIdType myId;
048        private String myOperation;
049        private Map<String, String[]> myParameters;
050        private String myRequestPath;
051        private RequestTypeEnum myRequestType;
052        private String myResourceName;
053        private boolean myRespondGzip;
054        private RestOperationTypeEnum myRestOperationType;
055        private String mySecondaryOperation;
056        private Map<String, List<String>> myUnqualifiedToQualifiedNames;
057        private IRestfulResponse myResponse;
058
059        public String getCompartmentName() {
060                return myCompartmentName;
061        }
062
063        public String getCompleteUrl() {
064                return myCompleteUrl;
065        }
066
067        /**
068         * The fhir server base url, independant of the query being executed
069         * 
070         * @return the fhir server base url
071         */
072        public String getFhirServerBase() {
073                return myFhirServerBase;
074        }
075
076        public IIdType getId() {
077                return myId;
078        }
079
080        public String getOperation() {
081                return myOperation;
082        }
083
084        public Map<String, String[]> getParameters() {
085                return myParameters;
086        }
087
088        /**
089         * The part of the request URL that comes after the server base.
090         * <p>
091         * Will not contain a leading '/'
092         * </p>
093         */
094        public String getRequestPath() {
095                return myRequestPath;
096        }
097
098        public RequestTypeEnum getRequestType() {
099                return myRequestType;
100        }
101
102        public String getResourceName() {
103                return myResourceName;
104        }
105
106        public RestOperationTypeEnum getRestOperationType() {
107                return myRestOperationType;
108        }
109
110        public String getSecondaryOperation() {
111                return mySecondaryOperation;
112        }
113
114        public abstract IRestfulServerDefaults getServer();
115
116        public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
117                return myUnqualifiedToQualifiedNames;
118        }
119
120        public boolean isRespondGzip() {
121                return myRespondGzip;
122        }
123
124        public void setCompartmentName(String theCompartmentName) {
125                myCompartmentName = theCompartmentName;
126        }
127
128        public void setCompleteUrl(String theCompleteUrl) {
129                myCompleteUrl = theCompleteUrl;
130        }
131
132        public void setFhirServerBase(String theFhirServerBase) {
133                myFhirServerBase = theFhirServerBase;
134        }
135
136        public void setId(IIdType theId) {
137                myId = theId;
138        }
139
140        public void setOperation(String theOperation) {
141                myOperation = theOperation;
142        }
143
144        public void setParameters(Map<String, String[]> theParams) {
145                myParameters = theParams;
146
147                for (String next : theParams.keySet()) {
148                        for (int i = 0; i < next.length(); i++) {
149                                char nextChar = next.charAt(i);
150                                if (nextChar == ':' || nextChar == '.') {
151                                        if (myUnqualifiedToQualifiedNames == null) {
152                                                myUnqualifiedToQualifiedNames = new HashMap<String, List<String>>();
153                                        }
154                                        String unqualified = next.substring(0, i);
155                                        List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
156                                        if (list == null) {
157                                                list = new ArrayList<String>(4);
158                                                myUnqualifiedToQualifiedNames.put(unqualified, list);
159                                        }
160                                        list.add(next);
161                                        break;
162                                }
163                        }
164                }
165
166                if (myUnqualifiedToQualifiedNames == null) {
167                        myUnqualifiedToQualifiedNames = Collections.emptyMap();
168                }
169
170        }
171
172        public void setRequestPath(String theRequestPath) {
173                assert theRequestPath.length() == 0 || theRequestPath.charAt(0) != '/';
174                myRequestPath = theRequestPath;
175        }
176
177        public void setRequestType(RequestTypeEnum theRequestType) {
178                myRequestType = theRequestType;
179        }
180
181        public void setResourceName(String theResourceName) {
182                myResourceName = theResourceName;
183        }
184
185        public void setRespondGzip(boolean theRespondGzip) {
186                myRespondGzip = theRespondGzip;
187        }
188
189        public void setRestOperationType(RestOperationTypeEnum theRestOperationType) {
190                myRestOperationType = theRestOperationType;
191        }
192
193        public void setSecondaryOperation(String theSecondaryOperation) {
194                mySecondaryOperation = theSecondaryOperation;
195        }
196
197        public IRestfulResponse getResponse() {
198                return myResponse;
199        }
200
201        public void setResponse(IRestfulResponse theResponse) {
202                this.myResponse = theResponse;
203        }
204
205        public abstract String getHeader(String name);
206
207        public final byte[] loadRequestContents() {
208                if (myRequestContents == null) {
209                        myRequestContents = getByteStreamRequestContents();
210                }
211                return myRequestContents;
212        }
213
214        protected abstract byte[] getByteStreamRequestContents();
215
216        public abstract List<String> getHeaders(String name);
217
218        /**
219         * Retrieves the body of the request as character data using a <code>BufferedReader</code>. The reader translates the
220         * character data according to the character encoding used on the body. Either this method or {@link #getInputStream}
221         * may be called to read the body, not both.
222         * 
223         * @return a <code>Reader</code> containing the body of the request
224         *
225         * @exception UnsupportedEncodingException
226         *               if the character set encoding used is not supported and the text cannot be decoded
227         *
228         * @exception IllegalStateException
229         *               if {@link #getInputStream} method has been called on this request
230         *
231         * @exception IOException
232         *               if an input or output exception occurred
233         *
234         * @see javax.servlet.http.HttpServletRequest#getInputStream
235         */
236        public abstract Reader getReader() throws IOException;
237
238        /**
239         * Retrieves the body of the request as binary data. Either this method or {@link #getReader} may be called to read
240         * the body, not both.
241         *
242         * @return a {@link InputStream} object containing the body of the request
243         *
244         * @exception IllegalStateException
245         *               if the {@link #getReader} method has already been called for this request
246         *
247         * @exception IOException
248         *               if an input or output exception occurred
249         */
250        public abstract InputStream getInputStream() throws IOException;
251
252        /**
253         * Returns the server base URL (with no trailing '/') for a given request
254         */
255        public abstract String getServerBaseForRequest();
256
257}