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