-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
DaoConfig.java
3141 lines (2895 loc) · 115 KB
/
DaoConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package ca.uhn.fhir.jpa.api.config;
import ca.uhn.fhir.jpa.api.model.HistoryCountModeEnum;
import ca.uhn.fhir.jpa.api.model.WarmCacheEntry;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
import ca.uhn.fhir.system.HapiSystemProperties;
import ca.uhn.fhir.util.HapiExtensions;
import ca.uhn.fhir.validation.FhirValidator;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.dstu2.model.Subscription;
import org.hl7.fhir.r4.model.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/*
* #%L
* HAPI FHIR Storage api
* %%
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class DaoConfig {
/**
* Default value for {@link #setReuseCachedSearchResultsForMillis(Long)}: 60000ms (one minute)
*/
public static final Long DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS = DateUtils.MILLIS_PER_MINUTE;
/**
* Default value for {@link #myTranslationCachesExpireAfterWriteInMinutes}: 60 minutes
*
* @see #myTranslationCachesExpireAfterWriteInMinutes
*/
public static final Long DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES = 60L;
/**
* Default {@link #setBundleTypesAllowedForStorage(Set)} value:
* <ul>
* <li>collection</li>
* <li>document</li>
* <li>message</li>
* </ul>
*/
@SuppressWarnings("WeakerAccess")
public static final Set<String> DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE = Collections.unmodifiableSet(new TreeSet<>(Sets.newHashSet(
Bundle.BundleType.COLLECTION.toCode(),
Bundle.BundleType.DOCUMENT.toCode(),
Bundle.BundleType.MESSAGE.toCode()
)));
// update setter javadoc if default changes
public static final int DEFAULT_MAX_EXPANSION_SIZE = 1000;
public static final HistoryCountModeEnum DEFAULT_HISTORY_COUNT_MODE = HistoryCountModeEnum.CACHED_ONLY_WITHOUT_OFFSET;
/**
* This constant applies to task enablement, e.g. {@link #setEnableTaskStaleSearchCleanup(boolean)}.
* <p>
* By default, all are enabled.
*/
public static final boolean DEFAULT_ENABLE_TASKS = true;
public static final int DEFAULT_MAXIMUM_INCLUDES_TO_LOAD_PER_PAGE = 1000;
/**
* @since 5.5.0
*/
public static final TagStorageModeEnum DEFAULT_TAG_STORAGE_MODE = TagStorageModeEnum.VERSIONED;
public static final int DEFAULT_EXPUNGE_BATCH_SIZE = 800;
/**
* @since 5.6.0
*/
// Thread Pool size used by batch in bundle
public static final int DEFAULT_BUNDLE_BATCH_POOL_SIZE = 20; // 1 for single thread
public static final int DEFAULT_BUNDLE_BATCH_MAX_POOL_SIZE = 100; // 1 for single thread
public static final int DEFAULT_BUNDLE_BATCH_QUEUE_CAPACITY = 200;
/**
* Default value for {@link #setMaximumSearchResultCountInTransaction(Integer)}
*
* @see #setMaximumSearchResultCountInTransaction(Integer)
*/
private static final Integer DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION = null;
private static final Integer DEFAULT_MAXIMUM_TRANSACTION_BUNDLE_SIZE = null;
private static final Logger ourLog = LoggerFactory.getLogger(DaoConfig.class);
private static final int DEFAULT_REINDEX_BATCH_SIZE = 800;
private static final int DEFAULT_MAXIMUM_DELETE_CONFLICT_COUNT = 60;
/**
* Child Configurations
*/
private static final Integer DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE = 10000;
private final ModelConfig myModelConfig = new ModelConfig();
/**
* Do not change default of {@code 0}!
*
* @since 4.1.0
*/
private final int myPreExpandValueSetsDefaultOffset = 0;
/**
* update setter javadoc if default changes
*/
@Nonnull
private final Long myTranslationCachesExpireAfterWriteInMinutes = DEFAULT_TRANSLATION_CACHES_EXPIRE_AFTER_WRITE_IN_MINUTES;
/**
* @since 5.5.0
*/
@Nullable
private Integer myMaximumIncludesToLoadPerPage = DEFAULT_MAXIMUM_INCLUDES_TO_LOAD_PER_PAGE;
private IndexEnabledEnum myIndexMissingFieldsEnabled = IndexEnabledEnum.DISABLED;
/**
* update setter javadoc if default changes
*/
private boolean myAllowInlineMatchUrlReferences = true;
private boolean myAllowMultipleDelete;
/**
* update setter javadoc if default changes
*/
private int myDeferIndexingForCodesystemsOfSize = 100;
private boolean myDeleteStaleSearches = true;
private boolean myEnforceReferentialIntegrityOnDelete = true;
private boolean myUniqueIndexesEnabled = true;
private boolean myUniqueIndexesCheckedBeforeSave = true;
private boolean myEnforceReferentialIntegrityOnWrite = true;
private SearchTotalModeEnum myDefaultTotalMode = null;
private int myEverythingIncludesFetchPageSize = 50;
private int myBulkImportMaxRetryCount = 10;
private TagStorageModeEnum myTagStorageMode = DEFAULT_TAG_STORAGE_MODE;
/**
* update setter javadoc if default changes
*/
private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
/**
* update setter javadoc if default changes
*/
private Integer myFetchSizeDefaultMaximum = null;
private int myMaximumExpansionSize = DEFAULT_MAX_EXPANSION_SIZE;
private Integer myMaximumSearchResultCountInTransaction = DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION;
private Integer myMaximumTransactionBundleSize = DEFAULT_MAXIMUM_TRANSACTION_BUNDLE_SIZE;
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
/**
* update setter javadoc if default changes
*/
private Integer myResourceMetaCountHardLimit = 1000;
private Long myReuseCachedSearchResultsForMillis = DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
private boolean mySchedulingDisabled;
private boolean mySuppressUpdatesWithNoChange = true;
private boolean myAutoCreatePlaceholderReferenceTargets;
private Integer myCacheControlNoStoreMaxResultsUpperLimit = 1000;
private Integer myCountSearchResultsUpTo = null;
private boolean myStatusBasedReindexingDisabled;
private IdStrategyEnum myResourceServerIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC;
private boolean myMarkResourcesForReindexingUponSearchParameterChange;
private boolean myExpungeEnabled;
private boolean myDeleteExpungeEnabled;
private int myExpungeBatchSize = DEFAULT_EXPUNGE_BATCH_SIZE;
private int myReindexBatchSize = DEFAULT_REINDEX_BATCH_SIZE;
private int myReindexThreadCount;
private int myExpungeThreadCount;
private Set<String> myBundleTypesAllowedForStorage;
private boolean myValidateSearchParameterExpressionsOnSave = true;
// start with a tiny number so our first page always loads quickly.
// If they fetch the second page, fetch more.
// Use prime sizes to avoid empty next links.
private List<Integer> mySearchPreFetchThresholds = Arrays.asList(13, 503, 2003, -1);
private List<WarmCacheEntry> myWarmCacheEntries = new ArrayList<>();
private boolean myDisableHashBasedSearches;
private boolean myEnableInMemorySubscriptionMatching = true;
private boolean myEnforceReferenceTargetTypes = true;
private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
private boolean myFilterParameterEnabled = false;
private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID;
private HistoryCountModeEnum myHistoryCountMode = DEFAULT_HISTORY_COUNT_MODE;
private int myInternalSynchronousSearchSize = DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE;
/**
* update setter javadoc if default changes
*/
private Integer myMaximumDeleteConflictQueryCount = DEFAULT_MAXIMUM_DELETE_CONFLICT_COUNT;
/**
* Do not change default of {@code true}!
*
* @since 4.1.0
*/
private boolean myPreExpandValueSets = true;
/**
* Do not change default of {@code 1000}!
*
* @since 4.1.0
*/
private int myPreExpandValueSetsDefaultCount = 1000;
/**
* Do not change default of {@code 1000}!
*
* @since 4.1.0
*/
private int myPreExpandValueSetsMaxCount = 1000;
/**
* Do not change default of {@code true}!
*
* @since 4.2.0
*/
private boolean myPopulateIdentifierInAutoCreatedPlaceholderReferenceTargets = true;
/**
* @since 5.0.0
*/
private boolean myDeleteEnabled = true;
/**
* @since 5.1.0
*/
private boolean myLastNEnabled = false;
/**
* @since 5.2.0
*/
private boolean myUseLegacySearchBuilder = false;
/**
* @since 5.5.0
*/
private boolean myReindexEnabled = true;
/**
* @since 5.4.0
*/
private boolean myMatchUrlCacheEnabled;
/**
* @since 5.5.0
*/
private boolean myEnableTaskBulkImportJobExecution;
/**
* @since 5.5.0
*/
private boolean myEnableTaskStaleSearchCleanup;
/**
* @since 5.5.0
*/
private boolean myEnableTaskPreExpandValueSets;
/**
* @since 5.5.0
*/
private boolean myEnableTaskResourceReindexing;
/**
* @since 5.5.0
*/
private boolean myEnableTaskBulkExportJobExecution;
private boolean myMassIngestionMode;
private boolean myAccountForDateIndexNulls;
private boolean myTriggerSubscriptionsForNonVersioningChanges;
/**
* @since 5.6.0
*/
private String myHSearchIndexPrefix;
private Integer myBundleBatchPoolSize = DEFAULT_BUNDLE_BATCH_POOL_SIZE;
private Integer myBundleBatchMaxPoolSize = DEFAULT_BUNDLE_BATCH_MAX_POOL_SIZE;
/**
* Activates the new HSearch indexing of search parameters.
* When active, string, token, and reference parameters will be indexed and
* queried within Hibernate Search.
*
* @since 5.6.0
*/
private boolean myAdvancedHSearchIndexing = false;
/**
* If set to a positive number, any resources with a character length at or below the given number
* of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
* separate LOB column.
*
* @since 5.7.0
*/
private int myInlineResourceTextBelowSize = 0;
/**
* @since 5.7.0
*/
private boolean myStoreResourceInHSearchIndex;
/**
* @see FhirValidator#isConcurrentBundleValidation()
* @since 5.7.0
*/
private boolean myConcurrentBundleValidation;
/**
* Since 6.0.0
*/
private boolean myAllowAutoInflateBinaries = true;
/**
* Since 6.0.0
*/
private long myAutoInflateBinariesMaximumBytes = 10 * FileUtils.ONE_MB;
/**
* Since 6.0.0
*/
private int myBulkExportFileRetentionPeriodHours = 2;
/**
* Since 6.2.0
*/
private boolean myEnableBulkExportJobReuse = true;
/**
* Since 6.1.0
*/
private boolean myUpdateWithHistoryRewriteEnabled = false;
/**
* Since 6.2.0
*/
private boolean myPreserveRequestIdInResourceBody = false;
/**
* Since 6.2.0
*/
private int myBulkExportFileMaximumCapacity = 1_000;
/**
* Since 6.4.0
*/
private boolean myJobFastTrackingEnabled = false;
/**
* Since 6.4.0
*/
private boolean myQualifySubscriptionMatchingChannelName = true;
/**
* Constructor
*/
public DaoConfig() {
setMarkResourcesForReindexingUponSearchParameterChange(true);
setReindexThreadCount(Runtime.getRuntime().availableProcessors());
setExpungeThreadCount(Runtime.getRuntime().availableProcessors());
setBundleTypesAllowedForStorage(DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE);
// Scheduled tasks are all enabled by default
setEnableTaskBulkImportJobExecution(DEFAULT_ENABLE_TASKS);
setEnableTaskBulkExportJobExecution(DEFAULT_ENABLE_TASKS);
setEnableTaskStaleSearchCleanup(DEFAULT_ENABLE_TASKS);
setEnableTaskPreExpandValueSets(DEFAULT_ENABLE_TASKS);
setEnableTaskResourceReindexing(DEFAULT_ENABLE_TASKS);
if (HapiSystemProperties.isDisableStatusBasedReindex()) {
ourLog.info("Status based reindexing is DISABLED");
setStatusBasedReindexingDisabled(true);
}
if (HapiSystemProperties.isUnitTestModeEnabled()) {
setJobFastTrackingEnabled(true);
}
}
/**
* If set to a positive number, any resources with a character length at or below the given number
* of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
* separate LOB column.
*
* @since 5.7.0
*/
public int getInlineResourceTextBelowSize() {
return myInlineResourceTextBelowSize;
}
/**
* If set to a positive number, any resources with a character length at or below the given number
* of characters will be stored inline in the <code>HFJ_RES_VER</code> table instead of using a
* separate LOB column.
*
* @since 5.7.0
*/
public void setInlineResourceTextBelowSize(int theInlineResourceTextBelowSize) {
myInlineResourceTextBelowSize = theInlineResourceTextBelowSize;
}
/**
* Sets the tag storage mode for the server. Default is {@link TagStorageModeEnum#VERSIONED}.
*
* @since 5.5.0
*/
@Nonnull
public TagStorageModeEnum getTagStorageMode() {
return myTagStorageMode;
}
/**
* Sets the tag storage mode for the server. Default is {@link TagStorageModeEnum#VERSIONED}.
*
* @since 5.5.0
*/
public void setTagStorageMode(@Nonnull TagStorageModeEnum theTagStorageMode) {
Validate.notNull(theTagStorageMode, "theTagStorageMode must not be null");
myTagStorageMode = theTagStorageMode;
}
/**
* Specifies the maximum number of times that a chunk will be retried during bulk import
* processes before giving up.
*
* @since 5.5.0
*/
public int getBulkImportMaxRetryCount() {
return myBulkImportMaxRetryCount;
}
/**
* Specifies the maximum number of times that a chunk will be retried during bulk import
* processes before giving up.
*
* @since 5.5.0
*/
public void setBulkImportMaxRetryCount(int theBulkImportMaxRetryCount) {
myBulkImportMaxRetryCount = theBulkImportMaxRetryCount;
}
/**
* Specifies the maximum number of <code>_include</code> and <code>_revinclude</code> results to return in a
* single page of results. The default is <code>1000</code>, and <code>null</code> may be used
* to indicate that there is no limit.
*
* @since 5.5.0
*/
@Nullable
public Integer getMaximumIncludesToLoadPerPage() {
return myMaximumIncludesToLoadPerPage;
}
/**
* Specifies the maximum number of <code>_include</code> and <code>_revinclude</code> results to return in a
* single page of results. The default is <code>1000</code>, and <code>null</code> may be used
* to indicate that there is no limit.
*
* @since 5.5.0
*/
public void setMaximumIncludesToLoadPerPage(@Nullable Integer theMaximumIncludesToLoadPerPage) {
myMaximumIncludesToLoadPerPage = theMaximumIncludesToLoadPerPage;
}
/**
* When performing a FHIR history operation, a <code>Bundle.total</code> value is included in the
* response, indicating the total number of history entries. This response is calculated using a
* SQL COUNT query statement which can be expensive. This setting allows the results of the count
* query to be cached, resulting in a much lighter load on the server, at the expense of
* returning total values that may be slightly out of date. Total counts can also be disabled,
* or forced to always be accurate.
* <p>
* In {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET} mode, a loading cache is used to fetch the value,
* meaning that only one thread per JVM will fetch the count, and others will block while waiting
* for the cache to load, avoiding excessive load on the database.
* </p>
* <p>
* Default is {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET}
* </p>
*
* @since 5.4.0
*/
public HistoryCountModeEnum getHistoryCountMode() {
return myHistoryCountMode;
}
/**
* When performing a FHIR history operation, a <code>Bundle.total</code> value is included in the
* response, indicating the total number of history entries. This response is calculated using a
* SQL COUNT query statement which can be expensive. This setting allows the results of the count
* query to be cached, resulting in a much lighter load on the server, at the expense of
* returning total values that may be slightly out of date. Total counts can also be disabled,
* or forced to always be accurate.
* <p>
* In {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET} mode, a loading cache is used to fetch the value,
* meaning that only one thread per JVM will fetch the count, and others will block while waiting
* for the cache to load, avoiding excessive load on the database.
* </p>
* <p>
* Default is {@link HistoryCountModeEnum#CACHED_ONLY_WITHOUT_OFFSET}
* </p>
*
* @since 5.4.0
*/
public void setHistoryCountMode(@Nonnull HistoryCountModeEnum theHistoryCountMode) {
Validate.notNull(theHistoryCountMode, "theHistoryCountMode must not be null");
myHistoryCountMode = theHistoryCountMode;
}
/**
* If set to <code>true</code> (default is <code>false</code>) the <code>$lastn</code> operation will be enabled for
* indexing Observation resources. This operation involves creating a special set of tables in hsearch for
* discovering Observation resources. Enabling this setting increases the amount of storage space required, and can
* slow write operations, but can be very useful for searching for collections of Observations for some applications.
*
* @since 5.1.0
*/
public boolean isLastNEnabled() {
return myLastNEnabled;
}
/**
* If set to <code>true</code> (default is <code>false</code>) the <code>$lastn</code> operation will be enabled for
* indexing Observation resources. This operation involves creating a special set of tables in hsearch for
* discovering Observation resources. Enabling this setting increases the amount of storage space required, and can
* slow write operations, but can be very useful for searching for collections of Observations for some applications.
*
* @since 5.1.0
*/
public void setLastNEnabled(boolean theLastNEnabled) {
myLastNEnabled = theLastNEnabled;
}
/**
* This method controls whether to use the new non-hibernate search SQL builder that was introduced in HAPI FHIR 5.2.0.
* By default this will be <code>false</code> meaning that the new SQL builder is used. Set to <code>true</code> to use the
* legacy SQL builder based on Hibernate.
* <p>Note that this method will be removed in HAPI FHIR 5.4.0</p>
*
* @since 5.3.0
*/
public boolean isUseLegacySearchBuilder() {
return false;
}
/**
* This method controls whether to use the new non-hibernate search SQL builder that was introduced in HAPI FHIR 5.2.0.
* By default this will be <code>false</code> meaning that the new SQL builder is used. Set to <code>true</code> to use the
* legacy SQL builder based on Hibernate.
* <p>Note that this method will be removed in HAPI FHIR 5.4.0</p>
*
* @since 5.3.0
* @deprecated in 6.1.0, this toggle will be removed in 6.2.0 as the Legacy Search Builder has been removed.
*/
@Deprecated
public void setUseLegacySearchBuilder(boolean theUseLegacySearchBuilder) {
//Nop
}
/**
* Specifies the duration in minutes for which values will be retained after being
* written to the terminology translation cache. Defaults to 60.
*/
@Nonnull
public Long getTranslationCachesExpireAfterWriteInMinutes() {
return myTranslationCachesExpireAfterWriteInMinutes;
}
/**
* If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
* cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
* where conditional operations are frequently performed, but note that this cache will not be
* invalidated based on updates to resources so this may have detrimental effects.
* <p>
* Default is <code>false</code>
*
* @since 5.4.0
* @deprecated Deprecated in 5.5.0. Use {@link #isMatchUrlCacheEnabled()} instead (the name of this method is misleading)
*/
@Deprecated
public boolean getMatchUrlCache() {
return myMatchUrlCacheEnabled;
}
/**
* If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
* cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
* where conditional operations are frequently performed, but note that this cache will not be
* invalidated based on updates to resources so this may have detrimental effects.
* <p>
* Default is <code>false</code>
*
* @since 5.4.0
* @deprecated Deprecated in 5.5.0. Use {@link #setMatchUrlCacheEnabled(boolean)} instead (the name of this method is misleading)
*/
@Deprecated
public void setMatchUrlCache(boolean theMatchUrlCache) {
myMatchUrlCacheEnabled = theMatchUrlCache;
}
/**
* If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
* cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
* where conditional operations are frequently performed, but note that this cache will not be
* invalidated based on updates to resources so this may have detrimental effects.
* <p>
* Default is <code>false</code>
*
* @since 5.5.0
*/
public boolean isMatchUrlCacheEnabled() {
return getMatchUrlCache();
}
/**
* If enabled, resolutions for match URLs (e.g. conditional create URLs, conditional update URLs, etc) will be
* cached in an in-memory cache. This cache can have a noticeable improvement on write performance on servers
* where conditional operations are frequently performed, but note that this cache will not be
* invalidated based on updates to resources so this may have detrimental effects.
* <p>
* Default is <code>false</code>
*
* @since 5.5.0
*/
public void setMatchUrlCacheEnabled(boolean theMatchUrlCache) {
setMatchUrlCache(theMatchUrlCache);
}
/**
* If set to <code>true</code> (default is true) when a resource is being persisted,
* the target resource types of references will be validated to ensure that they
* are appropriate for the field containing the reference. This is generally a good idea
* because invalid reference target types may not be searchable.
*/
public boolean isEnforceReferenceTargetTypes() {
return myEnforceReferenceTargetTypes;
}
/**
* If set to <code>true</code> (default is true) when a resource is being persisted,
* the target resource types of references will be validated to ensure that they
* are appropriate for the field containing the reference. This is generally a good idea
* because invalid reference target types may not be searchable.
*/
public void setEnforceReferenceTargetTypes(boolean theEnforceReferenceTargetTypes) {
myEnforceReferenceTargetTypes = theEnforceReferenceTargetTypes;
}
/**
* If a non-null value is supplied (default is <code>null</code>), a default
* for the <code>_total</code> parameter may be specified here. For example,
* setting this value to {@link SearchTotalModeEnum#ACCURATE} will force a
* count to always be calculated for all searches. This can have a performance impact
* since it means that a count query will always be performed, but this is desirable
* for some solutions.
*/
public SearchTotalModeEnum getDefaultTotalMode() {
return myDefaultTotalMode;
}
/**
* If a non-null value is supplied (default is <code>null</code>), a default
* for the <code>_total</code> parameter may be specified here. For example,
* setting this value to {@link SearchTotalModeEnum#ACCURATE} will force a
* count to always be calculated for all searches. This can have a performance impact
* since it means that a count query will always be performed, but this is desirable
* for some solutions.
*/
public void setDefaultTotalMode(SearchTotalModeEnum theDefaultTotalMode) {
myDefaultTotalMode = theDefaultTotalMode;
}
/**
* Returns a set of searches that should be kept "warm", meaning that
* searches will periodically be performed in the background to
* keep results ready for this search
*/
public List<WarmCacheEntry> getWarmCacheEntries() {
if (myWarmCacheEntries == null) {
myWarmCacheEntries = new ArrayList<>();
}
return myWarmCacheEntries;
}
public void setWarmCacheEntries(List<WarmCacheEntry> theWarmCacheEntries) {
myWarmCacheEntries = theWarmCacheEntries;
}
/**
* If set to <code>true</code> (default is false), the reindexing of search parameters
* using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
* This query is just not efficient on Oracle and bogs the system down when there are
* a lot of resources. A more efficient way of doing this will be introduced
* in the next release of HAPI FHIR.
*
* @since 3.5.0
*/
public boolean isStatusBasedReindexingDisabled() {
return myStatusBasedReindexingDisabled;
}
/**
* If set to <code>true</code> (default is false), the reindexing of search parameters
* using a query on the HFJ_RESOURCE.SP_INDEX_STATUS column will be disabled completely.
* This query is just not efficient on Oracle and bogs the system down when there are
* a lot of resources. A more efficient way of doing this will be introduced
* in the next release of HAPI FHIR.
*
* @since 3.5.0
*/
public void setStatusBasedReindexingDisabled(boolean theStatusBasedReindexingDisabled) {
myStatusBasedReindexingDisabled = theStatusBasedReindexingDisabled;
}
/**
* Add a value to the {@link #setTreatReferencesAsLogical(Set) logical references list}.
*
* @see #setTreatReferencesAsLogical(Set)
*/
public void addTreatReferencesAsLogical(String theTreatReferencesAsLogical) {
myModelConfig.addTreatReferencesAsLogical(theTreatReferencesAsLogical);
}
/**
* This setting specifies the bundle types (<code>Bundle.type</code>) that
* are allowed to be stored as-is on the /Bundle endpoint.
*
* @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
*/
public Set<String> getBundleTypesAllowedForStorage() {
return myBundleTypesAllowedForStorage;
}
/**
* This setting specifies the bundle types (<code>Bundle.type</code>) that
* are allowed to be stored as-is on the /Bundle endpoint.
*
* @see #DEFAULT_BUNDLE_TYPES_ALLOWED_FOR_STORAGE
*/
public void setBundleTypesAllowedForStorage(Set<String> theBundleTypesAllowedForStorage) {
Validate.notNull(theBundleTypesAllowedForStorage, "theBundleTypesAllowedForStorage must not be null");
myBundleTypesAllowedForStorage = theBundleTypesAllowedForStorage;
}
/**
* Specifies the highest number that a client is permitted to use in a
* <code>Cache-Control: nostore, max-results=NNN</code>
* directive. If the client tries to exceed this limit, the
* request will be denied. Defaults to 1000.
*/
public Integer getCacheControlNoStoreMaxResultsUpperLimit() {
return myCacheControlNoStoreMaxResultsUpperLimit;
}
/**
* Specifies the highest number that a client is permitted to use in a
* <code>Cache-Control: nostore, max-results=NNN</code>
* directive. If the client tries to exceed this limit, the
* request will be denied. Defaults to 1000.
*/
public void setCacheControlNoStoreMaxResultsUpperLimit(Integer theCacheControlNoStoreMaxResults) {
myCacheControlNoStoreMaxResultsUpperLimit = theCacheControlNoStoreMaxResults;
}
/**
* When searching, if set to a non-null value (default is <code>null</code>) the
* search coordinator will attempt to find at least this many results
* before returning a response to the client. This parameter mainly affects
* whether a "total count" is included in the response bundle for searches that
* return large amounts of data.
* <p>
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* </p>
* <p>
* Set this value to <code>0</code> to always load all
* results before returning.
* </p>
*/
public Integer getCountSearchResultsUpTo() {
return myCountSearchResultsUpTo;
}
/**
* When searching, if set to a non-null value (default is <code>null</code>) the
* search coordinator will attempt to find at least this many results
* before returning a response to the client. This parameter mainly affects
* whether a "total count" is included in the response bundle for searches that
* return large amounts of data.
* <p>
* For a search that returns 10000 results, if this value is set to
* 10000 the search coordinator will find all 10000 results
* prior to returning, so the initial response bundle will have the
* total set to 10000. If this value is null (or less than 10000)
* the response bundle will likely return slightly faster, but will
* not include the total. Subsequent page requests will likely
* include the total however, if they are performed after the
* search coordinator has found all results.
* </p>
* <p>
* Set this value to <code>0</code> to always load all
* results before returning.
* </p>
*/
public void setCountSearchResultsUpTo(Integer theCountSearchResultsUpTo) {
myCountSearchResultsUpTo = theCountSearchResultsUpTo;
}
/**
* When a code system is added that contains more than this number of codes,
* the code system will be indexed later in an incremental process in order to
* avoid overwhelming Lucene with a huge number of codes in a single operation.
* <p>
* Defaults to 100
* </p>
*/
public int getDeferIndexingForCodesystemsOfSize() {
return myDeferIndexingForCodesystemsOfSize;
}
/**
* When a code system is added that contains more than this number of codes,
* the code system will be indexed later in an incremental process in order to
* avoid overwhelming Lucene with a huge number of codes in a single operation.
* <p>
* Defaults to 100
* </p>
*/
public void setDeferIndexingForCodesystemsOfSize(int theDeferIndexingForCodesystemsOfSize) {
myDeferIndexingForCodesystemsOfSize = theDeferIndexingForCodesystemsOfSize;
}
/**
* Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
* 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
* as the search results are paged over.
* <p>
* In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
* value may improve performance but may also cause memory issues.
* </p>
* <p>
* The default value is 50
* </p>
*/
public int getEverythingIncludesFetchPageSize() {
return myEverythingIncludesFetchPageSize;
}
/**
* Unlike with normal search queries, $everything queries have their _includes loaded by the main search thread and these included results
* 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
* as the search results are paged over.
* <p>
* In order to recursively load _includes, we process the original results in batches of this size. Adjust with caution, increasing this
* value may improve performance but may also cause memory issues.
* </p>
* <p>
* The default value is 50
* </p>
*/
public void setEverythingIncludesFetchPageSize(int theEverythingIncludesFetchPageSize) {
Validate.inclusiveBetween(1, Integer.MAX_VALUE, theEverythingIncludesFetchPageSize);
myEverythingIncludesFetchPageSize = theEverythingIncludesFetchPageSize;
}
/**
* Sets the number of milliseconds that search results for a given client search
* should be preserved before being purged from the database.
* <p>
* Search results are stored in the database so that they can be paged over multiple
* requests. After this
* number of milliseconds, they will be deleted from the database, and any paging links
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
* </p>
* <p>
* To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
* </p>
*
* @since 1.5
*/
public long getExpireSearchResultsAfterMillis() {
return myExpireSearchResultsAfterMillis;
}
/**
* Sets the number of milliseconds that search results for a given client search
* should be preserved before being purged from the database.
* <p>
* Search results are stored in the database so that they can be paged over multiple
* requests. After this
* number of milliseconds, they will be deleted from the database, and any paging links
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
* </p>
* <p>
* To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
* </p>
*
* @since 1.5
*/
public void setExpireSearchResultsAfterMillis(long theExpireSearchResultsAfterMillis) {
myExpireSearchResultsAfterMillis = theExpireSearchResultsAfterMillis;
}
/**
* Gets the default maximum number of results to load in a query.
* <p>
* For example, if the database has a million Patient resources in it, and
* the client requests <code>GET /Patient</code>, if this value is set
* to a non-null value (default is <code>null</code>) only this number
* of results will be fetched. Setting this value appropriately
* can be useful to improve performance in some situations.
* </p>
*/
public Integer getFetchSizeDefaultMaximum() {
return myFetchSizeDefaultMaximum;
}
/**
* Gets the default maximum number of results to load in a query.
* <p>
* For example, if the database has a million Patient resources in it, and
* the client requests <code>GET /Patient</code>, if this value is set
* to a non-null value (default is <code>null</code>) only this number
* of results will be fetched. Setting this value appropriately
* can be useful to improve performance in some situations.
* </p>
*/
public void setFetchSizeDefaultMaximum(Integer theFetchSizeDefaultMaximum) {
myFetchSizeDefaultMaximum = theFetchSizeDefaultMaximum;
}
/**
* If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
* the server will not create search indexes for search parameters with no values in resources.
* <p>
* Disabling this feature means that the <code>:missing</code> search modifier will not be
* supported on the server, but also means that storage and indexing (i.e. writes to the
* database) may be much faster on servers which have lots of search parameters and need
* to write quickly.
* </p>
* <p>
* This feature may be enabled on servers where supporting the use of the :missing parameter is
* of higher importance than raw write performance
* </p>
*/
public IndexEnabledEnum getIndexMissingFields() {
return myIndexMissingFieldsEnabled;
}
/**
* If set to {@link IndexEnabledEnum#DISABLED} (default is {@link IndexEnabledEnum#DISABLED})
* the server will not create search indexes for search parameters with no values in resources.
* <p>
* Disabling this feature means that the <code>:missing</code> search modifier will not be
* supported on the server, but also means that storage and indexing (i.e. writes to the
* database) may be much faster on servers which have lots of search parameters and need
* to write quickly.
* </p>
* <p>
* This feature may be enabled on servers where supporting the use of the :missing parameter is
* of higher importance than raw write performance
* </p>
* <p>
* Note that this setting also has an impact on sorting (i.e. using the
* <code>_sort</code> parameter on searches): If the server is configured
* to not index missing field.
* </p>
* <p>
* The following index may need to be added into the indexed tables such as <code>HFJ_SPIDX_TOKEN</code>
* to improve the search performance while <code>:missing</code> is enabled.
* <code>RES_TYPE, SP_NAME, SP_MISSING</code>
* </p>
*/
public void setIndexMissingFields(IndexEnabledEnum theIndexMissingFields) {
Validate.notNull(theIndexMissingFields, "theIndexMissingFields must not be null");
myIndexMissingFieldsEnabled = theIndexMissingFields;
}
/**
* See {@link #setMaximumExpansionSize(int)}
*/
public int getMaximumExpansionSize() {
return myMaximumExpansionSize;
}
/**
* Sets the maximum number of codes that will be added to an in-memory valueset expansion before
* the operation will be failed as too costly. Note that this setting applies only to
* in-memory expansions and does not apply to expansions that are being pre-calculated.
* <p>
* The default value for this setting is 1000.
* </p>
*/
public void setMaximumExpansionSize(int theMaximumExpansionSize) {
Validate.isTrue(theMaximumExpansionSize > 0, "theMaximumExpansionSize must be > 0");
myMaximumExpansionSize = theMaximumExpansionSize;
}
/**
* Provides the maximum number of results which may be returned by a search (HTTP GET) which