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