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