001package ca.uhn.fhir.rest.api;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2020 University Health Network
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 java.nio.charset.Charset;
024import java.nio.charset.StandardCharsets;
025import java.util.*;
026
027public class Constants {
028
029        public static final String CT_TEXT_CSV = "text/csv";
030        public static final String HEADER_REQUEST_ID = "X-Request-ID";
031        public static final String HEADER_REQUEST_SOURCE = "X-Request-Source";
032        public static final String CACHE_CONTROL_MAX_RESULTS = "max-results";
033        public static final String CACHE_CONTROL_NO_CACHE = "no-cache";
034        public static final String CACHE_CONTROL_NO_STORE = "no-store";
035        public static final String CHARSET_NAME_UTF8 = "UTF-8";
036        public static final Charset CHARSET_UTF8;
037        public static final String CHARSET_UTF8_CTSUFFIX = "; charset=" + CHARSET_NAME_UTF8;
038        /**
039         * Contains a standard set of headers which are used by FHIR / HAPI FHIR, and therefore
040         * would make a useful set for CORS AllowedHeader declarations
041         */
042        public static final Set<String> CORS_ALLOWED_HEADERS;
043        /**
044         * Contains a standard set of HTTP Methods which are used by FHIR / HAPI FHIR, and therefore
045         * would make a useful set for CORS AllowedMethod declarations
046         */
047        public static final Set<String> CORS_ALLWED_METHODS;
048        public static final String CT_FHIR_JSON = "application/json+fhir";
049        public static final String CT_RDF_TURTLE = "application/x-turtle";
050        /**
051         * The FHIR MimeType for JSON encoding in FHIR DSTU3+
052         */
053        public static final String CT_FHIR_JSON_NEW = "application/fhir+json";
054        public static final String CT_FHIR_XML = "application/xml+fhir";
055        /**
056         * The FHIR MimeType for XML encoding in FHIR DSTU3+
057         */
058        public static final String CT_FHIR_XML_NEW = "application/fhir+xml";
059        public static final String CT_HTML = "text/html";
060        public static final String CT_HTML_WITH_UTF8 = "text/html" + CHARSET_UTF8_CTSUFFIX;
061        public static final String CT_JSON = "application/json";
062        public static final String CT_JSON_PATCH = "application/json-patch+json";
063        public static final String CT_OCTET_STREAM = "application/octet-stream";
064        public static final String CT_TEXT = "text/plain";
065        public static final String CT_TEXT_WITH_UTF8 = CT_TEXT + CHARSET_UTF8_CTSUFFIX;
066        public static final String CT_X_FORM_URLENCODED = "application/x-www-form-urlencoded";
067        public static final String CT_XML = "application/xml";
068        public static final String CT_XML_PATCH = "application/xml-patch+xml";
069        public static final String ENCODING_GZIP = "gzip";
070        public static final String EXTOP_PROCESS_MESSAGE = "$process-message"; //Used in messaging
071        public static final String EXTOP_VALIDATE = "$validate";
072        public static final String EXTOP_VALIDATE_MODE = "mode";
073        public static final String EXTOP_VALIDATE_PROFILE = "profile";
074        public static final String EXTOP_VALIDATE_RESOURCE = "resource";
075        public static final String FORMAT_HTML = "html";
076        public static final String FORMAT_JSON = "json";
077        public static final String FORMAT_XML = "xml";
078        public static final String FORMAT_TURTLE = "text/turtle";
079
080
081        /**
082         * "text/html" and "html"
083         */
084        public static final Set<String> FORMATS_HTML;
085        public static final String FORMATS_HTML_JSON = "html/json";
086        public static final String FORMATS_HTML_XML = "html/xml";
087        public static final String HEADER_ACCEPT = "Accept";
088        public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
089        public static final String HEADER_ACCEPT_VALUE_JSON_NON_LEGACY = CT_FHIR_JSON_NEW + ";q=1.0, " + CT_FHIR_JSON + ";q=0.9";
090        public static final String HEADER_ACCEPT_VALUE_XML_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_XML + ";q=0.9";
091        public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY = CT_FHIR_XML + ";q=1.0, " + CT_FHIR_JSON + ";q=1.0";
092        public static final String HEADER_ACCEPT_VALUE_XML_OR_JSON_NON_LEGACY = CT_FHIR_XML_NEW + ";q=1.0, " + CT_FHIR_JSON_NEW + ";q=1.0, " + HEADER_ACCEPT_VALUE_XML_OR_JSON_LEGACY.replace("1.0", "0.9");
093        public static final String HEADER_ALLOW = "Allow";
094        public static final String HEADER_AUTHORIZATION = "Authorization";
095        public static final String HEADER_AUTHORIZATION_VALPREFIX_BASIC = "Basic ";
096        public static final String HEADER_AUTHORIZATION_VALPREFIX_BEARER = "Bearer ";
097        public static final String HEADER_CACHE_CONTROL = "Cache-Control";
098        public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
099        public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
100        public static final String HEADER_CONTENT_LOCATION = "Content-Location";
101        public static final String HEADER_CONTENT_LOCATION_LC = HEADER_CONTENT_LOCATION.toLowerCase();
102        public static final String HEADER_CONTENT_TYPE = "Content-Type";
103        public static final String HEADER_CONTENT_TYPE_LC = HEADER_CONTENT_TYPE.toLowerCase();
104        public static final String HEADER_COOKIE = "Cookie";
105        public static final String HEADER_CORS_ALLOW_METHODS = "Access-Control-Allow-Methods";
106        public static final String HEADER_CORS_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
107        public static final String HEADER_CORS_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
108        public static final String HEADER_ETAG = "ETag";
109        public static final String HEADER_ETAG_LC = HEADER_ETAG.toLowerCase();
110        public static final String HEADER_IF_MATCH = "If-Match";
111        public static final String HEADER_IF_MATCH_LC = HEADER_IF_MATCH.toLowerCase();
112        public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
113        public static final String HEADER_IF_MODIFIED_SINCE_LC = HEADER_IF_MODIFIED_SINCE.toLowerCase();
114        public static final String HEADER_IF_NONE_EXIST = "If-None-Exist";
115        public static final String HEADER_IF_NONE_EXIST_LC = HEADER_IF_NONE_EXIST.toLowerCase();
116        public static final String HEADER_IF_NONE_MATCH = "If-None-Match";
117        public static final String HEADER_IF_NONE_MATCH_LC = HEADER_IF_NONE_MATCH.toLowerCase();
118        public static final String HEADER_LAST_MODIFIED = "Last-Modified";
119        public static final String HEADER_LAST_MODIFIED_LOWERCASE = HEADER_LAST_MODIFIED.toLowerCase();
120        public static final String HEADER_LOCATION = "Location";
121        public static final String HEADER_LOCATION_LC = HEADER_LOCATION.toLowerCase();
122        public static final String HEADER_ORIGIN = "Origin";
123        public static final String HEADER_PREFER = "Prefer";
124        public static final String HEADER_PREFER_RETURN = "return";
125        public static final String HEADER_PREFER_RETURN_MINIMAL = "minimal";
126        public static final String HEADER_PREFER_RETURN_REPRESENTATION = "representation";
127        public static final String HEADER_PREFER_RETURN_OPERATION_OUTCOME = "OperationOutcome";
128        public static final String HEADER_SUFFIX_CT_UTF_8 = "; charset=UTF-8";
129        public static final String HEADERVALUE_CORS_ALLOW_METHODS_ALL = "GET, POST, PUT, DELETE, OPTIONS";
130        public static final Map<Integer, String> HTTP_STATUS_NAMES;
131        public static final String LINK_FHIR_BASE = "fhir-base";
132        public static final String LINK_FIRST = "first";
133        public static final String LINK_LAST = "last";
134        public static final String LINK_NEXT = "next";
135        public static final String LINK_PREVIOUS = "previous";
136        public static final String LINK_SELF = "self";
137        public static final String OPENSEARCH_NS_OLDER = "http://purl.org/atompub/tombstones/1.0";
138        public static final String PARAM_ASYNC = "async"; //Used in messaging
139        public static final String PARAM_AT = "_at";
140        /**
141         * Used in paging links
142         */
143        public static final String PARAM_BUNDLETYPE = "_bundletype";
144        public static final String PARAM_FILTER = "_filter";
145        public static final String PARAM_CONTENT = "_content";
146        public static final String PARAM_COUNT = "_count";
147        public static final String PARAM_DELETE = "_delete";
148        public static final String PARAM_ELEMENTS = "_elements";
149        public static final String PARAM_ELEMENTS_EXCLUDE_MODIFIER = ":exclude";
150        public static final String PARAM_FORMAT = "_format";
151        public static final String PARAM_HAS = "_has";
152        public static final String PARAM_HISTORY = "_history";
153        public static final String PARAM_INCLUDE = "_include";
154        public static final String PARAM_INCLUDE_QUALIFIER_RECURSE = ":recurse";
155        public static final String PARAM_INCLUDE_RECURSE = "_include" + PARAM_INCLUDE_QUALIFIER_RECURSE;
156        public static final String PARAM_INCLUDE_QUALIFIER_ITERATE = ":iterate";
157        public static final String PARAM_INCLUDE_ITERATE = "_include" + PARAM_INCLUDE_QUALIFIER_ITERATE;
158        public static final String PARAM_LASTUPDATED = "_lastUpdated";
159        public static final String PARAM_NARRATIVE = "_narrative";
160        public static final String PARAM_PAGINGACTION = "_getpages";
161        public static final String PARAM_PAGINGOFFSET = "_getpagesoffset";
162        public static final String PARAM_PRETTY = "_pretty";
163        public static final String PARAM_PRETTY_VALUE_FALSE = "false";
164        public static final String PARAM_PRETTY_VALUE_TRUE = "true";
165        public static final String PARAM_PROFILE = "_profile";
166        public static final String PARAM_QUERY = "_query";
167        public static final String PARAM_RESPONSE_URL = "response-url"; //Used in messaging
168        public static final String PARAM_REVINCLUDE = "_revinclude";
169        public static final String PARAM_REVINCLUDE_RECURSE = PARAM_REVINCLUDE + PARAM_INCLUDE_QUALIFIER_RECURSE;
170        public static final String PARAM_REVINCLUDE_ITERATE = PARAM_REVINCLUDE + PARAM_INCLUDE_QUALIFIER_ITERATE;
171        public static final String PARAM_SEARCH = "_search";
172        public static final String PARAM_SECURITY = "_security";
173        public static final String PARAM_SINCE = "_since";
174        public static final String PARAM_SORT = "_sort";
175        public static final String PARAM_SORT_ASC = "_sort:asc";
176        public static final String PARAM_SORT_DESC = "_sort:desc";
177        public static final String PARAM_SOURCE = "_source";
178        public static final String PARAM_SUMMARY = "_summary";
179        public static final String PARAM_TAG = "_tag";
180        public static final String PARAM_TAGS = "_tags";
181        public static final String PARAM_TEXT = "_text";
182        public static final String PARAM_VALIDATE = "_validate";
183        public static final String PARAMQUALIFIER_MISSING = ":missing";
184        public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
185        public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
186        public static final String PARAMQUALIFIER_STRING_CONTAINS = ":contains";
187        public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
188        public static final String PARAMQUALIFIER_TOKEN_TEXT = ":text";
189        public static final int STATUS_HTTP_200_OK = 200;
190        public static final int STATUS_HTTP_201_CREATED = 201;
191        public static final int STATUS_HTTP_204_NO_CONTENT = 204;
192        public static final int STATUS_HTTP_304_NOT_MODIFIED = 304;
193        public static final int STATUS_HTTP_400_BAD_REQUEST = 400;
194        public static final int STATUS_HTTP_401_CLIENT_UNAUTHORIZED = 401;
195        public static final int STATUS_HTTP_403_FORBIDDEN = 403;
196
197        public static final int STATUS_HTTP_404_NOT_FOUND = 404;
198        public static final int STATUS_HTTP_405_METHOD_NOT_ALLOWED = 405;
199        public static final int STATUS_HTTP_409_CONFLICT = 409;
200        public static final int STATUS_HTTP_410_GONE = 410;
201        public static final int STATUS_HTTP_412_PRECONDITION_FAILED = 412;
202        public static final int STATUS_HTTP_422_UNPROCESSABLE_ENTITY = 422;
203        public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
204        public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
205        public static final String TAG_SUBSETTED_CODE = "SUBSETTED";
206        public static final String TAG_SUBSETTED_SYSTEM_DSTU3 = "http://hl7.org/fhir/v3/ObservationValue";
207        public static final String TAG_SUBSETTED_SYSTEM_R4 = "http://terminology.hl7.org/CodeSystem/v3-ObservationValue";
208        public static final String URL_TOKEN_HISTORY = "_history";
209        public static final String URL_TOKEN_METADATA = "metadata";
210        public static final String OO_INFOSTATUS_PROCESSING = "processing";
211        public static final String PARAM_GRAPHQL_QUERY = "query";
212        public static final String HEADER_X_CACHE = "X-Cache";
213        public static final String HEADER_X_SECURITY_CONTEXT = "X-Security-Context";
214        public static final String POWERED_BY_HEADER = "X-Powered-By";
215        public static final Charset CHARSET_US_ASCII;
216        public static final String PARAM_PAGEID = "_pageId";
217        /**
218         * This is provided for testing only! Use with caution as this property may change.
219         */
220        public static final String TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS = "TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS";
221        public static final String PARAM_SEARCH_TOTAL_MODE = "_total";
222        public static final String CAPABILITYSTATEMENT_WEBSOCKET_URL = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-websocket";
223        public static final String PARAMETER_CASCADE_DELETE = "_cascade";
224        public static final String HEADER_CASCADE = "X-Cascade";
225        public static final String CASCADE_DELETE = "delete";
226        public static final int MAX_RESOURCE_NAME_LENGTH = 100;
227        public static final String CACHE_CONTROL_PRIVATE = "private";
228        public static final String CT_FHIR_NDJSON = "application/fhir+ndjson";
229        public static final String CT_APP_NDJSON = "application/ndjson";
230        public static final String CT_NDJSON = "ndjson";
231        public static final Set<String> CTS_NDJSON;
232        public static final String HEADER_PREFER_RESPOND_ASYNC = "respond-async";
233        public static final int STATUS_HTTP_412_PAYLOAD_TOO_LARGE = 413;
234        public static final String OPERATION_NAME_GRAPHQL = "$graphql";
235        /**
236         * Note that this constant is used in a number of places including DB column lengths! Be careful if you decide to change it.
237         */
238        public static final int REQUEST_ID_LENGTH = 16;
239        public static final int STATUS_HTTP_202_ACCEPTED = 202;
240        public static final String HEADER_X_PROGRESS = "X-Progress";
241        public static final String HEADER_RETRY_AFTER = "Retry-After";
242        /**
243         * Operation name for the $lastn operation
244         */
245        public static final String OPERATION_LASTN = "$lastn";
246        /**
247         * <p>
248         * This extension represents the equivalent of the
249         * <code>Resource.meta.source</code> field within R4+ resources, and is for
250         * use in DSTU3 resources. It should contain a value of type <code>uri</code>
251         * and will be located on the Resource.meta
252         * </p>
253         */
254        public static final String EXT_META_SOURCE = "http://hapifhir.io/fhir/StructureDefinition/resource-meta-source";
255        public static final String CODESYSTEM_VALIDATE_NOT_NEEDED = UUID.randomUUID().toString();
256
257        static {
258                CHARSET_UTF8 = StandardCharsets.UTF_8;
259                CHARSET_US_ASCII = StandardCharsets.ISO_8859_1;
260
261                HashSet<String> ctsNdjson = new HashSet<>();
262                ctsNdjson.add(CT_FHIR_NDJSON);
263                ctsNdjson.add(CT_APP_NDJSON);
264                ctsNdjson.add(CT_NDJSON);
265                CTS_NDJSON = Collections.unmodifiableSet(ctsNdjson);
266
267                HashMap<Integer, String> statusNames = new HashMap<>();
268                statusNames.put(200, "OK");
269                statusNames.put(201, "Created");
270                statusNames.put(202, "Accepted");
271                statusNames.put(203, "Non-Authoritative Information");
272                statusNames.put(204, "No Content");
273                statusNames.put(205, "Reset Content");
274                statusNames.put(206, "Partial Content");
275                statusNames.put(207, "Multi-Status");
276                statusNames.put(208, "Already Reported");
277                statusNames.put(226, "IM Used");
278                statusNames.put(300, "Multiple Choices");
279                statusNames.put(301, "Moved Permanently");
280                statusNames.put(302, "Found");
281                statusNames.put(303, "See Other");
282                statusNames.put(304, "Not Modified");
283                statusNames.put(305, "Use Proxy");
284                statusNames.put(307, "Temporary Redirect");
285                statusNames.put(308, "Permanent Redirect");
286                statusNames.put(400, "Bad Request");
287                statusNames.put(401, "Unauthorized");
288                statusNames.put(402, "Payment Required");
289                statusNames.put(403, "Forbidden");
290                statusNames.put(404, "Not Found");
291                statusNames.put(405, "Method Not Allowed");
292                statusNames.put(406, "Not Acceptable");
293                statusNames.put(407, "Proxy Authentication Required");
294                statusNames.put(408, "Request Timeout");
295                statusNames.put(409, "Conflict");
296                statusNames.put(410, "Gone");
297                statusNames.put(411, "Length Required");
298                statusNames.put(412, "Precondition Failed");
299                statusNames.put(413, "Payload Too Large");
300                statusNames.put(414, "URI Too Long");
301                statusNames.put(415, "Unsupported Media Type");
302                statusNames.put(416, "Requested range not satisfiable");
303                statusNames.put(417, "Expectation Failed");
304                statusNames.put(418, "I'm a teapot");
305                statusNames.put(419, "Insufficient Space On Resource");
306                statusNames.put(420, "Method Failure");
307                statusNames.put(421, "Destination Locked");
308                statusNames.put(422, "Unprocessable Entity");
309                statusNames.put(423, "Locked");
310                statusNames.put(424, "Failed Dependency");
311                statusNames.put(426, "Upgrade Required");
312                statusNames.put(428, "Precondition Required");
313                statusNames.put(429, "Too Many Requests");
314                statusNames.put(431, "Request Header Fields Too Large");
315                statusNames.put(500, "Internal Server Error");
316                statusNames.put(501, "Not Implemented");
317                statusNames.put(502, "Bad Gateway");
318                statusNames.put(503, "Service Unavailable");
319                statusNames.put(504, "Gateway Timeout");
320                statusNames.put(505, "HTTP Version not supported");
321                statusNames.put(506, "Variant Also Negotiates");
322                statusNames.put(507, "Insufficient Storage");
323                statusNames.put(508, "Loop Detected");
324                statusNames.put(509, "Bandwidth Limit Exceeded");
325                statusNames.put(510, "Not Extended");
326                statusNames.put(511, "Network Authentication Required");
327                HTTP_STATUS_NAMES = Collections.unmodifiableMap(statusNames);
328
329                Set<String> formatsHtml = new HashSet<>();
330                formatsHtml.add(CT_HTML);
331                formatsHtml.add(FORMAT_HTML);
332                FORMATS_HTML = Collections.unmodifiableSet(formatsHtml);
333
334                // *********************************************************
335                // Update CorsInterceptor's constructor documentation if you change these:
336                // *********************************************************
337                HashSet<String> corsAllowedHeaders = new HashSet<>();
338                corsAllowedHeaders.add("Accept");
339                corsAllowedHeaders.add("Access-Control-Request-Headers");
340                corsAllowedHeaders.add("Access-Control-Request-Method");
341                corsAllowedHeaders.add("Cache-Control");
342                corsAllowedHeaders.add("Content-Type");
343                corsAllowedHeaders.add("Origin");
344                corsAllowedHeaders.add("Prefer");
345                corsAllowedHeaders.add("X-FHIR-Starter");
346                corsAllowedHeaders.add("X-Requested-With");
347                CORS_ALLOWED_HEADERS = Collections.unmodifiableSet(corsAllowedHeaders);
348
349                // *********************************************************
350                // Update CorsInterceptor's constructor documentation if you change these:
351                // *********************************************************
352                HashSet<String> corsAllowedMethods = new HashSet<>();
353                corsAllowedMethods.addAll(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
354                CORS_ALLWED_METHODS = Collections.unmodifiableSet(corsAllowedMethods);
355        }
356
357        public static boolean codeSystemNotNeeded(String theCodeSystem) {
358                return Constants.CODESYSTEM_VALIDATE_NOT_NEEDED.equals(theCodeSystem);
359        }
360
361
362        public static String codeSystemWithDefaultDescription(String theSystem) {
363                if (codeSystemNotNeeded(theSystem)) {
364                        return "(none)";
365                } else {
366                        return theSystem;
367                }
368        }
369}