Compare commits

...

87 Commits

Author SHA1 Message Date
peartree bdf831e803 Merge remote-tracking branch 'origin/master' into consent_service_resource_filtering_leads_to_empty_pages_with_next_link 2023-12-15 10:40:23 -05:00
James Agnew 7863f03c68
Fix postgres / Remove use of LOB content column (#5555)
* Work on fixing postgres

* Test fix

* wip

* wip

* wip

* wip

* wip

* adding support for h2 embedded and renaming postgressIT

* Work on postgres

* Remove use of gzip content on postgres

* Cleanup

* Test fixes

* Spotless

* Restore fake db for DDL generator

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-12-15 08:07:26 -05:00
James Agnew d187399ce5
LastUpdated search doesn't work with HFQL (#5510)
* LastUpdated search doesn't work with HFQL

* Spotless
2023-12-14 17:24:04 -05:00
Luke deGruchy c4ac940e14
Migration: Add new indexes to hfj_spidx_string and hfj_spidx_uri if collation is NOT 'C' (#5544)
* First commit for conditional logic in execute migration tasks along with logic to create new indexes on hfj_spidx_string and hfj_spidx_uri if sp_normalized_value or sp_uri, respectively, have a collation other than "C".

* More fixes.  Still TODOs to resolve.

* Add changelog.  Clean up TODOs.  New message code for precondition SQL checking.  javadoc.  Unit test enhancements.

* Spotless.  Small tweaks.  Fix conditional logic for more than one checking.

* Add details to upgrade document.

* Code review feedback.

* Spotless
2023-12-14 21:04:15 +00:00
Luke deGruchy 9f81fa334c
Fix bad doc links referring to .md instead of .html. (#5551)
* Fix bad doc links referring to .md instead of .html.

* Fix link path

* Fix link in changelog.
2023-12-14 19:13:26 +00:00
RBRi 592856c779
HtmlUnit excludes for xerxes/xml-api no longer required (#5545)
Since version 2.68 HtmlUnit does no longer uses xerces. You can cleanup the pom a bit here.
2023-12-13 13:15:52 -05:00
Tadgh 9e20659680
Add docs, upgrade guide, upgrade.md (#5543) 2023-12-12 23:08:00 +00:00
Martha Mitran 564ae46008
Fixes for validation lookupCode method and improve remote terminology tests (#5535)
* Fixes for validation lookupCode method:

(1) NullPointerException when processing designation in the remote terminology implementation
(2) Inconsistency between input and output type  vs.  for property parameter across the board
(3) Fix most of the warnings in the updated classes.
(4) Code review changes

* Fix unit test failure by reverting assertion to FOO_COLUMN.

* Revert commit.

* Update tests

* Update tests - move utility class back

* Update fix and tests

* spotless fix

* Missing branches for exception cases and add tests for the same

* Spotless fix

* fix tests

* fix test

* Address code review comments. Write the remote terminology tests in a way to make them more readable.

* Revert moving utility test class

* Small changes in tests

* Small changes

* fix checkstyle

* Minor changes in exception handling and add a missing test

* Address code review comments. Decouple other tests from lookupCode tests.

* Update declaration of constants

---------

Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>
2023-12-12 10:05:21 -05:00
James Agnew b28fe3b882
Jakarta Bump Part 2 (#5533)
* Make expunge service extensible

* Work

* Licence headers

* Version bump some dependencies

* Version bumps

* Adapt to new html unit version

* Reintroduce errorprone

* Test fix

* Header

* Work on jakarta

* Test fixes

* Restore errorprone

* More pom tweaks

* Apply spotless

* Errorprone tweak

* errorprone tweak

* Version bump

* License headers

* Version bump

* Postgres bump
2023-12-11 18:24:40 -05:00
TynerGjs d8298e38d4
Resovle 5505-remove-broken-member-match-from-hapi (#5517)
* - Removed IConsentExtensionProvider, MemberMatchR4ResourceProvider and MemberMatcherR4Helper, as well as corresponding usages and tests

* - Removed IMemberMatchConsentHook.java

* spotless reformat

* added changelog

* removed constants for $member-match parameters

* removed error message for $member-match

* completely removed MemberMatchR4ResourceProvider.java

* removed operation constant for $member-match

* version bump
2023-12-07 13:16:31 -05:00
volodymyr-korzh 4d0670b0ad
Empty, id-only content Payload types are not supported for Topic based Subscriptions (#5499)
* added support of Empty, id-only content Payload types for Topic based Subscriptions
2023-12-07 09:05:51 -07:00
Luke deGruchy 78a50f92bc
Replace all nullable/nonnull imports of javax.annotation with jakarta.annotation (#5540)
* Replace all nullable/nonnull imports of javax.annotation with jakarta.annotation.

* Fix checkstyle.  Update checkstyle version.
2023-12-07 09:16:48 -05:00
Chris0296 e9f15c61a8
Update Documentation Step for Batch Job being Cancelled. (#5518)
* Update Documentation Step for Batch Job being Cancelled.

* Fix changelog type
2023-12-06 17:02:54 -05:00
kateryna-mironova da9be29047
Fixed search for resources for $everything operation with partitions and MDM (#5504)
* Fixed search for resources for $everything operation with partitions and client id mode = ANY

* fixed formatting

* changelog file renamed for tests

* code review fixes: moved generics mocks to class fields, changed size > 0 to empty check

* removed unused fields

* moved fields back to methods, changed generic anys

* changed imports from javax to jakarta

* code review fixes
2023-12-06 16:26:52 -05:00
James Agnew 9027138962
Fix postgres startup failure (#5539)
* Fix postgres startup failure

* Spotless
2023-12-06 12:33:34 -05:00
Luke deGruchy 5fa20438b6
SQL Migration: Support lowercase for SQL columns and overridden column type/driver type SQL type string rules (#5534)
* 1. Allow callers to choose uppercase or lowercase column names.  Default uppercase.
2. Allow callers to pass custom sorting rules:  Default no special sorting.

* Spotless.

* Msg.code.

* Get rid of factory method and fix constructor.

* Maintain old constructor for backward compatibility.

* Fix JDK 11 compile error, spotless, and class header.

* Introduce a mechanism to override default SQL column mappings by column type and driver type.

* Add error message code.  Tweak column type algorithm.

* Replace javax.annotation with jakarta.annotation.

* Spotless.

* Fix unit test by restoring FOO_COLUMN assertion.

* Add changelog.

* Code review feedback.

* spotless

* Fix Msg.code().

* Add unit test.
2023-12-06 09:05:36 -05:00
Luke deGruchy f5cb674345
Update pre-commit from 0.3.3 to 0..3.4. (#5537)
* test branch.

* Upgrade pre-commit to 0.3.4.

* Reverse cosmetic change.
2023-12-06 00:52:53 +00:00
Tadgh 293cd3ef3c
Fix case sensitivity on package name lookup (#5524)
* 90% working test

* wip

* Modify test, changelog, add implementation

* Revert "90% working test"

This reverts commit 64a8f1d806.

* fix typo

* spotless
2023-12-05 17:43:00 +00:00
Luke deGruchy 4070b40fb1 Revert commit 2023-12-05 11:38:42 -05:00
Luke deGruchy a9db6c11a9 Test master commit hook 2023-12-05 11:37:26 -05:00
Luke deGruchy 80ca324e82 Revert commit. 2023-12-05 11:33:46 -05:00
Luke deGruchy 96fc596109 Fix unit test failure by reverting assertion to FOO_COLUMN. 2023-12-05 11:29:14 -05:00
Luke deGruchy 65f133186e Reverse commit. 2023-12-04 12:15:00 -05:00
Luke deGruchy 941ba21de3 See if I can push to master 2023-12-04 12:09:43 -05:00
Etienne Poirier fdeaf8384f
Request for exposing client id and username in batch job status api (#5526)
* initial tests and implementation of the feature persistence layer.

* initial tests and implementation pointcut to modify JobInstance before persistence.

* spotless happy.

* Addressing comments from first code review.

* happy spotless

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-12-04 11:44:48 -05:00
Luke deGruchy adb84da651 Reverse commit to master. 2023-12-04 09:11:42 -05:00
James Agnew 6d58df0f44
Jakarta/Javax Servlet Migration (#5429)
* Servlet migrsation changes

* Apply spotless

* Work on migration

* Start working on JPA migration

* Test fixes

* Test fixes

* Test fixes

* Work

* Work on servlet migration

* Work on migration

* Work on fixes

* Imports fix

* Work on tests

* Test fix

* All tests passing

* Work on migration

* Schema generator

* Refactor ID strategy

* Some test fixes

* Test fixes

* API additions

* Work on websockets

* Test fixe

* Version bump

* Work on migration

* All tests have passed!

* Work on test fixes

* Fixes

* Work on fixes

* CDR fix

* Work on migration

* Fixes

* Spotless

* Disable onetoone ban

* Adjust migratyions

* Transaction service fix

* Add tinyint to migrator

* Work

* Migration

* Compile fix

* Add license

* Test fix

* Test fix

* Cleanup

* Cleanup attempt

* Test fix

* Reslve fixmes

* Remove legacy lastn implementation

* Test cleanup

* Cleanup

* Remove dead import

* Bad import setups

* Review comments

* Review fixes

* Build fix

* Test fix

* Spotless

* Account for CR changes

* Compile fixes

* Rollback one change

* Test tweak

* License header

* Test fix

* Test fix part 2:

* Clean up tx isolation

* Spotless

* Spotless apply

* Drop min SQL Server level

* Attempted test fix

* Test fix

* Test fix

* Test fix

* Bump hibernate

* Test fix

* Test fixes

* Test fixes

* Test fixes

* Test cleanup

* One more test fix

* Test fix

* Try to fix test

* Clean up expunge

* Test fix

* Remove unneeded task

* Spotless

* Bump compiler plugin

* Spotless

* Compile fix

* Add license headers

* License header

* Test fixes

* Bump animal sniffer

* Spotless

* Bump Jetty version

* Test fix and version bump

* Cleanup

---------

Co-authored-by: Tadgh <garygrantgraham@gmail.com>
2023-12-03 11:15:37 -05:00
Luke deGruchy 113cf4002d First commit with very rough partial solution and test. 2023-12-01 17:00:05 -05:00
James Agnew d597cf2763
Allow chained searches in Bundles where the fullUrl is fully qualified (#5529)
* Allow chained searches in Bundles where the fullUrl is fully qualified

* Add changelog

* Spotless
2023-12-01 20:19:51 +00:00
Luke deGruchy ec5402abd4
Restore changes for 5502. (#5525)
* Restore changes for 5502.

* Spotless.
2023-12-01 15:16:56 +00:00
Luke deGruchy 59936ee70c
Revert 5502. (#5521) 2023-12-01 09:02:54 +00:00
Luke deGruchy 0c8258f93c Revert the revert 2023-11-30 18:54:49 -05:00
Luke deGruchy 8237c0795d test change 2023-11-30 18:23:13 -05:00
Luke deGruchy ee4ecacbdb Revert changes for 5502. 2023-11-30 18:10:05 -05:00
Michael Buckley fab00ca3a0
Expose the desired Propagation in a tx template (#5516) 2023-11-30 21:43:10 +00:00
Luke deGruchy 8fbbaef079
Add a new field to the CLIENT_RESPONSE pointcut in order to allow clients to mutate an HTTP response from the BaseClient. (#5488)
* Add a new field to the CLIENT_RESPONSE pointcut in order to allow clients to mutate an HTTP response from the BaseClient.

* Add FhirContext to ClientResponseContext.

* Introduce a ModifiedStringApacheHttpResponse.  Run spotless.

* Remove TDOOs, add and update javadoc.

* Spotless and copyright header.

* Add changelog.

* Unique error message code.

* Only trigger the interceptor if the expected return type is a Bundle.

* Fix spotless.

* Code review feedback.

* Spotless.

* Bump to 6.11.3-SNAPSHOT
2023-11-30 14:56:46 -05:00
Ken Stevens e15d0430d0
Oracle create index migration recovery (#5511) 2023-11-29 18:15:28 -05:00
James Agnew 469873aff7
Add migrator to uhnfhirtest (#5508)
* Add migrator to uhnfhirtest

* Fix spotless

* Test fix
2023-11-29 09:16:41 -05:00
TipzCM 6e683405a1
5237 fixing empty last page if even results (#5506)
paging will not return empty pages if no results left
2023-11-28 21:28:17 +00:00
Martha Mitran ee414b73d9
Pass properties through to Remote Terminology Service on CodeSystem lookup (#5477)
* Pass properties through to Remote Terminology Service on CodeSystem  operation

* Propagate list of property names throughout. Introduce a parameter object for the lookupCode method. Mark other lookupCode methods as deprecated. Add unit tests.

* Update remote terminology service tests

* Address code review comments

* Fix unit tests

* Address latest code review comments to update default methods

* Address latest code review comments to update default methods - update fallback condition

* Address latest code review comments to update default methods - update fallback condition
2023-11-28 16:12:05 -05:00
Taha 63eed3936b
(#5442) fetch should also resolve canonical URL references (#5443)
* (#5442) fetch should also resolve canonical URL references

* (#5442) - added test

* (#5442) - cleanup?

* (#5442) - changelog and reorganize test

* (#5442) PR feedback

* (#5442) PR feedback

* (#5442) cleared ValidatorResourceFetcher linter warnings

* (#5442) - new error code

* (#5442) caught additional error

* (#5442) spotless apply

* (#5442) spotless apply

---------

Co-authored-by: taha.attari@smilecdr.com <taha.attari@smilecdr.com>
2023-11-27 23:12:35 -05:00
Michael Buckley 83bfa817ae
Batch - ensure we target the default partition for non-gated jobs (#5496)
* Target the default partition for batch2 storage.
2023-11-27 17:32:58 -05:00
Etienne Poirier 4cc4682245
CLI tool command migrate-database executing in dry-run mode insert entries into table FLY_HFJ_MIGRATION (#5487)
* initial test

* Solution with changelog.

* making spotless hapi

* addressing comments from code reviews

* making the test better.

* addressing code review comment and adding test.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-11-24 20:55:03 +00:00
dotasek f39dbb5751
Bump setup-java action to v3 (#5491) 2023-11-24 14:06:18 -05:00
TynerGjs d546ce34e5
Resolve 5483-update-consent-storage-to-latest-spec (#5484)
* removed the adding of memberIdentifier to the consent

* - fixed corresponding test
- added changelog
2023-11-24 13:40:13 -05:00
TynerGjs 9f827a75c7
Resolve 5480 Update member-match signature to match the spec (#5481)
* - Changed member-match function param names, and return value
- modified existing tests to accomodate for the change

* removed tests unsuitable for new return value

* resolve code review comments

* version bump
2023-11-24 09:49:33 -05:00
jmarchionatto a1aa9c4a36
Issue 5081 support mdm on version r5 (#5099)
* Create SubscriptionTopic before creating Subscription for MDM loader when on R5

* Remove unused properties

* MdmSubscriptionLoader changes to support R5 in MDM - added SubscriptionTopic queryCriteria (draft)

* MDM not supported for R5 - implementation

* MDM not supported for R5 - implementation

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fix

* MDM not supported for R5 - implementation fixes, changelog

* MDM not supported for R5 - fixes

* MDM not supported for R5 - fixes

* MDM not supported for R5 - fixes

* MDM not supported for R5 - fix

---------

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
Co-authored-by: volodymyr <volodymyr.korzh@smilecdr.com>
2023-11-23 12:22:05 -05:00
Tadgh f624cf75ad
Rel 6 10 mb (#5474)
* Allow cached search with consent active when safe (#5387)

Allow the search cache when using consent if safe

* Change package installation behaviour such that it updates the existing SearchParameter base with remaining resources (#5376)

* Change package installation behavior such that it updates the existing SearchParameter base with remaining resources

* Change package installation behavior such that it updates the existing SearchParameter base with remaining resources

* Use resourceType in the package installer output to fix tests. Minor change with resourceType condition. Update changelog description to make it more readable.

* Use resourceType in the package installer output to fix tests. Minor change with resourceType condition. Update changelog description to make it more readable.

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning (#5389)

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning - Implementation

* Reverse Chaining searches returns an error when invoked with parameter _lastUpdated. (#5177)

* version bump

* Bump to core release 6.0.22 (#5028)

* Bump to core release 6.0.16

* Bump to core version 6.0.20

* Fix errors thrown as a result of VersionSpecificWorkerContextWrapper

* Bump to core 6.0.22

* Resolve 5126 hfj res ver prov might cause migration error on db that automatically indexes the primary key (#5127)

* dropped old index FK_RESVERPROV_RES_PID on RES_PID column before adding IDX_RESVERPROV_RES_PID

* added changelog

* changed to valid version number

* changed to valid version number, need to be ordered by version number...

* 5123 - Use DEFAULT partition for server-based requests if none specified (#5124)

5123 - Use DEFAULT partition for server-based requests if none specified

* consent remove all suppresses next link in bundle (#5119)

* added FIXME with source of issue

* added FIXME with root cause

* added FIXME with root cause

* Providing solution to the issue and removing fixmes.

* Providing changelog

* auto-formatting.

* Adding new test.

* Adding a new test for standard paging

* let's try this and see if it works...?

* fix tests

* cleanup to trigger a new run

* fixing tests

---------

Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* 5117 MDM Score for No Match Fields Should Not Be Included in Total Score  (#5118)

* fix, test, changelog

* fix, test, changelog

---------

Co-authored-by: justindar <justin.dar@smilecdr.com>

* _source search parameter needs to support modifiers (#5095)

_source search parameter needs to support modifiers - added support form :contains, :missing, :above modifiers

* Fix HFQL docs (#5151)

* Expunge operation on codesystem may throw 500 internal error with precondition fail message. (#5156)

* Initial failing test.

* Solution with changelog.

* fixing format.

* Addressing comment from code review.

* fixing failing test.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* documentation update (#5154)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* Fix hsql jdbc driver deps (#5168)

Avoid non-included classes in jdbc driver dependencies.

* $delete-expunge over 10k resources will now delete all resources (#5144)

* First commit with very rough fix and unit test.

* Refinements to ResourceIdListStep and Batch2DaoSvcImpl.  Make LoadIdsStepTest pass.   Enhance Batch2DaoSvcImplTest.

* Spotless

* Fix checkstyle errors.

* Fix test failures.

* Minor refactoring.  New unit test.  Finalize changelist.

* Spotless fix.

* Delete now useless code from unit test.

* Delete more useless code.

* Test pre-commit hook

* More spotless fixes.

* Address most code review feedback.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Fix the noUrl case by passing an unlimited Pegeable instead.  Effectively stop using page size for most databases.

* Deprecate the old method and have it call the new one by default.

* updating documentation (#5170)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* _source search parameter modifiers for Subscription matching (#5159)

* _source search parameter modifiers for Subscription matching - test, implementation and changelog

* first fix

* tests and preliminary fixes

* wip, commit before switching to release branch.

* adding capability to handle _lastUpdated in reverse search (_has)

* adding changelog

* applying spotless.

* addressing code review comments.

---------

Co-authored-by: tadgh <garygrantgraham@gmail.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com>
Co-authored-by: TipzCM <leif.stawnyczy@gmail.com>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>

* Br 20231019 add cr settings for cds hooks (#5394)

* Add settings used in CR CDS Services.  Remove config dependency on Spring Boot.

* Add changelog

* Use String.format rather than concat strings

* spotless apply

* Add javadoc

* Upgrade notes for the forced-id change (#5400)

Add upgrade notes for forced-id

* Clean stale search results more aggressively. (#5396)

Use bulk DMA statements when cleaning the search cache.
The cleaner job now works as long as possible until a deadline based on the scheduling frequency.

* bump version of clinical reasoning (#5406)

* Transaction fails if SearchNarrowingInterceptor is registered and Partitioning Enabled - fix cross-tenant requests failure (#5408)

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning - fix and tests added

* removed unused alias from SQL query of mdm-clear (#5416)

* Issue 5418 support Boolean class return type in BaseInterceptorService (#5421)

* Enable child classes to use Boolean class return type

* spotless

---------

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>

* If AutoInflateBinaries is enabled, binaries are created on the disk only for the first resource entry of the bundle (#5420)

* If AutoInflateBinaries is enabled, binaries created on disk by bundled requests are created only for the first resource entry - fix

* Revert "Issue 5418 support Boolean class return type in BaseInterceptorService (#5421)" (#5423)

This reverts commit 4e295a59fb.

Co-authored-by: Nathan Doef <nathaniel.doef@smilecdr.com>

* Use new FHIR_ID column for sorting (#5405)

* Sort `_id` using new FHIR_ID column.
* Fix old tests that put client-assigned ids first.

* Better indexing for sort

* Bump core to 6.1.2.2 (#5425)

* Bump core to 6.1.2.1

Patch release that uses https for primary org.hl7.fhir.core package server

* Bump core to 6.1.2.2

* Make sure to return always a value for Boolean class return type. (#5424)

Implement change in a non-disruptive way for overriders

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>

* Add non-standard __pid SP for breaking ties cheaply during sorts. (#5428)

Add a non-standard __pid SP.

* Review changes for new _pid SP. (#5430)

Change name to _pid to match our standard and add warning.

* Fix VersionCanonicalizer conversion from R5 into DSTU2 for CapabilityStatement, Parameters and StructuredDefinition (#5432)

* Fix VersionCanonicalizer conversion from R5 into DSTU2 for CapabilityStatement, Parameters and StructuredDefinition.

* Fix spotless issue

* CVEs for 6.10.0 (#5433)

* Bump jetty

* Bump okio-jvm

* 8.2.0 mysql connector

* Jena and elastic bumps

* Fix test

* 5412 post bundle on partition incorrect response.link shown (#5413)

* Initial fix and unit test provided

* spottless check

* Made relevant changes to make solution version agnostic

* relevant logic changes made

* spotless changes made

* New logic added to fix failing test cases

* formatting

* New logic to make the function more robust

* spotless checks

* Left a trailing slash in the tests

* Made relevant test changes and changed logic

* spotless changes

* Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5412-during-partition-fullUrl-not-shown-in-response.yaml

changing changelog

Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>

* Formatting requirements

---------

Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>

* Resolve We don't have guaranteed subscription delivery if a resource is too large (#5414)

* first fix

* - added the ability to handle null payload to SubscriptionDeliveringMessageSubscriber and SubscriptionDeliveringEmailSubscriber
- refactored code to reduce repeated code
- cleaned unnecessary comments and reformatted files

* Changed myResourceModifiedMessagePersistenceSvc to be autowired

* removed unused import

* added error handling when inflating the message to email and message subscriber

* reformatted code

* Fixing subscription tests with mocked IResourceModifiedMessagePersistenceSvc

* Changes by gary

* Reformatted file

* fixed failed tests

* implemented test for message and email delivery subscriber. Fixed logical error. Reformatted File.

* - implemented IT
- fixed logical error
- added changelog

* fix for cdr tests, NOTE: this makes the assumption that we will always succeed for inflating the database in the tests that uses SynchronousSubscriptionMatcherInterceptor

* fix for cdr tests, NOTE: this makes the assumption that we will always succeed for inflating the database in the tests that uses SynchronousSubscriptionMatcherInterceptor

* resolve code review comments

* reformatted files

* fixed tests

* Fix for failing IT test in jpaserver-starter (#5435)

Co-authored-by: dotasek <dotasek.dev@gmail.com>

* wip

* Bump jackson databind

* Pin Version

* Ignored duplicate classes

* Updating version to: 6.10.1 post release.

* Fix pom

* Skip remorte nexus

* make release faster

* Updating version to: 6.10.1 post release.

* remove skiptests

---------

Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
Co-authored-by: Martha Mitran <martha.mitran@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: TynerGjs <132295567+TynerGjs@users.noreply.github.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com>
Co-authored-by: TipzCM <leif.stawnyczy@gmail.com>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>
Co-authored-by: Brenin Rhodes <brenin@alphora.com>
Co-authored-by: Justin McKelvy <60718638+Capt-Mac@users.noreply.github.com>
Co-authored-by: jmarchionatto <60409882+jmarchionatto@users.noreply.github.com>
Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
Co-authored-by: Nathan Doef <nathaniel.doef@smilecdr.com>
Co-authored-by: LalithE <132382565+LalithE@users.noreply.github.com>
Co-authored-by: dotasek <dotasek.dev@gmail.com>
Co-authored-by: markiantorno <markiantorno@gmail.com>
2023-11-22 16:01:31 -08:00
Martha Mitran f1adacf827
Add package installer property resource filter on status (#5470)
* Expanding a ValueSet using hierarchical CodeSystem would fail in different scenarios with a constraint violation exception when codes (term concepts) were being persisted

* Expanding a ValueSet using hierarchical CodeSystem would fail in different scenarios with a constraint violation exception when codes (term concepts) were being persisted

* Small changes after code review. Doing some variable/method renaming and correcting changelog Jira issue number.

* There is a programmatic filter enabled which skips installation for certain resources based on their status
in PackageInstallerSvcImpl. The filter can now be controlled via StorageSettings.

* Fix typo in variable name from recent pull request 5461.
2023-11-22 16:18:03 -05:00
Justin McKelvy 86ea069437
feature swap to non javax clinical reasoning (#5463)
* Update to a version of Clinical Reasoning/CQL that no longer includes javax dependencies

* Rev to CR 3.0.0-PRE10

* version bump, pom changes for jakarta conflicts

* undo exclusions from other modules

* Rework exclusions

* Fix type in dependency

* new cr version, exclude conflicts in cr and cds-hooks

* remove exclusions

* pom update

* Redo the exclusions

* add retrieveSettings config

* new CR retrieve settings and config

* update config to new enums and parameters

* update unit tests and config for new cql and terminology properties

* bump CR to 3.0.0-PRE12

* spotless edits, update class path for CR config

* missing dependencies

* swap for jakarta

* moving conflicting dependencies

* Fix a couple code review items

---------

Co-authored-by: Jonathan Percival <jonathan.i.percival@gmail.com>
2023-11-22 10:30:51 -05:00
Michael Buckley 9aa173a981
Target the default partition for batch2 storage. (#5475) 2023-11-22 00:12:38 +00:00
James Agnew f519f17fc5
Remove mandatory caffeine dependency (#5472)
* Remove mandatory caffeine dependency

* Add changelog

* Test fix
2023-11-21 09:36:06 -08:00
Ken Stevens d5a1b0cdf3
fix terserutil clear (#5473)
* fix test

* review
2023-11-21 16:39:18 +00:00
Michael Buckley 6abfed603e
Use streams to avoid multiple queries during batch job id chunking. (#5444)
Use stream for chunking instead of repeated sorted query pages.
2023-11-20 22:39:36 +00:00
Martha Mitran 6f84d17b13
Expanding ValueSet using hierarchical CodeSystem fails with constraint violation exception (#5461)
* Expanding a ValueSet using hierarchical CodeSystem would fail in different scenarios with a constraint violation exception when codes (term concepts) were being persisted

* Expanding a ValueSet using hierarchical CodeSystem would fail in different scenarios with a constraint violation exception when codes (term concepts) were being persisted

* Small changes after code review. Doing some variable/method renaming and correcting changelog Jira issue number.
2023-11-20 13:23:37 -05:00
Etienne Poirier 2e4f8fe4b6
fixing formatting. (#5458)
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-11-16 19:42:47 +00:00
michaelabuckley 7efea956ee
Document the hfj_spidx_* tables. (#5456) 2023-11-16 17:06:20 +00:00
Etienne Poirier 1412873cac
Providing parameter '_total' when searching may lead to paging issues. (#5455)
* Initial failing test.

* Initial failing test.

* fix and changelog.

* applying spotless check.

* small code refactoring.

* test refactoring

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-11-16 07:18:35 -05:00
TynerGjs 41d9abf6ac
Resolve 5452-mdm-query-link-returns-scientific-notation-in-linkcreated-and-linkupdated (#5453)
* set the scale to 0 when transforming double to BigDecimal

* - set negative scale to 0 when transforming double to BigDecimal
- added test
2023-11-14 13:53:49 -08:00
Aditya Dave 9dace159b4
5426 enhance bundleutil (#5451)
* failing test

* fix and more tests

* cleanup

* spotless

* remove class paths

* add changelog

---------

Co-authored-by: aditya_dave <aditya@smilecdr.com>
2023-11-13 19:50:11 +00:00
Tadgh 777859ad00
Rel 6 10 mb (#5441)
* Allow cached search with consent active when safe (#5387)

Allow the search cache when using consent if safe

* Change package installation behaviour such that it updates the existing SearchParameter base with remaining resources (#5376)

* Change package installation behavior such that it updates the existing SearchParameter base with remaining resources

* Change package installation behavior such that it updates the existing SearchParameter base with remaining resources

* Use resourceType in the package installer output to fix tests. Minor change with resourceType condition. Update changelog description to make it more readable.

* Use resourceType in the package installer output to fix tests. Minor change with resourceType condition. Update changelog description to make it more readable.

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning (#5389)

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning - Implementation

* Reverse Chaining searches returns an error when invoked with parameter _lastUpdated. (#5177)

* version bump

* Bump to core release 6.0.22 (#5028)

* Bump to core release 6.0.16

* Bump to core version 6.0.20

* Fix errors thrown as a result of VersionSpecificWorkerContextWrapper

* Bump to core 6.0.22

* Resolve 5126 hfj res ver prov might cause migration error on db that automatically indexes the primary key (#5127)

* dropped old index FK_RESVERPROV_RES_PID on RES_PID column before adding IDX_RESVERPROV_RES_PID

* added changelog

* changed to valid version number

* changed to valid version number, need to be ordered by version number...

* 5123 - Use DEFAULT partition for server-based requests if none specified (#5124)

5123 - Use DEFAULT partition for server-based requests if none specified

* consent remove all suppresses next link in bundle (#5119)

* added FIXME with source of issue

* added FIXME with root cause

* added FIXME with root cause

* Providing solution to the issue and removing fixmes.

* Providing changelog

* auto-formatting.

* Adding new test.

* Adding a new test for standard paging

* let's try this and see if it works...?

* fix tests

* cleanup to trigger a new run

* fixing tests

---------

Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* 5117 MDM Score for No Match Fields Should Not Be Included in Total Score  (#5118)

* fix, test, changelog

* fix, test, changelog

---------

Co-authored-by: justindar <justin.dar@smilecdr.com>

* _source search parameter needs to support modifiers (#5095)

_source search parameter needs to support modifiers - added support form :contains, :missing, :above modifiers

* Fix HFQL docs (#5151)

* Expunge operation on codesystem may throw 500 internal error with precondition fail message. (#5156)

* Initial failing test.

* Solution with changelog.

* fixing format.

* Addressing comment from code review.

* fixing failing test.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* documentation update (#5154)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* Fix hsql jdbc driver deps (#5168)

Avoid non-included classes in jdbc driver dependencies.

* $delete-expunge over 10k resources will now delete all resources (#5144)

* First commit with very rough fix and unit test.

* Refinements to ResourceIdListStep and Batch2DaoSvcImpl.  Make LoadIdsStepTest pass.   Enhance Batch2DaoSvcImplTest.

* Spotless

* Fix checkstyle errors.

* Fix test failures.

* Minor refactoring.  New unit test.  Finalize changelist.

* Spotless fix.

* Delete now useless code from unit test.

* Delete more useless code.

* Test pre-commit hook

* More spotless fixes.

* Address most code review feedback.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Fix the noUrl case by passing an unlimited Pegeable instead.  Effectively stop using page size for most databases.

* Deprecate the old method and have it call the new one by default.

* updating documentation (#5170)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* _source search parameter modifiers for Subscription matching (#5159)

* _source search parameter modifiers for Subscription matching - test, implementation and changelog

* first fix

* tests and preliminary fixes

* wip, commit before switching to release branch.

* adding capability to handle _lastUpdated in reverse search (_has)

* adding changelog

* applying spotless.

* addressing code review comments.

---------

Co-authored-by: tadgh <garygrantgraham@gmail.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com>
Co-authored-by: TipzCM <leif.stawnyczy@gmail.com>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>

* Br 20231019 add cr settings for cds hooks (#5394)

* Add settings used in CR CDS Services.  Remove config dependency on Spring Boot.

* Add changelog

* Use String.format rather than concat strings

* spotless apply

* Add javadoc

* Upgrade notes for the forced-id change (#5400)

Add upgrade notes for forced-id

* Clean stale search results more aggressively. (#5396)

Use bulk DMA statements when cleaning the search cache.
The cleaner job now works as long as possible until a deadline based on the scheduling frequency.

* bump version of clinical reasoning (#5406)

* Transaction fails if SearchNarrowingInterceptor is registered and Partitioning Enabled - fix cross-tenant requests failure (#5408)

* Transaction with conditional update fails if SearchNarrowingInterceptor is registered and Enabled Partitioning - fix and tests added

* removed unused alias from SQL query of mdm-clear (#5416)

* Issue 5418 support Boolean class return type in BaseInterceptorService (#5421)

* Enable child classes to use Boolean class return type

* spotless

---------

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>

* If AutoInflateBinaries is enabled, binaries are created on the disk only for the first resource entry of the bundle (#5420)

* If AutoInflateBinaries is enabled, binaries created on disk by bundled requests are created only for the first resource entry - fix

* Revert "Issue 5418 support Boolean class return type in BaseInterceptorService (#5421)" (#5423)

This reverts commit 4e295a59fb.

Co-authored-by: Nathan Doef <nathaniel.doef@smilecdr.com>

* Use new FHIR_ID column for sorting (#5405)

* Sort `_id` using new FHIR_ID column.
* Fix old tests that put client-assigned ids first.

* Better indexing for sort

* Bump core to 6.1.2.2 (#5425)

* Bump core to 6.1.2.1

Patch release that uses https for primary org.hl7.fhir.core package server

* Bump core to 6.1.2.2

* Make sure to return always a value for Boolean class return type. (#5424)

Implement change in a non-disruptive way for overriders

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>

* Add non-standard __pid SP for breaking ties cheaply during sorts. (#5428)

Add a non-standard __pid SP.

* Review changes for new _pid SP. (#5430)

Change name to _pid to match our standard and add warning.

* Fix VersionCanonicalizer conversion from R5 into DSTU2 for CapabilityStatement, Parameters and StructuredDefinition (#5432)

* Fix VersionCanonicalizer conversion from R5 into DSTU2 for CapabilityStatement, Parameters and StructuredDefinition.

* Fix spotless issue

* CVEs for 6.10.0 (#5433)

* Bump jetty

* Bump okio-jvm

* 8.2.0 mysql connector

* Jena and elastic bumps

* Fix test

* 5412 post bundle on partition incorrect response.link shown (#5413)

* Initial fix and unit test provided

* spottless check

* Made relevant changes to make solution version agnostic

* relevant logic changes made

* spotless changes made

* New logic added to fix failing test cases

* formatting

* New logic to make the function more robust

* spotless checks

* Left a trailing slash in the tests

* Made relevant test changes and changed logic

* spotless changes

* Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5412-during-partition-fullUrl-not-shown-in-response.yaml

changing changelog

Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>

* Formatting requirements

---------

Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>

* Resolve We don't have guaranteed subscription delivery if a resource is too large (#5414)

* first fix

* - added the ability to handle null payload to SubscriptionDeliveringMessageSubscriber and SubscriptionDeliveringEmailSubscriber
- refactored code to reduce repeated code
- cleaned unnecessary comments and reformatted files

* Changed myResourceModifiedMessagePersistenceSvc to be autowired

* removed unused import

* added error handling when inflating the message to email and message subscriber

* reformatted code

* Fixing subscription tests with mocked IResourceModifiedMessagePersistenceSvc

* Changes by gary

* Reformatted file

* fixed failed tests

* implemented test for message and email delivery subscriber. Fixed logical error. Reformatted File.

* - implemented IT
- fixed logical error
- added changelog

* fix for cdr tests, NOTE: this makes the assumption that we will always succeed for inflating the database in the tests that uses SynchronousSubscriptionMatcherInterceptor

* fix for cdr tests, NOTE: this makes the assumption that we will always succeed for inflating the database in the tests that uses SynchronousSubscriptionMatcherInterceptor

* resolve code review comments

* reformatted files

* fixed tests

* Fix for failing IT test in jpaserver-starter (#5435)

Co-authored-by: dotasek <dotasek.dev@gmail.com>

* wip

---------

Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
Co-authored-by: Martha Mitran <martha.mitran@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: TynerGjs <132295567+TynerGjs@users.noreply.github.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com>
Co-authored-by: TipzCM <leif.stawnyczy@gmail.com>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>
Co-authored-by: Brenin Rhodes <brenin@alphora.com>
Co-authored-by: Justin McKelvy <60718638+Capt-Mac@users.noreply.github.com>
Co-authored-by: jmarchionatto <60409882+jmarchionatto@users.noreply.github.com>
Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
Co-authored-by: Nathan Doef <nathaniel.doef@smilecdr.com>
Co-authored-by: LalithE <132382565+LalithE@users.noreply.github.com>
Co-authored-by: dotasek <dotasek.dev@gmail.com>
2023-11-10 14:00:08 -08:00
Ken Stevens 3bba9fb1f2
add terminology troubleshooting log (#5439)
* init rev

* init rev

* changelog and additional logging

* changelog and additional logging

* changelog and additional logging

* spotless

* review feedback
2023-11-10 19:54:51 +00:00
TynerGjs 8a39da4e91
- Added logs when MDM candidate search parameters are not defined and candidate search limit is exceeded. (#5446)
- fixed extra indentation for example survivorship rule in quickstart.md
2023-11-10 10:51:26 -08:00
jmarchionatto c89fc46863
Add ITermConceptClientMappingSvc interface to represent terminology t… (#5410)
* Add ITermConceptClientMappingSvc interface to represent terminology translate functions

* Add javadoc

---------

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
2023-10-31 13:21:35 -04:00
Ken Stevens a7a446903f
5401 add terserutil clear by fhirpath (#5402)
* begin with failing test

* test passes

* test passes

* changelog

* moar testor
2023-10-26 03:35:20 +00:00
longma1 84e3becf1c
6 8 5 mb (#5399)
* version bump

* Bump to core release 6.0.22 (#5028)

* Bump to core release 6.0.16

* Bump to core version 6.0.20

* Fix errors thrown as a result of VersionSpecificWorkerContextWrapper

* Bump to core 6.0.22

* Resolve 5126 hfj res ver prov might cause migration error on db that automatically indexes the primary key (#5127)

* dropped old index FK_RESVERPROV_RES_PID on RES_PID column before adding IDX_RESVERPROV_RES_PID

* added changelog

* changed to valid version number

* changed to valid version number, need to be ordered by version number...

* 5123 - Use DEFAULT partition for server-based requests if none specified (#5124)

5123 - Use DEFAULT partition for server-based requests if none specified

* consent remove all suppresses next link in bundle (#5119)

* added FIXME with source of issue

* added FIXME with root cause

* added FIXME with root cause

* Providing solution to the issue and removing fixmes.

* Providing changelog

* auto-formatting.

* Adding new test.

* Adding a new test for standard paging

* let's try this and see if it works...?

* fix tests

* cleanup to trigger a new run

* fixing tests

---------

Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* 5117 MDM Score for No Match Fields Should Not Be Included in Total Score  (#5118)

* fix, test, changelog

* fix, test, changelog

---------

Co-authored-by: justindar <justin.dar@smilecdr.com>

* _source search parameter needs to support modifiers (#5095)

_source search parameter needs to support modifiers - added support form :contains, :missing, :above modifiers

* Fix HFQL docs (#5151)

* Expunge operation on codesystem may throw 500 internal error with precondition fail message. (#5156)

* Initial failing test.

* Solution with changelog.

* fixing format.

* Addressing comment from code review.

* fixing failing test.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* documentation update (#5154)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* Fix hsql jdbc driver deps (#5168)

Avoid non-included classes in jdbc driver dependencies.

* $delete-expunge over 10k resources will now delete all resources (#5144)

* First commit with very rough fix and unit test.

* Refinements to ResourceIdListStep and Batch2DaoSvcImpl.  Make LoadIdsStepTest pass.   Enhance Batch2DaoSvcImplTest.

* Spotless

* Fix checkstyle errors.

* Fix test failures.

* Minor refactoring.  New unit test.  Finalize changelist.

* Spotless fix.

* Delete now useless code from unit test.

* Delete more useless code.

* Test pre-commit hook

* More spotless fixes.

* Address most code review feedback.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Remove use of pageSize parameter and see if this breaks the pipeline.

* Fix the noUrl case by passing an unlimited Pegeable instead.  Effectively stop using page size for most databases.

* Deprecate the old method and have it call the new one by default.

* updating documentation (#5170)

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>

* _source search parameter modifiers for Subscription matching (#5159)

* _source search parameter modifiers for Subscription matching - test, implementation and changelog

* Removal of meta tags during updates do not trigger subscription (#5181)

* Initial failing test.

* adding solution;
fixing documentation;

* spotless apply

* adding changelog

* modifying current test

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* Issue 5173 get gateway everything doesnt return all patients (#5174)

* Failing test

* Also set offset and count in base DAO override

* Changelog

* Fix for specific case where count has been set in parameters

* spotless

* Improve checks

---------

Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>

* Do not 500 and continue IG ingestion when different IGs try to save different ValueSets with colliding FHIR IDs (#5175)

* First commit with failing unit test and small tweaks.

* Swallow resource version exceptions from colliding ValueSet OIDs and log a descriptive error instead.  Add more detailed unit testing.

* Tweaks to logic and update the changelog.  Reverse all changes to TermReadSvcImpl.

* Revert PackageResourceParsingSvc to release branch baseline.

* Accept code reviewer suggestion to change changelog description.

Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>

---------

Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>

* Fix link

* Remove target slf4j version

* dont use new API for a bit (#5191)

* Return DropIdGeneratorTask from the Builder to permit clients to mutate the (#5193)

DropIdGeneratorTask.

* Dqm performance bug update and provider loader fix (#5180)

* update tests, move properties, update operation loader

* update wip

* remove test

* fixing tests, adding config

* update config and provider loader

* fix bundles

* fix cache settings on tests

* version bump and change log

* version bump

* fix formatting

* CVE-2022-45868

* wip cve change

* cve h2 add back in

---------

Co-authored-by: justin.mckelvy <justin.mckelvy@smilecdr.com>

* bulkExportReuse with POST and GET (#5161)

* string manipulation

* Code to ensure bulkExportReuse works with POST and GET requests

* Added formatting changes

* Fixed tests that were not working

* Formatting

* Code clean up

* fixing test failures

* fixing test failures

* Removed arrOfParams to now utilize ObjectMapper

* Removing stack trace and adding an exception

* Fixed test issue

* formatting

* formatting

* Resolving code review comments

* Reduce size of subscription max results (#5194)

* Reduce MAX_SUBSCRIPTION_RESULTS to 10000

* Add changelog

* 5037 goldenresource remains when target resource deleted (#5038)

* draft test and fix

* remove unused fields

* remove unused fields

* remove unused fields

* draft test + solution for possible match case

* combine sql statement + more error checking

* add test case for possible duplicate

* add config for autodeleting grs

* refactoring, adding support for mongo, docs

* refactoring + fixing mongo queries

* add changelogs

* fix both way link removal

* clean up test comments

* rename method

* remove unnecessary bean

* merge master/resolve conflicts

* mvn spotless

* address comment

* changes to avoid version bumping

* spotless

* change error code

---------

Co-authored-by: justindar <justin.dar@smilecdr.com>

* dont use new API for a bit (#5190)

* licenses

* Fixing terminology upload with large file. (#5204)

* create initial test

* adding fix;
adding changelog;

* fixing format.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* up version to 6.8.0 from snapshot

* fix up some duplicate deps for skipping

* Force deployment of other projects

* make dummy java class to pass sonatype checks

* make dummy java class to pass sonatype checks

* Cheeky test removal

* Another test removal

* Updating version to: 6.8.1 post release.

* adding back in tests for release pipelines

* Fix bad version insert

* Bump to core library version 6.0.22.2 (#5261)

* Bump to core library version 6.0.22.2

* Bump HAPI to 6.8.1-SNAPSHOT, core library version to 6.0.22.2

* up version to 6.8.1

* Prevent remote deployment

* Updating version to: 6.8.2 post release.

* Re-add deploy plugin skip

* re-add version

* Bump core library version to 6.0.22.2

* Bump HAPI to 6.8.2-SNAPSHOT

* Fix up version enum

* Version bump

* Updating version to: 6.8.3 post release.

* Make display name validation configurable (#5321)

* Test fixes

* Build cleanup

* Initial test passing

* Test fixes

* Tests all seem to be working

* Make display validation level configurable

* Should be all working

* Add changelog

* Add to changelog

---------

Co-authored-by: Tadgh <garygrantgraham@gmail.com>

* wip

* wip

* Fix conflicts

* add backport info

* Fix versioning

* test fixes

* disabled 1 test

* backported 5271 to fix validation message tests

* wip

* Changelog

* Fix tests

* Fix backport

* Add upgrade.md

* Fix test

* Fix key

* Updating version to: 6.8.4 post release.

* 5353 iterate on revincludes and includes does not return correct resources when used with non iterate revincludes (#5354)

* added failing test

* implemented solution

* added doc generation

* added changelog

* fixed the order of includes and revincludes, based on what was implemented before

* fixed formatting

* fixed wording

---------

Co-authored-by: Steven Li <steven@smilecdr.com>

* added changelog

* Updating version to: 6.8.5 post release.

* merge back 5377

* changelog

* undo unintended changes from mergeback

---------

Co-authored-by: tadgh <garygrantgraham@gmail.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: TynerGjs <132295567+TynerGjs@users.noreply.github.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Etienne Poirier <33007955+epeartree@users.noreply.github.com>
Co-authored-by: TipzCM <leif.stawnyczy@gmail.com>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
Co-authored-by: michaelabuckley <michaelabuckley@gmail.com>
Co-authored-by: Luke deGruchy <luke.degruchy@smilecdr.com>
Co-authored-by: jmarchionatto <60409882+jmarchionatto@users.noreply.github.com>
Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
Co-authored-by: Justin McKelvy <60718638+Capt-Mac@users.noreply.github.com>
Co-authored-by: justin.mckelvy <justin.mckelvy@smilecdr.com>
Co-authored-by: LalithE <132382565+LalithE@users.noreply.github.com>
Co-authored-by: Long Ma <long@smilecdr.com>
Co-authored-by: markiantorno <markiantorno@gmail.com>
Co-authored-by: volodymyr <volodymyr.korzh@smilecdr.com>
Co-authored-by: James Agnew <jamesagnew@gmail.com>
Co-authored-by: StevenXLi <stevenli_8118@hotmail.com>
Co-authored-by: Steven Li <steven@smilecdr.com>
2023-10-25 11:40:17 -06:00
Tadgh 1776a8a395
Bump version (#5386) 2023-10-21 09:35:21 -07:00
michaelabuckley 953f73529a
Review changes for #4803 (#5381)
review changes
2023-10-20 17:26:24 +00:00
michaelabuckley ee369269f8
Move forced-id to HFJ_RESOURCE - step 2 (#4803)
* First cut at forced-id step 2

Start using new fhir_id column in hfj_resource instead.

* demote fixme for build

* Start changelog

* Merge cleanups

* forced-id migration

various fixme cleanups

* checkstyle

* fix bad conversions to computeIfAbsent

* Ugh.  Lame checkstyle.

* Revert optimistic null assert

* missed import.

* Fixup broken tests

* Fix invalid test

* Add missing index annotation
2023-10-20 12:14:31 -04:00
TipzCM af1d46fb04
adding additional logging to resource modified submitter svc (#5370)
* adding additional logging to resource modified submitter svc

* s[otlestt

* review fixes

* spotless

* fixing test

---------

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-mbp.home>
2023-10-20 09:56:32 -04:00
James Agnew 20c8109a32
Speed up subscription triggering (#5377)
* Improve subscription trigger speed

* Speed up subscription triggering

* Add changelogf

* Spotless

* Move changelog
2023-10-20 10:51:35 +00:00
michaelabuckley e2ca967fd9
Force _summary=false when fetching CodeSystems and ValueSets with remote terminology (#5372)
Force _summary=false when fetching CodeSystems and ValueSets with remote terminology
2023-10-19 09:18:01 -04:00
Tadgh 25ce7d0b8f fix broken version 2023-10-16 12:16:58 -07:00
Tadgh 90bfe05b9d
Fix version enum (#5352)
* Fix version enum

* Add license
2023-10-16 08:19:16 -04:00
Justin McKelvy c832cf0507
Hapi cr codecache (#5360)
* WIP code cache config

* WIP test

* Passing unit test

* cachelistener IT

* hardening cache listener tests

* cache listener fixes & tests, measureService migration, add reporter parameter to r4

* fix ELMCache listener to match on version, update test, remove reporter parameter

* edit inline notes

* changelog, version bump, spotless apply

---------

Co-authored-by: Jonathan Percival <jonathan.i.percival@gmail.com>
2023-10-11 11:47:52 -07:00
James Agnew 88e9780004
Add additional resource docs to generated OpenAPI documentation (#5359)
* Add additional resource docs to generated OpenAPI documentation

* Test fix
2023-10-11 00:36:33 +00:00
c-schuler 424f26b897
Removed helperSvc bean override from JpaConfig (#5350)
* Removed helperSvc bean override from JpaConfig

* Added change log entry
2023-10-10 11:13:21 -04:00
TynerGjs 02f25a9063
typo fix (#5358) 2023-10-06 20:30:44 +00:00
StevenXLi 12519bde9f
5353 iterate on revincludes and includes does not return correct resources when used with non iterate revincludes (#5354)
* added failing test

* implemented solution

* added doc generation

* added changelog

* fixed the order of includes and revincludes, based on what was implemented before

* fixed formatting

* fixed wording

---------

Co-authored-by: Steven Li <steven@smilecdr.com>
2023-10-06 11:54:26 -04:00
Etienne Poirier e5f700fc21
5344 $expunge operation fails when the operation is executed on a specific partition (#5347)
* initial failing test.

* solution with changelog

* fixing pom dependency version

* fixing pom circular dependency issue and making the new wrapper class generic.

* Fixing tests assertion.

* Moving test to solve dependency issues.

* addressing code review comments.

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-10-05 12:40:16 -04:00
Brenin Rhodes 743e2c178b
Add Registries for CDS CR Services (#5342)
* Add registries for CdsCrServices and CrDiscoveryServices to allow registration of custom services

* Add changelog

* Fix broken find method

* Fix crDiscoveryServiceFactory
2023-10-03 07:15:32 -04:00
StevenXLi 4e9bd153cf
5339 bulk export errors when patient compartment searchparameter of the resource is not present (#5340)
* added failing test

* implemented solution, and fixed test

* added changelog

* fixed formatting

* fixed test not passing

* fixed test and formatting

* added warning for failing the active search param check

* code review change

---------

Co-authored-by: Steven Li <steven@smilecdr.com>
2023-10-02 11:32:58 -04:00
JasonRoberts-smile 5411622dee
add exclusions to terser reference method (#5343) 2023-10-02 09:23:42 -04:00
TipzCM 7e0fa9833c
adding metrics (#5301)
* hapi metrics

* step 1

* metrics service

* adding metrics service

* adding documentation

* refactor

* refactoring

* cleanup

* changing

* adding changelog

* some refactoring

* format

* review fixes part 1

* review points

* review fixes

* updates for code review

* updates for code review

* bumping versions

---------

Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-mbp.home>
Co-authored-by: leif stawnyczy <leifstawnyczy@leifs-MacBook-Pro.local>
2023-09-29 09:23:11 -04:00
TynerGjs c3ff3dae82
Resolve 5336 Mdm Link History Would Fail If Provided with Unknown Ids On Postgres (#5337)
* - Added checks in MdmLinkDaoJpaImpl to make sure no empty IN clauses are sent to database.
- Implemented tests for the above change.

* modified changelog
2023-09-27 15:01:45 -04:00
Brenin Rhodes a2204654df
Implement CDS on FHIR in CDS Hooks (#5240)
* WIP

* WIP refactor

* Initial commit

* measureRefactor WIP

* version bump

* Bump to core release 6.0.22 (#5028)

* Bump to core release 6.0.16

* Bump to core version 6.0.20

* Fix errors thrown as a result of VersionSpecificWorkerContextWrapper

* Bump to core 6.0.22

* adding tests WIP

* Rework MeasureServiceFActory

* measure refactor WIP

* Resolve 5126 hfj res ver prov might cause migration error on db that automatically indexes the primary key (#5127)

* dropped old index FK_RESVERPROV_RES_PID on RES_PID column before adding IDX_RESVERPROV_RES_PID

* added changelog

* changed to valid version number

* changed to valid version number, need to be ordered by version number...

* generic provider loader

* provider loader update

* tests wip

* 5123 - Use DEFAULT partition for server-based requests if none specified (#5124)

5123 - Use DEFAULT partition for server-based requests if none specified

* consent remove all suppresses next link in bundle (#5119)

* added FIXME with source of issue

* added FIXME with root cause

* added FIXME with root cause

* Providing solution to the issue and removing fixmes.

* Providing changelog

* auto-formatting.

* Adding new test.

* Adding a new test for standard paging

* let's try this and see if it works...?

* fix tests

* cleanup to trigger a new run

* fixing tests

---------

Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>

* 5117 MDM Score for No Match Fields Should Not Be Included in Total Score  (#5118)

* fix, test, changelog

* fix, test, changelog

---------

Co-authored-by: justindar <justin.dar@smilecdr.com>

* measureRefactor tests WIP

* update tests wip

* remove baseCrR4Test

* update imports

* add paging provider config to tests

* dstu3 tests

* _source search parameter needs to support modifiers (#5095)

_source search parameter needs to support modifiers - added support form :contains, :missing, :above modifiers

* latest work

* cleanup

* Refactor operation providers to support use in multiple modules

* Fix HFQL docs (#5151)

* repository measure refactor

* undo bundle edit, add config

* embedded library true

* undo post of bundle

* clear library cache on test

* fix sumbit-data test

* Fix tests

* cleanup

* Update MeasureService.java

* latest

* 3.0.0 engine update

* merge cleanup

* cr updates

* cleanup

* Only create services for PlanDefs that have a trigger with a named event

* Fix parameters being sent through invoke

* Handle system actions

* cleanup

* missing packages from cql

* fix test data and test cases for repository api

* latest

* fix pom

* fix test config

* cleanup

* 3.0.0 clinical reasoning uplift

* r4 cql execution provider and tests

* fix submitdata provider config

* wip cql tests

* debugging cql op wip

* wip debugging cql

* update tests for $cql, fix class names

* prep for Pre6 uplift

* spotless checks and test fixes

* bump to 3.0.0-PRE6

* cleanup

* fix version

* cleanup

* cleanup

* fix exlusions in pom

* add in cache invalidation config

* fix resource resolution

* cleanup

* search converter bug and test for repository

* update pom

* update searchconverter

* version bump, add changelog

* remove term config, move IDaoRegistryUser class

* Break out dstu3 providers and move config to version folders

* merge cleanup

* merge cleanup

* Add changelog

* spotless

* fix error codes

* cleanup

* cleanup

* Handle missing beans in Operation configs

* spotless

* Use CondtionalOnBean for CR Operation and Repository configs

* Fix test config

* Add RepositoryFactory and RestfulServer to CdsConfigService

* Move createRequestDetails into CdsConfigService

* spotless

* review comments

---------

Co-authored-by: justin.mckelvy <justin.mckelvy@smilecdr.com>
Co-authored-by: tadgh <garygrantgraham@gmail.com>
Co-authored-by: dotasek <david.otasek@smilecdr.com>
Co-authored-by: Jonathan Percival <jonathan.i.percival@gmail.com>
Co-authored-by: TynerGjs <132295567+TynerGjs@users.noreply.github.com>
Co-authored-by: Steve Corbett <137920358+steve-corbett-smilecdr@users.noreply.github.com>
Co-authored-by: Ken Stevens <khstevens@gmail.com>
Co-authored-by: Ken Stevens <ken@smilecdr.com>
Co-authored-by: peartree <etienne.poirier@smilecdr.com>
Co-authored-by: jdar8 <69840459+jdar8@users.noreply.github.com>
Co-authored-by: justindar <justin.dar@smilecdr.com>
Co-authored-by: volodymyr-korzh <132366313+volodymyr-korzh@users.noreply.github.com>
Co-authored-by: Nathan Doef <n.doef@protonmail.com>
Co-authored-by: Justin McKelvy <60718638+Capt-Mac@users.noreply.github.com>
2023-09-27 13:34:57 -04:00
Etienne Poirier 6ee6031a5f
CapabilityStatement doe not declare conformance to IG when a bulk data export provider is registered. (#5329)
* adding initial test

* adding initial test

* solution implementation

* spotless apply

* bumping to 6.9.8-SNAPSHOT

* addressing comments from review and fixing typo

* spotless

---------

Co-authored-by: peartree <etienne.poirier@smilecdr.com>
2023-09-26 13:56:13 -04:00
1820 changed files with 54208 additions and 38960 deletions

View File

@ -25,7 +25,7 @@ jobs:
if: ${{ github.event_name == 'pull_request' }} if: ${{ github.event_name == 'pull_request' }}
- name: Setup java - name: Setup java
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: zulu distribution: zulu
java-version: 17 java-version: 17

View File

@ -13,9 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.net.*;
import java.io.*; import java.io.File;
import java.nio.channels.*; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Properties; import java.util.Properties;
public class MavenWrapperDownloader { public class MavenWrapperDownloader {

View File

@ -4,7 +4,7 @@
repos: repos:
- repo: https://github.com/ejba/pre-commit-maven - repo: https://github.com/ejba/pre-commit-maven
rev: v0.3.3 rev: v0.3.4
hooks: hooks:
- id: maven-spotless-apply - id: maven-spotless-apply
stages: [pre-push] stages: [pre-push]

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -45,7 +45,6 @@
<checkRuntimeClasspath>false</checkRuntimeClasspath> <checkRuntimeClasspath>false</checkRuntimeClasspath>
<checkTestClasspath>false</checkTestClasspath> <checkTestClasspath>false</checkTestClasspath>
<skip>false</skip> <skip>false</skip>
<quiet>false</quiet>
<preferLocal>true</preferLocal> <preferLocal>true</preferLocal>
<useResultFile>true</useResultFile> <useResultFile>true</useResultFile>
<resultFileMinClasspathCount>2</resultFileMinClasspathCount> <resultFileMinClasspathCount>2</resultFileMinClasspathCount>
@ -103,14 +102,6 @@
<groupId>net.bytebuddy</groupId> <groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId> <artifactId>byte-buddy</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
</ignoredDependencies> </ignoredDependencies>
<ignoredResourcePatterns> <ignoredResourcePatterns>
<ignoredResourcePattern>.*\.txt$</ignoredResourcePattern> <ignoredResourcePattern>.*\.txt$</ignoredResourcePattern>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -131,12 +131,6 @@
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<configuration> <configuration>
<classFolders>
<classFolder>${basedir}/target/classes</classFolder>
</classFolders>
<sourceFolders>
<sourceFolder>${basedir}/src/main/java</sourceFolder>
</sourceFolders>
<dumpOnExit>true</dumpOnExit> <dumpOnExit>true</dumpOnExit>
</configuration> </configuration>
<executions> <executions>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -52,19 +52,13 @@
<!-- Only required for Schematron Validator Support --> <!-- Only required for Schematron Validator Support -->
<dependency> <dependency>
<groupId>com.helger</groupId> <groupId>com.helger.schematron</groupId>
<artifactId>ph-schematron</artifactId> <artifactId>ph-schematron-api</artifactId>
<optional>true</optional> <optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.helger</groupId> <groupId>com.helger.schematron</groupId>
<artifactId>ph-commons</artifactId> <artifactId>ph-schematron-xslt</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -122,10 +116,16 @@
</dependency> </dependency>
<!-- @Nonnull annotation --> <!-- @Nonnull annotation -->
<!-- We need to leave this in because otherwise hapi-fhir-structures-dstu3: will fail to generate javadoc -->
<dependency> <dependency>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId> <artifactId>jsr305</artifactId>
</dependency> </dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.awaitility</groupId> <groupId>org.awaitility</groupId>
@ -221,7 +221,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven_checkstyle_version}</version>
<configuration> <configuration>
<!--suppress UnresolvedMavenProperty --> <!--suppress UnresolvedMavenProperty -->
<configLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml</configLocation> <configLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml</configLocation>

View File

@ -20,6 +20,7 @@
package ca.uhn.fhir.context; package ca.uhn.fhir.context;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.api.annotation.Child;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseReference;
@ -78,6 +79,10 @@ public abstract class BaseRuntimeChildDefinition {
this.myReplacedParentDefinition = myReplacedParentDefinition; this.myReplacedParentDefinition = myReplacedParentDefinition;
} }
public boolean isMultipleCardinality() {
return this.getMax() > 1 || this.getMax() == Child.MAX_UNLIMITED;
}
public interface IAccessor { public interface IAccessor {
List<IBase> getValues(IBase theTarget); List<IBase> getValues(IBase theTarget);

View File

@ -21,6 +21,8 @@ package ca.uhn.fhir.context;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
@ -31,8 +33,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class BaseRuntimeElementDefinition<T extends IBase> { public abstract class BaseRuntimeElementDefinition<T extends IBase> {

View File

@ -49,6 +49,8 @@ import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.VersionUtil; import ca.uhn.fhir.util.VersionUtil;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.jena.riot.Lang; import org.apache.jena.riot.Lang;
@ -77,8 +79,6 @@ import java.util.Optional;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then * The FHIR context is the central starting point for the use of the HAPI FHIR API. It should be created once, and then

View File

@ -38,6 +38,7 @@ import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.XhtmlDt; import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.ReflectionUtil;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBackboneElement; import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
@ -67,7 +68,6 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
@ -498,7 +498,7 @@ class ModelScanner {
nextElementType = ReflectionUtil.getGenericCollectionTypeOfField(next); nextElementType = ReflectionUtil.getGenericCollectionTypeOfField(next);
} else if (Collection.class.isAssignableFrom(nextElementType)) { } else if (Collection.class.isAssignableFrom(nextElementType)) {
throw new ConfigurationException(Msg.code(1722) + "Field '" + next.getName() + "' in type '" throw new ConfigurationException(Msg.code(1722) + "Field '" + next.getName() + "' in type '"
+ next.getClass().getCanonicalName() + nextElementType.getCanonicalName()
+ "' is a Collection - Only java.util.List curently supported"); + "' is a Collection - Only java.util.List curently supported");
} }
return nextElementType; return nextElementType;

View File

@ -21,6 +21,8 @@ package ca.uhn.fhir.context;
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder; import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
@ -37,8 +39,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim; import static org.apache.commons.lang3.StringUtils.trim;

View File

@ -23,6 +23,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.util.ILockable; import ca.uhn.fhir.util.ILockable;
import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.ReflectionUtil;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -32,7 +33,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable;
/** /**
* This class returns the vocabulary that is shipped with the base FHIR * This class returns the vocabulary that is shipped with the base FHIR
@ -99,6 +99,11 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
} }
} }
@Override
public String getName() {
return myCtx.getVersion().getVersion() + " FHIR Standard Profile Validation Support";
}
@Override @Override
public List<IBaseResource> fetchAllConformanceResources() { public List<IBaseResource> fetchAllConformanceResources() {
return myDelegate.fetchAllConformanceResources(); return myDelegate.fetchAllConformanceResources();

View File

@ -28,6 +28,7 @@ import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.util.BundleUtil; import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.ClasspathUtil; import ca.uhn.fhir.util.ClasspathUtil;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -43,7 +44,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -24,9 +24,12 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.ParametersUtil; import ca.uhn.fhir.util.ParametersUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseParameters;
@ -41,8 +44,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
@ -294,8 +295,8 @@ public interface IValidationSupport {
*/ */
@Nullable @Nullable
default CodeValidationResult validateCode( default CodeValidationResult validateCode(
@Nonnull ValidationSupportContext theValidationSupportContext, ValidationSupportContext theValidationSupportContext,
@Nonnull ConceptValidationOptions theOptions, ConceptValidationOptions theOptions,
String theCodeSystem, String theCodeSystem,
String theCode, String theCode,
String theDisplay, String theDisplay,
@ -328,14 +329,16 @@ public interface IValidationSupport {
} }
/** /**
* Look up a code using the system and code value * Look up a code using the system and code value.
* @deprecated This method has been deprecated in HAPI FHIR 7.0.0. Use {@link IValidationSupport#lookupCode(ValidationSupportContext, LookupCodeRequest)} instead.
* *
* @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to * @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to
* other method in the support chain, so that they can be passed through the entire chain. Implementations of this interface may always safely ignore this parameter. * other method in the support chain, so that they can be passed through the entire chain. Implementations of this interface may always safely ignore this parameter.
* @param theSystem The CodeSystem URL * @param theSystem The CodeSystem URL
* @param theCode The code * @param theCode The code
* @param theDisplayLanguage to filter out the designation by the display language. To return all designation, set this value to <code>null</code>. * @param theDisplayLanguage Used to filter out the designation by the display language. To return all designation, set this value to <code>null</code>.
*/ */
@Deprecated
@Nullable @Nullable
default LookupCodeResult lookupCode( default LookupCodeResult lookupCode(
ValidationSupportContext theValidationSupportContext, ValidationSupportContext theValidationSupportContext,
@ -347,12 +350,14 @@ public interface IValidationSupport {
/** /**
* Look up a code using the system and code value * Look up a code using the system and code value
* @deprecated This method has been deprecated in HAPI FHIR 7.0.0. Use {@link IValidationSupport#lookupCode(ValidationSupportContext, LookupCodeRequest)} instead.
* *
* @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to * @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to
* other method in the support chain, so that they can be passed through the entire chain. Implementations of this interface may always safely ignore this parameter. * other method in the support chain, so that they can be passed through the entire chain. Implementations of this interface may always safely ignore this parameter.
* @param theSystem The CodeSystem URL * @param theSystem The CodeSystem URL
* @param theCode The code * @param theCode The code
*/ */
@Deprecated
@Nullable @Nullable
default LookupCodeResult lookupCode( default LookupCodeResult lookupCode(
ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) { ValidationSupportContext theValidationSupportContext, String theSystem, String theCode) {
@ -360,7 +365,26 @@ public interface IValidationSupport {
} }
/** /**
* Returns <code>true</code> if the given valueset can be validated by the given * Look up a code using the system, code and other parameters captured in {@link LookupCodeRequest}.
* @since 7.0.0
*
* @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to
* other method in the support chain, so that they can be passed through the entire chain. Implementations of this interface may always safely ignore this parameter.
* @param theLookupCodeRequest The parameters used to perform the lookup, including system and code.
*/
@Nullable
default LookupCodeResult lookupCode(
ValidationSupportContext theValidationSupportContext, @Nonnull LookupCodeRequest theLookupCodeRequest) {
// TODO: can change to return null once the deprecated methods are removed
return lookupCode(
theValidationSupportContext,
theLookupCodeRequest.getSystem(),
theLookupCodeRequest.getCode(),
theLookupCodeRequest.getDisplayLanguage());
}
/**
* Returns <code>true</code> if the given ValueSet can be validated by the given
* validation support module * validation support module
* *
* @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to * @param theValidationSupportContext The validation support module will be passed in to this method. This is convenient in cases where the operation needs to make calls to
@ -409,6 +433,13 @@ public interface IValidationSupport {
return null; return null;
} }
/**
* This field is used by the Terminology Troubleshooting Log to log which validation support module was used for the operation being logged.
*/
default String getName() {
return "Unknown " + getFhirContext().getVersion().getVersion() + " Validation Support";
}
enum IssueSeverity { enum IssueSeverity {
/** /**
* The issue caused the action to fail, and no further checking could be performed. * The issue caused the action to fail, and no further checking could be performed.
@ -495,8 +526,13 @@ public interface IValidationSupport {
public String getPropertyName() { public String getPropertyName() {
return myPropertyName; return myPropertyName;
} }
public abstract String getType();
} }
String TYPE_STRING = "string";
String TYPE_CODING = "Coding";
class StringConceptProperty extends BaseConceptProperty { class StringConceptProperty extends BaseConceptProperty {
private final String myValue; private final String myValue;
@ -513,6 +549,10 @@ public interface IValidationSupport {
public String getValue() { public String getValue() {
return myValue; return myValue;
} }
public String getType() {
return TYPE_STRING;
}
} }
class CodingConceptProperty extends BaseConceptProperty { class CodingConceptProperty extends BaseConceptProperty {
@ -543,9 +583,18 @@ public interface IValidationSupport {
public String getDisplay() { public String getDisplay() {
return myDisplay; return myDisplay;
} }
public String getType() {
return TYPE_CODING;
}
} }
class CodeValidationResult { class CodeValidationResult {
public static final String SOURCE_DETAILS = "sourceDetails";
public static final String RESULT = "result";
public static final String MESSAGE = "message";
public static final String DISPLAY = "display";
private String myCode; private String myCode;
private String myMessage; private String myMessage;
private IssueSeverity mySeverity; private IssueSeverity mySeverity;
@ -674,6 +723,23 @@ public interface IValidationSupport {
setSeverity(IssueSeverity.valueOf(theIssueSeverity.toUpperCase())); setSeverity(IssueSeverity.valueOf(theIssueSeverity.toUpperCase()));
return this; return this;
} }
public IBaseParameters toParameters(FhirContext theContext) {
IBaseParameters retVal = ParametersUtil.newInstance(theContext);
ParametersUtil.addParameterToParametersBoolean(theContext, retVal, RESULT, isOk());
if (isNotBlank(getMessage())) {
ParametersUtil.addParameterToParametersString(theContext, retVal, MESSAGE, getMessage());
}
if (isNotBlank(getDisplay())) {
ParametersUtil.addParameterToParametersString(theContext, retVal, DISPLAY, getDisplay());
}
if (isNotBlank(getSourceDetails())) {
ParametersUtil.addParameterToParametersString(theContext, retVal, SOURCE_DETAILS, getSourceDetails());
}
return retVal;
}
} }
class ValueSetExpansionOutcome { class ValueSetExpansionOutcome {
@ -806,7 +872,7 @@ public interface IValidationSupport {
} }
public IBaseParameters toParameters( public IBaseParameters toParameters(
FhirContext theContext, List<? extends IPrimitiveType<String>> theProperties) { FhirContext theContext, List<? extends IPrimitiveType<String>> thePropertyNames) {
IBaseParameters retVal = ParametersUtil.newInstance(theContext); IBaseParameters retVal = ParametersUtil.newInstance(theContext);
if (isNotBlank(getCodeSystemDisplayName())) { if (isNotBlank(getCodeSystemDisplayName())) {
@ -821,32 +887,42 @@ public interface IValidationSupport {
if (myProperties != null) { if (myProperties != null) {
Set<String> properties = Collections.emptySet(); Set<String> properties = Collections.emptySet();
if (theProperties != null) { if (thePropertyNames != null) {
properties = theProperties.stream() properties = thePropertyNames.stream()
.map(IPrimitiveType::getValueAsString) .map(IPrimitiveType::getValueAsString)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
for (BaseConceptProperty next : myProperties) { for (BaseConceptProperty next : myProperties) {
String propertyName = next.getPropertyName();
if (!properties.isEmpty()) { if (!properties.isEmpty() && !properties.contains(propertyName)) {
if (!properties.contains(next.getPropertyName())) { continue;
continue;
}
} }
IBase property = ParametersUtil.addParameterToParameters(theContext, retVal, "property"); IBase property = ParametersUtil.addParameterToParameters(theContext, retVal, "property");
ParametersUtil.addPartCode(theContext, property, "code", next.getPropertyName()); ParametersUtil.addPartCode(theContext, property, "code", propertyName);
if (next instanceof StringConceptProperty) { String propertyType = next.getType();
StringConceptProperty prop = (StringConceptProperty) next; switch (propertyType) {
ParametersUtil.addPartString(theContext, property, "value", prop.getValue()); case TYPE_STRING:
} else if (next instanceof CodingConceptProperty) { StringConceptProperty stringConceptProperty = (StringConceptProperty) next;
CodingConceptProperty prop = (CodingConceptProperty) next; ParametersUtil.addPartString(
ParametersUtil.addPartCoding( theContext, property, "value", stringConceptProperty.getValue());
theContext, property, "value", prop.getCodeSystem(), prop.getCode(), prop.getDisplay()); break;
} else { case TYPE_CODING:
throw new IllegalStateException(Msg.code(1739) + "Don't know how to handle " + next.getClass()); CodingConceptProperty codingConceptProperty = (CodingConceptProperty) next;
ParametersUtil.addPartCoding(
theContext,
property,
"value",
codingConceptProperty.getCodeSystem(),
codingConceptProperty.getCode(),
codingConceptProperty.getDisplay());
break;
default:
throw new IllegalStateException(
Msg.code(1739) + "Don't know how to handle " + next.getClass());
} }
} }
} }
@ -990,6 +1066,16 @@ public interface IValidationSupport {
public boolean isReverse() { public boolean isReverse() {
return myReverse; return myReverse;
} }
@Override
public String toString() {
return new ToStringBuilder(this)
.append("sourceValueSetUrl", mySourceValueSetUrl)
.append("targetSystemUrl", myTargetSystemUrl)
.append("targetValueSetUrl", myTargetValueSetUrl)
.append("reverse", myReverse)
.toString();
}
} }
/** /**

View File

@ -0,0 +1,75 @@
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* 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://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%
*/
package ca.uhn.fhir.context.support;
import java.util.Collection;
import java.util.Collections;
/**
* Represents parameters which can be passed to the $lookup operation for codes.
* @since 7.0.0
*/
public class LookupCodeRequest {
private final String mySystem;
private final String myCode;
private String myDisplayLanguage;
private Collection<String> myPropertyNames;
/**
* @param theSystem The CodeSystem URL
* @param theCode The code
*/
public LookupCodeRequest(String theSystem, String theCode) {
mySystem = theSystem;
myCode = theCode;
}
/**
* @param theSystem The CodeSystem URL
* @param theCode The code
* @param theDisplayLanguage Used to filter out the designation by the display language. To return all designation, set this value to <code>null</code>.
* @param thePropertyNames The collection of properties to be returned in the output. If no properties are specified, the implementor chooses what to return.
*/
public LookupCodeRequest(
String theSystem, String theCode, String theDisplayLanguage, Collection<String> thePropertyNames) {
this(theSystem, theCode);
myDisplayLanguage = theDisplayLanguage;
myPropertyNames = thePropertyNames;
}
public String getSystem() {
return mySystem;
}
public String getCode() {
return myCode;
}
public String getDisplayLanguage() {
return myDisplayLanguage;
}
public Collection<String> getPropertyNames() {
if (myPropertyNames == null) {
return Collections.emptyList();
}
return myPropertyNames;
}
}

View File

@ -19,11 +19,11 @@
*/ */
package ca.uhn.fhir.fhirpath; package ca.uhn.fhir.fhirpath;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull;
public interface IFhirPath { public interface IFhirPath {

View File

@ -19,12 +19,11 @@
*/ */
package ca.uhn.fhir.fhirpath; package ca.uhn.fhir.fhirpath;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public interface IFhirPathEvaluationContext { public interface IFhirPathEvaluationContext {
/** /**

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.interceptor.api;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import java.util.Collection; import java.util.Collection;
@ -29,7 +30,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
public class HookParams { public class HookParams {

View File

@ -19,10 +19,11 @@
*/ */
package ca.uhn.fhir.interceptor.api; package ca.uhn.fhir.interceptor.api;
import jakarta.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
import javax.annotation.Nullable;
public interface IBaseInterceptorService<POINTCUT extends IPointcut> extends IBaseInterceptorBroadcaster<POINTCUT> { public interface IBaseInterceptorService<POINTCUT extends IPointcut> extends IBaseInterceptorBroadcaster<POINTCUT> {

View File

@ -19,8 +19,9 @@
*/ */
package ca.uhn.fhir.interceptor.api; package ca.uhn.fhir.interceptor.api;
import jakarta.annotation.Nonnull;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
public interface IPointcut { public interface IPointcut {
@Nonnull @Nonnull

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.ValidationResult;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBaseConformance; import org.hl7.fhir.instance.model.api.IBaseConformance;
import java.io.Writer; import java.io.Writer;
@ -33,7 +34,6 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
/** /**
* Value for {@link Hook#value()} * Value for {@link Hook#value()}
@ -93,6 +93,10 @@ public enum Pointcut implements IPointcut {
* <li> * <li>
* ca.uhn.fhir.rest.client.api.IRestfulClient - The client object making the request * ca.uhn.fhir.rest.client.api.IRestfulClient - The client object making the request
* </li> * </li>
* <li>
* ca.uhn.fhir.rest.client.api.ClientResponseContext - Contains an IHttpRequest, an IHttpResponse, and an IRestfulClient
* and also allows the client to mutate the contained IHttpResponse
* </li>
* </ul> * </ul>
* </p> * </p>
* Hook methods must return <code>void</code>. * Hook methods must return <code>void</code>.
@ -101,7 +105,8 @@ public enum Pointcut implements IPointcut {
void.class, void.class,
"ca.uhn.fhir.rest.client.api.IHttpRequest", "ca.uhn.fhir.rest.client.api.IHttpRequest",
"ca.uhn.fhir.rest.client.api.IHttpResponse", "ca.uhn.fhir.rest.client.api.IHttpResponse",
"ca.uhn.fhir.rest.client.api.IRestfulClient"), "ca.uhn.fhir.rest.client.api.IRestfulClient",
"ca.uhn.fhir.rest.client.api.ClientResponseContext"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -153,10 +158,10 @@ public enum Pointcut implements IPointcut {
* Hooks may accept the following parameters: * Hooks may accept the following parameters:
* <ul> * <ul>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* </p> * </p>
@ -166,7 +171,7 @@ public enum Pointcut implements IPointcut {
* no further processing will occur and no further interceptors will be called. * no further processing will occur and no further interceptors will be called.
*/ */
SERVER_INCOMING_REQUEST_PRE_PROCESSED( SERVER_INCOMING_REQUEST_PRE_PROCESSED(
boolean.class, "javax.servlet.http.HttpServletRequest", "javax.servlet.http.HttpServletResponse"), boolean.class, "jakarta.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -193,10 +198,10 @@ public enum Pointcut implements IPointcut {
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException - The exception that was thrown * ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException - The exception that was thrown
@ -215,8 +220,8 @@ public enum Pointcut implements IPointcut {
boolean.class, boolean.class,
"ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse", "jakarta.servlet.http.HttpServletResponse",
"ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException"), "ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException"),
/** /**
@ -239,10 +244,10 @@ public enum Pointcut implements IPointcut {
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* <p> * <p>
@ -263,8 +268,8 @@ public enum Pointcut implements IPointcut {
boolean.class, boolean.class,
"ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse"), "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -286,10 +291,10 @@ public enum Pointcut implements IPointcut {
* only be populated when operating in a RestfulServer implementation. It is provided as a convenience. * only be populated when operating in a RestfulServer implementation. It is provided as a convenience.
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* <p> * <p>
@ -308,8 +313,8 @@ public enum Pointcut implements IPointcut {
boolean.class, boolean.class,
"ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse"), "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -411,10 +416,10 @@ public enum Pointcut implements IPointcut {
* {@link NullPointerException} in the case of a bug being triggered. * {@link NullPointerException} in the case of a bug being triggered.
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* <p> * <p>
@ -429,8 +434,8 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"java.lang.Throwable", "java.lang.Throwable",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse"), "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -458,10 +463,10 @@ public enum Pointcut implements IPointcut {
* ca.uhn.fhir.rest.api.server.ResponseDetails - This object contains details about the response, including the contents. Hook methods may modify this object to change or replace the response. * ca.uhn.fhir.rest.api.server.ResponseDetails - This object contains details about the response, including the contents. Hook methods may modify this object to change or replace the response.
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* </p> * </p>
@ -482,8 +487,8 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"org.hl7.fhir.instance.model.api.IBaseResource", "org.hl7.fhir.instance.model.api.IBaseResource",
"ca.uhn.fhir.rest.api.server.ResponseDetails", "ca.uhn.fhir.rest.api.server.ResponseDetails",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse"), "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -549,10 +554,10 @@ public enum Pointcut implements IPointcut {
* java.lang.String - The GraphQL response * java.lang.String - The GraphQL response
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment * jakarta.servlet.http.HttpServletRequest - The servlet request, when running in a servlet environment
* </li> * </li>
* <li> * <li>
* javax.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment * jakarta.servlet.http.HttpServletResponse - The servlet response, when running in a servlet environment
* </li> * </li>
* </ul> * </ul>
* </p> * </p>
@ -573,8 +578,8 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails", "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails",
"java.lang.String", "java.lang.String",
"java.lang.String", "java.lang.String",
"javax.servlet.http.HttpServletRequest", "jakarta.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse"), "jakarta.servlet.http.HttpServletResponse"),
/** /**
* <b>Server Hook:</b> * <b>Server Hook:</b>
@ -2930,6 +2935,31 @@ public enum Pointcut implements IPointcut {
"ca.uhn.fhir.rest.api.server.RequestDetails", "ca.uhn.fhir.rest.api.server.RequestDetails",
"org.hl7.fhir.instance.model.api.IBaseResource"), "org.hl7.fhir.instance.model.api.IBaseResource"),
/**
* <b>Storage Hook:</b>
* Invoked before a batch job is persisted to the database.
* <p>
* Hooks will have access to the content of the job being created
* and may choose to make modifications to it. These changes will be
* reflected in permanent storage.
* </p>
* Hooks may accept the following parameters:
* <ul>
* <li>
* ca.uhn.fhir.batch2.model.JobInstance
* </li>
* <li>
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that lead to the creation
* of the jobInstance.
* </li>
* </ul>
* <p>
* Hooks should return <code>void</code>.
* </p>
*/
STORAGE_PRESTORAGE_BATCH_JOB_CREATE(
void.class, "ca.uhn.fhir.batch2.model.JobInstance", "ca.uhn.fhir.rest.api.server.RequestDetails"),
/** /**
* This pointcut is used only for unit tests. Do not use in production code as it may be changed or * This pointcut is used only for unit tests. Do not use in production code as it may be changed or
* removed at any time. * removed at any time.

View File

@ -31,6 +31,8 @@ import ca.uhn.fhir.util.ReflectionUtil;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
@ -57,8 +59,6 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & IPointcut> public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & IPointcut>
implements IBaseInterceptorService<POINTCUT>, IBaseInterceptorBroadcaster<POINTCUT> { implements IBaseInterceptorService<POINTCUT>, IBaseInterceptorBroadcaster<POINTCUT> {
@ -263,10 +263,14 @@ public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & I
return myRegisteredPointcuts.contains(thePointcut); return myRegisteredPointcuts.contains(thePointcut);
} }
protected Class<?> getBooleanReturnType() {
return boolean.class;
}
@Override @Override
public boolean callHooks(POINTCUT thePointcut, HookParams theParams) { public boolean callHooks(POINTCUT thePointcut, HookParams theParams) {
assert haveAppropriateParams(thePointcut, theParams); assert haveAppropriateParams(thePointcut, theParams);
assert thePointcut.getReturnType() == void.class || thePointcut.getReturnType() == boolean.class; assert thePointcut.getReturnType() == void.class || thePointcut.getReturnType() == getBooleanReturnType();
Object retValObj = doCallHooks(thePointcut, theParams, true); Object retValObj = doCallHooks(thePointcut, theParams, true);
return (Boolean) retValObj; return (Boolean) retValObj;
@ -282,14 +286,16 @@ public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & I
for (BaseInvoker nextInvoker : invokers) { for (BaseInvoker nextInvoker : invokers) {
Object nextOutcome = nextInvoker.invoke(theParams); Object nextOutcome = nextInvoker.invoke(theParams);
Class<?> pointcutReturnType = thePointcut.getReturnType(); Class<?> pointcutReturnType = thePointcut.getReturnType();
if (pointcutReturnType.equals(boolean.class)) { if (pointcutReturnType.equals(getBooleanReturnType())) {
Boolean nextOutcomeAsBoolean = (Boolean) nextOutcome; Boolean nextOutcomeAsBoolean = (Boolean) nextOutcome;
if (Boolean.FALSE.equals(nextOutcomeAsBoolean)) { if (Boolean.FALSE.equals(nextOutcomeAsBoolean)) {
ourLog.trace("callHooks({}) for invoker({}) returned false", thePointcut, nextInvoker); ourLog.trace("callHooks({}) for invoker({}) returned false", thePointcut, nextInvoker);
theRetVal = false; theRetVal = false;
break; break;
} else {
theRetVal = true;
} }
} else if (pointcutReturnType.equals(void.class) == false) { } else if (!pointcutReturnType.equals(void.class)) {
if (nextOutcome != null) { if (nextOutcome != null) {
theRetVal = nextOutcome; theRetVal = nextOutcome;
break; break;
@ -349,7 +355,7 @@ public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & I
List<BaseInvoker> retVal; List<BaseInvoker> retVal;
if (haveMultiple == false) { if (!haveMultiple) {
// The global list doesn't need to be sorted every time since it's sorted on // The global list doesn't need to be sorted every time since it's sorted on
// insertion each time. Doing so is a waste of cycles.. // insertion each time. Doing so is a waste of cycles..
@ -485,9 +491,9 @@ public abstract class BaseInterceptorService<POINTCUT extends Enum<POINTCUT> & I
myMethod = theHookMethod; myMethod = theHookMethod;
Class<?> returnType = theHookMethod.getReturnType(); Class<?> returnType = theHookMethod.getReturnType();
if (myPointcut.getReturnType().equals(boolean.class)) { if (myPointcut.getReturnType().equals(getBooleanReturnType())) {
Validate.isTrue( Validate.isTrue(
boolean.class.equals(returnType) || void.class.equals(returnType), getBooleanReturnType().equals(returnType) || void.class.equals(returnType),
"Method does not return boolean or void: %s", "Method does not return boolean or void: %s",
theHookMethod); theHookMethod);
} else if (myPointcut.getReturnType().equals(void.class)) { } else if (myPointcut.getReturnType().equals(void.class)) {

View File

@ -24,6 +24,8 @@ import ca.uhn.fhir.util.JsonUtil;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
@ -37,8 +39,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;

View File

@ -24,7 +24,11 @@ import ca.uhn.fhir.model.api.annotation.Description;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class BaseElement implements /*IElement, */ ISupportsUndeclaredExtensions { public abstract class BaseElement implements /*IElement, */ ISupportsUndeclaredExtensions {

View File

@ -19,10 +19,15 @@
*/ */
package ca.uhn.fhir.model.api; package ca.uhn.fhir.model.api;
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.fhirpath.IFhirPath; import ca.uhn.fhir.fhirpath.IFhirPath;
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory; import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
import org.hl7.fhir.instance.model.api.*; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.io.InputStream; import java.io.InputStream;
import java.util.Date; import java.util.Date;

View File

@ -28,6 +28,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.Logs; import ca.uhn.fhir.util.Logs;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.INarrative; import org.hl7.fhir.instance.model.api.INarrative;
@ -37,7 +38,6 @@ import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.defaultIfEmpty; import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -20,12 +20,12 @@
package ca.uhn.fhir.narrative2; package ca.uhn.fhir.narrative2;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import java.util.Collection; import java.util.Collection;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
public interface INarrativeTemplateManifest { public interface INarrativeTemplateManifest {
List<INarrativeTemplate> getTemplateByResourceName( List<INarrativeTemplate> getTemplateByResourceName(

View File

@ -28,6 +28,7 @@ import com.google.common.base.Charsets;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import jakarta.annotation.Nonnull;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
@ -41,10 +42,18 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.*;
import javax.annotation.Nonnull;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -45,6 +45,7 @@ import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import jakarta.annotation.Nullable;
import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.output.StringBuilderWriter;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
@ -78,7 +79,6 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -39,7 +39,6 @@ import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag; import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt; import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -659,9 +658,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
theEventWriter.endArray(); theEventWriter.endArray();
} }
BaseRuntimeChildDefinition replacedParentDefinition = nextChild.getReplacedParentDefinition(); BaseRuntimeChildDefinition replacedParentDefinition = nextChild.getReplacedParentDefinition();
if (isMultipleCardinality(nextChild.getMax()) if (nextChild.isMultipleCardinality()
|| (replacedParentDefinition != null || (replacedParentDefinition != null && replacedParentDefinition.isMultipleCardinality())) {
&& isMultipleCardinality(replacedParentDefinition.getMax()))) {
beginArray(theEventWriter, nextChildSpecificName); beginArray(theEventWriter, nextChildSpecificName);
inArray = true; inArray = true;
encodeChildElementToStreamWriter( encodeChildElementToStreamWriter(
@ -728,14 +726,14 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
List<HeldExtension> heldModExts = Collections.emptyList(); List<HeldExtension> heldModExts = Collections.emptyList();
if (extensions.size() > i if (extensions.size() > i
&& extensions.get(i) != null && extensions.get(i) != null
&& extensions.get(i).isEmpty() == false) { && !extensions.get(i).isEmpty()) {
haveContent = true; haveContent = true;
heldExts = extensions.get(i); heldExts = extensions.get(i);
} }
if (modifierExtensions.size() > i if (modifierExtensions.size() > i
&& modifierExtensions.get(i) != null && modifierExtensions.get(i) != null
&& modifierExtensions.get(i).isEmpty() == false) { && !modifierExtensions.get(i).isEmpty()) {
haveContent = true; haveContent = true;
heldModExts = modifierExtensions.get(i); heldModExts = modifierExtensions.get(i);
} }
@ -746,7 +744,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
} else { } else {
nextComments = null; nextComments = null;
} }
if (nextComments != null && nextComments.isEmpty() == false) { if (nextComments != null && !nextComments.isEmpty()) {
haveContent = true; haveContent = true;
} }
@ -804,10 +802,6 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
return myIsSupportsFhirComment; return myIsSupportsFhirComment;
} }
private boolean isMultipleCardinality(int maxCardinality) {
return maxCardinality > 1 || maxCardinality == Child.MAX_UNLIMITED;
}
private void encodeCompositeElementToStreamWriter( private void encodeCompositeElementToStreamWriter(
RuntimeResourceDefinition theResDef, RuntimeResourceDefinition theResDef,
IBaseResource theResource, IBaseResource theResource,
@ -917,10 +911,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
// Undeclared extensions // Undeclared extensions
extractUndeclaredExtensions( extractUndeclaredExtensions(
theResourceId, extensions, modifierExtensions, null, null, theEncodeContext, theContainedResource); theResourceId, extensions, modifierExtensions, null, null, theEncodeContext, theContainedResource);
boolean haveExtension = false; boolean haveExtension = !extensions.isEmpty();
if (!extensions.isEmpty()) {
haveExtension = true;
}
if (theResourceId.hasFormatComment() || haveExtension) { if (theResourceId.hasFormatComment() || haveExtension) {
beginObject(theEventWriter, "_id"); beginObject(theEventWriter, "_id");

View File

@ -28,6 +28,7 @@ import ca.uhn.fhir.parser.json.BaseJsonLikeWriter;
import ca.uhn.fhir.parser.json.JsonLikeStructure; import ca.uhn.fhir.parser.json.JsonLikeStructure;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.StreamReadConstraints; import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
@ -114,14 +115,38 @@ public class JacksonStructure implements JsonLikeStructure {
setNativeArray((ArrayNode) OBJECT_MAPPER.readTree(pbr)); setNativeArray((ArrayNode) OBJECT_MAPPER.readTree(pbr));
} }
} catch (Exception e) { } catch (Exception e) {
if (e.getMessage().startsWith("Unexpected char 39")) { String message;
if (e instanceof JsonProcessingException) {
/*
* Currently there is no way of preventing Jackson from adding this
* annoying REDACTED message from certain messages we get back from
* the parser, so we just manually strip them. Hopefully Jackson
* will accept this request at some point:
* https://github.com/FasterXML/jackson-core/issues/1158
*/
JsonProcessingException jpe = (JsonProcessingException) e;
StringBuilder messageBuilder = new StringBuilder();
String originalMessage = jpe.getOriginalMessage();
originalMessage = originalMessage.replace(
"Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); ", "");
messageBuilder.append(originalMessage);
if (jpe.getLocation() != null) {
messageBuilder.append("\n at [");
jpe.getLocation().appendOffsetDescription(messageBuilder);
messageBuilder.append("]");
}
message = messageBuilder.toString();
} else {
message = e.getMessage();
}
if (message.startsWith("Unexpected char 39")) {
throw new DataFormatException( throw new DataFormatException(
Msg.code(1860) + "Failed to parse JSON encoded FHIR content: " + e.getMessage() + " - " Msg.code(1860) + "Failed to parse JSON encoded FHIR content: " + message + " - "
+ "This may indicate that single quotes are being used as JSON escapes where double quotes are required", + "This may indicate that single quotes are being used as JSON escapes where double quotes are required",
e); e);
} }
throw new DataFormatException( throw new DataFormatException(Msg.code(1861) + "Failed to parse JSON encoded FHIR content: " + message, e);
Msg.code(1861) + "Failed to parse JSON encoded FHIR content: " + e.getMessage(), e);
} }
} }

View File

@ -45,29 +45,15 @@ public class JacksonWriter extends BaseJsonLikeWriter {
@Override @Override
public BaseJsonLikeWriter init() { public BaseJsonLikeWriter init() {
if (isPrettyPrint()) { if (isPrettyPrint()) {
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter() { DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter()
.withSeparators(new Separators(
/** Separators.DEFAULT_ROOT_VALUE_SEPARATOR,
* Objects should serialize as ':',
* <pre> Separators.Spacing.AFTER,
* { ',',
* "key": "value" Separators.Spacing.NONE,
* } ',',
* </pre> Separators.Spacing.NONE));
* in order to be consistent with Gson behaviour, instead of the jackson default
* <pre>
* {
* "key" : "value"
* }
* </pre>
*/
@Override
public DefaultPrettyPrinter withSeparators(Separators separators) {
_separators = separators;
_objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " ";
return this;
}
};
prettyPrinter = prettyPrinter.withObjectIndenter(new DefaultIndenter(" ", "\n")); prettyPrinter = prettyPrinter.withObjectIndenter(new DefaultIndenter(" ", "\n"));
myJsonGenerator.setPrettyPrinter(prettyPrinter); myJsonGenerator.setPrettyPrinter(prettyPrinter);

View File

@ -118,7 +118,7 @@ public @interface Operation {
* always the right choice), the framework will not attempt to generate a response to * always the right choice), the framework will not attempt to generate a response to
* this method. * this method.
* <p> * <p>
* This is useful if you want to include an {@link javax.servlet.http.HttpServletResponse} * This is useful if you want to include an {@link jakarta.servlet.http.HttpServletResponse}
* in your method parameters and create a response yourself directly from your * in your method parameters and create a response yourself directly from your
* <code>@Operation</code> method. * <code>@Operation</code> method.
* </p> * </p>
@ -134,7 +134,7 @@ public @interface Operation {
* always the right choice), the framework will not attempt to parse the request body, * always the right choice), the framework will not attempt to parse the request body,
* but will instead delegate it to the <code>@Operation</code> method. * but will instead delegate it to the <code>@Operation</code> method.
* <p> * <p>
* This is useful if you want to include an {@link javax.servlet.http.HttpServletRequest} * This is useful if you want to include an {@link jakarta.servlet.http.HttpServletRequest}
* in your method parameters and parse the request yourself. * in your method parameters and parse the request yourself.
* </p> * </p>
*/ */

View File

@ -23,7 +23,10 @@ import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.api.IRestfulClient; import ca.uhn.fhir.rest.client.api.IRestfulClient;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import java.lang.annotation.*; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* RESTful method annotation to be used for the FHIR <a href="http://hl7.org/implement/standards/fhir/http.html#read">read</a> and <a * RESTful method annotation to be used for the FHIR <a href="http://hl7.org/implement/standards/fhir/http.html#read">read</a> and <a

View File

@ -19,7 +19,10 @@
*/ */
package ca.uhn.fhir.rest.annotation; package ca.uhn.fhir.rest.annotation;
import java.lang.annotation.*; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* RESTful method annotation to be used for the FHIR <a href="http://hl7.org/implement/standards/fhir/http.html#transaction">transaction</a> method. * RESTful method annotation to be used for the FHIR <a href="http://hl7.org/implement/standards/fhir/http.html#transaction">transaction</a> method.

View File

@ -19,7 +19,10 @@
*/ */
package ca.uhn.fhir.rest.annotation; package ca.uhn.fhir.rest.annotation;
import java.lang.annotation.*; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List; import java.util.List;
/** /**

View File

@ -22,7 +22,10 @@ package ca.uhn.fhir.rest.annotation;
import ca.uhn.fhir.rest.api.ValidationModeEnum; import ca.uhn.fhir.rest.api.ValidationModeEnum;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import java.lang.annotation.*; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* RESTful method annotation to be used for the FHIR * RESTful method annotation to be used for the FHIR

View File

@ -199,6 +199,8 @@ public class Constants {
public static final String PARAM_PRETTY_VALUE_FALSE = "false"; public static final String PARAM_PRETTY_VALUE_FALSE = "false";
public static final String PARAM_PRETTY_VALUE_TRUE = "true"; public static final String PARAM_PRETTY_VALUE_TRUE = "true";
public static final String PARAM_PROFILE = "_profile"; public static final String PARAM_PROFILE = "_profile";
public static final String PARAM_PID = "_pid";
public static final String PARAM_QUERY = "_query"; public static final String PARAM_QUERY = "_query";
public static final String PARAM_RESPONSE_URL = "response-url"; // Used in messaging public static final String PARAM_RESPONSE_URL = "response-url"; // Used in messaging
public static final String PARAM_REVINCLUDE = "_revinclude"; public static final String PARAM_REVINCLUDE = "_revinclude";
@ -218,21 +220,6 @@ public class Constants {
public static final String PARAM_TEXT = "_text"; public static final String PARAM_TEXT = "_text";
public static final String PARAM_VALIDATE = "_validate"; public static final String PARAM_VALIDATE = "_validate";
/**
* $member-match operation
*/
public static final String PARAM_MEMBER_PATIENT = "MemberPatient";
public static final String PARAM_MEMBER_IDENTIFIER = "MemberIdentifier";
public static final String PARAM_OLD_COVERAGE = "OldCoverage";
public static final String PARAM_NEW_COVERAGE = "NewCoverage";
public static final String PARAM_CONSENT = "Consent";
public static final String PARAM_MEMBER_PATIENT_NAME = PARAM_MEMBER_PATIENT + " Name";
public static final String PARAM_MEMBER_PATIENT_BIRTHDATE = PARAM_MEMBER_PATIENT + " Birthdate";
public static final String PARAM_CONSENT_PATIENT_REFERENCE = PARAM_CONSENT + "'s Patient Reference";
public static final String PARAM_CONSENT_PERFORMER_REFERENCE = PARAM_CONSENT + "'s Performer Reference";
public static final String PARAMQUALIFIER_MISSING = ":missing"; public static final String PARAMQUALIFIER_MISSING = ":missing";
public static final String PARAMQUALIFIER_MISSING_FALSE = "false"; public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
public static final String PARAMQUALIFIER_MISSING_TRUE = "true"; public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
@ -331,6 +318,9 @@ public class Constants {
*/ */
public static final int UUID_LENGTH = 36; public static final int UUID_LENGTH = 36;
public static final String BULK_DATA_ACCESS_IG_URL =
"http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data";
/** /**
* Application configuration key used to enable or disable Hibernate Envers. * Application configuration key used to enable or disable Hibernate Envers.
*/ */

View File

@ -22,6 +22,8 @@ package ca.uhn.fhir.rest.api;
import ca.uhn.fhir.context.api.BundleInclusionRule; import ca.uhn.fhir.context.api.BundleInclusionRule;
import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -29,8 +31,6 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* This interface should be considered experimental and will likely change in future releases of HAPI. Use with caution! * This interface should be considered experimental and will likely change in future releases of HAPI. Use with caution!

View File

@ -23,10 +23,10 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.annotation.Patch; import ca.uhn.fhir.rest.annotation.Patch;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import jakarta.annotation.Nonnull;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;

View File

@ -19,7 +19,7 @@
*/ */
package ca.uhn.fhir.rest.api; package ca.uhn.fhir.rest.api;
import javax.annotation.Nullable; import jakarta.annotation.Nullable;
public class PreferHeader { public class PreferHeader {

View File

@ -19,8 +19,9 @@
*/ */
package ca.uhn.fhir.rest.api; package ca.uhn.fhir.rest.api;
import jakarta.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import javax.annotation.Nullable;
/** /**
* Represents values for "return" value as provided in the the <a href="https://tools.ietf.org/html/rfc7240#section-4.2">HTTP Prefer header</a>. * Represents values for "return" value as provided in the the <a href="https://tools.ietf.org/html/rfc7240#section-4.2">HTTP Prefer header</a>.

View File

@ -20,11 +20,11 @@
package ca.uhn.fhir.rest.api; package ca.uhn.fhir.rest.api;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
@CoverageIgnore @CoverageIgnore
public enum RestOperationTypeEnum { public enum RestOperationTypeEnum {

View File

@ -0,0 +1,103 @@
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* 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://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%
*/
package ca.uhn.fhir.rest.client.api;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.Pointcut;
import org.hl7.fhir.instance.model.api.IBaseResource;
import java.util.Objects;
import java.util.StringJoiner;
/**
* Used to pass context to {@link Pointcut#CLIENT_RESPONSE}, including a mutable {@link IHttpResponse}
*/
public class ClientResponseContext {
private final IHttpRequest myHttpRequest;
private IHttpResponse myHttpResponse;
private final IRestfulClient myRestfulClient;
private final FhirContext myFhirContext;
private final Class<? extends IBaseResource> myReturnType;
public ClientResponseContext(
IHttpRequest myHttpRequest,
IHttpResponse theHttpResponse,
IRestfulClient myRestfulClient,
FhirContext theFhirContext,
Class<? extends IBaseResource> theReturnType) {
this.myHttpRequest = myHttpRequest;
this.myHttpResponse = theHttpResponse;
this.myRestfulClient = myRestfulClient;
this.myFhirContext = theFhirContext;
this.myReturnType = theReturnType;
}
public IHttpRequest getHttpRequest() {
return myHttpRequest;
}
public IHttpResponse getHttpResponse() {
return myHttpResponse;
}
public IRestfulClient getRestfulClient() {
return myRestfulClient;
}
public FhirContext getFhirContext() {
return myFhirContext;
}
public Class<? extends IBaseResource> getReturnType() {
return myReturnType;
}
public void setHttpResponse(IHttpResponse theHttpResponse) {
this.myHttpResponse = theHttpResponse;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClientResponseContext that = (ClientResponseContext) o;
return Objects.equals(myHttpRequest, that.myHttpRequest)
&& Objects.equals(myHttpResponse, that.myHttpResponse)
&& Objects.equals(myRestfulClient, that.myRestfulClient)
&& Objects.equals(myFhirContext, that.myFhirContext)
&& Objects.equals(myReturnType, that.myReturnType);
}
@Override
public int hashCode() {
return Objects.hash(myHttpRequest, myHttpResponse, myRestfulClient, myFhirContext, myReturnType);
}
@Override
public String toString() {
return new StringJoiner(", ", ClientResponseContext.class.getSimpleName() + "[", "]")
.add("myHttpRequest=" + myHttpRequest)
.add("myHttpResponse=" + myHttpResponse)
.add("myRestfulClient=" + myRestfulClient)
.add("myFhirContext=" + myFhirContext)
.add("myReturnType=" + myReturnType)
.toString();
}
}

View File

@ -24,10 +24,9 @@ import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestFormatParamStyleEnum; import ca.uhn.fhir.rest.api.RequestFormatParamStyleEnum;
import ca.uhn.fhir.rest.api.SummaryEnum; import ca.uhn.fhir.rest.api.SummaryEnum;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import javax.annotation.Nonnull;
public interface IRestfulClient { public interface IRestfulClient {
/** /**

View File

@ -23,7 +23,9 @@ import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseCoding;
import java.util.*; import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;

View File

@ -27,6 +27,7 @@ import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.QualifiedParamList; import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.DateUtils; import ca.uhn.fhir.util.DateUtils;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -34,7 +35,6 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nonnull;
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.EQUAL; import static ca.uhn.fhir.rest.param.ParamPrefixEnum.EQUAL;
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.GREATERTHAN_OR_EQUALS; import static ca.uhn.fhir.rest.param.ParamPrefixEnum.GREATERTHAN_OR_EQUALS;

View File

@ -19,7 +19,9 @@
*/ */
package ca.uhn.fhir.rest.param; package ca.uhn.fhir.rest.param;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/** /**
* Comparator/qualifier for values used in REST params, such as {@link DateParam}, {@link NumberParam}, and * Comparator/qualifier for values used in REST params, such as {@link DateParam}, {@link NumberParam}, and

View File

@ -19,7 +19,11 @@
*/ */
package ca.uhn.fhir.util; package ca.uhn.fhir.util;
import ca.uhn.fhir.context.*; import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.ICompositeType; import org.hl7.fhir.instance.model.api.ICompositeType;

View File

@ -25,6 +25,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBackboneElement; import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
@ -36,8 +38,6 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.util.Date; import java.util.Date;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/** /**
* This class can be used to build a Bundle resource to be used as a FHIR transaction. Convenience methods provide * This class can be used to build a Bundle resource to be used as a FHIR transaction. Convenience methods provide
@ -196,11 +196,7 @@ public class BundleBuilder {
public UpdateBuilder addTransactionUpdateEntry(IBaseResource theResource) { public UpdateBuilder addTransactionUpdateEntry(IBaseResource theResource) {
Validate.notNull(theResource, "theResource must not be null"); Validate.notNull(theResource, "theResource must not be null");
IIdType id = theResource.getIdElement(); IIdType id = getIdTypeForUpdate(theResource);
if (id.hasIdPart() && !id.hasResourceType()) {
String resourceType = myContext.getResourceType(theResource);
id = id.withResourceType(resourceType);
}
String requestUrl = id.toUnqualifiedVersionless().getValue(); String requestUrl = id.toUnqualifiedVersionless().getValue();
String fullUrl = id.getValue(); String fullUrl = id.getValue();
@ -225,13 +221,29 @@ public class BundleBuilder {
myEntryRequestUrlChild.getMutator().setValue(request, url); myEntryRequestUrlChild.getMutator().setValue(request, url);
// Bundle.entry.request.method // Bundle.entry.request.method
IPrimitiveType<?> method = (IPrimitiveType<?>) addRequestMethod(request, theHttpVerb);
myEntryRequestMethodDef.newInstance(myEntryRequestMethodChild.getInstanceConstructorArguments());
method.setValueAsString(theHttpVerb);
myEntryRequestMethodChild.getMutator().setValue(request, method);
return url; return url;
} }
/**
* Adds an entry containing an update (UPDATE) request without the body of the resource.
* Also sets the Bundle.type value to "transaction" if it is not already set.
*
* @param theResource The resource to update.
*/
public void addTransactionUpdateIdOnlyEntry(IBaseResource theResource) {
setBundleField("type", "transaction");
Validate.notNull(theResource, "theResource must not be null");
IIdType id = getIdTypeForUpdate(theResource);
String requestUrl = id.toUnqualifiedVersionless().getValue();
String fullUrl = id.getValue();
String httpMethod = "PUT";
addIdOnlyEntry(requestUrl, httpMethod, fullUrl);
}
/** /**
* Adds an entry containing an create (POST) request. * Adds an entry containing an create (POST) request.
* Also sets the Bundle.type value to "transaction" if it is not already set. * Also sets the Bundle.type value to "transaction" if it is not already set.
@ -247,20 +259,47 @@ public class BundleBuilder {
String resourceType = myContext.getResourceType(theResource); String resourceType = myContext.getResourceType(theResource);
// Bundle.entry.request.url // Bundle.entry.request.url
IPrimitiveType<?> url = addRequestUrl(request, resourceType);
(IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
url.setValueAsString(resourceType);
myEntryRequestUrlChild.getMutator().setValue(request, url);
// Bundle.entry.request.url // Bundle.entry.request.method
IPrimitiveType<?> method = (IPrimitiveType<?>) addRequestMethod(request, "POST");
myEntryRequestMethodDef.newInstance(myEntryRequestMethodChild.getInstanceConstructorArguments());
method.setValueAsString("POST");
myEntryRequestMethodChild.getMutator().setValue(request, method);
return new CreateBuilder(request); return new CreateBuilder(request);
} }
/**
* Adds an entry containing a create (POST) request without the body of the resource.
* Also sets the Bundle.type value to "transaction" if it is not already set.
*
* @param theResource The resource to create
*/
public void addTransactionCreateEntryIdOnly(IBaseResource theResource) {
setBundleField("type", "transaction");
String requestUrl = myContext.getResourceType(theResource);
String fullUrl = theResource.getIdElement().getValue();
String httpMethod = "POST";
addIdOnlyEntry(requestUrl, httpMethod, fullUrl);
}
private void addIdOnlyEntry(String theRequestUrl, String theHttpMethod, String theFullUrl) {
IBase entry = addEntry();
// Bundle.entry.request
IBase request = myEntryRequestDef.newInstance();
myEntryRequestChild.getMutator().setValue(entry, request);
// Bundle.entry.request.url
addRequestUrl(request, theRequestUrl);
// Bundle.entry.request.method
addRequestMethod(request, theHttpMethod);
// Bundle.entry.fullUrl
addFullUrl(entry, theFullUrl);
}
/** /**
* Adds an entry containing a delete (DELETE) request. * Adds an entry containing a delete (DELETE) request.
* Also sets the Bundle.type value to "transaction" if it is not already set. * Also sets the Bundle.type value to "transaction" if it is not already set.
@ -341,20 +380,44 @@ public class BundleBuilder {
IBase request = addEntryAndReturnRequest(); IBase request = addEntryAndReturnRequest();
// Bundle.entry.request.url // Bundle.entry.request.url
IPrimitiveType<?> url = addRequestUrl(request, theDeleteUrl);
(IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
url.setValueAsString(theDeleteUrl);
myEntryRequestUrlChild.getMutator().setValue(request, url);
// Bundle.entry.request.method // Bundle.entry.request.method
IPrimitiveType<?> method = (IPrimitiveType<?>) addRequestMethod(request, "DELETE");
myEntryRequestMethodDef.newInstance(myEntryRequestMethodChild.getInstanceConstructorArguments());
method.setValueAsString("DELETE");
myEntryRequestMethodChild.getMutator().setValue(request, method);
return new DeleteBuilder(); return new DeleteBuilder();
} }
private IIdType getIdTypeForUpdate(IBaseResource theResource) {
IIdType id = theResource.getIdElement();
if (id.hasIdPart() && !id.hasResourceType()) {
String resourceType = myContext.getResourceType(theResource);
id = id.withResourceType(resourceType);
}
return id;
}
private void addFullUrl(IBase theEntry, String theFullUrl) {
IPrimitiveType<?> fullUrl =
(IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
fullUrl.setValueAsString(theFullUrl);
myEntryFullUrlChild.getMutator().setValue(theEntry, fullUrl);
}
private void addRequestUrl(IBase request, String theRequestUrl) {
IPrimitiveType<?> url =
(IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
url.setValueAsString(theRequestUrl);
myEntryRequestUrlChild.getMutator().setValue(request, url);
}
private void addRequestMethod(IBase theRequest, String theMethod) {
IPrimitiveType<?> method = (IPrimitiveType<?>)
myEntryRequestMethodDef.newInstance(myEntryRequestMethodChild.getInstanceConstructorArguments());
method.setValueAsString(theMethod);
myEntryRequestMethodChild.getMutator().setValue(theRequest, method);
}
/** /**
* Adds an entry for a Collection bundle type * Adds an entry for a Collection bundle type
*/ */
@ -406,10 +469,7 @@ public class BundleBuilder {
IBase entry = addEntry(); IBase entry = addEntry();
// Bundle.entry.fullUrl // Bundle.entry.fullUrl
IPrimitiveType<?> fullUrl = addFullUrl(entry, theFullUrl);
(IPrimitiveType<?>) myContext.getElementDefinition("uri").newInstance();
fullUrl.setValueAsString(theFullUrl);
myEntryFullUrlChild.getMutator().setValue(entry, fullUrl);
// Bundle.entry.resource // Bundle.entry.resource
myEntryResourceChild.getMutator().setValue(entry, theResource); myEntryResourceChild.getMutator().setValue(entry, theResource);

View File

@ -35,10 +35,12 @@ import ca.uhn.fhir.util.bundle.EntryListAccumulator;
import ca.uhn.fhir.util.bundle.ModifiableBundleEntry; import ca.uhn.fhir.util.bundle.ModifiableBundleEntry;
import ca.uhn.fhir.util.bundle.SearchBundleEntryParts; import ca.uhn.fhir.util.bundle.SearchBundleEntryParts;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBinary; import org.hl7.fhir.instance.model.api.IBaseBinary;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -693,6 +695,25 @@ public class BundleUtil {
return bundleEntry; return bundleEntry;
} }
/**
* Get resource from bundle by resource type and reference
* @param theContext FhirContext
* @param theBundle IBaseBundle
* @param theReference IBaseReference
* @return IBaseResource if found and null if not found.
*/
@Nonnull
public static IBaseResource getResourceByReferenceAndResourceType(
@Nonnull FhirContext theContext, @Nonnull IBaseBundle theBundle, @Nonnull IBaseReference theReference) {
return toListOfResources(theContext, theBundle).stream()
.filter(theResource -> theReference
.getReferenceElement()
.getIdPart()
.equals(theResource.getIdElement().getIdPart()))
.findFirst()
.orElse(null);
}
private static class SortLegality { private static class SortLegality {
private boolean myIsLegal; private boolean myIsLegal;

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import jakarta.annotation.Nonnull;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BOMInputStream; import org.apache.commons.io.input.BOMInputStream;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -37,7 +38,6 @@ import java.io.Reader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.function.Function; import java.util.function.Function;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import javax.annotation.Nonnull;
/** /**
* Use this API with caution, it may change! * Use this API with caution, it may change!

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.util;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseReference; import org.hl7.fhir.instance.model.api.IBaseReference;
@ -29,7 +30,6 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.util.Date; import java.util.Date;
import javax.annotation.Nonnull;
/** /**
* This class can be used to generate <code>Composition</code> resources in * This class can be used to generate <code>Composition</code> resources in

View File

@ -20,10 +20,10 @@
package ca.uhn.fhir.util; package ca.uhn.fhir.util;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import java.util.Date; import java.util.Date;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class DateRangeUtil { public class DateRangeUtil {

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.util;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
@ -33,7 +34,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
/** /**
* Utility for modifying with extensions in a FHIR version-independent approach. * Utility for modifying with extensions in a FHIR version-independent approach.

View File

@ -42,6 +42,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
@ -71,8 +73,6 @@ import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
@ -287,9 +287,33 @@ public class FhirTerser {
return retVal; return retVal;
} }
/**
* Extracts all outbound references from a resource
*
* @param theResource the resource to be analyzed
* @return a list of references to other resources
*/
public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) { public List<ResourceReferenceInfo> getAllResourceReferences(final IBaseResource theResource) {
return getAllResourceReferencesExcluding(theResource, Lists.newArrayList());
}
/**
* Extracts all outbound references from a resource, excluding any that are located on black-listed parts of the
* resource
*
* @param theResource the resource to be analyzed
* @param thePathsToExclude a list of dot-delimited paths not to include in the result
* @return a list of references to other resources
*/
public List<ResourceReferenceInfo> getAllResourceReferencesExcluding(
final IBaseResource theResource, List<String> thePathsToExclude) {
final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<>(); final ArrayList<ResourceReferenceInfo> retVal = new ArrayList<>();
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource); BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
List<List<String>> tokenizedPathsToExclude = thePathsToExclude.stream()
.map(path -> StringUtils.split(path, "."))
.map(Lists::newArrayList)
.collect(Collectors.toList());
visit(newMap(), theResource, theResource, null, null, def, new IModelVisitor() { visit(newMap(), theResource, theResource, null, null, def, new IModelVisitor() {
@Override @Override
public void acceptElement( public void acceptElement(
@ -301,6 +325,10 @@ public class FhirTerser {
if (theElement == null || theElement.isEmpty()) { if (theElement == null || theElement.isEmpty()) {
return; return;
} }
if (thePathToElement != null && pathShouldBeExcluded(tokenizedPathsToExclude, thePathToElement)) {
return;
}
if (IBaseReference.class.isAssignableFrom(theElement.getClass())) { if (IBaseReference.class.isAssignableFrom(theElement.getClass())) {
retVal.add(new ResourceReferenceInfo( retVal.add(new ResourceReferenceInfo(
myContext, theOuterResource, thePathToElement, (IBaseReference) theElement)); myContext, theOuterResource, thePathToElement, (IBaseReference) theElement));
@ -310,6 +338,19 @@ public class FhirTerser {
return retVal; return retVal;
} }
private boolean pathShouldBeExcluded(List<List<String>> theTokenizedPathsToExclude, List<String> thePathToElement) {
return theTokenizedPathsToExclude.stream().anyMatch(p -> {
// Check whether the path to the element starts with the path to be excluded
if (p.size() > thePathToElement.size()) {
return false;
}
List<String> prefix = thePathToElement.subList(0, p.size());
return Objects.equals(p, prefix);
});
}
private BaseRuntimeChildDefinition getDefinition( private BaseRuntimeChildDefinition getDefinition(
BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) { BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0)); BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));

View File

@ -27,12 +27,12 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import jakarta.annotation.Nonnull;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
public class JsonUtil { public class JsonUtil {

View File

@ -28,6 +28,9 @@ public class Logs {
private static final Logger ourNarrativeGenerationTroubleshootingLog = private static final Logger ourNarrativeGenerationTroubleshootingLog =
LoggerFactory.getLogger("ca.uhn.fhir.log.narrative_generation_troubleshooting"); LoggerFactory.getLogger("ca.uhn.fhir.log.narrative_generation_troubleshooting");
private static final Logger ourTerminologyTroubleshootingLog =
LoggerFactory.getLogger("ca.uhn.fhir.log.terminology_troubleshooting");
private static final Logger ourSubscriptionTroubleshootingLog = private static final Logger ourSubscriptionTroubleshootingLog =
LoggerFactory.getLogger("ca.cdr.log.subscription_troubleshooting"); LoggerFactory.getLogger("ca.cdr.log.subscription_troubleshooting");
@ -42,6 +45,10 @@ public class Logs {
return ourBatchTroubleshootingLog; return ourBatchTroubleshootingLog;
} }
public static Logger getTerminologyTroubleshootingLog() {
return ourTerminologyTroubleshootingLog;
}
public static Logger getSubscriptionTroubleshootingLog() { public static Logger getSubscriptionTroubleshootingLog() {
return ourSubscriptionTroubleshootingLog; return ourSubscriptionTroubleshootingLog;
} }

View File

@ -28,6 +28,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
@ -36,7 +37,6 @@ import org.hl7.fhir.instance.model.api.ICompositeType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -27,6 +27,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseDatatype; import org.hl7.fhir.instance.model.api.IBaseDatatype;
@ -45,7 +46,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank; import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
@ -403,8 +403,15 @@ public class ParametersUtil {
public static void addPartDecimal(FhirContext theContext, IBase theParameter, String theName, Double theValue) { public static void addPartDecimal(FhirContext theContext, IBase theParameter, String theName, Double theValue) {
IPrimitiveType<BigDecimal> value = (IPrimitiveType<BigDecimal>) IPrimitiveType<BigDecimal> value = (IPrimitiveType<BigDecimal>)
theContext.getElementDefinition("decimal").newInstance(); theContext.getElementDefinition("decimal").newInstance();
value.setValue(theValue == null ? null : BigDecimal.valueOf(theValue)); if (theValue == null) {
value.setValue(null);
} else {
BigDecimal decimalValue = BigDecimal.valueOf(theValue);
if (decimalValue.scale() < 0) {
decimalValue = decimalValue.setScale(0);
}
value.setValue(decimalValue);
}
addPart(theContext, theParameter, theName, value); addPart(theContext, theParameter, theName, value);
} }

View File

@ -22,6 +22,7 @@ package ca.uhn.fhir.util;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import jakarta.annotation.Nonnull;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -39,7 +40,6 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
public class ReflectionUtil { public class ReflectionUtil {

View File

@ -24,6 +24,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -34,7 +35,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class SearchParameterUtil { public class SearchParameterUtil {

View File

@ -0,0 +1,57 @@
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* 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://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%
*/
package ca.uhn.fhir.util;
import com.google.common.collect.Iterators;
import com.google.common.collect.UnmodifiableIterator;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class StreamUtil {
/** Static util class */
private StreamUtil() {}
/**
* Chunk the stream into Lists of size theChunkSize.
* The last chunk will be smaller unless the stream size is evenly divisible.
* Closes the underlying stream when done.
*
* @param theStream the input stream
* @param theChunkSize the chunk size.
* @return a stream of chunks
*/
public static <T> Stream<List<T>> partition(Stream<T> theStream, int theChunkSize) {
Spliterator<T> spliterator = theStream.spliterator();
Iterator<T> iterator = Spliterators.iterator(spliterator);
UnmodifiableIterator<List<T>> partition = Iterators.partition(iterator, theChunkSize);
// we could be fancier here and support parallel, and sizes; but serial-only is fine for now.
Spliterator<List<T>> partitionedSpliterator = Spliterators.spliteratorUnknownSize(partition, 0);
Stream<List<T>> result = StreamSupport.stream(partitionedSpliterator, false);
// we lose close() via the Iterator. Add it back.
return result.onClose(theStream::close);
}
}

View File

@ -19,11 +19,12 @@
*/ */
package ca.uhn.fhir.util; package ca.uhn.fhir.util;
import jakarta.annotation.Nonnull;
import java.io.CharArrayWriter; import java.io.CharArrayWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.Normalizer; import java.text.Normalizer;
import java.util.Arrays; import java.util.Arrays;
import javax.annotation.Nonnull;
public class StringUtil { public class StringUtil {

View File

@ -348,7 +348,30 @@ public final class TerserUtil {
public static void clearField(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) { public static void clearField(FhirContext theFhirContext, IBaseResource theResource, String theFieldName) {
BaseRuntimeChildDefinition childDefinition = BaseRuntimeChildDefinition childDefinition =
getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theResource); getBaseRuntimeChildDefinition(theFhirContext, theFieldName, theResource);
clear(childDefinition.getAccessor().getValues(theResource)); childDefinition.getMutator().setValue(theResource, null);
}
/**
* Clears the specified field on the resource provided by the FHIRPath. If more than one value matches
* the FHIRPath, all values will be cleared.
*
* @param theFhirContext
* @param theResource
* @param theFhirPath
*/
public static void clearFieldByFhirPath(FhirContext theFhirContext, IBaseResource theResource, String theFhirPath) {
if (theFhirPath.contains(".")) {
String parentPath = theFhirPath.substring(0, theFhirPath.lastIndexOf("."));
String fieldName = theFhirPath.substring(theFhirPath.lastIndexOf(".") + 1);
FhirTerser terser = theFhirContext.newTerser();
List<IBase> parents = terser.getValues(theResource, parentPath);
for (IBase parent : parents) {
clearField(theFhirContext, fieldName, parent);
}
} else {
clearField(theFhirContext, theResource, theFhirPath);
}
} }
/** /**
@ -362,7 +385,16 @@ public final class TerserUtil {
BaseRuntimeElementDefinition definition = theFhirContext.getElementDefinition(theBase.getClass()); BaseRuntimeElementDefinition definition = theFhirContext.getElementDefinition(theBase.getClass());
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName); BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
Validate.notNull(childDefinition); Validate.notNull(childDefinition);
clear(childDefinition.getAccessor().getValues(theBase)); BaseRuntimeChildDefinition.IAccessor accessor = childDefinition.getAccessor();
clear(accessor.getValues(theBase));
List<IBase> newValue = accessor.getValues(theBase);
if (newValue != null && !newValue.isEmpty()) {
// Our clear failed, probably because it was an immutable SingletonList returned by a FieldPlainAccessor
// that cannot be cleared.
// Let's just null it out instead.
childDefinition.getMutator().setValue(theBase, null);
}
} }
/** /**

View File

@ -28,6 +28,8 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import com.google.common.escape.Escaper; import com.google.common.escape.Escaper;
import com.google.common.net.PercentEscaper; import com.google.common.net.PercentEscaper;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.client.utils.URLEncodedUtils;
@ -50,8 +52,6 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank; import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.defaultString; import static org.apache.commons.lang3.StringUtils.defaultString;

View File

@ -123,8 +123,15 @@ public enum VersionEnum {
V6_8_0, V6_8_0,
V6_8_1, V6_8_1,
V6_8_2, V6_8_2,
V6_8_3,
V6_8_4,
V6_8_5,
V6_9_0, V6_9_0,
V6_10_0,
V6_10_1,
V6_11_0,
V7_0_0; V7_0_0;
public static VersionEnum latestVersion() { public static VersionEnum latestVersion() {

View File

@ -24,7 +24,8 @@ import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.Lang; import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.riot.RDFDataMgr;
import java.io.*; import java.io.Reader;
import java.io.Writer;
public class RDFUtil { public class RDFUtil {

View File

@ -21,9 +21,9 @@ package ca.uhn.fhir.validation;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import jakarta.annotation.Nonnull;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
public interface IValidationContext<T> { public interface IValidationContext<T> {

View File

@ -26,11 +26,11 @@ import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ObjectUtil; import ca.uhn.fhir.util.ObjectUtil;
import jakarta.annotation.Nonnull;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;

View File

@ -37,8 +37,8 @@ import com.helger.commons.io.resource.ClassPathResource;
import com.helger.commons.io.resource.IReadableResource; import com.helger.commons.io.resource.IReadableResource;
import com.helger.schematron.ISchematronResource; import com.helger.schematron.ISchematronResource;
import com.helger.schematron.SchematronHelper; import com.helger.schematron.SchematronHelper;
import com.helger.schematron.sch.SchematronResourceSCH;
import com.helger.schematron.svrl.jaxb.SchematronOutputType; import com.helger.schematron.svrl.jaxb.SchematronOutputType;
import com.helger.schematron.xslt.SchematronResourceSCH;
import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -90,7 +90,12 @@ public class SchematronBaseValidator implements IValidatorModule {
} }
StreamSource source = new StreamSource(new StringReader(resourceAsString)); StreamSource source = new StreamSource(new StringReader(resourceAsString));
SchematronOutputType results = SchematronHelper.applySchematron(sch, source); SchematronOutputType results;
try {
results = sch.applySchematronValidationToSVRL(source);
} catch (Exception e) {
throw new InternalErrorException(Msg.code(2433) + e.getMessage(), e);
}
if (results == null) { if (results == null) {
return; return;
} }

View File

@ -19,7 +19,7 @@
*/ */
package org.hl7.fhir.instance.model.api; package org.hl7.fhir.instance.model.api;
import javax.annotation.Nullable; import jakarta.annotation.Nullable;
public interface IPrimitiveType<T> extends IBaseDatatype { public interface IPrimitiveType<T> extends IBaseDatatype {

View File

@ -206,10 +206,3 @@ ca.uhn.fhir.jpa.provider.DiffProvider.cantDiffDifferentTypes=Unable to diff two
ca.uhn.fhir.jpa.interceptor.validation.RuleRequireProfileDeclaration.noMatchingProfile=Resource of type "{0}" does not declare conformance to profile from: {1} ca.uhn.fhir.jpa.interceptor.validation.RuleRequireProfileDeclaration.noMatchingProfile=Resource of type "{0}" does not declare conformance to profile from: {1}
ca.uhn.fhir.jpa.interceptor.validation.RuleRequireProfileDeclaration.illegalProfile=Resource of type "{0}" must not declare conformance to profile: {1} ca.uhn.fhir.jpa.interceptor.validation.RuleRequireProfileDeclaration.illegalProfile=Resource of type "{0}" must not declare conformance to profile: {1}
operation.member.match.error.coverage.not.found=Could not find coverage for member based on coverage id or coverage identifier.
operation.member.match.error.beneficiary.not.found=Could not find beneficiary for coverage.
operation.member.match.error.missing.parameter=Parameter "{0}" is required.
operation.member.match.error.beneficiary.without.identifier=Coverage beneficiary does not have an identifier.
operation.member.match.error.patient.not.found=Could not find matching patient for coverage.
operation.member.match.error.consent.release.data.mismatch=Consent policy does not match the data release segmentation capabilities.

View File

@ -1,12 +1,14 @@
package ca.uhn.fhir.i18n; package ca.uhn.fhir.i18n;
import static org.hamcrest.Matchers.*; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.Set; import java.util.Set;
import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class HapiLocalizerTest { public class HapiLocalizerTest {

View File

@ -2,7 +2,8 @@ package ca.uhn.fhir.model.api;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
public class ResourceMetadataKeyEnumTest { public class ResourceMetadataKeyEnumTest {

View File

@ -5,7 +5,10 @@ import org.junit.jupiter.api.Test;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TagTest { public class TagTest {

View File

@ -5,7 +5,9 @@ import org.junit.jupiter.api.Test;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class CacheControlDirectiveTest { public class CacheControlDirectiveTest {

View File

@ -2,7 +2,7 @@ package ca.uhn.fhir.rest.api;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
public class EncodingEnumTest { public class EncodingEnumTest {

View File

@ -7,7 +7,8 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Optional; import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class MethodOutcomeTest { class MethodOutcomeTest {

View File

@ -17,7 +17,9 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;
public class DateParamTest { public class DateParamTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DateParamTest.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DateParamTest.class);

View File

@ -3,7 +3,8 @@ package ca.uhn.fhir.rest.param;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class QualifierDetailsTest { public class QualifierDetailsTest {

View File

@ -1,14 +1,11 @@
package ca.uhn.fhir.rest.param; package ca.uhn.fhir.rest.param;
import static ca.uhn.fhir.rest.api.Constants.PARAMQUALIFIER_STRING_TEXT;
import static org.junit.jupiter.api.Assertions.*;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender; import ch.qos.logback.core.read.ListAppender;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
@ -18,12 +15,17 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static ca.uhn.fhir.rest.api.Constants.PARAMQUALIFIER_STRING_TEXT;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class StringParamTest { public class StringParamTest {

View File

@ -2,7 +2,7 @@ package ca.uhn.fhir.rest.server.exceptions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertTrue;
public class BaseServerResponseExceptionTest { public class BaseServerResponseExceptionTest {

View File

@ -5,7 +5,6 @@ import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
@ -19,7 +18,9 @@ import static ca.uhn.fhir.rest.param.ParamPrefixEnum.GREATERTHAN_OR_EQUALS;
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.LESSTHAN; import static ca.uhn.fhir.rest.param.ParamPrefixEnum.LESSTHAN;
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.LESSTHAN_OR_EQUALS; import static ca.uhn.fhir.rest.param.ParamPrefixEnum.LESSTHAN_OR_EQUALS;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
class DateRangeUtilTest { class DateRangeUtilTest {

View File

@ -5,7 +5,11 @@ import org.slf4j.Logger;
import org.slf4j.event.Level; import org.slf4j.event.Level;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
public class LogUtilTest { public class LogUtilTest {

View File

@ -1,15 +1,17 @@
package ca.uhn.fhir.util; package ca.uhn.fhir.util;
import static org.junit.jupiter.api.Assertions.*; import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.i18n.Msg;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ca.uhn.fhir.i18n.Msg; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import ca.uhn.fhir.context.ConfigurationException; import static org.junit.jupiter.api.Assertions.fail;
public class ReflectionUtilTest { public class ReflectionUtilTest {

View File

@ -0,0 +1,65 @@
package ca.uhn.fhir.util;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
class StreamUtilTest {
@ParameterizedTest
@MethodSource("streamPartitionTestCases")
void testStreamPartitionBy4(String theCase, List<Integer> theInput, List<List<Integer>> theOutput) {
List<List<Integer>> result = StreamUtil.partition(theInput.stream(), 4).toList();
assertEquals(theOutput, result, theCase);
}
static Object[][] streamPartitionTestCases() {
return new Object[][]{
{
"empty list produces empty stream",
List.of(),
List.of()
},
{
"short list produces single chunk",
List.of(1, 2, 3),
List.of(List.of(1, 2, 3))
},
{
"longer list produces several chunks",
List.of(1, 2, 3, 1, 2, 3, 1, 2, 3),
List.of(List.of(1, 2, 3, 1), List.of(2, 3, 1, 2), List.of(3))
},
{
"even size produces even chunks",
List.of(1, 2, 3,4,5,6,7,8),
List.of(List.of(1, 2, 3,4), List.of(5,6,7,8))
},
};
}
@Test
void testStreamPartitionClosesOriginalStream() {
// given
AtomicBoolean closed = new AtomicBoolean(false);
Stream<Integer> baseStream = Stream.of(1, 2, 3).onClose(()->closed.set(true));
// when
StreamUtil.partition(baseStream, 2).close();
// then
assertThat("partition closed underlying stream", closed.get());
}
}

View File

@ -8,7 +8,7 @@ import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import javax.annotation.Nonnull; import jakarta.annotation.Nonnull;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;

View File

@ -1,9 +1,9 @@
package ca.uhn.fhir.validation; package ca.uhn.fhir.validation;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ResultSeverityEnumTest { public class ResultSeverityEnumTest {
@Test @Test

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId> <artifactId>hapi-fhir-bom</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>HAPI FHIR BOM</name> <name>HAPI FHIR BOM</name>
@ -12,7 +12,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -42,7 +42,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.puppycrawl.tools</groupId> <groupId>com.puppycrawl.tools</groupId>
@ -109,7 +108,6 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven_checkstyle_version}</version>
<configuration> <configuration>
<excludes>**/osgi/**/*, **/.mvn/**/*, **/.mvn_/**/*</excludes> <excludes>**/osgi/**/*, **/.mvn/**/*, **/.mvn_/**/*</excludes>
<sourceDirectories> <sourceDirectories>

View File

@ -18,15 +18,32 @@
<property name="format" value="(?i)FIXME"/> <property name="format" value="(?i)FIXME"/>
</module> </module>
<!-- Ban star imports - TODO: enable this -->
<!--
<module name="RegexpSinglelineJava">
<property name="format" value="^import .*\*;"/>
</module>
-->
<module name="RegexpSinglelineJava"> <module name="RegexpSinglelineJava">
<property name="format" value="System\.out\.println"/> <property name="format" value="System\.out\.println"/>
<property name="ignoreComments" value="true"/> <property name="ignoreComments" value="true"/>
</module> </module>
<module name="RegexpSinglelineJava"> <module name="RegexpSinglelineJava">
<property name="format" value="org\.jetbrains\.annotations\.NotNull"/> <property name="format" value="org\.jetbrains\.annotations\.NotNull"/>
<property name="message" value="Incorrect &quot;org.jetbrains.annotation.NotNull&quot; annotation used: The &quot;jakarta.annotation.Nonnull&quot; annotation should be used for non-null values"/>
</module> </module>
<module name="RegexpSinglelineJava"> <module name="RegexpSinglelineJava">
<property name="format" value="org\.jetbrains\.annotations\.Nullable"/> <property name="format" value="org\.jetbrains\.annotations\.Nullable"/>
<property name="message" value="Incorrect &quot;org.jetbrains.annotation.Nullable&quot; annotation used: The &quot;jakarta.annotation.Nullable&quot; annotation should be used for nullable values"/>
</module>
<module name="RegexpSinglelineJava">
<property name="format" value="javax\.annotation\.Nonnull"/>
<property name="message" value="Incorrect &quot;javax.annotation.Nonnull&quot; used: &quot;jakarta.annotation.Nonnull&quot; should be used for non-null values"/>
</module>
<module name="RegexpSinglelineJava">
<property name="format" value="javax\.annotation\.Nullable"/>
<property name="message" value="Incorrect &quot;javax.annotation.Nullable&quot; used: &quot;jakarta.annotation.Nonnull&quot; should be used for nullable values"/>
</module> </module>
<!-- Should always use the Spring transactional interface, per: https://stackoverflow.com/questions/26387399/javax-transaction-transactional-vs-org-springframework-transaction-annotation-tr --> <!-- Should always use the Spring transactional interface, per: https://stackoverflow.com/questions/26387399/javax-transaction-transactional-vs-org-springframework-transaction-annotation-tr -->
<module name="RegexpSinglelineJava"> <module name="RegexpSinglelineJava">

View File

@ -73,7 +73,11 @@ public final class HapiErrorCodeCheck extends AbstractCheck {
} else { } else {
String location = getFilePath() + ":" + instantiation.getLineNo() + ":" String location = getFilePath() + ":" + instantiation.getLineNo() + ":"
+ instantiation.getColumnNo() + "(" + code + ")"; + instantiation.getColumnNo() + "(" + code + ")";
ourCache.put(code, location); // Ignore errors thrown in test for duplicates, as some fake implementations are throwing the same
// codes for test purpsoes.
if (!location.contains("/test/")) {
ourCache.put(code, location);
}
} }
} else { } else {
log(theAst.getLineNo(), "Called Msg.code() with a non-integer argument"); log(theAst.getLineNo(), "Called Msg.code() with a non-integer argument");

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>6.9.7-SNAPSHOT</version> <version>6.11.7-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -152,38 +152,25 @@
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<!-- Web Server -->
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty.ee10.websocket</groupId>
<artifactId>jetty-servlets</artifactId> <artifactId>jetty-ee10-websocket-jakarta-client</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>jakarta.websocket</groupId>
<artifactId>jetty-servlet</artifactId> <artifactId>jakarta.websocket-client-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId> <artifactId>jetty-server</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-util</artifactId> <artifactId>jetty-ee10-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-core-client</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-jetty-client</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId> <artifactId>jcl-over-slf4j</artifactId>
@ -195,39 +182,17 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.thymeleaf</groupId> <groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId> <artifactId>thymeleaf-spring6</artifactId>
</dependency> </dependency>
<!-- Dependencies for Schematron --> <!-- Dependencies for Schematron -->
<dependency> <dependency>
<groupId>com.helger</groupId> <groupId>com.helger.schematron</groupId>
<artifactId>ph-schematron</artifactId> <artifactId>ph-schematron-api</artifactId>
<exclusions>
<exclusion>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons-runtime</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.helger</groupId> <groupId>com.helger.schematron</groupId>
<artifactId>ph-commons</artifactId> <artifactId>ph-schematron-xslt</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency> </dependency>
@ -257,11 +222,30 @@
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.simplejavamail</groupId>
<artifactId>simple-java-mail</artifactId>
<!-- Excluded in favor of jakarta.activation:jakarta.activation-api -->
<exclusions>
<exclusion>
<groupId>com.sun.activation</groupId>
<artifactId>jakarta.activation</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>none</parallel>
<reuseForks>false</reuseForks>
<forkCount>1</forkCount>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -34,6 +34,7 @@ import com.google.common.base.Charsets;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import jakarta.annotation.Nullable;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option; import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.OptionGroup;
@ -75,7 +76,6 @@ import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import javax.annotation.Nullable;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;

View File

@ -31,6 +31,7 @@ import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ParametersUtil; import ca.uhn.fhir.util.ParametersUtil;
import jakarta.annotation.Nonnull;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
@ -40,11 +41,12 @@ import org.apache.commons.io.file.PathUtils;
import org.apache.commons.io.filefilter.FileFileFilter; import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.lang3.time.DateUtils;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.eclipse.jetty.ee10.servlet.ServletHolder;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -67,7 +69,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import javax.annotation.Nonnull;
public class BulkImportCommand extends BaseCommand { public class BulkImportCommand extends BaseCommand {
@ -234,7 +235,12 @@ public class BulkImportCommand extends BaseCommand {
private List<String> startServer(int thePort, List<File> files) { private List<String> startServer(int thePort, List<File> files) {
List<String> indexes = new ArrayList<>(); List<String> indexes = new ArrayList<>();
myServer = new Server(thePort);
myServer = new Server();
ServerConnector connector = new ServerConnector(myServer);
connector.setIdleTimeout(DateUtils.MILLIS_PER_MINUTE);
connector.setPort(myPort);
myServer.setConnectors(new Connector[] {connector});
myServlet = new BulkImportFileServlet(); myServlet = new BulkImportFileServlet();
for (File t : files) { for (File t : files) {

View File

@ -36,6 +36,11 @@ public class LoadingValidationSupportDstu2 implements IValidationSupport {
private static final org.slf4j.Logger ourLog = private static final org.slf4j.Logger ourLog =
org.slf4j.LoggerFactory.getLogger(LoadingValidationSupportDstu2.class); org.slf4j.LoggerFactory.getLogger(LoadingValidationSupportDstu2.class);
@Override
public String getName() {
return "Dstu2 CLI Loading Validation Support";
}
@Override @Override
public <T extends IBaseResource> T fetchResource(Class<T> theClass, String theUri) { public <T extends IBaseResource> T fetchResource(Class<T> theClass, String theUri) {
String resName = myCtx.getResourceType(theClass); String resName = myCtx.getResourceType(theClass);

View File

@ -35,6 +35,11 @@ public class LoadingValidationSupportDstu3 implements IValidationSupport {
private static final org.slf4j.Logger ourLog = private static final org.slf4j.Logger ourLog =
org.slf4j.LoggerFactory.getLogger(LoadingValidationSupportDstu3.class); org.slf4j.LoggerFactory.getLogger(LoadingValidationSupportDstu3.class);
@Override
public String getName() {
return "Dstu3 CLI Loading Validation Support";
}
@Override @Override
public <T extends IBaseResource> T fetchResource(Class<T> theClass, String theUri) { public <T extends IBaseResource> T fetchResource(Class<T> theClass, String theUri) {
String resName = myCtx.getResourceType(theClass); String resName = myCtx.getResourceType(theClass);

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.util.ParametersUtil; import ca.uhn.fhir.util.ParametersUtil;
import joptsimple.internal.Strings; import jakarta.annotation.Nonnull;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseParameters;
@ -32,7 +32,6 @@ import org.hl7.fhir.r4.model.Parameters;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull;
import static ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider.RESP_PARAM_SUCCESS; import static ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider.RESP_PARAM_SUCCESS;
@ -111,7 +110,7 @@ public class ReindexTerminologyCommand extends BaseRequestGeneratingCommand {
@Nonnull @Nonnull
private String getResponseMessage(IBaseParameters response) { private String getResponseMessage(IBaseParameters response) {
List<String> message = ParametersUtil.getNamedParameterValuesAsString(myFhirCtx, response, "message"); List<String> message = ParametersUtil.getNamedParameterValuesAsString(myFhirCtx, response, "message");
return Strings.join(message, NL); return String.join(NL, message);
} }
public static final String NL = System.getProperty("line.separator"); public static final String NL = System.getProperty("line.separator");

View File

@ -21,19 +21,17 @@ package ca.uhn.fhir.cli;
import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import jakarta.websocket.ClientEndpoint;
import jakarta.websocket.ContainerProvider;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.WebSocketContainer;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options; import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.eclipse.jetty.websocket.api.Frame;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import java.net.URI; import java.net.URI;
@ -46,6 +44,7 @@ public class WebsocketSubscribeCommand extends BaseCommand {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(WebsocketSubscribeCommand.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(WebsocketSubscribeCommand.class);
private boolean myQuit; private boolean myQuit;
private Session mySession;
@Override @Override
public String getCommandDescription() { public String getCommandDescription() {
@ -75,14 +74,13 @@ public class WebsocketSubscribeCommand extends BaseCommand {
IdDt subsId = new IdDt(theCommandLine.getOptionValue("i")); IdDt subsId = new IdDt(theCommandLine.getOptionValue("i"));
WebSocketClient client = new WebSocketClient();
SimpleEchoSocket socket = new SimpleEchoSocket(subsId.getIdPart()); SimpleEchoSocket socket = new SimpleEchoSocket(subsId.getIdPart());
try { try {
client.start();
URI echoUri = new URI(target); URI echoUri = new URI(target);
ClientUpgradeRequest request = new ClientUpgradeRequest();
ourLog.info("Connecting to : {}", echoUri); ourLog.info("Connecting to : {}", echoUri);
client.connect(socket, echoUri, request);
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
mySession = container.connectToServer(socket, echoUri);
while (!myQuit) { while (!myQuit) {
Thread.sleep(500L); Thread.sleep(500L);
@ -93,7 +91,9 @@ public class WebsocketSubscribeCommand extends BaseCommand {
throw new CommandFailureException(Msg.code(1537) + e); throw new CommandFailureException(Msg.code(1537) + e);
} finally { } finally {
try { try {
client.stop(); if (mySession != null) {
mySession.close();
}
} catch (Exception e) { } catch (Exception e) {
ourLog.error("Failure", e); ourLog.error("Failure", e);
} }
@ -103,7 +103,7 @@ public class WebsocketSubscribeCommand extends BaseCommand {
/** /**
* Basic Echo Client Socket * Basic Echo Client Socket
*/ */
@WebSocket(maxTextMessageSize = 64 * 1024) @ClientEndpoint
public class SimpleEchoSocket { public class SimpleEchoSocket {
private String mySubsId; private String mySubsId;
@ -115,37 +115,32 @@ public class WebsocketSubscribeCommand extends BaseCommand {
mySubsId = theSubsId; mySubsId = theSubsId;
} }
@OnWebSocketClose @OnClose
public void onClose(int statusCode, String reason) { public void onClose(int statusCode, String reason) {
ourLog.info("Received CLOSE status={} reason={}", statusCode, reason); ourLog.info("Received CLOSE status={} reason={}", statusCode, reason);
} }
@OnWebSocketConnect @OnOpen
public void onConnect(Session theSession) { public void onConnect(Session theSession) {
ourLog.info("Successfully connected"); ourLog.info("Successfully connected");
this.session = theSession; this.session = theSession;
try { try {
String sending = "bind " + mySubsId; String sending = "bind " + mySubsId;
LOG_SEND.info("{}", sending); LOG_SEND.info("{}", sending);
theSession.getRemote().sendString(sending); theSession.getBasicRemote().sendText(sending);
} catch (Throwable t) { } catch (Throwable t) {
ourLog.error("Failure", t); ourLog.error("Failure", t);
myQuit = true; myQuit = true;
} }
} }
@OnWebSocketError @OnError
public void onError(Throwable theError) { public void onError(Throwable theError) {
ourLog.error("Websocket error: ", theError); ourLog.error("Websocket error: ", theError);
myQuit = true; myQuit = true;
} }
@OnWebSocketFrame @OnMessage
public void onFrame(Frame theFrame) {
ourLog.debug("Websocket frame: {}", theFrame);
}
@OnWebSocketMessage
public void onMessage(String theMsg) { public void onMessage(String theMsg) {
LOG_RECV.info("{}", theMsg); LOG_RECV.info("{}", theMsg);
} }

Some files were not shown because too many files have changed in this diff Show More