View Javadoc
1   package ca.uhn.fhir.jpa.dao;
2   
3   import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
4   import ca.uhn.fhir.jpa.util.JpaConstants;
5   import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
6   import com.google.common.collect.Sets;
7   import org.apache.commons.lang3.ObjectUtils;
8   import org.apache.commons.lang3.Validate;
9   import org.apache.commons.lang3.time.DateUtils;
10  import org.hl7.fhir.r4.model.Bundle;
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import java.util.*;
15  
16  /*
17   * #%L
18   * HAPI FHIR JPA Server
19   * %%
20   * Copyright (C) 2014 - 2018 University Health Network
21   * %%
22   * Licensed under the Apache License, Version 2.0 (the "License");
23   * you may not use this file except in compliance with the License.
24   * You may obtain a copy of the License at
25   * 
26   * http://www.apache.org/licenses/LICENSE-2.0
27   * 
28   * Unless required by applicable law or agreed to in writing, software
29   * distributed under the License is distributed on an "AS IS" BASIS,
30   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31   * See the License for the specific language governing permissions and
32   * limitations under the License.
33   * #L%
34   */
35  
36  public class DaoConfig {
37  
38  	/**
39  	 * Default {@link #getTreatReferencesAsLogical() logical URL bases}. Includes the following
40  	 * values:
41  	 * <ul>
42  	 * <li><code>"http://hl7.org/fhir/valueset-*"</code></li>
43  	 * <li><code>"http://hl7.org/fhir/codesystem-*"</code></li>
44  	 * <li><code>"http://hl7.org/fhir/StructureDefinition/*"</code></li>
45  	 * </ul>
46  	 */
47  	public static final Set<String> DEFAULT_LOGICAL_BASE_URLS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
48  		"http://hl7.org/fhir/ValueSet/*",
49  		"http://hl7.org/fhir/CodeSystem/*",
50  		"http://hl7.org/fhir/valueset-*",
51  		"http://hl7.org/fhir/codesystem-*",
52  		"http://hl7.org/fhir/StructureDefinition/*")));
53  	/**
54  	 * Default value for {@link #setReuseCachedSearchResultsForMillis(Long)}: 60000ms (one minute)
55  	 */
56  	public static final Long DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS = DateUtils.MILLIS_PER_MINUTE;
57  	/**
58  	 * Default value for {@link #setTranslationCachesExpireAfterWriteInMinutes(Long)}: 60 minutes
59  	 *
60  	 * @see #setTranslationCachesExpireAfterWriteInMinutes(Long)
61  	 */
62  	public static final Long DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES = 60L;
63  	/**
64  	 * See {@link #setStatusBasedReindexingDisabled(boolean)}
65  	 */
66  	public static final String DISABLE_STATUS_BASED_REINDEX = "disable_status_based_reindex";
67  	/**
68  	 * Default value for {@link #setMaximumSearchResultCountInTransaction(Integer)}
69  	 *
70  	 * @see #setMaximumSearchResultCountInTransaction(Integer)
71  	 */
72  	private static final Integer DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION = null;
73  	/**
74  	 * Default {@link #setBundleTypesAllowedForStorage(Set)} value:
75  	 * <ul>
76  	 * <li>collection</li>
77  	 * <li>document</li>
78  	 * <li>message</li>
79  	 * </ul>
80  	 */
81  	private static final Set<String> DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE = Collections.unmodifiableSet(new TreeSet<>(Sets.newHashSet(
82  		Bundle.BundleType.COLLECTION.toCode(),
83  		Bundle.BundleType.DOCUMENT.toCode(),
84  		Bundle.BundleType.MESSAGE.toCode()
85  	)));
86  	private static final Logger ourLog = LoggerFactory.getLogger(DaoConfig.class);
87  	private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED;
88  	/**
89  	 * update setter javadoc if default changes
90  	 */
91  	private Long myTranslationCachesExpireAfterWriteInMinutes = DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES;
92  	/**
93  	 * update setter javadoc if default changes
94  	 */
95  	private boolean myAllowExternalReferences = false;
96  	/**
97  	 * update setter javadoc if default changes
98  	 */
99  	private boolean myAllowContainsSearches = false;
100 	/**
101 	 * update setter javadoc if default changes
102 	 */
103 	private boolean myAllowInlineMatchUrlReferences = true;
104 	private boolean myAllowMultipleDelete;
105 	private boolean myDefaultSearchParamsCanBeOverridden = false;
106 	/**
107 	 * update setter javadoc if default changes
108 	 */
109 	private int myDeferIndexingForCodesystemsOfSize = 2000;
110 	private boolean myDeleteStaleSearches = true;
111 	private boolean myEnforceReferentialIntegrityOnDelete = true;
112 	private boolean myUniqueIndexesEnabled = true;
113 	private boolean myUniqueIndexesCheckedBeforeSave = true;
114 	private boolean myEnforceReferentialIntegrityOnWrite = true;
115 	private int myEverythingIncludesFetchPageSize = 50;
116 	/**
117 	 * update setter javadoc if default changes
118 	 */
119 	private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
120 	/**
121 	 * update setter javadoc if default changes
122 	 */
123 	private Integer myFetchSizeDefaultMaximum = null;
124 	private int myHardTagListLimit = 1000;
125 	/**
126 	 * update setter javadoc if default changes
127 	 */
128 	private boolean myIndexContainedResources = true;
129 	private List<IServerInterceptor> myInterceptors;
130 	/**
131 	 * update setter javadoc if default changes
132 	 */
133 	private int myMaximumExpansionSize = 5000;
134 	private Integer myMaximumSearchResultCountInTransaction = DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION;
135 	private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
136 	/**
137 	 * update setter javadoc if default changes
138 	 */
139 	private Integer myResourceMetaCountHardLimit = 1000;
140 	private Long myReuseCachedSearchResultsForMillis = DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
141 	private boolean mySchedulingDisabled;
142 	private boolean mySuppressUpdatesWithNoChange = true;
143 	private Set<String> myTreatBaseUrlsAsLocal = new HashSet<>();
144 	private Set<String> myTreatReferencesAsLogical = new HashSet<>(DEFAULT_LOGICAL_BASE_URLS);
145 	private boolean myAutoCreatePlaceholderReferenceTargets;
146 	private Integer myCacheControlNoStoreMaxResultsUpperLimit = 1000;
147 	private Integer myCountSearchResultsUpTo = null;
148 	private boolean myStatusBasedReindexingDisabled;
149 	private IdStrategyEnum myResourceServerIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC;
150 	private boolean myMarkResourcesForReindexingUponSearchParameterChange;
151 	private boolean myExpungeEnabled;
152 	private int myReindexThreadCount;
153 	private Set<String> myBundleTypesAllowedForStorage;
154 	private boolean myValidateSearchParameterExpressionsOnSave = true;
155 
156 	/**
157 	 * Constructor
158 	 */
159 	public DaoConfig() {
160 		setSubscriptionEnabled(true);
161 		setSubscriptionPollDelay(0);
162 		setSubscriptionPurgeInactiveAfterMillis(Long.MAX_VALUE);
163 		setMarkResourcesForReindexingUponSearchParameterChange(true);
164 		setReindexThreadCount(Runtime.getRuntime().availableProcessors());
165 		setBundleTypesAllowedForStorage(DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE);
166 
167 
168 		if ("true".equalsIgnoreCase(System.getProperty(DISABLE_STATUS_BASED_REINDEX))) {
169 			ourLog.info("Status based reindexing is DISABLED");
170 			setStatusBasedReindexingDisabled(true);
171 		}
172 	}
173 
174 	/**
175 	 * If set to <code>true</code> (default is false), the reindexing of search parameters
176 	 * using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
177 	 * This query is just not efficient on Oracle and bogs the system down when there are
178 	 * a lot of resources. A more efficient way of doing this will be introduced
179 	 * in the next release of HAPI FHIR.
180 	 *
181 	 * @since 3.5.0
182 	 */
183 	public boolean isStatusBasedReindexingDisabled() {
184 		return myStatusBasedReindexingDisabled;
185 	}
186 
187 	/**
188 	 * If set to <code>true</code> (default is false), the reindexing of search parameters
189 	 * using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
190 	 * This query is just not efficient on Oracle and bogs the system down when there are
191 	 * a lot of resources. A more efficient way of doing this will be introduced
192 	 * in the next release of HAPI FHIR.
193 	 *
194 	 * @since 3.5.0
195 	 */
196 	public void setStatusBasedReindexingDisabled(boolean theStatusBasedReindexingDisabled) {
197 		myStatusBasedReindexingDisabled = theStatusBasedReindexingDisabled;
198 	}
199 
200 	/**
201 	 * Add a value to the {@link #setTreatReferencesAsLogical(Set) logical references list}.
202 	 *
203 	 * @see #setTreatReferencesAsLogical(Set)
204 	 */
205 	public void addTreatReferencesAsLogical(String theTreatReferencesAsLogical) {
206 		validateTreatBaseUrlsAsLocal(theTreatReferencesAsLogical);
207 
208 		if (myTreatReferencesAsLogical == null) {
209 			myTreatReferencesAsLogical = new HashSet<>();
210 		}
211 		myTreatReferencesAsLogical.add(theTreatReferencesAsLogical);
212 	}
213 
214 	/**
215 	 * This setting specifies the bundle types (<code>Bundle.type</code>) that
216 	 * are allowed to be stored as-is on the /Bundle endpoint.
217 	 *
218 	 * @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
219 	 */
220 	public Set<String> getBundleTypesAllowedForStorage() {
221 		return myBundleTypesAllowedForStorage;
222 	}
223 
224 	/**
225 	 * This setting specifies the bundle types (<code>Bundle.type</code>) that
226 	 * are allowed to be stored as-is on the /Bundle endpoint.
227 	 *
228 	 * @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
229 	 */
230 	public void setBundleTypesAllowedForStorage(Set<String> theBundleTypesAllowedForStorage) {
231 		Validate.notNull(theBundleTypesAllowedForStorage, "theBundleTypesAllowedForStorage must not be null");
232 		myBundleTypesAllowedForStorage = theBundleTypesAllowedForStorage;
233 	}
234 
235 	/**
236 	 * Specifies the highest number that a client is permitted to use in a
237 	 * <code>Cache-Control: nostore, max-results=NNN</code>
238 	 * directive. If the client tries to exceed this limit, the
239 	 * request will be denied. Defaults to 1000.
240 	 */
241 	public Integer getCacheControlNoStoreMaxResultsUpperLimit() {
242 		return myCacheControlNoStoreMaxResultsUpperLimit;
243 	}
244 
245 	/**
246 	 * Specifies the highest number that a client is permitted to use in a
247 	 * <code>Cache-Control: nostore, max-results=NNN</code>
248 	 * directive. If the client tries to exceed this limit, the
249 	 * request will be denied. Defaults to 1000.
250 	 */
251 	public void setCacheControlNoStoreMaxResultsUpperLimit(Integer theCacheControlNoStoreMaxResults) {
252 		myCacheControlNoStoreMaxResultsUpperLimit = theCacheControlNoStoreMaxResults;
253 	}
254 
255 	/**
256 	 * When searching, if set to a non-null value (default is <code>null</code>) the
257 	 * search coordinator will attempt to find at least this many results
258 	 * before returning a response to the client. This parameter mainly affects
259 	 * whether a "total count" is included in the response bundle for searches that
260 	 * return large amounts of data.
261 	 * <p>
262 	 * For a search that returns 10000 results, if this value is set to
263 	 * 10000 the search coordinator will find all 10000 results
264 	 * prior to returning, so the initial response bundle will have the
265 	 * total set to 10000. If this value is null (or less than 10000)
266 	 * the response bundle will likely return slightly faster, but will
267 	 * not include the total. Subsequent page requests will likely
268 	 * include the total however, if they are performed after the
269 	 * search coordinator has found all results.
270 	 * </p>
271 	 * <p>
272 	 * Set this value to <code>0</code> to always load all
273 	 * results before returning.
274 	 * </p>
275 	 */
276 	public Integer getCountSearchResultsUpTo() {
277 		return myCountSearchResultsUpTo;
278 	}
279 
280 	/**
281 	 * When searching, if set to a non-null value (default is <code>null</code>) the
282 	 * search coordinator will attempt to find at least this many results
283 	 * before returning a response to the client. This parameter mainly affects
284 	 * whether a "total count" is included in the response bundle for searches that
285 	 * return large amounts of data.
286 	 * <p>
287 	 * For a search that returns 10000 results, if this value is set to
288 	 * 10000 the search coordinator will find all 10000 results
289 	 * prior to returning, so the initial response bundle will have the
290 	 * total set to 10000. If this value is null (or less than 10000)
291 	 * the response bundle will likely return slightly faster, but will
292 	 * not include the total. Subsequent page requests will likely
293 	 * include the total however, if they are performed after the
294 	 * search coordinator has found all results.
295 	 * </p>
296 	 * <p>
297 	 * Set this value to <code>0</code> to always load all
298 	 * results before returning.
299 	 * </p>
300 	 */
301 	public void setCountSearchResultsUpTo(Integer theCountSearchResultsUpTo) {
302 		myCountSearchResultsUpTo = theCountSearchResultsUpTo;
303 	}
304 
305 	/**
306 	 * When a code system is added that contains more than this number of codes,
307 	 * the code system will be indexed later in an incremental process in order to
308 	 * avoid overwhelming Lucene with a huge number of codes in a single operation.
309 	 * <p>
310 	 * Defaults to 2000
311 	 * </p>
312 	 */
313 	public int getDeferIndexingForCodesystemsOfSize() {
314 		return myDeferIndexingForCodesystemsOfSize;
315 	}
316 
317 	/**
318 	 * When a code system is added that contains more than this number of codes,
319 	 * the code system will be indexed later in an incremental process in order to
320 	 * avoid overwhelming Lucene with a huge number of codes in a single operation.
321 	 * <p>
322 	 * Defaults to 2000
323 	 * </p>
324 	 */
325 	public void setDeferIndexingForCodesystemsOfSize(int theDeferIndexingForCodesystemsOfSize) {
326 		myDeferIndexingForCodesystemsOfSize = theDeferIndexingForCodesystemsOfSize;
327 	}
328 
329 	/**
330 	 * Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
331 	 * are added to the normal search results instead of being added on as extras in a page. This means that they will not appear multiple times
332 	 * as the search results are paged over.
333 	 * <p>
334 	 * In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
335 	 * value may improve performance but may also cause memory issues.
336 	 * </p>
337 	 * <p>
338 	 * The default value is 50
339 	 * </p>
340 	 */
341 	public int getEverythingIncludesFetchPageSize() {
342 		return myEverythingIncludesFetchPageSize;
343 	}
344 
345 	/**
346 	 * Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
347 	 * are added to the normal search results instead of being added on as extras in a page. This means that they will not appear multiple times
348 	 * as the search results are paged over.
349 	 * <p>
350 	 * In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
351 	 * value may improve performance but may also cause memory issues.
352 	 * </p>
353 	 * <p>
354 	 * The default value is 50
355 	 * </p>
356 	 */
357 	public void setEverythingIncludesFetchPageSize(int theEverythingIncludesFetchPageSize) {
358 		Validate.inclusiveBetween(1, Integer.MAX_VALUE, theEverythingIncludesFetchPageSize);
359 		myEverythingIncludesFetchPageSize = theEverythingIncludesFetchPageSize;
360 	}
361 
362 	/**
363 	 * Sets the number of milliseconds that search results for a given client search
364 	 * should be preserved before being purged from the database.
365 	 * <p>
366 	 * Search results are stored in the database so that they can be paged over multiple
367 	 * requests. After this
368 	 * number of milliseconds, they will be deleted from the database, and any paging links
369 	 * (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
370 	 * </p>
371 	 * <p>
372 	 * To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
373 	 * </p>
374 	 *
375 	 * @since 1.5
376 	 */
377 	public long getExpireSearchResultsAfterMillis() {
378 		return myExpireSearchResultsAfterMillis;
379 	}
380 
381 	/**
382 	 * Sets the number of milliseconds that search results for a given client search
383 	 * should be preserved before being purged from the database.
384 	 * <p>
385 	 * Search results are stored in the database so that they can be paged over multiple
386 	 * requests. After this
387 	 * number of milliseconds, they will be deleted from the database, and any paging links
388 	 * (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
389 	 * </p>
390 	 * <p>
391 	 * To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
392 	 * </p>
393 	 *
394 	 * @since 1.5
395 	 */
396 	public void setExpireSearchResultsAfterMillis(long theExpireSearchResultsAfterMillis) {
397 		myExpireSearchResultsAfterMillis = theExpireSearchResultsAfterMillis;
398 	}
399 
400 	/**
401 	 * Gets the default maximum number of results to load in a query.
402 	 * <p>
403 	 * For example, if the database has a million Patient resources in it, and
404 	 * the client requests <code>GET /Patient</code>, if this value is set
405 	 * to a non-null value (default is <code>null</code>) only this number
406 	 * of results will be fetched. Setting this value appropriately
407 	 * can be useful to improve performance in some situations.
408 	 * </p>
409 	 */
410 	public Integer getFetchSizeDefaultMaximum() {
411 		return myFetchSizeDefaultMaximum;
412 	}
413 
414 	/**
415 	 * Gets the default maximum number of results to load in a query.
416 	 * <p>
417 	 * For example, if the database has a million Patient resources in it, and
418 	 * the client requests <code>GET /Patient</code>, if this value is set
419 	 * to a non-null value (default is <code>null</code>) only this number
420 	 * of results will be fetched. Setting this value appropriately
421 	 * can be useful to improve performance in some situations.
422 	 * </p>
423 	 */
424 	public void setFetchSizeDefaultMaximum(Integer theFetchSizeDefaultMaximum) {
425 		myFetchSizeDefaultMaximum = theFetchSizeDefaultMaximum;
426 	}
427 
428 	/**
429 	 * Gets the maximum number of results to return in a GetTags query (DSTU1 only)
430 	 */
431 	public int getHardTagListLimit() {
432 		return myHardTagListLimit;
433 	}
434 
435 	/**
436 	 * Gets the maximum number of results to return in a GetTags query (DSTU1 only)
437 	 */
438 	public void setHardTagListLimit(int theHardTagListLimit) {
439 		myHardTagListLimit = theHardTagListLimit;
440 	}
441 
442 	/**
443 	 * If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
444 	 * the server will not create search indexes for search parameters with no values in resources.
445 	 * <p>
446 	 * Disabling this feature means that the <code>:missing</code> search modifier will not be
447 	 * supported on the server, but also means that storage and indexing (i.e. writes to the
448 	 * database) may be much faster on servers which have lots of search parameters and need
449 	 * to write quickly.
450 	 * </p>
451 	 * <p>
452 	 * This feature may be enabled on servers where supporting the use of the :missing parameter is
453 	 * of higher importance than raw write performance
454 	 * </p>
455 	 */
456 	public IndexEnabledEnum getIndexMissingFields() {
457 		return myIndexMissingFieldsEnabled;
458 	}
459 
460 	/**
461 	 * If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
462 	 * the server will not create search indexes for search parameters with no values in resources.
463 	 * <p>
464 	 * Disabling this feature means that the <code>:missing</code> search modifier will not be
465 	 * supported on the server, but also means that storage and indexing (i.e. writes to the
466 	 * database) may be much faster on servers which have lots of search parameters and need
467 	 * to write quickly.
468 	 * </p>
469 	 * <p>
470 	 * This feature may be enabled on servers where supporting the use of the :missing parameter is
471 	 * of higher importance than raw write performance
472 	 * </p>
473 	 * <p>
474 	 * Note that this setting also has an impact on sorting (i.e. using the
475 	 * <code>_sort</code> parameter on searches): If the server is configured
476 	 * to not index missing field.
477 	 * </p>
478 	 */
479 	public void setIndexMissingFields(IndexEnabledEnum theIndexMissingFields) {
480 		Validate.notNull(theIndexMissingFields, "theIndexMissingFields must not be null");
481 		myIndexMissingFieldsEnabled = theIndexMissingFields;
482 	}
483 
484 	/**
485 	 * Returns the interceptors which will be notified of operations.
486 	 *
487 	 * @see #setInterceptors(List)
488 	 */
489 	public List<IServerInterceptor> getInterceptors() {
490 		if (myInterceptors == null) {
491 			myInterceptors = new ArrayList<>();
492 		}
493 		return myInterceptors;
494 	}
495 
496 	/**
497 	 * This may be used to optionally register server interceptors directly against the DAOs.
498 	 */
499 	public void setInterceptors(List<IServerInterceptor> theInterceptors) {
500 		myInterceptors = theInterceptors;
501 	}
502 
503 	/**
504 	 * This may be used to optionally register server interceptors directly against the DAOs.
505 	 */
506 	public void setInterceptors(IServerInterceptor... theInterceptor) {
507 		setInterceptors(new ArrayList<IServerInterceptor>());
508 		if (theInterceptor != null && theInterceptor.length != 0) {
509 			getInterceptors().addAll(Arrays.asList(theInterceptor));
510 		}
511 	}
512 
513 	/**
514 	 * See {@link #setMaximumExpansionSize(int)}
515 	 */
516 	public int getMaximumExpansionSize() {
517 		return myMaximumExpansionSize;
518 	}
519 
520 	/**
521 	 * Sets the maximum number of codes that will be added to a valueset expansion before
522 	 * the operation will be failed as too costly
523 	 */
524 	public void setMaximumExpansionSize(int theMaximumExpansionSize) {
525 		Validate.isTrue(theMaximumExpansionSize > 0, "theMaximumExpansionSize must be > 0");
526 		myMaximumExpansionSize = theMaximumExpansionSize;
527 	}
528 
529 	/**
530 	 * Provides the maximum number of results which may be returned by a search (HTTP GET) which
531 	 * is executed as a sub-operation within within a FHIR <code>transaction</code> or
532 	 * <code>batch</code> operation. For example, if this value is set to <code>100</code> and
533 	 * a FHIR transaction is processed with a sub-request for <code>Patient?gender=male</code>,
534 	 * the server will throw an error (and the transaction will fail) if there are more than
535 	 * 100 resources on the server which match this query.
536 	 * <p>
537 	 * The default value is <code>null</code>, which means that there is no limit.
538 	 * </p>
539 	 */
540 	public Integer getMaximumSearchResultCountInTransaction() {
541 		return myMaximumSearchResultCountInTransaction;
542 	}
543 
544 	/**
545 	 * Provides the maximum number of results which may be returned by a search (HTTP GET) which
546 	 * is executed as a sub-operation within within a FHIR <code>transaction</code> or
547 	 * <code>batch</code> operation. For example, if this value is set to <code>100</code> and
548 	 * a FHIR transaction is processed with a sub-request for <code>Patient?gender=male</code>,
549 	 * the server will throw an error (and the transaction will fail) if there are more than
550 	 * 100 resources on the server which match this query.
551 	 * <p>
552 	 * The default value is <code>null</code>, which means that there is no limit.
553 	 * </p>
554 	 */
555 	public void setMaximumSearchResultCountInTransaction(Integer theMaximumSearchResultCountInTransaction) {
556 		myMaximumSearchResultCountInTransaction = theMaximumSearchResultCountInTransaction;
557 	}
558 
559 	/**
560 	 * This setting controls the number of threads allocated to resource reindexing
561 	 * (which is only ever used if SearchParameters change, or a manual reindex is
562 	 * triggered due to a HAPI FHIR upgrade or some other reason).
563 	 * <p>
564 	 * The default value is set to the number of available processors
565 	 * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
566 	 * for this setting must be a positive integer.
567 	 * </p>
568 	 */
569 	public int getReindexThreadCount() {
570 		return myReindexThreadCount;
571 	}
572 
573 	/**
574 	 * This setting controls the number of threads allocated to resource reindexing
575 	 * (which is only ever used if SearchParameters change, or a manual reindex is
576 	 * triggered due to a HAPI FHIR upgrade or some other reason).
577 	 * <p>
578 	 * The default value is set to the number of available processors
579 	 * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
580 	 * for this setting must be a positive integer.
581 	 * </p>
582 	 */
583 	public void setReindexThreadCount(int theReindexThreadCount) {
584 		myReindexThreadCount = theReindexThreadCount;
585 		myReindexThreadCount = Math.max(myReindexThreadCount, 1); // Minimum of 1
586 	}
587 
588 	public ResourceEncodingEnum getResourceEncoding() {
589 		return myResourceEncoding;
590 	}
591 
592 	public void setResourceEncoding(ResourceEncodingEnum theResourceEncoding) {
593 		myResourceEncoding = theResourceEncoding;
594 	}
595 
596 	/**
597 	 * If set, an individual resource will not be allowed to have more than the
598 	 * given number of tags, profiles, and security labels (the limit is for the combined
599 	 * total for all of these things on an individual resource).
600 	 * <p>
601 	 * If set to <code>null</code>, no limit will be applied.
602 	 * </p>
603 	 * <p>
604 	 * The default value for this setting is 1000.
605 	 * </p>
606 	 */
607 	public Integer getResourceMetaCountHardLimit() {
608 		return myResourceMetaCountHardLimit;
609 	}
610 
611 	/**
612 	 * If set, an individual resource will not be allowed to have more than the
613 	 * given number of tags, profiles, and security labels (the limit is for the combined
614 	 * total for all of these things on an individual resource).
615 	 * <p>
616 	 * If set to <code>null</code>, no limit will be applied.
617 	 * </p>
618 	 * <p>
619 	 * The default value for this setting is 1000.
620 	 * </p>
621 	 */
622 	public void setResourceMetaCountHardLimit(Integer theResourceMetaCountHardLimit) {
623 		myResourceMetaCountHardLimit = theResourceMetaCountHardLimit;
624 	}
625 
626 	/**
627 	 * This setting configures the strategy to use in generating IDs for newly
628 	 * created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
629 	 */
630 	public IdStrategyEnum getResourceServerIdStrategy() {
631 		return myResourceServerIdStrategy;
632 	}
633 
634 	/**
635 	 * This setting configures the strategy to use in generating IDs for newly
636 	 * created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
637 	 *
638 	 * @param theResourceIdStrategy The strategy. Must not be null.
639 	 */
640 	public void setResourceServerIdStrategy(IdStrategyEnum theResourceIdStrategy) {
641 		Validate.notNull(theResourceIdStrategy, "theResourceIdStrategy must not be null");
642 		myResourceServerIdStrategy = theResourceIdStrategy;
643 	}
644 
645 	/**
646 	 * If set to a non {@literal null} value (default is {@link #DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS non null})
647 	 * if an identical search is requested multiple times within this window, the same results will be returned
648 	 * to multiple queries. For example, if this value is set to 1 minute and a client searches for all
649 	 * patients named "smith", and then a second client also performs the same search within 1 minute,
650 	 * the same cached results will be returned.
651 	 * <p>
652 	 * This approach can improve performance, especially under heavy load, but can also mean that
653 	 * searches may potentially return slightly out-of-date results.
654 	 * </p>
655 	 * <p>
656 	 * Note that if this is set to a non-null value, clients may override this setting by using
657 	 * the <code>Cache-Control</code> header. If this is set to <code>null</code>, the Cache-Control
658 	 * header will be ignored.
659 	 * </p>
660 	 */
661 	public Long getReuseCachedSearchResultsForMillis() {
662 		return myReuseCachedSearchResultsForMillis;
663 	}
664 
665 	/**
666 	 * If set to a non {@literal null} value (default is {@link #DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS non null})
667 	 * if an identical search is requested multiple times within this window, the same results will be returned
668 	 * to multiple queries. For example, if this value is set to 1 minute and a client searches for all
669 	 * patients named "smith", and then a second client also performs the same search within 1 minute,
670 	 * the same cached results will be returned.
671 	 * <p>
672 	 * This approach can improve performance, especially under heavy load, but can also mean that
673 	 * searches may potentially return slightly out-of-date results.
674 	 * </p>
675 	 * <p>
676 	 * Note that if this is set to a non-null value, clients may override this setting by using
677 	 * the <code>Cache-Control</code> header. If this is set to <code>null</code>, the Cache-Control
678 	 * header will be ignored.
679 	 * </p>
680 	 */
681 	public void setReuseCachedSearchResultsForMillis(Long theReuseCachedSearchResultsForMillis) {
682 		myReuseCachedSearchResultsForMillis = theReuseCachedSearchResultsForMillis;
683 	}
684 
685 	/**
686 	 * Specifies the duration in minutes for which values will be retained after being
687 	 * written to the terminology translation cache. Defaults to 60.
688 	 */
689 	public Long getTranslationCachesExpireAfterWriteInMinutes() {
690 		return myTranslationCachesExpireAfterWriteInMinutes;
691 	}
692 
693 	/**
694 	 * Specifies the duration in minutes for which values will be retained after being
695 	 * written to the terminology translation cache. Defaults to 60.
696 	 */
697 	public void setTranslationCachesExpireAfterWriteInMinutes(Long translationCachesExpireAfterWriteInMinutes) {
698 		myTranslationCachesExpireAfterWriteInMinutes = translationCachesExpireAfterWriteInMinutes;
699 	}
700 
701 	/**
702 	 * This setting may be used to advise the server that any references found in
703 	 * resources that have any of the base URLs given here will be replaced with
704 	 * simple local references.
705 	 * <p>
706 	 * For example, if the set contains the value <code>http://example.com/base/</code>;
707 	 * and a resource is submitted to the server that contains a reference to
708 	 * <code>http://example.com/base/Patient/1</code>, the server will automatically
709 	 * convert this reference to <code>Patient/1</code>
710 	 * </p>
711 	 * <p>
712 	 * Note that this property has different behaviour from {@link DaoConfig#getTreatReferencesAsLogical()}
713 	 * </p>
714 	 *
715 	 * @see #getTreatReferencesAsLogical()
716 	 */
717 	public Set<String> getTreatBaseUrlsAsLocal() {
718 		return myTreatBaseUrlsAsLocal;
719 	}
720 
721 	/**
722 	 * This setting may be used to advise the server that any references found in
723 	 * resources that have any of the base URLs given here will be replaced with
724 	 * simple local references.
725 	 * <p>
726 	 * For example, if the set contains the value <code>http://example.com/base/</code>;
727 	 * and a resource is submitted to the server that contains a reference to
728 	 * <code>http://example.com/base/Patient/1</code>, the server will automatically
729 	 * convert this reference to <code>Patient/1</code>
730 	 * </p>
731 	 *
732 	 * @param theTreatBaseUrlsAsLocal The set of base URLs. May be <code>null</code>, which
733 	 *                                means no references will be treated as external
734 	 */
735 	public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
736 		if (theTreatBaseUrlsAsLocal != null) {
737 			for (String next : theTreatBaseUrlsAsLocal) {
738 				validateTreatBaseUrlsAsLocal(next);
739 			}
740 		}
741 
742 		HashSet<String> treatBaseUrlsAsLocal = new HashSet<String>();
743 		for (String next : ObjectUtils.defaultIfNull(theTreatBaseUrlsAsLocal, new HashSet<String>())) {
744 			while (next.endsWith("/")) {
745 				next = next.substring(0, next.length() - 1);
746 			}
747 			treatBaseUrlsAsLocal.add(next);
748 		}
749 		myTreatBaseUrlsAsLocal = treatBaseUrlsAsLocal;
750 	}
751 
752 	/**
753 	 * This setting may be used to advise the server that any references found in
754 	 * resources that have any of the base URLs given here will be treated as logical
755 	 * references instead of being treated as real references.
756 	 * <p>
757 	 * A logical reference is a reference which is treated as an identifier, and
758 	 * does not neccesarily resolve. See <a href="http://hl7.org/fhir/references.html">references</a> for
759 	 * a description of logical references. For example, the valueset
760 	 * <a href="http://hl7.org/fhir/valueset-quantity-comparator.html">valueset-quantity-comparator</a> is a logical
761 	 * reference.
762 	 * </p>
763 	 * <p>
764 	 * Values for this field may take either of the following forms:
765 	 * </p>
766 	 * <ul>
767 	 * <li><code>http://example.com/some-url</code> <b>(will be matched exactly)</b></li>
768 	 * <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
769 	 * </ul>
770 	 *
771 	 * @see #DEFAULT_LOGICAL_BASE_URLS Default values for this property
772 	 */
773 	public Set<String> getTreatReferencesAsLogical() {
774 		return myTreatReferencesAsLogical;
775 	}
776 
777 	/**
778 	 * This setting may be used to advise the server that any references found in
779 	 * resources that have any of the base URLs given here will be treated as logical
780 	 * references instead of being treated as real references.
781 	 * <p>
782 	 * A logical reference is a reference which is treated as an identifier, and
783 	 * does not neccesarily resolve. See <a href="http://hl7.org/fhir/references.html">references</a> for
784 	 * a description of logical references. For example, the valueset
785 	 * <a href="http://hl7.org/fhir/valueset-quantity-comparator.html">valueset-quantity-comparator</a> is a logical
786 	 * reference.
787 	 * </p>
788 	 * <p>
789 	 * Values for this field may take either of the following forms:
790 	 * </p>
791 	 * <ul>
792 	 * <li><code>http://example.com/some-url</code> <b>(will be matched exactly)</b></li>
793 	 * <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
794 	 * </ul>
795 	 *
796 	 * @see #DEFAULT_LOGICAL_BASE_URLS Default values for this property
797 	 */
798 	public DaoConfig setTreatReferencesAsLogical(Set<String> theTreatReferencesAsLogical) {
799 		myTreatReferencesAsLogical = theTreatReferencesAsLogical;
800 		return this;
801 	}
802 
803 	/**
804 	 * If enabled, the server will support the use of :contains searches,
805 	 * which are helpful but can have adverse effects on performance.
806 	 * <p>
807 	 * Default is <code>false</code> (Note that prior to HAPI FHIR
808 	 * 3.5.0 the default was <code>true</code>)
809 	 * </p>
810 	 * <p>
811 	 * Note: If you change this value after data already has
812 	 * already been stored in the database, you must for a reindexing
813 	 * of all data in the database or resources may not be
814 	 * searchable.
815 	 * </p>
816 	 */
817 	public boolean isAllowContainsSearches() {
818 		return myAllowContainsSearches;
819 	}
820 
821 	/**
822 	 * If enabled, the server will support the use of :contains searches,
823 	 * which are helpful but can have adverse effects on performance.
824 	 * <p>
825 	 * Default is <code>false</code> (Note that prior to HAPI FHIR
826 	 * 3.5.0 the default was <code>true</code>)
827 	 * </p>
828 	 * <p>
829 	 * Note: If you change this value after data already has
830 	 * already been stored in the database, you must for a reindexing
831 	 * of all data in the database or resources may not be
832 	 * searchable.
833 	 * </p>
834 	 */
835 	public void setAllowContainsSearches(boolean theAllowContainsSearches) {
836 		this.myAllowContainsSearches = theAllowContainsSearches;
837 	}
838 
839 	/**
840 	 * If set to <code>true</code> (default is <code>false</code>) the server will allow
841 	 * resources to have references to external servers. For example if this server is
842 	 * running at <code>http://example.com/fhir</code> and this setting is set to
843 	 * <code>true</code> the server will allow a Patient resource to be saved with a
844 	 * Patient.organization value of <code>http://foo.com/Organization/1</code>.
845 	 * <p>
846 	 * Under the default behaviour if this value has not been changed, the above
847 	 * resource would be rejected by the server because it requires all references
848 	 * to be resolvable on the local server.
849 	 * </p>
850 	 * <p>
851 	 * Note that external references will be indexed by the server and may be searched
852 	 * (e.g. <code>Patient:organization</code>), but
853 	 * chained searches (e.g. <code>Patient:organization.name</code>) will not work across
854 	 * these references.
855 	 * </p>
856 	 * <p>
857 	 * It is recommended to also set {@link #setTreatBaseUrlsAsLocal(Set)} if this value
858 	 * is set to <code>true</code>
859 	 * </p>
860 	 *
861 	 * @see #setTreatBaseUrlsAsLocal(Set)
862 	 * @see #setAllowExternalReferences(boolean)
863 	 */
864 	public boolean isAllowExternalReferences() {
865 		return myAllowExternalReferences;
866 	}
867 
868 	/**
869 	 * If set to <code>true</code> (default is <code>false</code>) the server will allow
870 	 * resources to have references to external servers. For example if this server is
871 	 * running at <code>http://example.com/fhir</code> and this setting is set to
872 	 * <code>true</code> the server will allow a Patient resource to be saved with a
873 	 * Patient.organization value of <code>http://foo.com/Organization/1</code>.
874 	 * <p>
875 	 * Under the default behaviour if this value has not been changed, the above
876 	 * resource would be rejected by the server because it requires all references
877 	 * to be resolvable on the local server.
878 	 * </p>
879 	 * <p>
880 	 * Note that external references will be indexed by the server and may be searched
881 	 * (e.g. <code>Patient:organization</code>), but
882 	 * chained searches (e.g. <code>Patient:organization.name</code>) will not work across
883 	 * these references.
884 	 * </p>
885 	 * <p>
886 	 * It is recommended to also set {@link #setTreatBaseUrlsAsLocal(Set)} if this value
887 	 * is set to <code>true</code>
888 	 * </p>
889 	 *
890 	 * @see #setTreatBaseUrlsAsLocal(Set)
891 	 * @see #setAllowExternalReferences(boolean)
892 	 */
893 	public void setAllowExternalReferences(boolean theAllowExternalReferences) {
894 		myAllowExternalReferences = theAllowExternalReferences;
895 	}
896 
897 	/**
898 	 * @see #setAllowInlineMatchUrlReferences(boolean)
899 	 */
900 	public boolean isAllowInlineMatchUrlReferences() {
901 		return myAllowInlineMatchUrlReferences;
902 	}
903 
904 	/**
905 	 * Should references containing match URLs be resolved and replaced in create and update operations. For
906 	 * example, if this property is set to true and a resource is created containing a reference
907 	 * to "Patient?identifier=12345", this is reference match URL will be resolved and replaced according
908 	 * to the usual match URL rules.
909 	 * <p>
910 	 * Default is {@literal true} beginning in HAPI FHIR 2.4, since this
911 	 * feature is now specified in the FHIR specification. (Previously it
912 	 * was an experimental/rpposed feature)
913 	 * </p>
914 	 *
915 	 * @since 1.5
916 	 */
917 	public void setAllowInlineMatchUrlReferences(boolean theAllowInlineMatchUrlReferences) {
918 		myAllowInlineMatchUrlReferences = theAllowInlineMatchUrlReferences;
919 	}
920 
921 	public boolean isAllowMultipleDelete() {
922 		return myAllowMultipleDelete;
923 	}
924 
925 	public void setAllowMultipleDelete(boolean theAllowMultipleDelete) {
926 		myAllowMultipleDelete = theAllowMultipleDelete;
927 	}
928 
929 	/**
930 	 * When creating or updating a resource: If this property is set to <code>true</code>
931 	 * (default is <code>false</code>), if the resource has a reference to another resource
932 	 * on the local server but that reference does not exist, a placeholder resource will be
933 	 * created.
934 	 * <p>
935 	 * In other words, if an observation with subject <code>Patient/FOO</code> is created, but
936 	 * there is no resource called <code>Patient/FOO</code> on the server, this property causes
937 	 * an empty patient with ID "FOO" to be created in order to prevent this operation
938 	 * from failing.
939 	 * </p>
940 	 * <p>
941 	 * This property can be useful in cases where replication between two servers is wanted.
942 	 * Note however that references containing purely numeric IDs will not be auto-created
943 	 * as they are never allowed to be client supplied in HAPI FHIR JPA.
944 	 * </p>
945 	 */
946 	public boolean isAutoCreatePlaceholderReferenceTargets() {
947 		return myAutoCreatePlaceholderReferenceTargets;
948 	}
949 
950 	/**
951 	 * When creating or updating a resource: If this property is set to <code>true</code>
952 	 * (default is <code>false</code>), if the resource has a reference to another resource
953 	 * on the local server but that reference does not exist, a placeholder resource will be
954 	 * created.
955 	 * <p>
956 	 * In other words, if an observation with subject <code>Patient/FOO</code> is created, but
957 	 * there is no resource called <code>Patient/FOO</code> on the server, this property causes
958 	 * an empty patient with ID "FOO" to be created in order to prevent this operation
959 	 * from failing.
960 	 * </p>
961 	 * <p>
962 	 * This property can be useful in cases where replication between two servers is wanted.
963 	 * Note however that references containing purely numeric IDs will not be auto-created
964 	 * as they are never allowed to be client supplied in HAPI FHIR JPA.
965 	 * </p>
966 	 */
967 	public void setAutoCreatePlaceholderReferenceTargets(boolean theAutoCreatePlaceholderReferenceTargets) {
968 		myAutoCreatePlaceholderReferenceTargets = theAutoCreatePlaceholderReferenceTargets;
969 	}
970 
971 	/**
972 	 * If set to {@code true} the default search params (i.e. the search parameters that are
973 	 * defined by the FHIR specification itself) may be overridden by uploading search
974 	 * parameters to the server with the same code as the built-in search parameter.
975 	 * <p>
976 	 * This can be useful if you want to be able to disable or alter
977 	 * the behaviour of the default search parameters.
978 	 * </p>
979 	 * <p>
980 	 * The default value for this setting is {@code false}
981 	 * </p>
982 	 */
983 	public boolean isDefaultSearchParamsCanBeOverridden() {
984 		return myDefaultSearchParamsCanBeOverridden;
985 	}
986 
987 	/**
988 	 * If set to {@code true} the default search params (i.e. the search parameters that are
989 	 * defined by the FHIR specification itself) may be overridden by uploading search
990 	 * parameters to the server with the same code as the built-in search parameter.
991 	 * <p>
992 	 * This can be useful if you want to be able to disable or alter
993 	 * the behaviour of the default search parameters.
994 	 * </p>
995 	 * <p>
996 	 * The default value for this setting is {@code false}
997 	 * </p>
998 	 */
999 	public void setDefaultSearchParamsCanBeOverridden(boolean theDefaultSearchParamsCanBeOverridden) {
1000 		myDefaultSearchParamsCanBeOverridden = theDefaultSearchParamsCanBeOverridden;
1001 	}
1002 
1003 	/**
1004 	 * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1005 	 * deleted even if other resources currently contain references to them.
1006 	 * <p>
1007 	 * This property can cause confusing results for clients of the server since searches, includes,
1008 	 * and other FHIR features may not behave as expected when referential integrity is not
1009 	 * preserved. Use this feature with caution.
1010 	 * </p>
1011 	 */
1012 	public boolean isEnforceReferentialIntegrityOnDelete() {
1013 		return myEnforceReferentialIntegrityOnDelete;
1014 	}
1015 
1016 	/**
1017 	 * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1018 	 * deleted even if other resources currently contain references to them.
1019 	 * <p>
1020 	 * This property can cause confusing results for clients of the server since searches, includes,
1021 	 * and other FHIR features may not behave as expected when referential integrity is not
1022 	 * preserved. Use this feature with caution.
1023 	 * </p>
1024 	 */
1025 	public void setEnforceReferentialIntegrityOnDelete(boolean theEnforceReferentialIntegrityOnDelete) {
1026 		myEnforceReferentialIntegrityOnDelete = theEnforceReferentialIntegrityOnDelete;
1027 	}
1028 
1029 	/**
1030 	 * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1031 	 * created or updated even if they contain references to local resources that do not exist.
1032 	 * <p>
1033 	 * For example, if a patient contains a reference to managing organization <code>Organization/FOO</code>
1034 	 * but FOO is not a valid ID for an organization on the server, the operation will be blocked unless
1035 	 * this propery has been set to <code>false</code>
1036 	 * </p>
1037 	 * <p>
1038 	 * This property can cause confusing results for clients of the server since searches, includes,
1039 	 * and other FHIR features may not behave as expected when referential integrity is not
1040 	 * preserved. Use this feature with caution.
1041 	 * </p>
1042 	 */
1043 	public boolean isEnforceReferentialIntegrityOnWrite() {
1044 		return myEnforceReferentialIntegrityOnWrite;
1045 	}
1046 
1047 	/**
1048 	 * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1049 	 * created or updated even if they contain references to local resources that do not exist.
1050 	 * <p>
1051 	 * For example, if a patient contains a reference to managing organization <code>Organization/FOO</code>
1052 	 * but FOO is not a valid ID for an organization on the server, the operation will be blocked unless
1053 	 * this propery has been set to <code>false</code>
1054 	 * </p>
1055 	 * <p>
1056 	 * This property can cause confusing results for clients of the server since searches, includes,
1057 	 * and other FHIR features may not behave as expected when referential integrity is not
1058 	 * preserved. Use this feature with caution.
1059 	 * </p>
1060 	 */
1061 	public void setEnforceReferentialIntegrityOnWrite(boolean theEnforceReferentialIntegrityOnWrite) {
1062 		myEnforceReferentialIntegrityOnWrite = theEnforceReferentialIntegrityOnWrite;
1063 	}
1064 
1065 	/**
1066 	 * If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
1067 	 * task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
1068 	 * <p>
1069 	 * This feature is useful if you want to define your own process for deleting these (e.g. because
1070 	 * you are running in a cluster)
1071 	 * </p>
1072 	 */
1073 	public boolean isExpireSearchResults() {
1074 		return myDeleteStaleSearches;
1075 	}
1076 
1077 	/**
1078 	 * If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
1079 	 * task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
1080 	 * <p>
1081 	 * This feature is useful if you want to define your own process for deleting these (e.g. because
1082 	 * you are running in a cluster)
1083 	 * </p>
1084 	 */
1085 	public void setExpireSearchResults(boolean theDeleteStaleSearches) {
1086 		myDeleteStaleSearches = theDeleteStaleSearches;
1087 	}
1088 
1089 	/**
1090 	 * If set to <code>true</code> (default is <code>false</code>), the $expunge operation
1091 	 * will be enabled on this server. This operation is potentially dangerous since it allows
1092 	 * a client to physically delete data in a way that can not be recovered (without resorting
1093 	 * to backups).
1094 	 * <p>
1095 	 * It is recommended to not enable this setting without appropriate security
1096 	 * in place on your server to prevent non-administrators from using this
1097 	 * operation.
1098 	 * </p>
1099 	 */
1100 	public boolean isExpungeEnabled() {
1101 		return myExpungeEnabled;
1102 	}
1103 
1104 	/**
1105 	 * If set to <code>true</code> (default is <code>false</code>), the $expunge operation
1106 	 * will be enabled on this server. This operation is potentially dangerous since it allows
1107 	 * a client to physically delete data in a way that can not be recovered (without resorting
1108 	 * to backups).
1109 	 * <p>
1110 	 * It is recommended to not enable this setting without appropriate security
1111 	 * in place on your server to prevent non-administrators from using this
1112 	 * operation.
1113 	 * </p>
1114 	 */
1115 	public void setExpungeEnabled(boolean theExpungeEnabled) {
1116 		myExpungeEnabled = theExpungeEnabled;
1117 	}
1118 
1119 	/**
1120 	 * Should contained IDs be indexed the same way that non-contained IDs are (default is
1121 	 * <code>true</code>)
1122 	 */
1123 	public boolean isIndexContainedResources() {
1124 		return myIndexContainedResources;
1125 	}
1126 
1127 	/**
1128 	 * Should contained IDs be indexed the same way that non-contained IDs are (default is
1129 	 * <code>true</code>)
1130 	 */
1131 	public void setIndexContainedResources(boolean theIndexContainedResources) {
1132 		myIndexContainedResources = theIndexContainedResources;
1133 	}
1134 
1135 	/**
1136 	 * Should resources be marked as needing reindexing when a
1137 	 * SearchParameter resource is added or changed. This should generally
1138 	 * be true (which is the default)
1139 	 */
1140 	public boolean isMarkResourcesForReindexingUponSearchParameterChange() {
1141 		return myMarkResourcesForReindexingUponSearchParameterChange;
1142 	}
1143 
1144 	/**
1145 	 * Should resources be marked as needing reindexing when a
1146 	 * SearchParameter resource is added or changed. This should generally
1147 	 * be true (which is the default)
1148 	 */
1149 	public void setMarkResourcesForReindexingUponSearchParameterChange(boolean theMarkResourcesForReindexingUponSearchParameterChange) {
1150 		myMarkResourcesForReindexingUponSearchParameterChange = theMarkResourcesForReindexingUponSearchParameterChange;
1151 	}
1152 
1153 	public boolean isSchedulingDisabled() {
1154 		return mySchedulingDisabled;
1155 	}
1156 
1157 	public void setSchedulingDisabled(boolean theSchedulingDisabled) {
1158 		mySchedulingDisabled = theSchedulingDisabled;
1159 	}
1160 
1161 	/**
1162 	 * If set to {@literal true} (default is true), if a client performs an update which does not actually
1163 	 * result in any chance to a given resource (e.g. an update where the resource body matches the
1164 	 * existing resource body in the database) the operation will succeed but a new version (and corresponding history
1165 	 * entry) will not actually be created. The existing resource version will be returned to the client.
1166 	 * <p>
1167 	 * If set to {@literal false}, all updates will result in the creation of a new version
1168 	 * </p>
1169 	 */
1170 	public boolean isSuppressUpdatesWithNoChange() {
1171 		return mySuppressUpdatesWithNoChange;
1172 	}
1173 
1174 	/**
1175 	 * If set to {@literal true} (default is true), if a client performs an update which does not actually
1176 	 * result in any chance to a given resource (e.g. an update where the resource body matches the
1177 	 * existing resource body in the database) the operation will succeed but a new version (and corresponding history
1178 	 * entry) will not actually be created. The existing resource version will be returned to the client.
1179 	 * <p>
1180 	 * If set to {@literal false}, all updates will result in the creation of a new version
1181 	 * </p>
1182 	 */
1183 	public void setSuppressUpdatesWithNoChange(boolean theSuppressUpdatesWithNoChange) {
1184 		mySuppressUpdatesWithNoChange = theSuppressUpdatesWithNoChange;
1185 
1186 	}
1187 
1188 	/**
1189 	 * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this
1190 	 * setting is set to <code>true</code> (default is <code>true</code>) the system
1191 	 * will test for the existence of a particular unique index value prior to saving
1192 	 * a new one.
1193 	 * <p>
1194 	 * This causes friendlier error messages to be generated, but adds an
1195 	 * extra round-trip to the database for eavh save so it can cause
1196 	 * a small performance hit.
1197 	 * </p>
1198 	 */
1199 	public boolean isUniqueIndexesCheckedBeforeSave() {
1200 		return myUniqueIndexesCheckedBeforeSave;
1201 	}
1202 
1203 	/**
1204 	 * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this
1205 	 * setting is set to <code>true</code> (default is <code>true</code>) the system
1206 	 * will test for the existence of a particular unique index value prior to saving
1207 	 * a new one.
1208 	 * <p>
1209 	 * This causes friendlier error messages to be generated, but adds an
1210 	 * extra round-trip to the database for each save so it can cause
1211 	 * a small performance hit.
1212 	 * </p>
1213 	 */
1214 	public void setUniqueIndexesCheckedBeforeSave(boolean theUniqueIndexesCheckedBeforeSave) {
1215 		myUniqueIndexesCheckedBeforeSave = theUniqueIndexesCheckedBeforeSave;
1216 	}
1217 
1218 	/**
1219 	 * If set to <code>true</code> (default is <code>true</code>), indexes will be
1220 	 * created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
1221 	 * This is a HAPI FHIR specific extension which can be used to specify that no more than one
1222 	 * resource can exist which matches a given criteria, using a database constraint to
1223 	 * enforce this.
1224 	 */
1225 	public boolean isUniqueIndexesEnabled() {
1226 		return myUniqueIndexesEnabled;
1227 	}
1228 
1229 	/**
1230 	 * If set to <code>true</code> (default is <code>true</code>), indexes will be
1231 	 * created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}.
1232 	 * This is a HAPI FHIR specific extension which can be used to specify that no more than one
1233 	 * resource can exist which matches a given criteria, using a database constraint to
1234 	 * enforce this.
1235 	 */
1236 	public void setUniqueIndexesEnabled(boolean theUniqueIndexesEnabled) {
1237 		myUniqueIndexesEnabled = theUniqueIndexesEnabled;
1238 	}
1239 
1240 	/**
1241 	 * If <code>true</code> (default is <code>true</code>), before allowing a
1242 	 * SearchParameter resource to be stored (create, update, etc.) the
1243 	 * expression will be performed against an empty resource to ensure that
1244 	 * the FHIRPath executor is able to process it.
1245 	 * <p>
1246 	 * This should proabably always be set to true, but is configurable
1247 	 * in order to support some unit tests.
1248 	 * </p>
1249 	 */
1250 	public boolean isValidateSearchParameterExpressionsOnSave() {
1251 		return myValidateSearchParameterExpressionsOnSave;
1252 	}
1253 
1254 	/**
1255 	 * If <code>true</code> (default is <code>true</code>), before allowing a
1256 	 * SearchParameter resource to be stored (create, update, etc.) the
1257 	 * expression will be performed against an empty resource to ensure that
1258 	 * the FHIRPath executor is able to process it.
1259 	 * <p>
1260 	 * This should proabably always be set to true, but is configurable
1261 	 * in order to support some unit tests.
1262 	 * </p>
1263 	 */
1264 	public void setValidateSearchParameterExpressionsOnSave(boolean theValidateSearchParameterExpressionsOnSave) {
1265 		myValidateSearchParameterExpressionsOnSave = theValidateSearchParameterExpressionsOnSave;
1266 	}
1267 
1268 	/**
1269 	 * Do not call this method, it exists only for legacy reasons. It
1270 	 * will be removed in a future version. Configure the page size on your
1271 	 * paging provider instead.
1272 	 *
1273 	 * @deprecated This method does not do anything. Configure the page size on your
1274 	 * paging provider instead. Deprecated in HAPI FHIR 2.3 (Jan 2017)
1275 	 */
1276 	@Deprecated
1277 	public void setHardSearchLimit(int theHardSearchLimit) {
1278 		// this method does nothing
1279 	}
1280 
1281 	/**
1282 	 * This is the maximum number of resources that will be added to a single page of returned resources. Because of
1283 	 * includes with wildcards and other possibilities it is possible for a client to make requests that include very
1284 	 * large amounts of data, so this hard limit can be imposed to prevent runaway requests.
1285 	 *
1286 	 * @deprecated Deprecated in HAPI FHIR 3.2.0 as this method doesn't actually do anything
1287 	 */
1288 	@Deprecated
1289 	public void setIncludeLimit(@SuppressWarnings("unused") int theIncludeLimit) {
1290 		// nothing
1291 	}
1292 
1293 	/**
1294 	 * @deprecated As of HAPI FHIR 3.0.0, subscriptions no longer use polling for
1295 	 * detecting changes, so this setting has no effect
1296 	 */
1297 	@Deprecated
1298 	public void setSubscriptionEnabled(boolean theSubscriptionEnabled) {
1299 		// nothing
1300 	}
1301 
1302 	/**
1303 	 * @deprecated As of HAPI FHIR 3.0.0, subscriptions no longer use polling for
1304 	 * detecting changes, so this setting has no effect
1305 	 */
1306 	@Deprecated
1307 	public void setSubscriptionPollDelay(long theSubscriptionPollDelay) {
1308 		// ignore
1309 	}
1310 
1311 	/**
1312 	 * @deprecated As of HAPI FHIR 3.0.0, subscriptions no longer use polling for
1313 	 * detecting changes, so this setting has no effect
1314 	 */
1315 	@Deprecated
1316 	public void setSubscriptionPurgeInactiveAfterMillis(Long theMillis) {
1317 		// ignore
1318 	}
1319 
1320 	public void setSubscriptionPurgeInactiveAfterSeconds(int theSeconds) {
1321 		setSubscriptionPurgeInactiveAfterMillis(theSeconds * DateUtils.MILLIS_PER_SECOND);
1322 	}
1323 
1324 	public enum IndexEnabledEnum {
1325 		ENABLED,
1326 		DISABLED
1327 	}
1328 
1329 	public enum IdStrategyEnum {
1330 		/**
1331 		 * This strategy is the default strategy, and it simply uses a sequential
1332 		 * numeric ID for each newly created resource.
1333 		 */
1334 		SEQUENTIAL_NUMERIC,
1335 		/**
1336 		 * Each resource will receive a randomly generated UUID
1337 		 */
1338 		UUID
1339 	}
1340 
1341 	private static void validateTreatBaseUrlsAsLocal(String theUrl) {
1342 		Validate.notBlank(theUrl, "Base URL must not be null or empty");
1343 
1344 		int starIdx = theUrl.indexOf('*');
1345 		if (starIdx != -1) {
1346 			if (starIdx != theUrl.length() - 1) {
1347 				throw new IllegalArgumentException("Base URL wildcard character (*) can only appear at the end of the string: " + theUrl);
1348 			}
1349 		}
1350 
1351 	}
1352 
1353 }