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