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