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