Merge remote-tracking branch 'origin/master' into consent_service_resource_filtering_leads_to_empty_pages_with_next_link

This commit is contained in:
peartree 2023-12-15 10:40:23 -05:00
commit bdf831e803
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(
theContext, property, "value", stringConceptProperty.getValue());
break;
case TYPE_CODING:
CodingConceptProperty codingConceptProperty = (CodingConceptProperty) next;
ParametersUtil.addPartCoding( ParametersUtil.addPartCoding(
theContext, property, "value", prop.getCodeSystem(), prop.getCode(), prop.getDisplay()); theContext,
} else { property,
throw new IllegalStateException(Msg.code(1739) + "Don't know how to handle " + next.getClass()); "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,8 +73,12 @@ public final class HapiErrorCodeCheck extends AbstractCheck {
} else { } else {
String location = getFilePath() + ":" + instantiation.getLineNo() + ":" String location = getFilePath() + ":" + instantiation.getLineNo() + ":"
+ instantiation.getColumnNo() + "(" + code + ")"; + instantiation.getColumnNo() + "(" + code + ")";
// 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); 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