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