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