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