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