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