001package ca.uhn.fhir.jpa.api.config;
002
003import ca.uhn.fhir.jpa.api.model.HistoryCountModeEnum;
004import ca.uhn.fhir.jpa.api.model.WarmCacheEntry;
005import ca.uhn.fhir.jpa.model.entity.ModelConfig;
006import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
007import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
008import ca.uhn.fhir.util.HapiExtensions;
009import ca.uhn.fhir.validation.FhirValidator;
010import com.google.common.annotations.VisibleForTesting;
011import com.google.common.collect.Sets;
012import org.apache.commons.lang3.StringUtils;
013import org.apache.commons.lang3.Validate;
014import org.apache.commons.lang3.time.DateUtils;
015import org.hl7.fhir.dstu2.model.Subscription;
016import org.hl7.fhir.r4.model.Bundle;
017import org.slf4j.Logger;
018import org.slf4j.LoggerFactory;
019
020import javax.annotation.Nonnull;
021import javax.annotation.Nullable;
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.Collections;
025import java.util.List;
026import java.util.Set;
027import java.util.TreeSet;
028
029/*
030 * #%L
031 * HAPI FHIR Storage api
032 * %%
033 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
034 * %%
035 * Licensed under the Apache License, Version 2.0 (the "License");
036 * you may not use this file except in compliance with the License.
037 * You may obtain a copy of the License at
038 *
039 * http://www.apache.org/licenses/LICENSE-2.0
040 *
041 * Unless required by applicable law or agreed to in writing, software
042 * distributed under the License is distributed on an "AS IS" BASIS,
043 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
044 * See the License for the specific language governing permissions and
045 * limitations under the License.
046 * #L%
047 */
048
049public class DaoConfig {
050
051        /**
052         * Default value for {@link #setReuseCachedSearchResultsForMillis(Long)}: 60000ms (one minute)
053         */
054        public static final Long DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS = DateUtils.MILLIS_PER_MINUTE;
055        /**
056         * See {@link #setStatusBasedReindexingDisabled(boolean)}
057         */
058        public static final String DISABLE_STATUS_BASED_REINDEX = "disable_status_based_reindex";
059        /**
060         * Default value for {@link #setTranslationCachesExpireAfterWriteInMinutes(Long)}: 60 minutes
061         *
062         * @see #setTranslationCachesExpireAfterWriteInMinutes(Long)
063         */
064        public static final Long DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES = 60L;
065        /**
066         * Default {@link #setBundleTypesAllowedForStorage(Set)} value:
067         * <ul>
068         * <li>collection</li>
069         * <li>document</li>
070         * <li>message</li>
071         * </ul>
072         */
073        @SuppressWarnings("WeakerAccess")
074        public static final Set<String> DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE = Collections.unmodifiableSet(new TreeSet<>(Sets.newHashSet(
075                Bundle.BundleType.COLLECTION.toCode(),
076                Bundle.BundleType.DOCUMENT.toCode(),
077                Bundle.BundleType.MESSAGE.toCode()
078        )));
079        // update setter javadoc if default changes
080        public static final int DEFAULT_MAX_EXPANSION_SIZE = 1000;
081        public static final HistoryCountModeEnum DEFAULT_HISTORY_COUNT_MODE = HistoryCountModeEnum.CACHED_ONLY_WITHOUT_OFFSET;
082        /**
083         * This constant applies to task enablement, e.g. {@link #setEnableTaskStaleSearchCleanup(boolean)}.
084         * <p>
085         * By default, all are enabled.
086         */
087        public static final boolean DEFAULT_ENABLE_TASKS = true;
088        public static final int DEFAULT_MAXIMUM_INCLUDES_TO_LOAD_PER_PAGE = 1000;
089        /**
090         * @since 5.5.0
091         */
092        public static final TagStorageModeEnum DEFAULT_TAG_STORAGE_MODE = TagStorageModeEnum.VERSIONED;
093        public static final int DEFAULT_EXPUNGE_BATCH_SIZE = 800;
094        /**
095         * @since 5.6.0
096         */
097        // Thread Pool size used by batch in bundle
098        public static final int DEFAULT_BUNDLE_BATCH_POOL_SIZE = 20; // 1 for single thread
099        public static final int DEFAULT_BUNDLE_BATCH_MAX_POOL_SIZE = 100; // 1 for single thread
100        public static final int DEFAULT_BUNDLE_BATCH_QUEUE_CAPACITY = 200;
101        /**
102         * Default value for {@link #setMaximumSearchResultCountInTransaction(Integer)}
103         *
104         * @see #setMaximumSearchResultCountInTransaction(Integer)
105         */
106        private static final Integer DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION = null;
107        private static final Integer DEFAULT_MAXIMUM_TRANSACTION_BUNDLE_SIZE = null;
108        private static final Logger ourLog = LoggerFactory.getLogger(DaoConfig.class);
109        private static final int DEFAULT_REINDEX_BATCH_SIZE = 800;
110        private static final int DEFAULT_MAXIMUM_DELETE_CONFLICT_COUNT = 60;
111        /**
112         * Child Configurations
113         */
114        private static final Integer DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE = 10000;
115        private final ModelConfig myModelConfig = new ModelConfig();
116        /**
117         * Do not change default of {@code 0}!
118         *
119         * @since 4.1.0
120         */
121        private final int myPreExpandValueSetsDefaultOffset = 0;
122        /**
123         * update setter javadoc if default changes
124         */
125        @Nonnull
126        private final Long myTranslationCachesExpireAfterWriteInMinutes = DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES;
127        /**
128         * @since 5.5.0
129         */
130        @Nullable
131        private Integer myMaximumIncludesToLoadPerPage = DEFAULT_MAXIMUM_INCLUDES_TO_LOAD_PER_PAGE;
132        private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED;
133        /**
134         * update setter javadoc if default changes
135         */
136        private boolean myAllowInlineMatchUrlReferences = true;
137        private boolean myAllowMultipleDelete;
138        /**
139         * update setter javadoc if default changes
140         */
141        private int myDeferIndexingForCodesystemsOfSize = 100;
142        private boolean myDeleteStaleSearches = true;
143        private boolean myEnforceReferentialIntegrityOnDelete = true;
144        private boolean myUniqueIndexesEnabled = true;
145        private boolean myUniqueIndexesCheckedBeforeSave = true;
146        private boolean myEnforceReferentialIntegrityOnWrite = true;
147        private SearchTotalModeEnum myDefaultTotalMode = null;
148        private int myEverythingIncludesFetchPageSize = 50;
149        private int myBulkImportMaxRetryCount = 10;
150        private TagStorageModeEnum myTagStorageMode = DEFAULT_TAG_STORAGE_MODE;
151        /**
152         * update setter javadoc if default changes
153         */
154        private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
155        /**
156         * update setter javadoc if default changes
157         */
158        private Integer myFetchSizeDefaultMaximum = null;
159        private int myMaximumExpansionSize = DEFAULT_MAX_EXPANSION_SIZE;
160        private Integer myMaximumSearchResultCountInTransaction = DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION;
161        private Integer myMaximumTransactionBundleSize = DEFAULT_MAXIMUM_TRANSACTION_BUNDLE_SIZE;
162        private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
163        /**
164         * update setter javadoc if default changes
165         */
166        private Integer myResourceMetaCountHardLimit = 1000;
167        private Long myReuseCachedSearchResultsForMillis = DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
168        private boolean mySchedulingDisabled;
169        private boolean mySuppressUpdatesWithNoChange = true;
170        private boolean myAutoCreatePlaceholderReferenceTargets;
171        private Integer myCacheControlNoStoreMaxResultsUpperLimit = 1000;
172        private Integer myCountSearchResultsUpTo = null;
173        private boolean myStatusBasedReindexingDisabled;
174        private IdStrategyEnum myResourceServerIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC;
175        private boolean myMarkResourcesForReindexingUponSearchParameterChange;
176        private boolean myExpungeEnabled;
177        private boolean myDeleteExpungeEnabled;
178        private int myExpungeBatchSize = DEFAULT_EXPUNGE_BATCH_SIZE;
179        private int myReindexBatchSize = DEFAULT_REINDEX_BATCH_SIZE;
180        private int myReindexThreadCount;
181        private int myExpungeThreadCount;
182        private Set<String> myBundleTypesAllowedForStorage;
183        private boolean myValidateSearchParameterExpressionsOnSave = true;
184        private List<Integer> mySearchPreFetchThresholds = Arrays.asList(500, 2000, -1);
185        private List<WarmCacheEntry> myWarmCacheEntries = new ArrayList<>();
186        private boolean myDisableHashBasedSearches;
187        private boolean myEnableInMemorySubscriptionMatching = true;
188        private boolean myEnforceReferenceTargetTypes = true;
189        private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
190        private boolean myFilterParameterEnabled = false;
191        private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID;
192        private HistoryCountModeEnum myHistoryCountMode = DEFAULT_HISTORY_COUNT_MODE;
193        private int myInternalSynchronousSearchSize = DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE;
194        /**
195         * update setter javadoc if default changes
196         */
197        private Integer myMaximumDeleteConflictQueryCount = DEFAULT_MAXIMUM_DELETE_CONFLICT_COUNT;
198        /**
199         * Do not change default of {@code true}!
200         *
201         * @since 4.1.0
202         */
203        private boolean myPreExpandValueSets = true;
204        /**
205         * Do not change default of {@code 1000}!
206         *
207         * @since 4.1.0
208         */
209        private int myPreExpandValueSetsDefaultCount = 1000;
210        /**
211         * Do not change default of {@code 1000}!
212         *
213         * @since 4.1.0
214         */
215        private int myPreExpandValueSetsMaxCount = 1000;
216        /**
217         * Do not change default of {@code true}!
218         *
219         * @since 4.2.0
220         */
221        private boolean myPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets = true;
222        /**
223         * @since 5.0.0
224         */
225        private boolean myDeleteEnabled = true;
226        /**
227         * @since 5.1.0
228         */
229        private boolean myLastNEnabled = false;
230        /**
231         * @since 5.2.0
232         */
233        private boolean myUseLegacySearchBuilder = false;
234        /**
235         * @since 5.5.0
236         */
237        private boolean myReindexEnabled = true;
238        /**
239         * @since 5.4.0
240         */
241        private boolean myMatchUrlCacheEnabled;
242        /**
243         * @since 5.5.0
244         */
245        private boolean myEnableTaskBulkImportJobExecution;
246        /**
247         * @since 5.5.0
248         */
249        private boolean myEnableTaskStaleSearchCleanup;
250        /**
251         * @since 5.5.0
252         */
253        private boolean myEnableTaskPreExpandValueSets;
254        /**
255         * @since 5.5.0
256         */
257        private boolean myEnableTaskResourceReindexing;
258        /**
259         * @since 5.5.0
260         */
261        private boolean myEnableTaskBulkExportJobExecution;
262        private boolean myMassIngestionMode;
263        private boolean myAccountForDateIndexNulls;
264        private boolean myTriggerSubscriptionsForNonVersioningChanges;
265        /**
266         * @since 5.6.0
267         */
268        private String myElasicSearchIndexPrefix;
269        private Integer myBundleBatchPoolSize = DEFAULT_BUNDLE_BATCH_POOL_SIZE;
270        private Integer myBundleBatchMaxPoolSize = DEFAULT_BUNDLE_BATCH_MAX_POOL_SIZE;
271
272        /**
273         * Activates the new Lucene/Elasticsearch indexing of search parameters.
274         * When active, string, token, and reference parameters will be indexed and
275         * queried within Hibernate Search.
276         *
277         * @since 5.6.0
278         * TODO mb test more with this true
279         */
280        private boolean myAdvancedLuceneIndexing = false;
281        /**
282         * If set to a positive number, any resources with a character length at or below the given number
283         * of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
284         * separate LOB column.
285         *
286         * @since 5.7.0
287         */
288        private int myInlineResourceTextBelowSize = 0;
289
290        /**
291         * @since 5.7.0
292         */
293        private boolean myStoreResourceInLuceneIndex;
294
295        /**
296         * @see FhirValidator#isConcurrentBundleValidation()
297         * @since 5.7.0
298         */
299        private boolean myConcurrentBundleValidation;
300
301        /**
302         * Constructor
303         */
304        public DaoConfig() {
305                setMarkResourcesForReindexingUponSearchParameterChange(true);
306                setReindexThreadCount(Runtime.getRuntime().availableProcessors());
307                setExpungeThreadCount(Runtime.getRuntime().availableProcessors());
308                setBundleTypesAllowedForStorage(DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE);
309
310                // Scheduled tasks are all enabled by default
311                setEnableTaskBulkImportJobExecution(DEFAULT_ENABLE_TASKS);
312                setEnableTaskBulkExportJobExecution(DEFAULT_ENABLE_TASKS);
313                setEnableTaskStaleSearchCleanup(DEFAULT_ENABLE_TASKS);
314                setEnableTaskPreExpandValueSets(DEFAULT_ENABLE_TASKS);
315                setEnableTaskResourceReindexing(DEFAULT_ENABLE_TASKS);
316
317                if ("true".equalsIgnoreCase(System.getProperty(DISABLE_STATUS_BASED_REINDEX))) {
318                        ourLog.info("Status based reindexing is DISABLED");
319                        setStatusBasedReindexingDisabled(true);
320                }
321        }
322
323        /**
324         * If set to a positive number, any resources with a character length at or below the given number
325         * of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
326         * separate LOB column.
327         *
328         * @since 5.7.0
329         */
330        public int getInlineResourceTextBelowSize() {
331                return myInlineResourceTextBelowSize;
332        }
333
334        /**
335         * If set to a positive number, any resources with a character length at or below the given number
336         * of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
337         * separate LOB column.
338         *
339         * @since 5.7.0
340         */
341        public void setInlineResourceTextBelowSize(int theInlineResourceTextBelowSize) {
342                myInlineResourceTextBelowSize = theInlineResourceTextBelowSize;
343        }
344
345        /**
346         * Sets the tag storage mode for the server. Default is {@link TagStorageModeEnum#VERSIONED}.
347         *
348         * @since 5.5.0
349         */
350        @Nonnull
351        public TagStorageModeEnum getTagStorageMode() {
352                return myTagStorageMode;
353        }
354
355        /**
356         * Sets the tag storage mode for the server. Default is {@link TagStorageModeEnum#VERSIONED}.
357         *
358         * @since 5.5.0
359         */
360        public void setTagStorageMode(@Nonnull TagStorageModeEnum theTagStorageMode) {
361                Validate.notNull(theTagStorageMode, "theTagStorageMode must not be null");
362                myTagStorageMode = theTagStorageMode;
363        }
364
365        /**
366         * Specifies the maximum number of times that a chunk will be retried during bulk import
367         * processes before giving up.
368         *
369         * @since 5.5.0
370         */
371        public int getBulkImportMaxRetryCount() {
372                return myBulkImportMaxRetryCount;
373        }
374
375        /**
376         * Specifies the maximum number of times that a chunk will be retried during bulk import
377         * processes before giving up.
378         *
379         * @since 5.5.0
380         */
381        public void setBulkImportMaxRetryCount(int theBulkImportMaxRetryCount) {
382                myBulkImportMaxRetryCount = theBulkImportMaxRetryCount;
383        }
384
385        /**
386         * Specifies the maximum number of <code>_include</code> and <code>_revinclude</code> results to return in a
387         * single page of results. The default is <code>1000</code>, and <code>null</code> may be used
388         * to indicate that there is no limit.
389         *
390         * @since 5.5.0
391         */
392        @Nullable
393        public Integer getMaximumIncludesToLoadPerPage() {
394                return myMaximumIncludesToLoadPerPage;
395        }
396
397        /**
398         * Specifies the maximum number of <code>_include</code> and <code>_revinclude</code> results to return in a
399         * single page of results. The default is <code>1000</code>, and <code>null</code> may be used
400         * to indicate that there is no limit.
401         *
402         * @since 5.5.0
403         */
404        public void setMaximumIncludesToLoadPerPage(@Nullable Integer theMaximumIncludesToLoadPerPage) {
405                myMaximumIncludesToLoadPerPage = theMaximumIncludesToLoadPerPage;
406        }
407
408        /**
409         * When performing a FHIR history operation, a <code>Bundle.total</code> value is included in the
410         * response, indicating the total number of history entries. This response is calculated using a
411         * SQL COUNT query statement which can be expensive. This setting allows the results of the count
412         * query to be cached, resulting in a much lighter load on the server, at the expense of
413         * returning total values that may be slightly out of date. Total counts can also be disabled,
414         * or forced to always be accurate.
415         * <p>
416         * In {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET} mode, a loading cache is used to fetch the value,
417         * meaning that only one thread per JVM will fetch the count, and others will block while waiting
418         * for the cache to load, avoiding excessive load on the database.
419         * </p>
420         * <p>
421         * Default is {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET}
422         * </p>
423         *
424         * @since 5.4.0
425         */
426        public HistoryCountModeEnum getHistoryCountMode() {
427                return myHistoryCountMode;
428        }
429
430        /**
431         * When performing a FHIR history operation, a <code>Bundle.total</code> value is included in the
432         * response, indicating the total number of history entries. This response is calculated using a
433         * SQL COUNT query statement which can be expensive. This setting allows the results of the count
434         * query to be cached, resulting in a much lighter load on the server, at the expense of
435         * returning total values that may be slightly out of date. Total counts can also be disabled,
436         * or forced to always be accurate.
437         * <p>
438         * In {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET} mode, a loading cache is used to fetch the value,
439         * meaning that only one thread per JVM will fetch the count, and others will block while waiting
440         * for the cache to load, avoiding excessive load on the database.
441         * </p>
442         * <p>
443         * Default is {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET}
444         * </p>
445         *
446         * @since 5.4.0
447         */
448        public void setHistoryCountMode(@Nonnull HistoryCountModeEnum theHistoryCountMode) {
449
450                Validate.notNull(theHistoryCountMode, "theHistoryCountMode must not be null");
451                myHistoryCountMode = theHistoryCountMode;
452        }
453
454        /**
455         * If set to <code>true</code> (default is <code>false</code>) the <code>$lastn</code> operation will be enabled for
456         * indexing Observation resources. This operation involves creating a special set of tables in ElasticSearch for
457         * discovering Observation resources. Enabling this setting increases the amount of storage space required, and can
458         * slow write operations, but can be very useful for searching for collections of Observations for some applications.
459         *
460         * @since 5.1.0
461         */
462        public boolean isLastNEnabled() {
463                return myLastNEnabled;
464        }
465
466        /**
467         * If set to <code>true</code> (default is <code>false</code>) the <code>$lastn</code> operation will be enabled for
468         * indexing Observation resources. This operation involves creating a special set of tables in ElasticSearch for
469         * discovering Observation resources. Enabling this setting increases the amount of storage space required, and can
470         * slow write operations, but can be very useful for searching for collections of Observations for some applications.
471         *
472         * @since 5.1.0
473         */
474        public void setLastNEnabled(boolean theLastNEnabled) {
475                myLastNEnabled = theLastNEnabled;
476        }
477
478        /**
479         * This method controls whether to use the new non-hibernate search SQL builder that was introduced in HAPI FHIR 5.2.0.
480         * By default this will be <code>false</code> meaning that the new SQL builder is used. Set to <code>true</code> to use the
481         * legacy SQL builder based on Hibernate.
482         * <p>Note that this method will be removed in HAPI FHIR 5.4.0</p>
483         *
484         * @since 5.3.0
485         */
486        public boolean isUseLegacySearchBuilder() {
487                return myUseLegacySearchBuilder;
488        }
489
490        /**
491         * This method controls whether to use the new non-hibernate search SQL builder that was introduced in HAPI FHIR 5.2.0.
492         * By default this will be <code>false</code> meaning that the new SQL builder is used. Set to <code>true</code> to use the
493         * legacy SQL builder based on Hibernate.
494         * <p>Note that this method will be removed in HAPI FHIR 5.4.0</p>
495         *
496         * @since 5.3.0
497         */
498        public void setUseLegacySearchBuilder(boolean theUseLegacySearchBuilder) {
499                myUseLegacySearchBuilder = theUseLegacySearchBuilder;
500        }
501
502        /**
503         * Specifies the duration in minutes for which values will be retained after being
504         * written to the terminology translation cache. Defaults to 60.
505         */
506        @Nonnull
507        public Long getTranslationCachesExpireAfterWriteInMinutes() {
508                return myTranslationCachesExpireAfterWriteInMinutes;
509        }
510
511        /**
512         * If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
513         * cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
514         * where conditional operations are frequently performed, but note that this cache will not be
515         * invalidated based on updates to resources so this may have detrimental effects.
516         * <p>
517         * Default is <code>false</code>
518         *
519         * @since 5.4.0
520         * @deprecated Deprecated in 5.5.0. Use {@link #isMatchUrlCacheEnabled()} instead (the name of this method is misleading)
521         */
522        @Deprecated
523        public boolean getMatchUrlCache() {
524                return myMatchUrlCacheEnabled;
525        }
526
527        /**
528         * If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
529         * cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
530         * where conditional operations are frequently performed, but note that this cache will not be
531         * invalidated based on updates to resources so this may have detrimental effects.
532         * <p>
533         * Default is <code>false</code>
534         *
535         * @since 5.4.0
536         * @deprecated Deprecated in 5.5.0. Use {@link #setMatchUrlCacheEnabled(boolean)} instead (the name of this method is misleading)
537         */
538        @Deprecated
539        public void setMatchUrlCache(boolean theMatchUrlCache) {
540                myMatchUrlCacheEnabled = theMatchUrlCache;
541        }
542
543        /**
544         * If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
545         * cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
546         * where conditional operations are frequently performed, but note that this cache will not be
547         * invalidated based on updates to resources so this may have detrimental effects.
548         * <p>
549         * Default is <code>false</code>
550         *
551         * @since 5.5.0
552         */
553        public boolean isMatchUrlCacheEnabled() {
554                return getMatchUrlCache();
555        }
556
557        /**
558         * If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
559         * cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
560         * where conditional operations are frequently performed, but note that this cache will not be
561         * invalidated based on updates to resources so this may have detrimental effects.
562         * <p>
563         * Default is <code>false</code>
564         *
565         * @since 5.5.0
566         */
567        public void setMatchUrlCacheEnabled(boolean theMatchUrlCache) {
568                setMatchUrlCache(theMatchUrlCache);
569        }
570
571        /**
572         * If set to <code>true</code> (default is true) when a resource is being persisted,
573         * the target resource types of references will be validated to ensure that they
574         * are appropriate for the field containing the reference. This is generally a good idea
575         * because invalid reference target types may not be searchable.
576         */
577        public boolean isEnforceReferenceTargetTypes() {
578                return myEnforceReferenceTargetTypes;
579        }
580
581        /**
582         * If set to <code>true</code> (default is true) when a resource is being persisted,
583         * the target resource types of references will be validated to ensure that they
584         * are appropriate for the field containing the reference. This is generally a good idea
585         * because invalid reference target types may not be searchable.
586         */
587        public void setEnforceReferenceTargetTypes(boolean theEnforceReferenceTargetTypes) {
588                myEnforceReferenceTargetTypes = theEnforceReferenceTargetTypes;
589        }
590
591        /**
592         * If a non-null value is supplied (default is <code>null</code>), a default
593         * for the <code>_total</code> parameter may be specified here. For example,
594         * setting this value to {@link SearchTotalModeEnum#ACCURATE} will force a
595         * count to always be calculated for all searches. This can have a performance impact
596         * since it means that a count query will always be performed, but this is desirable
597         * for some solutions.
598         */
599        public SearchTotalModeEnum getDefaultTotalMode() {
600                return myDefaultTotalMode;
601        }
602
603        /**
604         * If a non-null value is supplied (default is <code>null</code>), a default
605         * for the <code>_total</code> parameter may be specified here. For example,
606         * setting this value to {@link SearchTotalModeEnum#ACCURATE} will force a
607         * count to always be calculated for all searches. This can have a performance impact
608         * since it means that a count query will always be performed, but this is desirable
609         * for some solutions.
610         */
611        public void setDefaultTotalMode(SearchTotalModeEnum theDefaultTotalMode) {
612                myDefaultTotalMode = theDefaultTotalMode;
613        }
614
615        /**
616         * Returns a set of searches that should be kept "warm", meaning that
617         * searches will periodically be performed in the background to
618         * keep results ready for this search
619         */
620        public List<WarmCacheEntry> getWarmCacheEntries() {
621                if (myWarmCacheEntries == null) {
622                        myWarmCacheEntries = new ArrayList<>();
623                }
624                return myWarmCacheEntries;
625        }
626
627        public void setWarmCacheEntries(List<WarmCacheEntry> theWarmCacheEntries) {
628                myWarmCacheEntries = theWarmCacheEntries;
629        }
630
631        /**
632         * If set to <code>true</code> (default is false), the reindexing of search parameters
633         * using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
634         * This query is just not efficient on Oracle and bogs the system down when there are
635         * a lot of resources. A more efficient way of doing this will be introduced
636         * in the next release of HAPI FHIR.
637         *
638         * @since 3.5.0
639         */
640        public boolean isStatusBasedReindexingDisabled() {
641                return myStatusBasedReindexingDisabled;
642        }
643
644        /**
645         * If set to <code>true</code> (default is false), the reindexing of search parameters
646         * using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
647         * This query is just not efficient on Oracle and bogs the system down when there are
648         * a lot of resources. A more efficient way of doing this will be introduced
649         * in the next release of HAPI FHIR.
650         *
651         * @since 3.5.0
652         */
653        public void setStatusBasedReindexingDisabled(boolean theStatusBasedReindexingDisabled) {
654                myStatusBasedReindexingDisabled = theStatusBasedReindexingDisabled;
655        }
656
657        /**
658         * Add a value to the {@link #setTreatReferencesAsLogical(Set) logical references list}.
659         *
660         * @see #setTreatReferencesAsLogical(Set)
661         */
662        public void addTreatReferencesAsLogical(String theTreatReferencesAsLogical) {
663                myModelConfig.addTreatReferencesAsLogical(theTreatReferencesAsLogical);
664        }
665
666        /**
667         * This setting specifies the bundle types (<code>Bundle.type</code>) that
668         * are allowed to be stored as-is on the /Bundle endpoint.
669         *
670         * @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
671         */
672        public Set<String> getBundleTypesAllowedForStorage() {
673                return myBundleTypesAllowedForStorage;
674        }
675
676        /**
677         * This setting specifies the bundle types (<code>Bundle.type</code>) that
678         * are allowed to be stored as-is on the /Bundle endpoint.
679         *
680         * @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
681         */
682        public void setBundleTypesAllowedForStorage(Set<String> theBundleTypesAllowedForStorage) {
683                Validate.notNull(theBundleTypesAllowedForStorage, "theBundleTypesAllowedForStorage must not be null");
684                myBundleTypesAllowedForStorage = theBundleTypesAllowedForStorage;
685        }
686
687        /**
688         * Specifies the highest number that a client is permitted to use in a
689         * <code>Cache-Control: nostore, max-results=NNN</code>
690         * directive. If the client tries to exceed this limit, the
691         * request will be denied. Defaults to 1000.
692         */
693        public Integer getCacheControlNoStoreMaxResultsUpperLimit() {
694                return myCacheControlNoStoreMaxResultsUpperLimit;
695        }
696
697        /**
698         * Specifies the highest number that a client is permitted to use in a
699         * <code>Cache-Control: nostore, max-results=NNN</code>
700         * directive. If the client tries to exceed this limit, the
701         * request will be denied. Defaults to 1000.
702         */
703        public void setCacheControlNoStoreMaxResultsUpperLimit(Integer theCacheControlNoStoreMaxResults) {
704                myCacheControlNoStoreMaxResultsUpperLimit = theCacheControlNoStoreMaxResults;
705        }
706
707        /**
708         * When searching, if set to a non-null value (default is <code>null</code>) the
709         * search coordinator will attempt to find at least this many results
710         * before returning a response to the client. This parameter mainly affects
711         * whether a "total count" is included in the response bundle for searches that
712         * return large amounts of data.
713         * <p>
714         * For a search that returns 10000 results, if this value is set to
715         * 10000 the search coordinator will find all 10000 results
716         * prior to returning, so the initial response bundle will have the
717         * total set to 10000. If this value is null (or less than 10000)
718         * the response bundle will likely return slightly faster, but will
719         * not include the total. Subsequent page requests will likely
720         * include the total however, if they are performed after the
721         * search coordinator has found all results.
722         * </p>
723         * <p>
724         * Set this value to <code>0</code> to always load all
725         * results before returning.
726         * </p>
727         */
728        public Integer getCountSearchResultsUpTo() {
729                return myCountSearchResultsUpTo;
730        }
731
732        /**
733         * When searching, if set to a non-null value (default is <code>null</code>) the
734         * search coordinator will attempt to find at least this many results
735         * before returning a response to the client. This parameter mainly affects
736         * whether a "total count" is included in the response bundle for searches that
737         * return large amounts of data.
738         * <p>
739         * For a search that returns 10000 results, if this value is set to
740         * 10000 the search coordinator will find all 10000 results
741         * prior to returning, so the initial response bundle will have the
742         * total set to 10000. If this value is null (or less than 10000)
743         * the response bundle will likely return slightly faster, but will
744         * not include the total. Subsequent page requests will likely
745         * include the total however, if they are performed after the
746         * search coordinator has found all results.
747         * </p>
748         * <p>
749         * Set this value to <code>0</code> to always load all
750         * results before returning.
751         * </p>
752         */
753        public void setCountSearchResultsUpTo(Integer theCountSearchResultsUpTo) {
754                myCountSearchResultsUpTo = theCountSearchResultsUpTo;
755        }
756
757        /**
758         * When a code system is added that contains more than this number of codes,
759         * the code system will be indexed later in an incremental process in order to
760         * avoid overwhelming Lucene with a huge number of codes in a single operation.
761         * <p>
762         * Defaults to 100
763         * </p>
764         */
765        public int getDeferIndexingForCodesystemsOfSize() {
766                return myDeferIndexingForCodesystemsOfSize;
767        }
768
769        /**
770         * When a code system is added that contains more than this number of codes,
771         * the code system will be indexed later in an incremental process in order to
772         * avoid overwhelming Lucene with a huge number of codes in a single operation.
773         * <p>
774         * Defaults to 100
775         * </p>
776         */
777        public void setDeferIndexingForCodesystemsOfSize(int theDeferIndexingForCodesystemsOfSize) {
778                myDeferIndexingForCodesystemsOfSize = theDeferIndexingForCodesystemsOfSize;
779        }
780
781        /**
782         * Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
783         * 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
784         * as the search results are paged over.
785         * <p>
786         * In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
787         * value may improve performance but may also cause memory issues.
788         * </p>
789         * <p>
790         * The default value is 50
791         * </p>
792         */
793        public int getEverythingIncludesFetchPageSize() {
794                return myEverythingIncludesFetchPageSize;
795        }
796
797        /**
798         * Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
799         * 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
800         * as the search results are paged over.
801         * <p>
802         * In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
803         * value may improve performance but may also cause memory issues.
804         * </p>
805         * <p>
806         * The default value is 50
807         * </p>
808         */
809        public void setEverythingIncludesFetchPageSize(int theEverythingIncludesFetchPageSize) {
810                Validate.inclusiveBetween(1, Integer.MAX_VALUE, theEverythingIncludesFetchPageSize);
811                myEverythingIncludesFetchPageSize = theEverythingIncludesFetchPageSize;
812        }
813
814        /**
815         * Sets the number of milliseconds that search results for a given client search
816         * should be preserved before being purged from the database.
817         * <p>
818         * Search results are stored in the database so that they can be paged over multiple
819         * requests. After this
820         * number of milliseconds, they will be deleted from the database, and any paging links
821         * (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
822         * </p>
823         * <p>
824         * To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
825         * </p>
826         *
827         * @since 1.5
828         */
829        public long getExpireSearchResultsAfterMillis() {
830                return myExpireSearchResultsAfterMillis;
831        }
832
833        /**
834         * Sets the number of milliseconds that search results for a given client search
835         * should be preserved before being purged from the database.
836         * <p>
837         * Search results are stored in the database so that they can be paged over multiple
838         * requests. After this
839         * number of milliseconds, they will be deleted from the database, and any paging links
840         * (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
841         * </p>
842         * <p>
843         * To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
844         * </p>
845         *
846         * @since 1.5
847         */
848        public void setExpireSearchResultsAfterMillis(long theExpireSearchResultsAfterMillis) {
849                myExpireSearchResultsAfterMillis = theExpireSearchResultsAfterMillis;
850        }
851
852        /**
853         * Gets the default maximum number of results to load in a query.
854         * <p>
855         * For example, if the database has a million Patient resources in it, and
856         * the client requests <code>GET /Patient</code>, if this value is set
857         * to a non-null value (default is <code>null</code>) only this number
858         * of results will be fetched. Setting this value appropriately
859         * can be useful to improve performance in some situations.
860         * </p>
861         */
862        public Integer getFetchSizeDefaultMaximum() {
863                return myFetchSizeDefaultMaximum;
864        }
865
866        /**
867         * Gets the default maximum number of results to load in a query.
868         * <p>
869         * For example, if the database has a million Patient resources in it, and
870         * the client requests <code>GET /Patient</code>, if this value is set
871         * to a non-null value (default is <code>null</code>) only this number
872         * of results will be fetched. Setting this value appropriately
873         * can be useful to improve performance in some situations.
874         * </p>
875         */
876        public void setFetchSizeDefaultMaximum(Integer theFetchSizeDefaultMaximum) {
877                myFetchSizeDefaultMaximum = theFetchSizeDefaultMaximum;
878        }
879
880        /**
881         * If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
882         * the server will not create search indexes for search parameters with no values in resources.
883         * <p>
884         * Disabling this feature means that the <code>:missing</code> search modifier will not be
885         * supported on the server, but also means that storage and indexing (i.e. writes to the
886         * database) may be much faster on servers which have lots of search parameters and need
887         * to write quickly.
888         * </p>
889         * <p>
890         * This feature may be enabled on servers where supporting the use of the :missing parameter is
891         * of higher importance than raw write performance
892         * </p>
893         */
894        public IndexEnabledEnum getIndexMissingFields() {
895                return myIndexMissingFieldsEnabled;
896        }
897
898        /**
899         * If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
900         * the server will not create search indexes for search parameters with no values in resources.
901         * <p>
902         * Disabling this feature means that the <code>:missing</code> search modifier will not be
903         * supported on the server, but also means that storage and indexing (i.e. writes to the
904         * database) may be much faster on servers which have lots of search parameters and need
905         * to write quickly.
906         * </p>
907         * <p>
908         * This feature may be enabled on servers where supporting the use of the :missing parameter is
909         * of higher importance than raw write performance
910         * </p>
911         * <p>
912         * Note that this setting also has an impact on sorting (i.e. using the
913         * <code>_sort</code> parameter on searches): If the server is configured
914         * to not index missing field.
915         * </p>
916         * <p>
917         * The following index may need to be added into the indexed tables such as <code>HFJ_SPIDX_TOKEN</code>
918         * to improve the search performance while <code>:missing</code> is enabled.
919         * <code>RES_TYPE, SP_NAME, SP_MISSING</code>
920         * </p>
921         */
922        public void setIndexMissingFields(IndexEnabledEnum theIndexMissingFields) {
923                Validate.notNull(theIndexMissingFields, "theIndexMissingFields must not be null");
924                myIndexMissingFieldsEnabled = theIndexMissingFields;
925        }
926
927        /**
928         * See {@link #setMaximumExpansionSize(int)}
929         */
930        public int getMaximumExpansionSize() {
931                return myMaximumExpansionSize;
932        }
933
934        /**
935         * Sets the maximum number of codes that will be added to an in-memory valueset expansion before
936         * the operation will be failed as too costly. Note that this setting applies only to
937         * in-memory expansions and does not apply to expansions that are being pre-calculated.
938         * <p>
939         * The default value for this setting is 1000.
940         * </p>
941         */
942        public void setMaximumExpansionSize(int theMaximumExpansionSize) {
943                Validate.isTrue(theMaximumExpansionSize > 0, "theMaximumExpansionSize must be > 0");
944                myMaximumExpansionSize = theMaximumExpansionSize;
945        }
946
947        /**
948         * Provides the maximum number of results which may be returned by a search (HTTP GET) which
949         * is executed as a sub-operation within within a FHIR <code>transaction</code> or
950         * <code>batch</code> operation. For example, if this value is set to <code>100</code> and
951         * a FHIR transaction is processed with a sub-request for <code>Patient?gender=male</code>,
952         * the server will throw an error (and the transaction will fail) if there are more than
953         * 100 resources on the server which match this query.
954         * <p>
955         * The default value is <code>null</code>, which means that there is no limit.
956         * </p>
957         */
958        public Integer getMaximumSearchResultCountInTransaction() {
959                return myMaximumSearchResultCountInTransaction;
960        }
961
962        /**
963         * Provides the maximum number of results which may be returned by a search (HTTP GET) which
964         * is executed as a sub-operation within within a FHIR <code>transaction</code> or
965         * <code>batch</code> operation. For example, if this value is set to <code>100</code> and
966         * a FHIR transaction is processed with a sub-request for <code>Patient?gender=male</code>,
967         * the server will throw an error (and the transaction will fail) if there are more than
968         * 100 resources on the server which match this query.
969         * <p>
970         * The default value is <code>null</code>, which means that there is no limit.
971         * </p>
972         */
973        public void setMaximumSearchResultCountInTransaction(Integer theMaximumSearchResultCountInTransaction) {
974                myMaximumSearchResultCountInTransaction = theMaximumSearchResultCountInTransaction;
975        }
976
977        /**
978         * Specifies the maximum number of resources permitted within a single transaction bundle.
979         * If a transaction bundle is submitted with more than this number of resources, it will be
980         * rejected with a PayloadTooLarge exception.
981         * <p>
982         * The default value is <code>null</code>, which means that there is no limit.
983         * </p>
984         */
985        public Integer getMaximumTransactionBundleSize() {
986                return myMaximumTransactionBundleSize;
987        }
988
989        /**
990         * Specifies the maximum number of resources permitted within a single transaction bundle.
991         * If a transaction bundle is submitted with more than this number of resources, it will be
992         * rejected with a PayloadTooLarge exception.
993         * <p>
994         * The default value is <code>null</code>, which means that there is no limit.
995         * </p>
996         */
997        public DaoConfig setMaximumTransactionBundleSize(Integer theMaximumTransactionBundleSize) {
998                myMaximumTransactionBundleSize = theMaximumTransactionBundleSize;
999                return this;
1000        }
1001
1002        /**
1003         * This setting controls the number of threads allocated to resource reindexing
1004         * (which is only ever used if SearchParameters change, or a manual reindex is
1005         * triggered due to a HAPI FHIR upgrade or some other reason).
1006         * <p>
1007         * The default value is set to the number of available processors
1008         * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
1009         * for this setting must be a positive integer.
1010         * </p>
1011         */
1012        public int getReindexThreadCount() {
1013                return myReindexThreadCount;
1014        }
1015
1016        /**
1017         * This setting controls the number of threads allocated to resource reindexing
1018         * (which is only ever used if SearchParameters change, or a manual reindex is
1019         * triggered due to a HAPI FHIR upgrade or some other reason).
1020         * <p>
1021         * The default value is set to the number of available processors
1022         * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
1023         * for this setting must be a positive integer.
1024         * </p>
1025         */
1026        public void setReindexThreadCount(int theReindexThreadCount) {
1027                myReindexThreadCount = theReindexThreadCount;
1028                myReindexThreadCount = Math.max(myReindexThreadCount, 1); // Minimum of 1
1029        }
1030
1031        /**
1032         * This setting controls the number of threads allocated to the expunge operation
1033         * <p>
1034         * The default value is set to the number of available processors
1035         * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
1036         * for this setting must be a positive integer.
1037         * </p>
1038         */
1039        public int getExpungeThreadCount() {
1040                return myExpungeThreadCount;
1041        }
1042
1043        /**
1044         * This setting controls the number of threads allocated to the expunge operation
1045         * <p>
1046         * The default value is set to the number of available processors
1047         * (via <code>Runtime.getRuntime().availableProcessors()</code>). Value
1048         * for this setting must be a positive integer.
1049         * </p>
1050         */
1051        public void setExpungeThreadCount(int theExpungeThreadCount) {
1052                myExpungeThreadCount = theExpungeThreadCount;
1053                myExpungeThreadCount = Math.max(myExpungeThreadCount, 1); // Minimum of 1
1054        }
1055
1056        public ResourceEncodingEnum getResourceEncoding() {
1057                return myResourceEncoding;
1058        }
1059
1060        public void setResourceEncoding(ResourceEncodingEnum theResourceEncoding) {
1061                myResourceEncoding = theResourceEncoding;
1062        }
1063
1064        /**
1065         * If set, an individual resource will not be allowed to have more than the
1066         * given number of tags, profiles, and security labels (the limit is for the combined
1067         * total for all of these things on an individual resource).
1068         * <p>
1069         * If set to <code>null</code>, no limit will be applied.
1070         * </p>
1071         * <p>
1072         * The default value for this setting is 1000.
1073         * </p>
1074         */
1075        public Integer getResourceMetaCountHardLimit() {
1076                return myResourceMetaCountHardLimit;
1077        }
1078
1079        /**
1080         * If set, an individual resource will not be allowed to have more than the
1081         * given number of tags, profiles, and security labels (the limit is for the combined
1082         * total for all of these things on an individual resource).
1083         * <p>
1084         * If set to <code>null</code>, no limit will be applied.
1085         * </p>
1086         * <p>
1087         * The default value for this setting is 1000.
1088         * </p>
1089         */
1090        public void setResourceMetaCountHardLimit(Integer theResourceMetaCountHardLimit) {
1091                myResourceMetaCountHardLimit = theResourceMetaCountHardLimit;
1092        }
1093
1094        /**
1095         * Controls the behaviour when a client-assigned ID is encountered, i.e. an HTTP PUT
1096         * on a resource ID that does not already exist in the database.
1097         * <p>
1098         * Default is {@link ClientIdStrategyEnum#ALPHANUMERIC}
1099         * </p>
1100         */
1101        public ClientIdStrategyEnum getResourceClientIdStrategy() {
1102                return myResourceClientIdStrategy;
1103        }
1104
1105        /**
1106         * Controls the behaviour when a client-assigned ID is encountered, i.e. an HTTP PUT
1107         * on a resource ID that does not already exist in the database.
1108         * <p>
1109         * Default is {@link ClientIdStrategyEnum#ALPHANUMERIC}
1110         * </p>
1111         *
1112         * @param theResourceClientIdStrategy Must not be <code>null</code>
1113         */
1114        public void setResourceClientIdStrategy(ClientIdStrategyEnum theResourceClientIdStrategy) {
1115                Validate.notNull(theResourceClientIdStrategy, "theClientIdStrategy must not be null");
1116                myResourceClientIdStrategy = theResourceClientIdStrategy;
1117        }
1118
1119        /**
1120         * This setting configures the strategy to use in generating IDs for newly
1121         * created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
1122         * <p>
1123         * This strategy is only used for server-assigned IDs, i.e. for HTTP POST
1124         * where the client is requesing that the server store a new resource and give
1125         * it an ID.
1126         * </p>
1127         */
1128        public IdStrategyEnum getResourceServerIdStrategy() {
1129                return myResourceServerIdStrategy;
1130        }
1131
1132        /**
1133         * This setting configures the strategy to use in generating IDs for newly
1134         * created resources on the server. The default is {@link IdStrategyEnum#SEQUENTIAL_NUMERIC}.
1135         * <p>
1136         * This strategy is only used for server-assigned IDs, i.e. for HTTP POST
1137         * where the client is requesing that the server store a new resource and give
1138         * it an ID.
1139         * </p>
1140         *
1141         * @param theResourceIdStrategy The strategy. Must not be <code>null</code>.
1142         */
1143        public void setResourceServerIdStrategy(IdStrategyEnum theResourceIdStrategy) {
1144                Validate.notNull(theResourceIdStrategy, "theResourceIdStrategy must not be null");
1145                myResourceServerIdStrategy = theResourceIdStrategy;
1146        }
1147
1148        /**
1149         * If set to a non {@literal null} value (default is {@link #DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS non null})
1150         * if an identical search is requested multiple times within this window, the same results will be returned
1151         * to multiple queries. For example, if this value is set to 1 minute and a client searches for all
1152         * patients named "smith", and then a second client also performs the same search within 1 minute,
1153         * the same cached results will be returned.
1154         * <p>
1155         * This approach can improve performance, especially under heavy load, but can also mean that
1156         * searches may potentially return slightly out-of-date results.
1157         * </p>
1158         * <p>
1159         * Note that if this is set to a non-null value, clients may override this setting by using
1160         * the <code>Cache-Control</code> header. If this is set to <code>null</code>, the Cache-Control
1161         * header will be ignored.
1162         * </p>
1163         */
1164        public Long getReuseCachedSearchResultsForMillis() {
1165                return myReuseCachedSearchResultsForMillis;
1166        }
1167
1168        /**
1169         * If set to a non {@literal null} value (default is {@link #DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS non null})
1170         * if an identical search is requested multiple times within this window, the same results will be returned
1171         * to multiple queries. For example, if this value is set to 1 minute and a client searches for all
1172         * patients named "smith", and then a second client also performs the same search within 1 minute,
1173         * the same cached results will be returned.
1174         * <p>
1175         * This approach can improve performance, especially under heavy load, but can also mean that
1176         * searches may potentially return slightly out-of-date results.
1177         * </p>
1178         * <p>
1179         * Note that if this is set to a non-null value, clients may override this setting by using
1180         * the <code>Cache-Control</code> header. If this is set to <code>null</code>, the Cache-Control
1181         * header will be ignored.
1182         * </p>
1183         */
1184        public void setReuseCachedSearchResultsForMillis(Long theReuseCachedSearchResultsForMillis) {
1185                myReuseCachedSearchResultsForMillis = theReuseCachedSearchResultsForMillis;
1186        }
1187
1188        /**
1189         * This setting may be used to advise the server that any references found in
1190         * resources that have any of the base URLs given here will be treated as logical
1191         * references instead of being treated as real references.
1192         * <p>
1193         * A logical reference is a reference which is treated as an identifier, and
1194         * does not neccesarily resolve. See <a href="http://hl7.org/fhir/references.html">references</a> for
1195         * a description of logical references. For example, the valueset
1196         * <a href="http://hl7.org/fhir/valueset-quantity-comparator.html">valueset-quantity-comparator</a> is a logical
1197         * reference.
1198         * </p>
1199         * <p>
1200         * Values for this field may take either of the following forms:
1201         * </p>
1202         * <ul>
1203         * <li><code>http://example.com/some-url</code> <b>(will be matched exactly)</b></li>
1204         * <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
1205         * </ul>
1206         *
1207         * @see ModelConfig#DEFAULT_LOGICAL_BASE_URLS Default values for this property
1208         */
1209        public Set<String> getTreatReferencesAsLogical() {
1210                return myModelConfig.getTreatReferencesAsLogical();
1211        }
1212
1213        /**
1214         * This setting may be used to advise the server that any references found in
1215         * resources that have any of the base URLs given here will be treated as logical
1216         * references instead of being treated as real references.
1217         * <p>
1218         * A logical reference is a reference which is treated as an identifier, and
1219         * does not neccesarily resolve. See <a href="http://hl7.org/fhir/references.html">references</a> for
1220         * a description of logical references. For example, the valueset
1221         * <a href="http://hl7.org/fhir/valueset-quantity-comparator.html">valueset-quantity-comparator</a> is a logical
1222         * reference.
1223         * </p>
1224         * <p>
1225         * Values for this field may take either of the following forms:
1226         * </p>
1227         * <ul>
1228         * <li><code>http://example.com/some-url</code> <b>(will be matched exactly)</b></li>
1229         * <li><code>http://example.com/some-base*</code> <b>(will match anything beginning with the part before the *)</b></li>
1230         * </ul>
1231         *
1232         * @see ModelConfig#DEFAULT_LOGICAL_BASE_URLS Default values for this property
1233         */
1234        public DaoConfig setTreatReferencesAsLogical(Set<String> theTreatReferencesAsLogical) {
1235                myModelConfig.setTreatReferencesAsLogical(theTreatReferencesAsLogical);
1236                return this;
1237        }
1238
1239        /**
1240         * If set to <code>true</code> (default is <code>false</code>) the server will allow
1241         * resources to have references to external servers. For example if this server is
1242         * running at <code>http://example.com/fhir</code> and this setting is set to
1243         * <code>true</code> the server will allow a Patient resource to be saved with a
1244         * Patient.organization value of <code>http://foo.com/Organization/1</code>.
1245         * <p>
1246         * Under the default behaviour if this value has not been changed, the above
1247         * resource would be rejected by the server because it requires all references
1248         * to be resolvable on the local server.
1249         * </p>
1250         * <p>
1251         * Note that external references will be indexed by the server and may be searched
1252         * (e.g. <code>Patient:organization</code>), but
1253         * chained searches (e.g. <code>Patient:organization.name</code>) will not work across
1254         * these references.
1255         * </p>
1256         * <p>
1257         * It is recommended to also set {@link #setTreatBaseUrlsAsLocal(Set)} if this value
1258         * is set to <code>true</code>
1259         * </p>
1260         *
1261         * @see #setTreatBaseUrlsAsLocal(Set)
1262         * @see #setAllowExternalReferences(boolean)
1263         */
1264        public boolean isAllowExternalReferences() {
1265                return myModelConfig.isAllowExternalReferences();
1266        }
1267
1268        /**
1269         * If set to <code>true</code> (default is <code>false</code>) the server will allow
1270         * resources to have references to external servers. For example if this server is
1271         * running at <code>http://example.com/fhir</code> and this setting is set to
1272         * <code>true</code> the server will allow a Patient resource to be saved with a
1273         * Patient.organization value of <code>http://foo.com/Organization/1</code>.
1274         * <p>
1275         * Under the default behaviour if this value has not been changed, the above
1276         * resource would be rejected by the server because it requires all references
1277         * to be resolvable on the local server.
1278         * </p>
1279         * <p>
1280         * Note that external references will be indexed by the server and may be searched
1281         * (e.g. <code>Patient:organization</code>), but
1282         * chained searches (e.g. <code>Patient:organization.name</code>) will not work across
1283         * these references.
1284         * </p>
1285         * <p>
1286         * It is recommended to also set {@link #setTreatBaseUrlsAsLocal(Set)} if this value
1287         * is set to <code>true</code>
1288         * </p>
1289         *
1290         * @see #setTreatBaseUrlsAsLocal(Set)
1291         * @see #setAllowExternalReferences(boolean)
1292         */
1293        public void setAllowExternalReferences(boolean theAllowExternalReferences) {
1294                myModelConfig.setAllowExternalReferences(theAllowExternalReferences);
1295        }
1296
1297        /**
1298         * @see #setAllowInlineMatchUrlReferences(boolean)
1299         */
1300        public boolean isAllowInlineMatchUrlReferences() {
1301                return myAllowInlineMatchUrlReferences;
1302        }
1303
1304        /**
1305         * Should references containing match URLs be resolved and replaced in create and update operations. For
1306         * example, if this property is set to true and a resource is created containing a reference
1307         * to "Patient?identifier=12345", this is reference match URL will be resolved and replaced according
1308         * to the usual match URL rules.
1309         * <p>
1310         * Default is {@literal true} beginning in HAPI FHIR 2.4, since this
1311         * feature is now specified in the FHIR specification. (Previously it
1312         * was an experimental/proposed feature)
1313         * </p>
1314         *
1315         * @since 1.5
1316         */
1317        public void setAllowInlineMatchUrlReferences(boolean theAllowInlineMatchUrlReferences) {
1318                myAllowInlineMatchUrlReferences = theAllowInlineMatchUrlReferences;
1319        }
1320
1321        public boolean isAllowMultipleDelete() {
1322                return myAllowMultipleDelete;
1323        }
1324
1325        public void setAllowMultipleDelete(boolean theAllowMultipleDelete) {
1326                myAllowMultipleDelete = theAllowMultipleDelete;
1327        }
1328
1329        /**
1330         * When creating or updating a resource: If this property is set to <code>true</code>
1331         * (default is <code>false</code>), if the resource has a reference to another resource
1332         * on the local server but that reference does not exist, a placeholder resource will be
1333         * created.
1334         * <p>
1335         * In other words, if an observation with subject <code>Patient/FOO</code> is created, but
1336         * there is no resource called <code>Patient/FOO</code> on the server, this property causes
1337         * an empty patient with ID "FOO" to be created in order to prevent this operation
1338         * from failing.
1339         * </p>
1340         * <p>
1341         * This property can be useful in cases where replication between two servers is wanted.
1342         * Note however that references containing purely numeric IDs will not be auto-created
1343         * as they are never allowed to be client supplied in HAPI FHIR JPA.
1344         * <p>
1345         * All placeholder resources created in this way have an extension
1346         * with the URL {@link HapiExtensions#EXT_RESOURCE_PLACEHOLDER} and the value "true".
1347         * </p>
1348         */
1349        public boolean isAutoCreatePlaceholderReferenceTargets() {
1350                return myAutoCreatePlaceholderReferenceTargets;
1351        }
1352
1353        /**
1354         * When creating or updating a resource: If this property is set to <code>true</code>
1355         * (default is <code>false</code>), if the resource has a reference to another resource
1356         * on the local server but that reference does not exist, a placeholder resource will be
1357         * created.
1358         * <p>
1359         * In other words, if an observation with subject <code>Patient/FOO</code> is created, but
1360         * there is no resource called <code>Patient/FOO</code> on the server, this property causes
1361         * an empty patient with ID "FOO" to be created in order to prevent this operation
1362         * from failing.
1363         * </p>
1364         * <p>
1365         * This property can be useful in cases where replication between two servers is wanted.
1366         * Note however that references containing purely numeric IDs will not be auto-created
1367         * as they are never allowed to be client supplied in HAPI FHIR JPA.
1368         * <p>
1369         * All placeholder resources created in this way have an extension
1370         * with the URL {@link HapiExtensions#EXT_RESOURCE_PLACEHOLDER} and the value "true".
1371         * </p>
1372         */
1373        public void setAutoCreatePlaceholderReferenceTargets(boolean theAutoCreatePlaceholderReferenceTargets) {
1374                myAutoCreatePlaceholderReferenceTargets = theAutoCreatePlaceholderReferenceTargets;
1375        }
1376
1377        /**
1378         * When {@link #setAutoCreatePlaceholderReferenceTargets(boolean)} is enabled, if this
1379         * setting is set to <code>true</code> (default is <code>true</code>) and the source
1380         * reference has an identifier populated, the identifier will be copied to the target
1381         * resource.
1382         * <p>
1383         * When enabled, if an Observation contains a reference like the one below,
1384         * and no existing resource was found that matches the given ID, a new
1385         * one will be created and its <code>Patient.identifier</code> value will be
1386         * populated using the value from <code>Observation.subject.identifier</code>.
1387         * </p>
1388         * <pre>
1389         * {
1390         *   "resourceType": "Observation",
1391         *   "subject": {
1392         *     "reference": "Patient/ABC",
1393         *     "identifier": {
1394         *       "system": "http://foo",
1395         *       "value": "123"
1396         *     }
1397         *   }
1398         * }
1399         * </pre>
1400         * <p>
1401         * This method is often combined with {@link #setAllowInlineMatchUrlReferences(boolean)}.
1402         * </p>
1403         * <p>
1404         * In other words if an Observation contains a reference like the one below,
1405         * and no existing resource was found that matches the given match URL, a new
1406         * one will be created and its <code>Patient.identifier</code> value will be
1407         * populated using the value from <code>Observation.subject.identifier</code>.
1408         * </p>
1409         * <pre>
1410         * {
1411         *   "resourceType": "Observation",
1412         *   "subject": {
1413         *     "reference": "Patient?identifier=http://foo|123",
1414         *     "identifier": {
1415         *       "system": "http://foo",
1416         *       "value": "123"
1417         *     }
1418         *   }
1419         * }
1420         * </pre>
1421         * <p>
1422         * Note that the default for this setting was previously <code>false</code>, and was changed to <code>true</code>
1423         * in 5.4.0 with consideration to the following:
1424         * </p>
1425         * <pre>
1426         * CP = Auto-Create Placeholder Reference Targets
1427         * PI = Populate Identifier in Auto-Created Placeholder Reference Targets
1428         *
1429         * CP | PI
1430         * -------
1431         *  F | F  <- PI=F is ignored
1432         *  F | T  <- PI=T is ignored
1433         *  T | F  <- resources may reference placeholder reference targets that are never updated : (
1434         *  T | T  <- placeholder reference targets can be updated : )
1435         * </pre>
1436         * <p>
1437         * Where CP=T and PI=F, the following could happen:
1438         * </p>
1439         * <ol>
1440         *    <li>
1441         *       Resource instance A is created with a reference to resource instance B. B is a placeholder reference target
1442         *       without an identifier.
1443         *    </li>
1444         *    <li>
1445         *         Resource instance C is conditionally created using a match URL. It is not matched to B although these
1446         *         resources represent the same entity.
1447         *    </li>
1448         *    <li>
1449         *       A continues to reference placeholder B, and does not reference populated C.
1450         *    </li>
1451         * </ol>
1452         * <p>
1453         * There may be cases where configuring this setting to <code>false</code> would be appropriate; however, these are
1454         * exceptional cases that should be opt-in.
1455         * </p>
1456         *
1457         * @since 4.2.0
1458         */
1459        public boolean isPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets() {
1460                return myPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets;
1461        }
1462
1463        /**
1464         * When {@link #setAutoCreatePlaceholderReferenceTargets(boolean)} is enabled, if this
1465         * setting is set to <code>true</code> (default is <code>true</code>) and the source
1466         * reference has an identifier populated, the identifier will be copied to the target
1467         * resource.
1468         * <p>
1469         * When enabled, if an Observation contains a reference like the one below,
1470         * and no existing resource was found that matches the given ID, a new
1471         * one will be created and its <code>Patient.identifier</code> value will be
1472         * populated using the value from <code>Observation.subject.identifier</code>.
1473         * </p>
1474         * <pre>
1475         * {
1476         *   "resourceType": "Observation",
1477         *   "subject": {
1478         *     "reference": "Patient/ABC",
1479         *     "identifier": {
1480         *       "system": "http://foo",
1481         *       "value": "123"
1482         *     }
1483         *   }
1484         * }
1485         * </pre>
1486         * <p>
1487         * This method is often combined with {@link #setAllowInlineMatchUrlReferences(boolean)}.
1488         * </p>
1489         * <p>
1490         * In other words if an Observation contains a reference like the one below,
1491         * and no existing resource was found that matches the given match URL, a new
1492         * one will be created and its <code>Patient.identifier</code> value will be
1493         * populated using the value from <code>Observation.subject.identifier</code>.
1494         * </p>
1495         * <pre>
1496         * {
1497         *   "resourceType": "Observation",
1498         *   "subject": {
1499         *     "reference": "Patient?identifier=http://foo|123",
1500         *     "identifier": {
1501         *       "system": "http://foo",
1502         *       "value": "123"
1503         *     }
1504         *   }
1505         * }
1506         * </pre>
1507         * <p>
1508         * Note that the default for this setting was previously <code>false</code>, and was changed to <code>true</code>
1509         * in 5.4.0 with consideration to the following:
1510         * </p>
1511         * <pre>
1512         * CP = Auto-Create Placeholder Reference Targets
1513         * PI = Populate Identifier in Auto-Created Placeholder Reference Targets
1514         *
1515         * CP | PI
1516         * -------
1517         *  F | F  <- PI=F is ignored
1518         *  F | T  <- PI=T is ignored
1519         *  T | F  <- resources may reference placeholder reference targets that are never updated : (
1520         *  T | T  <- placeholder reference targets can be updated : )
1521         * </pre>
1522         * <p>
1523         * Where CP=T and PI=F, the following could happen:
1524         * </p>
1525         * <ol>
1526         *    <li>
1527         *       Resource instance A is created with a reference to resource instance B. B is a placeholder reference target
1528         *       without an identifier.
1529         *    </li>
1530         *    <li>
1531         *         Resource instance C is conditionally created using a match URL. It is not matched to B although these
1532         *         resources represent the same entity.
1533         *    </li>
1534         *    <li>
1535         *       A continues to reference placeholder B, and does not reference populated C.
1536         *    </li>
1537         * </ol>
1538         * <p>
1539         * There may be cases where configuring this setting to <code>false</code> would be appropriate; however, these are
1540         * exceptional cases that should be opt-in.
1541         * </p>
1542         *
1543         * @since 4.2.0
1544         */
1545        public void setPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets(boolean thePopulateIdentifierInAutoCreatedPlaceholderReferenceTargets) {
1546                myPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets = thePopulateIdentifierInAutoCreatedPlaceholderReferenceTargets;
1547        }
1548
1549        /**
1550         * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1551         * deleted even if other resources currently contain references to them.
1552         * <p>
1553         * This property can cause confusing results for clients of the server since searches, includes,
1554         * and other FHIR features may not behave as expected when referential integrity is not
1555         * preserved. Use this feature with caution.
1556         * </p>
1557         */
1558        public boolean isEnforceReferentialIntegrityOnDelete() {
1559                return myEnforceReferentialIntegrityOnDelete;
1560        }
1561
1562        /**
1563         * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1564         * deleted even if other resources currently contain references to them.
1565         * <p>
1566         * This property can cause confusing results for clients of the server since searches, includes,
1567         * and other FHIR features may not behave as expected when referential integrity is not
1568         * preserved. Use this feature with caution.
1569         * </p>
1570         */
1571        public void setEnforceReferentialIntegrityOnDelete(boolean theEnforceReferentialIntegrityOnDelete) {
1572                myEnforceReferentialIntegrityOnDelete = theEnforceReferentialIntegrityOnDelete;
1573        }
1574
1575        /**
1576         * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1577         * created or updated even if they contain references to local resources that do not exist.
1578         * <p>
1579         * For example, if a patient contains a reference to managing organization <code>Organization/FOO</code>
1580         * but FOO is not a valid ID for an organization on the server, the operation will be blocked unless
1581         * this propery has been set to <code>false</code>
1582         * </p>
1583         * <p>
1584         * This property can cause confusing results for clients of the server since searches, includes,
1585         * and other FHIR features may not behave as expected when referential integrity is not
1586         * preserved. Use this feature with caution.
1587         * </p>
1588         */
1589        public boolean isEnforceReferentialIntegrityOnWrite() {
1590                return myEnforceReferentialIntegrityOnWrite;
1591        }
1592
1593        /**
1594         * If set to <code>false</code> (default is <code>true</code>) resources will be permitted to be
1595         * created or updated even if they contain references to local resources that do not exist.
1596         * <p>
1597         * For example, if a patient contains a reference to managing organization <code>Organization/FOO</code>
1598         * but FOO is not a valid ID for an organization on the server, the operation will be blocked unless
1599         * this propery has been set to <code>false</code>
1600         * </p>
1601         * <p>
1602         * This property can cause confusing results for clients of the server since searches, includes,
1603         * and other FHIR features may not behave as expected when referential integrity is not
1604         * preserved. Use this feature with caution.
1605         * </p>
1606         */
1607        public void setEnforceReferentialIntegrityOnWrite(boolean theEnforceReferentialIntegrityOnWrite) {
1608                myEnforceReferentialIntegrityOnWrite = theEnforceReferentialIntegrityOnWrite;
1609        }
1610
1611        /**
1612         * If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
1613         * task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
1614         * <p>
1615         * This feature is useful if you want to define your own process for deleting these (e.g. because
1616         * you are running in a cluster)
1617         * </p>
1618         */
1619        public boolean isExpireSearchResults() {
1620                return myDeleteStaleSearches;
1621        }
1622
1623        /**
1624         * If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
1625         * task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
1626         * <p>
1627         * This feature is useful if you want to define your own process for deleting these (e.g. because
1628         * you are running in a cluster)
1629         * </p>
1630         */
1631        public void setExpireSearchResults(boolean theDeleteStaleSearches) {
1632                myDeleteStaleSearches = theDeleteStaleSearches;
1633        }
1634
1635        /**
1636         * If set to <code>true</code> (default is <code>false</code>), the $expunge operation
1637         * will be enabled on this server. This operation is potentially dangerous since it allows
1638         * a client to physically delete data in a way that can not be recovered (without resorting
1639         * to backups).
1640         * <p>
1641         * It is recommended to not enable this setting without appropriate security
1642         * in place on your server to prevent non-administrators from using this
1643         * operation.
1644         * </p>
1645         */
1646        public boolean isExpungeEnabled() {
1647                return myExpungeEnabled;
1648        }
1649
1650        /**
1651         * If set to <code>true</code> (default is <code>false</code>), the $expunge operation
1652         * will be enabled on this server. This operation is potentially dangerous since it allows
1653         * a client to physically delete data in a way that can not be recovered (without resorting
1654         * to backups).
1655         * <p>
1656         * It is recommended to not enable this setting without appropriate security
1657         * in place on your server to prevent non-administrators from using this
1658         * operation.
1659         * </p>
1660         */
1661        public void setExpungeEnabled(boolean theExpungeEnabled) {
1662                myExpungeEnabled = theExpungeEnabled;
1663        }
1664
1665        /**
1666         * If set to <code>true</code> (default is <code>false</code>), the _expunge parameter on the DELETE
1667         * operation will be enabled on this server. DELETE _expunge removes all data associated with a resource in a highly performant
1668         * way, skipping most of the the checks that are enforced with usual DELETE operations.  The only check
1669         * that is performed before deleting the data is that no other resources reference the resources about to
1670         * be deleted.  This operation is potentially dangerous since it allows
1671         * a client to physically delete data in a way that can not be recovered (without resorting
1672         * to backups).
1673         * <p>
1674         * It is recommended to not enable this setting without appropriate security
1675         * in place on your server to prevent non-administrators from using this
1676         * operation.
1677         * </p>
1678         */
1679        public boolean isDeleteExpungeEnabled() {
1680                return myDeleteExpungeEnabled;
1681        }
1682
1683        /**
1684         * If set to <code>true</code> (default is <code>false</code>), the _expunge parameter on the DELETE
1685         * operation will be enabled on this server. DELETE _expunge removes all data associated with a resource in a highly performant
1686         * way, skipping most of the the checks that are enforced with usual DELETE operations.  The only check
1687         * that is performed before deleting the resources and their indexes is that no other resources reference the resources about to
1688         * be deleted.  This operation is potentially dangerous since it allows
1689         * a client to physically delete data in a way that can not be recovered (without resorting
1690         * to backups).
1691         * <p>
1692         * It is recommended to not enable this setting without appropriate security
1693         * in place on your server to prevent non-administrators from using this
1694         * operation.
1695         * </p>
1696         */
1697        public void setDeleteExpungeEnabled(boolean theDeleteExpungeEnabled) {
1698                myDeleteExpungeEnabled = theDeleteExpungeEnabled;
1699        }
1700
1701        /**
1702         * The expunge batch size (default 800) determines the number of records deleted within a single transaction by the
1703         * expunge operation.  When expunging via DELETE ?_expunge=true, then this value determines the batch size for
1704         * the number of resources deleted and expunged at a time.
1705         */
1706        public int getExpungeBatchSize() {
1707                return myExpungeBatchSize;
1708        }
1709
1710        /**
1711         * The expunge batch size (default 800) determines the number of records deleted within a single transaction by the
1712         * expunge operation.  When expunging via DELETE ?_expunge=true, then this value determines the batch size for
1713         * the number of resources deleted and expunged at a time.
1714         */
1715        public void setExpungeBatchSize(int theExpungeBatchSize) {
1716                myExpungeBatchSize = theExpungeBatchSize;
1717        }
1718
1719        /**
1720         * The reindex batch size (default 800) determines the number of records reindexed in a single transaction.
1721         */
1722        public int getReindexBatchSize() {
1723                return myReindexBatchSize;
1724        }
1725
1726        /**
1727         * The reindex batch size (default 800) determines the number of records reindexed in a single transaction.
1728         */
1729        public void setReindexBatchSize(int theReindexBatchSize) {
1730                myReindexBatchSize = theReindexBatchSize;
1731        }
1732
1733
1734        /**
1735         * If set to <code>false</code> (default is <code>true</code>), reindexing of resources will be disabled on this
1736         * server.
1737         */
1738        public boolean isReindexEnabled() {
1739                return myReindexEnabled;
1740        }
1741
1742        /**
1743         * If set to <code>false</code> (default is <code>true</code>), reindexing of resources will be disabled on this
1744         * server.
1745         */
1746
1747        public void setReindexEnabled(boolean theReindexEnabled) {
1748                myReindexEnabled = theReindexEnabled;
1749        }
1750
1751        /**
1752         * Should resources be marked as needing reindexing when a
1753         * SearchParameter resource is added or changed. This should generally
1754         * be true (which is the default)
1755         */
1756        public boolean isMarkResourcesForReindexingUponSearchParameterChange() {
1757                return myMarkResourcesForReindexingUponSearchParameterChange;
1758        }
1759
1760        /**
1761         * Should resources be marked as needing reindexing when a
1762         * SearchParameter resource is added or changed. This should generally
1763         * be true (which is the default)
1764         */
1765        public void setMarkResourcesForReindexingUponSearchParameterChange(boolean theMarkResourcesForReindexingUponSearchParameterChange) {
1766                myMarkResourcesForReindexingUponSearchParameterChange = theMarkResourcesForReindexingUponSearchParameterChange;
1767        }
1768
1769        public boolean isSchedulingDisabled() {
1770                return mySchedulingDisabled;
1771        }
1772
1773        public void setSchedulingDisabled(boolean theSchedulingDisabled) {
1774                mySchedulingDisabled = theSchedulingDisabled;
1775        }
1776
1777        /**
1778         * If set to {@literal true} (default is true), if a client performs an update which does not actually
1779         * result in any chance to a given resource (e.g. an update where the resource body matches the
1780         * existing resource body in the database) the operation will succeed but a new version (and corresponding history
1781         * entry) will not actually be created. The existing resource version will be returned to the client.
1782         * <p>
1783         * If set to {@literal false}, all updates will result in the creation of a new version
1784         * </p>
1785         */
1786        public boolean isSuppressUpdatesWithNoChange() {
1787                return mySuppressUpdatesWithNoChange;
1788        }
1789
1790        /**
1791         * If set to {@literal true} (default is true), if a client performs an update which does not actually
1792         * result in any chance to a given resource (e.g. an update where the resource body matches the
1793         * existing resource body in the database) the operation will succeed but a new version (and corresponding history
1794         * entry) will not actually be created. The existing resource version will be returned to the client.
1795         * <p>
1796         * If set to {@literal false}, all updates will result in the creation of a new version
1797         * </p>
1798         */
1799        public void setSuppressUpdatesWithNoChange(boolean theSuppressUpdatesWithNoChange) {
1800                mySuppressUpdatesWithNoChange = theSuppressUpdatesWithNoChange;
1801
1802        }
1803
1804        /**
1805         * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this
1806         * setting is set to <code>true</code> (default is <code>true</code>) the system
1807         * will test for the existence of a particular unique index value prior to saving
1808         * a new one.
1809         * <p>
1810         * This causes friendlier error messages to be generated, but adds an
1811         * extra round-trip to the database for eavh save so it can cause
1812         * a small performance hit.
1813         * </p>
1814         */
1815        public boolean isUniqueIndexesCheckedBeforeSave() {
1816                return myUniqueIndexesCheckedBeforeSave;
1817        }
1818
1819        /**
1820         * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this
1821         * setting is set to <code>true</code> (default is <code>true</code>) the system
1822         * will test for the existence of a particular unique index value prior to saving
1823         * a new one.
1824         * <p>
1825         * This causes friendlier error messages to be generated, but adds an
1826         * extra round-trip to the database for each save so it can cause
1827         * a small performance hit.
1828         * </p>
1829         */
1830        public void setUniqueIndexesCheckedBeforeSave(boolean theUniqueIndexesCheckedBeforeSave) {
1831                myUniqueIndexesCheckedBeforeSave = theUniqueIndexesCheckedBeforeSave;
1832        }
1833
1834        /**
1835         * If set to <code>true</code> (default is <code>true</code>), indexes will be
1836         * created for search parameters marked as {@link HapiExtensions#EXT_SP_UNIQUE}.
1837         * This is a HAPI FHIR specific extension which can be used to specify that no more than one
1838         * resource can exist which matches a given criteria, using a database constraint to
1839         * enforce this.
1840         */
1841        public boolean isUniqueIndexesEnabled() {
1842                return myUniqueIndexesEnabled;
1843        }
1844
1845        /**
1846         * If set to <code>true</code> (default is <code>true</code>), indexes will be
1847         * created for search parameters marked as {@link HapiExtensions#EXT_SP_UNIQUE}.
1848         * This is a HAPI FHIR specific extension which can be used to specify that no more than one
1849         * resource can exist which matches a given criteria, using a database constraint to
1850         * enforce this.
1851         */
1852        public void setUniqueIndexesEnabled(boolean theUniqueIndexesEnabled) {
1853                myUniqueIndexesEnabled = theUniqueIndexesEnabled;
1854        }
1855
1856        /**
1857         * If <code>true</code> (default is <code>true</code>), before allowing a
1858         * SearchParameter resource to be stored (create, update, etc.) the
1859         * expression will be performed against an empty resource to ensure that
1860         * the FHIRPath executor is able to process it.
1861         * <p>
1862         * This should proabably always be set to true, but is configurable
1863         * in order to support some unit tests.
1864         * </p>
1865         */
1866        public boolean isValidateSearchParameterExpressionsOnSave() {
1867                return myValidateSearchParameterExpressionsOnSave;
1868        }
1869
1870        /**
1871         * If <code>true</code> (default is <code>true</code>), before allowing a
1872         * SearchParameter resource to be stored (create, update, etc.) the
1873         * expression will be performed against an empty resource to ensure that
1874         * the FHIRPath executor is able to process it.
1875         * <p>
1876         * This should proabably always be set to true, but is configurable
1877         * in order to support some unit tests.
1878         * </p>
1879         */
1880        public void setValidateSearchParameterExpressionsOnSave(boolean theValidateSearchParameterExpressionsOnSave) {
1881                myValidateSearchParameterExpressionsOnSave = theValidateSearchParameterExpressionsOnSave;
1882        }
1883
1884        /**
1885         * This setting sets the number of search results to prefetch. For example, if this list
1886         * is set to [100, 1000, -1] then the server will initially load 100 results and not
1887         * attempt to load more. If the user requests subsequent page(s) of results and goes
1888         * past 100 results, the system will load the next 900 (up to the following threshold of 1000).
1889         * The system will progressively work through these thresholds.
1890         *
1891         * <p>
1892         * A threshold of -1 means to load all results. Note that if the final threshold is a
1893         * number other than <code>-1</code>, the system will never prefetch more than the
1894         * given number.
1895         * </p>
1896         */
1897        public List<Integer> getSearchPreFetchThresholds() {
1898                return mySearchPreFetchThresholds;
1899        }
1900
1901        /**
1902         * This setting sets the number of search results to prefetch. For example, if this list
1903         * is set to [100, 1000, -1] then the server will initially load 100 results and not
1904         * attempt to load more. If the user requests subsequent page(s) of results and goes
1905         * past 100 results, the system will load the next 900 (up to the following threshold of 1000).
1906         * The system will progressively work through these thresholds.
1907         *
1908         * <p>
1909         * A threshold of -1 means to load all results. Note that if the final threshold is a
1910         * number other than <code>-1</code>, the system will never prefetch more than the
1911         * given number.
1912         * </p>
1913         */
1914        public void setSearchPreFetchThresholds(List<Integer> thePreFetchThresholds) {
1915                Validate.isTrue(thePreFetchThresholds.size() > 0, "thePreFetchThresholds must not be empty");
1916                int last = 0;
1917                for (Integer nextInt : thePreFetchThresholds) {
1918                        Validate.isTrue(nextInt > 0 || nextInt == -1, nextInt + " is not a valid prefetch threshold");
1919                        Validate.isTrue(nextInt != last, "Prefetch thresholds must be sequential");
1920                        Validate.isTrue(nextInt > last || nextInt == -1, "Prefetch thresholds must be sequential");
1921                        Validate.isTrue(last != -1, "Prefetch thresholds must be sequential");
1922                        last = nextInt;
1923                }
1924                mySearchPreFetchThresholds = thePreFetchThresholds;
1925        }
1926
1927        /**
1928         * If set to <code>true</code> (default is false) the server will not use
1929         * hash based searches. These searches were introduced in HAPI FHIR 3.5.0
1930         * and are the new default way of searching. However they require a very
1931         * large data migration if an existing system has a large amount of data
1932         * so this setting can be used to use the old search mechanism while data
1933         * is migrated.
1934         *
1935         * @since 3.6.0
1936         */
1937        public boolean getDisableHashBasedSearches() {
1938                return myDisableHashBasedSearches;
1939        }
1940
1941        /**
1942         * If set to <code>true</code> (default is false) the server will not use
1943         * hash based searches. These searches were introduced in HAPI FHIR 3.5.0
1944         * and are the new default way of searching. However they require a very
1945         * large data migration if an existing system has a large amount of data
1946         * so this setting can be used to use the old search mechanism while data
1947         * is migrated.
1948         *
1949         * @since 3.6.0
1950         */
1951        public void setDisableHashBasedSearches(boolean theDisableHashBasedSearches) {
1952                myDisableHashBasedSearches = theDisableHashBasedSearches;
1953        }
1954
1955        /**
1956         * If set to <code>false</code> (default is true) the server will not use
1957         * in-memory subscription searching and instead use the database matcher for all subscription
1958         * criteria matching.
1959         * <p>
1960         * When there are subscriptions registered
1961         * on the server, the default behaviour is to compare the changed resource to the
1962         * subscription criteria directly in-memory without going out to the database.
1963         * Certain types of subscription criteria, e.g. chained references of queries with
1964         * qualifiers or prefixes, are not supported by the in-memory matcher and will fall back
1965         * to a database matcher.
1966         * <p>
1967         * The database matcher performs a query against the
1968         * database by prepending ?id=XYZ to the subscription criteria where XYZ is the id of the changed entity
1969         *
1970         * @since 3.6.1
1971         */
1972
1973        public boolean isEnableInMemorySubscriptionMatching() {
1974                return myEnableInMemorySubscriptionMatching;
1975        }
1976
1977        /**
1978         * If set to <code>false</code> (default is true) the server will not use
1979         * in-memory subscription searching and instead use the database matcher for all subscription
1980         * criteria matching.
1981         * <p>
1982         * When there are subscriptions registered
1983         * on the server, the default behaviour is to compare the changed resource to the
1984         * subscription criteria directly in-memory without going out to the database.
1985         * Certain types of subscription criteria, e.g. chained references of queries with
1986         * qualifiers or prefixes, are not supported by the in-memory matcher and will fall back
1987         * to a database matcher.
1988         * <p>
1989         * The database matcher performs a query against the
1990         * database by prepending ?id=XYZ to the subscription criteria where XYZ is the id of the changed entity
1991         *
1992         * @since 3.6.1
1993         */
1994
1995        public void setEnableInMemorySubscriptionMatching(boolean theEnableInMemorySubscriptionMatching) {
1996                myEnableInMemorySubscriptionMatching = theEnableInMemorySubscriptionMatching;
1997        }
1998
1999        public ModelConfig getModelConfig() {
2000                return myModelConfig;
2001        }
2002
2003        /**
2004         * If enabled, the server will support the use of :contains searches,
2005         * which are helpful but can have adverse effects on performance.
2006         * <p>
2007         * Default is <code>false</code> (Note that prior to HAPI FHIR
2008         * 3.5.0 the default was <code>true</code>)
2009         * </p>
2010         * <p>
2011         * Note: If you change this value after data already has
2012         * already been stored in the database, you must for a reindexing
2013         * of all data in the database or resources may not be
2014         * searchable.
2015         * </p>
2016         */
2017        public boolean isAllowContainsSearches() {
2018                return this.myModelConfig.isAllowContainsSearches();
2019        }
2020
2021        /**
2022         * If enabled, the server will support the use of :contains searches,
2023         * which are helpful but can have adverse effects on performance.
2024         * <p>
2025         * Default is <code>false</code> (Note that prior to HAPI FHIR
2026         * 3.5.0 the default was <code>true</code>)
2027         * </p>
2028         * <p>
2029         * Note: If you change this value after data already has
2030         * already been stored in the database, you must for a reindexing
2031         * of all data in the database or resources may not be
2032         * searchable.
2033         * </p>
2034         */
2035        public void setAllowContainsSearches(boolean theAllowContainsSearches) {
2036                this.myModelConfig.setAllowContainsSearches(theAllowContainsSearches);
2037        }
2038
2039        /**
2040         * If enabled, the server will support the use of :mdm search parameter qualifier on Reference Search Parameters.
2041         * This Parameter Qualifier is HAPI-specific, and not defined anywhere in the FHIR specification. Using this qualifier
2042         * will result in an MDM expansion being done on the reference, which will expand the search scope. For example, if Patient/1
2043         * is MDM-matched to Patient/2 and you execute the search:
2044         * Observation?subject:mdm=Patient/1 , you will receive observations for both Patient/1 and Patient/2.
2045         * <p>
2046         * Default is <code>false</code>
2047         * </p>
2048         *
2049         * @since 5.4.0
2050         */
2051        public boolean isAllowMdmExpansion() {
2052                return myModelConfig.isAllowMdmExpansion();
2053        }
2054
2055        /**
2056         * If enabled, the server will support the use of :mdm search parameter qualifier on Reference Search Parameters.
2057         * This Parameter Qualifier is HAPI-specific, and not defined anywhere in the FHIR specification. Using this qualifier
2058         * will result in an MDM expansion being done on the reference, which will expand the search scope. For example, if Patient/1
2059         * is MDM-matched to Patient/2 and you execute the search:
2060         * Observation?subject:mdm=Patient/1 , you will receive observations for both Patient/1 and Patient/2.
2061         * <p>
2062         * Default is <code>false</code>
2063         * </p>
2064         *
2065         * @since 5.4.0
2066         */
2067        public void setAllowMdmExpansion(boolean theAllowMdmExpansion) {
2068                myModelConfig.setAllowMdmExpansion(theAllowMdmExpansion);
2069        }
2070
2071        /**
2072         * This setting may be used to advise the server that any references found in
2073         * resources that have any of the base URLs given here will be replaced with
2074         * simple local references.
2075         * <p>
2076         * For example, if the set contains the value <code>http://example.com/base/</code>
2077         * and a resource is submitted to the server that contains a reference to
2078         * <code>http://example.com/base/Patient/1</code>, the server will automatically
2079         * convert this reference to <code>Patient/1</code>
2080         * </p>
2081         * <p>
2082         * Note that this property has different behaviour from {@link DaoConfig#getTreatReferencesAsLogical()}
2083         * </p>
2084         *
2085         * @see #getTreatReferencesAsLogical()
2086         */
2087        public Set<String> getTreatBaseUrlsAsLocal() {
2088                return myModelConfig.getTreatBaseUrlsAsLocal();
2089        }
2090
2091        /**
2092         * This setting may be used to advise the server that any references found in
2093         * resources that have any of the base URLs given here will be replaced with
2094         * simple local references.
2095         * <p>
2096         * For example, if the set contains the value <code>http://example.com/base/</code>
2097         * and a resource is submitted to the server that contains a reference to
2098         * <code>http://example.com/base/Patient/1</code>, the server will automatically
2099         * convert this reference to <code>Patient/1</code>
2100         * </p>
2101         *
2102         * @param theTreatBaseUrlsAsLocal The set of base URLs. May be <code>null</code>, which
2103         *                                means no references will be treated as external
2104         */
2105        public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
2106                myModelConfig.setTreatBaseUrlsAsLocal(theTreatBaseUrlsAsLocal);
2107        }
2108
2109        /**
2110         * If set to {@code true} the default search params (i.e. the search parameters that are
2111         * defined by the FHIR specification itself) may be overridden by uploading search
2112         * parameters to the server with the same code as the built-in search parameter.
2113         * <p>
2114         * This can be useful if you want to be able to disable or alter
2115         * the behaviour of the default search parameters.
2116         * </p>
2117         * <p>
2118         * The default value for this setting is {@code false}
2119         * </p>
2120         */
2121        public boolean isDefaultSearchParamsCanBeOverridden() {
2122                return myModelConfig.isDefaultSearchParamsCanBeOverridden();
2123        }
2124
2125        /**
2126         * If set to {@code true} the default search params (i.e. the search parameters that are
2127         * defined by the FHIR specification itself) may be overridden by uploading search
2128         * parameters to the server with the same code as the built-in search parameter.
2129         * <p>
2130         * This can be useful if you want to be able to disable or alter
2131         * the behaviour of the default search parameters.
2132         * </p>
2133         * <p>
2134         * The default value for this setting is {@code false}
2135         * </p>
2136         */
2137        public void setDefaultSearchParamsCanBeOverridden(boolean theDefaultSearchParamsCanBeOverridden) {
2138                myModelConfig.setDefaultSearchParamsCanBeOverridden(theDefaultSearchParamsCanBeOverridden);
2139        }
2140
2141        /**
2142         * This setting indicates which subscription channel types are supported by the server.  Any subscriptions submitted
2143         * to the server matching these types will be activated.
2144         */
2145        public DaoConfig addSupportedSubscriptionType(Subscription.SubscriptionChannelType theSubscriptionChannelType) {
2146                myModelConfig.addSupportedSubscriptionType(theSubscriptionChannelType);
2147                return this;
2148        }
2149
2150        /**
2151         * This setting indicates which subscription channel types are supported by the server.  Any subscriptions submitted
2152         * to the server matching these types will be activated.
2153         *
2154         * @see #addSupportedSubscriptionType(Subscription.SubscriptionChannelType)
2155         */
2156        public Set<Subscription.SubscriptionChannelType> getSupportedSubscriptionTypes() {
2157                return myModelConfig.getSupportedSubscriptionTypes();
2158        }
2159
2160        @VisibleForTesting
2161        public void clearSupportedSubscriptionTypesForUnitTest() {
2162                myModelConfig.clearSupportedSubscriptionTypesForUnitTest();
2163        }
2164
2165        /**
2166         * If e-mail subscriptions are supported, the From address used when sending e-mails
2167         */
2168
2169        public String getEmailFromAddress() {
2170                return myModelConfig.getEmailFromAddress();
2171        }
2172
2173        /**
2174         * If e-mail subscriptions are supported, the From address used when sending e-mails
2175         */
2176
2177        public void setEmailFromAddress(String theEmailFromAddress) {
2178                myModelConfig.setEmailFromAddress(theEmailFromAddress);
2179        }
2180
2181        /**
2182         * If websocket subscriptions are enabled, this defines the context path that listens to them.  Default value "/websocket".
2183         */
2184
2185        public String getWebsocketContextPath() {
2186                return myModelConfig.getWebsocketContextPath();
2187        }
2188
2189        /**
2190         * If websocket subscriptions are enabled, this defines the context path that listens to them.  Default value "/websocket".
2191         */
2192
2193        public void setWebsocketContextPath(String theWebsocketContextPath) {
2194                myModelConfig.setWebsocketContextPath(theWebsocketContextPath);
2195        }
2196
2197        /**
2198         * If set to <code>true</code> the _filter search parameter will be enabled on this server. Note that _filter
2199         * is very powerful, but also potentially dangerous as it can allow a user to create a query for which there
2200         * are no indexes or efficient query plans for the database to leverage while performing the query.
2201         * As a result, this feature is recommended only for servers where the querying applications are known in advance
2202         * and a database administrator can properly tune the database for the resulting queries.
2203         */
2204        public boolean isFilterParameterEnabled() {
2205                return myFilterParameterEnabled;
2206        }
2207
2208        /**
2209         * If set to <code>true</code> the _filter search parameter will be enabled on this server. Note that _filter
2210         * is very powerful, but also potentially dangerous as it can allow a user to create a query for which there
2211         * are no indexes or efficient query plans for the database to leverage while performing the query.
2212         * As a result, this feature is recommended only for servers where the querying applications are known in advance
2213         * and a database administrator can properly tune the database for the resulting queries.
2214         */
2215        public void setFilterParameterEnabled(boolean theFilterParameterEnabled) {
2216                myFilterParameterEnabled = theFilterParameterEnabled;
2217        }
2218
2219        /**
2220         * If enabled, resource source information (<code>Resource.meta.source</code>) will be persisted along with
2221         * each resource. This adds extra table and index space so it should be disabled if it is not being
2222         * used.
2223         * <p>
2224         * Default is {@link StoreMetaSourceInformationEnum#SOURCE_URI_AND_REQUEST_ID}
2225         * </p>
2226         */
2227        public StoreMetaSourceInformationEnum getStoreMetaSourceInformation() {
2228                return myStoreMetaSourceInformation;
2229        }
2230
2231        /**
2232         * If enabled, resource source information (<code>Resource.meta.source</code>) will be persisted along with
2233         * each resource. This adds extra table and index space so it should be disabled if it is not being
2234         * used.
2235         * <p>
2236         * Default is {@link StoreMetaSourceInformationEnum#SOURCE_URI_AND_REQUEST_ID}
2237         * </p>
2238         */
2239        public void setStoreMetaSourceInformation(StoreMetaSourceInformationEnum theStoreMetaSourceInformation) {
2240                Validate.notNull(theStoreMetaSourceInformation, "theStoreMetaSourceInformation must not be null");
2241                myStoreMetaSourceInformation = theStoreMetaSourceInformation;
2242        }
2243
2244        /**
2245         * <p>
2246         * If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
2247         * optimization of the $expand operation on large ValueSets.
2248         * </p>
2249         * <p>
2250         * The default value for this setting is {@code true}.
2251         * </p>
2252         *
2253         * @since 4.1.0
2254         */
2255        public boolean isPreExpandValueSets() {
2256                return myPreExpandValueSets;
2257        }
2258
2259        /**
2260         * <p>
2261         * If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
2262         * optimization of the $expand operation on large ValueSets.
2263         * </p>
2264         * <p>
2265         * The default value for this setting is {@code true}.
2266         * </p>
2267         *
2268         * @since 4.1.0
2269         */
2270        public void setPreExpandValueSets(boolean thePreExpandValueSets) {
2271                myPreExpandValueSets = thePreExpandValueSets;
2272        }
2273
2274        /**
2275         * <p>
2276         * This is the default value of {@code offset} parameter for the ValueSet {@code $expand} operation when
2277         * {@link DaoConfig#isPreExpandValueSets()} returns {@code true}.
2278         * </p>
2279         * <p>
2280         * The default value for this setting is {@code 0}.
2281         * </p>
2282         *
2283         * @since 4.1.0
2284         */
2285        public int getPreExpandValueSetsDefaultOffset() {
2286                return myPreExpandValueSetsDefaultOffset;
2287        }
2288
2289        /**
2290         * <p>
2291         * This is the default value of {@code count} parameter for the ValueSet {@code $expand} operation when
2292         * {@link DaoConfig#isPreExpandValueSets()} returns {@code true}.
2293         * </p>
2294         * <p>
2295         * The default value for this setting is {@code 1000}.
2296         * </p>
2297         *
2298         * @since 4.1.0
2299         */
2300        public int getPreExpandValueSetsDefaultCount() {
2301                return myPreExpandValueSetsDefaultCount;
2302        }
2303
2304        /**
2305         * <p>
2306         * This is the default value of {@code count} parameter for the ValueSet {@code $expand} operation when
2307         * {@link DaoConfig#isPreExpandValueSets()} returns {@code true}.
2308         * </p>
2309         * <p>
2310         * If {@code thePreExpandValueSetsDefaultCount} is greater than
2311         * {@link DaoConfig#getPreExpandValueSetsMaxCount()}, the lesser value is used.
2312         * </p>
2313         * <p>
2314         * The default value for this setting is {@code 1000}.
2315         * </p>
2316         *
2317         * @since 4.1.0
2318         */
2319        public void setPreExpandValueSetsDefaultCount(int thePreExpandValueSetsDefaultCount) {
2320                myPreExpandValueSetsDefaultCount = Math.min(thePreExpandValueSetsDefaultCount, getPreExpandValueSetsMaxCount());
2321        }
2322
2323        /**
2324         * <p>
2325         * This is the max value of {@code count} parameter for the ValueSet {@code $expand} operation when
2326         * {@link DaoConfig#isPreExpandValueSets()} returns {@code true}.
2327         * </p>
2328         * <p>
2329         * The default value for this setting is {@code 1000}.
2330         * </p>
2331         *
2332         * @since 4.1.0
2333         */
2334        public int getPreExpandValueSetsMaxCount() {
2335                return myPreExpandValueSetsMaxCount;
2336        }
2337
2338        /**
2339         * <p>
2340         * This is the max value of {@code count} parameter for the ValueSet {@code $expand} operation when
2341         * {@link DaoConfig#isPreExpandValueSets()} returns {@code true}.
2342         * </p>
2343         * <p>
2344         * If {@code thePreExpandValueSetsMaxCount} is lesser than
2345         * {@link DaoConfig#getPreExpandValueSetsDefaultCount()}, the default {@code count} is lowered to the
2346         * new max {@code count}.
2347         * </p>
2348         * <p>
2349         * The default value for this setting is {@code 1000}.
2350         * </p>
2351         *
2352         * @since 4.1.0
2353         */
2354        public void setPreExpandValueSetsMaxCount(int thePreExpandValueSetsMaxCount) {
2355                myPreExpandValueSetsMaxCount = thePreExpandValueSetsMaxCount;
2356                setPreExpandValueSetsDefaultCount(Math.min(getPreExpandValueSetsDefaultCount(), getPreExpandValueSetsMaxCount()));
2357        }
2358
2359        /**
2360         * This setting should be disabled (set to <code>false</code>) on servers that are not allowing
2361         * deletes. Default is <code>true</code>. If deletes are disabled, some checks for resource
2362         * deletion can be skipped, which improves performance. This is particularly helpful when large
2363         * amounts of data containing client-assigned IDs are being loaded, but it can also improve
2364         * search performance.
2365         *
2366         * @since 5.0.0
2367         */
2368        public boolean isDeleteEnabled() {
2369                return myDeleteEnabled;
2370        }
2371
2372        /**
2373         * This setting should be disabled (set to <code>false</code>) on servers that are not allowing
2374         * deletes. Default is <code>true</code>. If deletes are disabled, some checks for resource
2375         * deletion can be skipped, which improves performance. This is particularly helpful when large
2376         * amounts of data containing client-assigned IDs are being loaded, but it can also improve
2377         * search performance.
2378         *
2379         * @since 5.0.0
2380         */
2381        public void setDeleteEnabled(boolean theDeleteEnabled) {
2382                myDeleteEnabled = theDeleteEnabled;
2383        }
2384
2385        /**
2386         * <p>
2387         * This determines the maximum number of conflicts that should be fetched and handled while retrying a delete of a resource.
2388         * </p>
2389         * <p>
2390         * The default value for this setting is {@code 60}.
2391         * </p>
2392         *
2393         * @since 5.1.0
2394         */
2395        public Integer getMaximumDeleteConflictQueryCount() {
2396                return myMaximumDeleteConflictQueryCount;
2397        }
2398
2399        /**
2400         * <p>
2401         * This determines the maximum number of conflicts that should be fetched and handled while retrying a delete of a resource.
2402         * </p>
2403         * <p>
2404         * The default value for this setting is {@code 60}.
2405         * </p>
2406         *
2407         * @since 5.1.0
2408         */
2409        public void setMaximumDeleteConflictQueryCount(Integer theMaximumDeleteConflictQueryCount) {
2410                myMaximumDeleteConflictQueryCount = theMaximumDeleteConflictQueryCount;
2411        }
2412
2413        /**
2414         * <p>
2415         * This determines whether $binary-access-write operations should first load the InputStream into memory before persisting the
2416         * contents to the database. This needs to be enabled for MS SQL Server as this DB requires that the blob size be known
2417         * in advance.
2418         * </p>
2419         * <p>
2420         * Note that this setting should be enabled with caution as it can lead to significant demands on memory.
2421         * </p>
2422         * <p>
2423         * The default value for this setting is {@code false}.
2424         * </p>
2425         *
2426         * @since 5.1.0
2427         * @deprecated In 5.2.0 this setting no longer does anything
2428         */
2429        @Deprecated
2430        public void setPreloadBlobFromInputStream(Boolean thePreloadBlobFromInputStream) {
2431                // ignore
2432        }
2433
2434        /**
2435         * <p>
2436         * This determines the internal search size that is run synchronously during operations such as searching for
2437         * Code System IDs by System and Code
2438         * </p>
2439         *
2440         * @since 5.4.0
2441         */
2442        public Integer getInternalSynchronousSearchSize() {
2443                return myInternalSynchronousSearchSize;
2444        }
2445
2446        /**
2447         * <p>
2448         * This determines the internal search size that is run synchronously during operations such as searching for
2449         * Code System IDs by System and Code
2450         * </p>
2451         *
2452         * @since 5.4.0
2453         */
2454        public void setInternalSynchronousSearchSize(Integer theInternalSynchronousSearchSize) {
2455                myInternalSynchronousSearchSize = theInternalSynchronousSearchSize;
2456        }
2457
2458
2459        /**
2460         * If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Import</b>
2461         * batch jobs. Otherwise, this server will not.
2462         *
2463         * @since 5.5.0
2464         */
2465        public boolean isEnableTaskBulkImportJobExecution() {
2466                return myEnableTaskBulkImportJobExecution;
2467        }
2468
2469        /**
2470         * If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Import</b>
2471         * batch jobs. Otherwise, this server will not.
2472         *
2473         * @since 5.5.0
2474         */
2475        public void setEnableTaskBulkImportJobExecution(boolean theEnableTaskBulkImportJobExecution) {
2476                myEnableTaskBulkImportJobExecution = theEnableTaskBulkImportJobExecution;
2477        }
2478
2479        /**
2480         * If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Export</b>
2481         * batch jobs. Otherwise, this server will not.
2482         *
2483         * @since 5.5.0
2484         */
2485        public boolean isEnableTaskBulkExportJobExecution() {
2486                return myEnableTaskBulkExportJobExecution;
2487        }
2488
2489        /**
2490         * If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Export</b>
2491         * batch jobs. Otherwise, this server will not.
2492         *
2493         * @since 5.5.0
2494         */
2495        public void setEnableTaskBulkExportJobExecution(boolean theEnableTaskBulkExportJobExecution) {
2496                myEnableTaskBulkExportJobExecution = theEnableTaskBulkExportJobExecution;
2497        }
2498
2499        /**
2500         * If this is enabled (this is the default), this server will attempt to pre-expand any ValueSets that
2501         * have been uploaded and are not yet pre-expanded. Otherwise, this server will not.
2502         *
2503         * @since 5.5.0
2504         */
2505        public boolean isEnableTaskPreExpandValueSets() {
2506                return myEnableTaskPreExpandValueSets;
2507        }
2508
2509        /**
2510         * If this is enabled (this is the default), this server will attempt to pre-expand any ValueSets that
2511         * have been uploaded and are not yet pre-expanded. Otherwise, this server will not.
2512         *
2513         * @since 5.5.0
2514         */
2515        public void setEnableTaskPreExpandValueSets(boolean theEnableTaskPreExpandValueSets) {
2516                myEnableTaskPreExpandValueSets = theEnableTaskPreExpandValueSets;
2517        }
2518
2519        /**
2520         * If this is enabled (this is the default), this server will periodically scan for and try to delete
2521         * stale searches in the database. Otherwise, this server will not.
2522         *
2523         * @since 5.5.0
2524         */
2525        public boolean isEnableTaskStaleSearchCleanup() {
2526                return myEnableTaskStaleSearchCleanup;
2527        }
2528
2529        /**
2530         * If this is enabled (this is the default), this server will periodically scan for and try to delete
2531         * stale searches in the database. Otherwise, this server will not.
2532         *
2533         * @since 5.5.0
2534         */
2535        public void setEnableTaskStaleSearchCleanup(boolean theEnableTaskStaleSearchCleanup) {
2536                myEnableTaskStaleSearchCleanup = theEnableTaskStaleSearchCleanup;
2537        }
2538
2539        /**
2540         * If this is enabled (this is the default), this server will attempt to run resource reindexing jobs.
2541         * Otherwise, this server will not.
2542         *
2543         * @since 5.5.0
2544         */
2545        public boolean isEnableTaskResourceReindexing() {
2546                return myEnableTaskResourceReindexing;
2547        }
2548
2549        /**
2550         * If this is enabled (this is the default), this server will attempt to run resource reindexing jobs.
2551         * Otherwise, this server will not.
2552         *
2553         * @since 5.5.0
2554         */
2555        public void setEnableTaskResourceReindexing(boolean theEnableTaskResourceReindexing) {
2556                myEnableTaskResourceReindexing = theEnableTaskResourceReindexing;
2557        }
2558
2559        /**
2560         * If this is enabled (disabled by default), Mass Ingestion Mode is enabled. In this mode, a number of
2561         * runtime checks are disabled. This mode is designed for rapid backloading of data while the system is not
2562         * being otherwise used.
2563         * <p>
2564         * In this mode:
2565         * <p>
2566         * - Tags/Profiles/Security Labels will not be updated on existing resources that already have them
2567         * - Resources modification checks will be skipped in favour of a simple hash check
2568         * - Extra resource ID caching is enabled
2569         *
2570         * @since 5.5.0
2571         */
2572        public boolean isMassIngestionMode() {
2573                return myMassIngestionMode;
2574        }
2575
2576        /**
2577         * If this is enabled (disabled by default), Mass Ingestion Mode is enabled. In this mode, a number of
2578         * runtime checks are disabled. This mode is designed for rapid backloading of data while the system is not
2579         * being otherwise used.
2580         * <p>
2581         * In this mode:
2582         * <p>
2583         * - Tags/Profiles/Security Labels will not be updated on existing resources that already have them
2584         * - Resources modification checks will be skipped in favour of a simple hash check
2585         * - Extra resource ID caching is enabled
2586         *
2587         * @since 5.5.0
2588         */
2589        public void setMassIngestionMode(boolean theMassIngestionMode) {
2590                myMassIngestionMode = theMassIngestionMode;
2591        }
2592
2593        /**
2594         * If set to true (default is false), date indexes will account for null values in the range columns. As of 5.3.0
2595         * we no longer place null values in these columns, but legacy data may exist that still has these values. Note that
2596         * enabling this results in more complexity in the search SQL.
2597         *
2598         * @since 5.5.0
2599         */
2600        public boolean isAccountForDateIndexNulls() {
2601                return myAccountForDateIndexNulls;
2602        }
2603
2604        /**
2605         * If set to true (default is false), date indexes will account for null values in the range columns. As of 5.3.0
2606         * we no longer place null values in these columns, but legacy data may exist that still has these values. Note that
2607         * enabling this results in more complexity in the search SQL.
2608         *
2609         * @since 5.5.0
2610         */
2611        public void setAccountForDateIndexNulls(boolean theAccountForDateIndexNulls) {
2612                myAccountForDateIndexNulls = theAccountForDateIndexNulls;
2613        }
2614
2615        /**
2616         * If set to true (default is false) then subscriptions will be triggered for resource updates even if they
2617         * do not trigger a new version (e.g. $meta-add and $meta-delete).
2618         *
2619         * @since 5.5.0
2620         */
2621        public boolean isTriggerSubscriptionsForNonVersioningChanges() {
2622                return myTriggerSubscriptionsForNonVersioningChanges;
2623        }
2624
2625        /**
2626         * If set to true (default is false) then subscriptions will be triggered for resource updates even if they
2627         * do not trigger a new version (e.g. $meta-add and $meta-delete).
2628         *
2629         * @since 5.5.0
2630         */
2631        public void setTriggerSubscriptionsForNonVersioningChanges(boolean theTriggerSubscriptionsForNonVersioningChanges) {
2632                myTriggerSubscriptionsForNonVersioningChanges = theTriggerSubscriptionsForNonVersioningChanges;
2633        }
2634
2635        /**
2636         * Get the batch transaction thread pool size.
2637         *
2638         * @since 5.6.0
2639         */
2640        public Integer getBundleBatchPoolSize() {
2641                return myBundleBatchPoolSize;
2642        }
2643
2644        /**
2645         * Set the batch transaction thread pool size. The default is @see {@link #DEFAULT_BUNDLE_BATCH_POOL_SIZE}
2646         * set pool size to 1 for single thread
2647         *
2648         * @since 5.6.0
2649         */
2650        public void setBundleBatchPoolSize(Integer theBundleBatchPoolSize) {
2651                this.myBundleBatchPoolSize = theBundleBatchPoolSize;
2652        }
2653
2654        /**
2655         * Get the batch transaction thread max pool size.
2656         * set max pool size to 1 for single thread
2657         *
2658         * @since 5.6.0
2659         */
2660        public Integer getBundleBatchMaxPoolSize() {
2661                return myBundleBatchMaxPoolSize;
2662        }
2663
2664        /**
2665         * Set the batch transaction thread pool size. The default is @see {@link #DEFAULT_BUNDLE_BATCH_MAX_POOL_SIZE}
2666         *
2667         * @since 5.6.0
2668         */
2669        public void setBundleBatchMaxPoolSize(Integer theBundleBatchMaxPoolSize) {
2670                this.myBundleBatchMaxPoolSize = theBundleBatchMaxPoolSize;
2671        }
2672
2673        public boolean canDeleteExpunge() {
2674                return isAllowMultipleDelete() && isExpungeEnabled() && isDeleteExpungeEnabled();
2675        }
2676
2677        public String cannotDeleteExpungeReason() {
2678                List<String> reasons = new ArrayList<>();
2679                if (!isAllowMultipleDelete()) {
2680                        reasons.add("Multiple Delete");
2681                }
2682                if (!isExpungeEnabled()) {
2683                        reasons.add("Expunge");
2684                }
2685                if (!isDeleteExpungeEnabled()) {
2686                        reasons.add("Delete Expunge");
2687                }
2688                String retval = "Delete Expunge is not supported on this server.  ";
2689                if (reasons.size() == 1) {
2690                        retval += reasons.get(0) + " is disabled.";
2691                } else {
2692                        retval += "The following configurations are disabled: " + StringUtils.join(reasons, ", ");
2693                }
2694                return retval;
2695        }
2696
2697        /**
2698         * Sets a prefix for any indexes created when interacting with elasticsearch. This will apply to fulltext search indexes
2699         * and terminology expansion indexes.
2700         *
2701         * @since 5.6.0
2702         */
2703        public String getElasticSearchIndexPrefix() {
2704                return myElasicSearchIndexPrefix;
2705        }
2706
2707        /**
2708         * Sets a prefix for any indexes created when interacting with elasticsearch. This will apply to fulltext search indexes
2709         * and terminology expansion indexes.
2710         *
2711         * @since 5.6.0
2712         */
2713        public void setElasticSearchIndexPrefix(String thePrefix) {
2714                myElasicSearchIndexPrefix = thePrefix;
2715        }
2716
2717        /**
2718         * Is lucene/hibernate indexing enabled beyond _contains or _text?
2719         *
2720         * @since 5.6.0
2721         */
2722        public boolean isAdvancedLuceneIndexing() {
2723                return myAdvancedLuceneIndexing;
2724        }
2725
2726        /**
2727         * Enable/disable lucene/hibernate indexing enabled beyond _contains or _text.
2728         * <p>
2729         * String, token, and reference parameters can be indexed in Lucene.
2730         * This extends token search to support :text searches, as well as supporting
2731         * :contains and :text on string parameters.
2732         *
2733         * @since 5.6.0
2734         */
2735        public void setAdvancedLuceneIndexing(boolean theAdvancedLuceneIndexing) {
2736                this.myAdvancedLuceneIndexing = theAdvancedLuceneIndexing;
2737        }
2738
2739        /**
2740         * Is storing of Resource in Lucene index enabled?
2741         *
2742         * @since 5.7.0
2743         */
2744        public boolean isStoreResourceInLuceneIndex() {
2745                return myStoreResourceInLuceneIndex;
2746        }
2747
2748        /**
2749         * <p>
2750         * Enable Resource to be stored inline with Lucene index mappings.
2751         * This is useful in cases where after performing a search operation the resulting resource identifiers don't have to be
2752         * looked up in the persistent storage, but rather the inline stored resource can be used instead.
2753         * </p>
2754         * <p>
2755         * For e.g - Storing Observation resource in lucene index would be useful when performing
2756         * <a href="https://www.hl7.org/fhir/observation-operation-lastn.html">$lastn</a> operation.
2757         * </p>
2758         *
2759         * @since 5.7.0
2760         */
2761        public void setStoreResourceInLuceneIndex(boolean theStoreResourceInLuceneIndex) {
2762                myStoreResourceInLuceneIndex = theStoreResourceInLuceneIndex;
2763        }
2764
2765        /**
2766         * @see FhirValidator#isConcurrentBundleValidation()
2767         * @since 5.7.0
2768         */
2769        public boolean isConcurrentBundleValidation() {
2770                return myConcurrentBundleValidation;
2771        }
2772
2773        /**
2774         * @see FhirValidator#isConcurrentBundleValidation()
2775         * @since 5.7.0
2776         */
2777        public DaoConfig setConcurrentBundleValidation(boolean theConcurrentBundleValidation) {
2778                myConcurrentBundleValidation = theConcurrentBundleValidation;
2779                return this;
2780        }
2781
2782        /**
2783         * This setting indicates if a cross-partition subscription can be made.
2784         *
2785         * @see ModelConfig#setCrossPartitionSubscription(boolean)
2786         * @since 7.5.0
2787         */
2788        public boolean isCrossPartitionSubscription() {
2789                return this.myModelConfig.isCrossPartitionSubscription();
2790        }
2791
2792        /**
2793         * This setting indicates if a cross-partition subscription can be made.
2794         *
2795         * @see ModelConfig#setCrossPartitionSubscription(boolean)
2796         * @since 7.5.0
2797         */
2798        public void setCrossPartitionSubscription(boolean theAllowCrossPartitionSubscription) {
2799                this.myModelConfig.setCrossPartitionSubscription(theAllowCrossPartitionSubscription);
2800        }
2801
2802        public enum StoreMetaSourceInformationEnum {
2803                NONE(false, false),
2804                SOURCE_URI(true, false),
2805                REQUEST_ID(false, true),
2806                SOURCE_URI_AND_REQUEST_ID(true, true);
2807
2808                private final boolean myStoreSourceUri;
2809                private final boolean myStoreRequestId;
2810
2811                StoreMetaSourceInformationEnum(boolean theStoreSourceUri, boolean theStoreRequestId) {
2812                        myStoreSourceUri = theStoreSourceUri;
2813                        myStoreRequestId = theStoreRequestId;
2814                }
2815
2816                public boolean isStoreSourceUri() {
2817                        return myStoreSourceUri;
2818                }
2819
2820                public boolean isStoreRequestId() {
2821                        return myStoreRequestId;
2822                }
2823        }
2824
2825
2826        public enum IndexEnabledEnum {
2827                ENABLED,
2828                DISABLED
2829        }
2830
2831        /**
2832         * This enum provides allowable options for {@link #setResourceServerIdStrategy(IdStrategyEnum)}
2833         */
2834        public enum IdStrategyEnum {
2835                /**
2836                 * This strategy is the default strategy, and it simply uses a sequential
2837                 * numeric ID for each newly created resource.
2838                 */
2839                SEQUENTIAL_NUMERIC,
2840                /**
2841                 * Each resource will receive a randomly generated UUID
2842                 */
2843                UUID
2844        }
2845
2846        /**
2847         * This enum provides allowable options for {@link #setResourceClientIdStrategy(ClientIdStrategyEnum)}
2848         */
2849        public enum ClientIdStrategyEnum {
2850                /**
2851                 * Clients are not allowed to supply IDs for resources that do not
2852                 * already exist
2853                 */
2854                NOT_ALLOWED,
2855
2856                /**
2857                 * Clients may supply IDs but these IDs are not permitted to be purely
2858                 * numeric. In other words, values such as "A", "A1" and "000A" would be considered
2859                 * valid but "123" would not.
2860                 * <p><b>This is the default setting.</b></p>
2861                 */
2862                ALPHANUMERIC,
2863
2864                /**
2865                 * Clients may supply any ID including purely numeric IDs. Note that this setting should
2866                 * only be set on an empty database, or on a database that has always had this setting
2867                 * set as it causes a "forced ID" to be used for all resources.
2868                 * <p>
2869                 * Note that if you use this setting, it is highly recommended that you also
2870                 * set the {@link #setResourceServerIdStrategy(IdStrategyEnum) ResourceServerIdStrategy}
2871                 * to {@link IdStrategyEnum#UUID} in order to avoid any potential for conflicts. Otherwise
2872                 * a database sequence will be used to generate IDs and these IDs can conflict with
2873                 * client-assigned numeric IDs.
2874                 * </p>
2875                 */
2876                ANY
2877        }
2878
2879        public enum TagStorageModeEnum {
2880
2881                /**
2882                 * A separate set of tags is stored for each resource version
2883                 */
2884                VERSIONED,
2885
2886                /**
2887                 * A single set of tags is shared by all resource versions
2888                 */
2889                NON_VERSIONED,
2890
2891                /**
2892                 * Tags are stored directly in the resource body (in the {@link ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable}
2893                 * entry for the resource, meaning that they are not indexed separately, and are versioned with the rest
2894                 * of the resource.
2895                 */
2896                INLINE
2897
2898        }
2899}