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