Bump corelib to FHIR R5 Final (#4727)
* Core bump * Build build issues * Bump core * Cleanup * Cleanup * Resolve intermittent * Work on core * Add failing test for a check * Test fixes * Fixes * DOn't mangle subscriptions * Fix * License headers * Build fixes * Version bump * Compile fixes * Fix compile issues
This commit is contained in:
parent
2171ad04a2
commit
e2717bd63a
|
@ -42,8 +42,6 @@ stages:
|
|||
module: hapi-fhir-checkstyle
|
||||
- name: hapi_fhir_cli_api
|
||||
module: hapi-fhir-cli/hapi-fhir-cli-api
|
||||
# - name: hapi_fhir_cli_jpaserver
|
||||
# module: hapi-fhir-cli/hapi-fhir-cli-jpaserver
|
||||
- name: hapi_fhir_client
|
||||
module: hapi-fhir-client
|
||||
- name: hapi_fhir_client_okhttp
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -128,7 +128,7 @@ public class FhirContext {
|
|||
private volatile Boolean myFormatJsonSupported;
|
||||
private volatile Boolean myFormatNDJsonSupported;
|
||||
private volatile Boolean myFormatRdfSupported;
|
||||
private IFhirValidatorFactory myFhirValidatorFactory = fhirContext -> new FhirValidator(fhirContext);
|
||||
private IFhirValidatorFactory myFhirValidatorFactory = FhirValidator::new;
|
||||
|
||||
/**
|
||||
* @deprecated It is recommended that you use one of the static initializer methods instead
|
||||
|
|
|
@ -128,26 +128,22 @@ public enum FhirVersionEnum {
|
|||
return myIsRi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FhirContext for this FHIR version
|
||||
*/
|
||||
public FhirContext newContext() {
|
||||
switch (this) {
|
||||
case DSTU2:
|
||||
return FhirContext.forDstu2();
|
||||
case DSTU2_HL7ORG:
|
||||
return FhirContext.forDstu2Hl7Org();
|
||||
case DSTU2_1:
|
||||
return FhirContext.forDstu2_1();
|
||||
case DSTU3:
|
||||
return FhirContext.forDstu3();
|
||||
case R4:
|
||||
return FhirContext.forR4();
|
||||
case R4B:
|
||||
return FhirContext.forR4B();
|
||||
case R5:
|
||||
return FhirContext.forR5();
|
||||
}
|
||||
throw new IllegalStateException(Msg.code(1711) + "Unknown version: " + this); // should not happen
|
||||
return new FhirContext(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FhirContext for this FHIR version, or returns a previously created one if one exists. This
|
||||
* method uses {@link FhirContext#forCached(FhirVersionEnum)} to return a cached instance.
|
||||
*/
|
||||
public FhirContext newContextCached() {
|
||||
return FhirContext.forCached(this);
|
||||
}
|
||||
|
||||
|
||||
private interface IVersionProvider {
|
||||
String provideVersion();
|
||||
}
|
||||
|
|
|
@ -19,35 +19,20 @@
|
|||
*/
|
||||
package ca.uhn.fhir.context.support;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.parser.LenientErrorHandler;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import ca.uhn.fhir.util.ILockable;
|
||||
import ca.uhn.fhir.util.ReflectionUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/**
|
||||
* This class returns the vocabulary that is shipped with the base FHIR
|
||||
|
@ -61,16 +46,14 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
public class DefaultProfileValidationSupport implements IValidationSupport {
|
||||
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class);
|
||||
private static final Map<FhirVersionEnum, IValidationSupport> ourImplementations = Collections.synchronizedMap(new HashMap<>());
|
||||
private final FhirContext myCtx;
|
||||
|
||||
private Map<String, IBaseResource> myCodeSystems;
|
||||
private Map<String, IBaseResource> myStructureDefinitions;
|
||||
private Map<String, IBaseResource> myValueSets;
|
||||
private List<String> myTerminologyResources;
|
||||
private List<String> myStructureDefinitionResources;
|
||||
/**
|
||||
* This module just delegates all calls to a concrete implementation which will
|
||||
* be in this field. Which implementation gets used depends on the FHIR version.
|
||||
*/
|
||||
private final IValidationSupport myDelegate;
|
||||
private final Runnable myFlush;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -79,202 +62,71 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
*/
|
||||
public DefaultProfileValidationSupport(FhirContext theFhirContext) {
|
||||
myCtx = theFhirContext;
|
||||
}
|
||||
|
||||
IValidationSupport strategy;
|
||||
synchronized (ourImplementations) {
|
||||
strategy = ourImplementations.get(theFhirContext.getVersion().getVersion());
|
||||
|
||||
private void initializeResourceLists() {
|
||||
|
||||
if (myTerminologyResources != null && myStructureDefinitionResources != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> terminologyResources = new ArrayList<>();
|
||||
List<String> structureDefinitionResources = new ArrayList<>();
|
||||
switch (getFhirContext().getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
case DSTU2_HL7ORG:
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml");
|
||||
Properties profileNameProperties = new Properties();
|
||||
try {
|
||||
profileNameProperties.load(DefaultProfileValidationSupport.class.getResourceAsStream("/org/hl7/fhir/instance/model/profile/profiles.properties"));
|
||||
for (Object nextKey : profileNameProperties.keySet()) {
|
||||
structureDefinitionResources.add("/org/hl7/fhir/instance/model/profile/" + nextKey);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException(Msg.code(1740) + e);
|
||||
if (strategy == null) {
|
||||
if (theFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R5)) {
|
||||
/*
|
||||
* I don't love that we use reflection here, but this class is in
|
||||
* hapi-fhir-base, and the class we're creating is in
|
||||
* hapi-fhir-validation. There are complicated dependency chains that
|
||||
* make this hard to clean up. At some point it'd be nice to figure out
|
||||
* a cleaner solution though.
|
||||
*/
|
||||
strategy = ReflectionUtil.newInstance("org.hl7.fhir.common.hapi.validation.support.DefaultProfileValidationSupportNpmStrategy", IValidationSupport.class, new Class[]{FhirContext.class}, new Object[]{theFhirContext});
|
||||
((ILockable)strategy).lock();
|
||||
} else {
|
||||
strategy = new DefaultProfileValidationSupportBundleStrategy(theFhirContext);
|
||||
}
|
||||
break;
|
||||
case DSTU2_1:
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-others.xml");
|
||||
break;
|
||||
case DSTU3:
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R4:
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R4B:
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R5:
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/extension/extension-definitions.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/v3-codesystems.xml");
|
||||
break;
|
||||
ourImplementations.put(theFhirContext.getVersion().getVersion(), strategy);
|
||||
}
|
||||
}
|
||||
|
||||
myTerminologyResources = terminologyResources;
|
||||
myStructureDefinitionResources = structureDefinitionResources;
|
||||
myDelegate = strategy;
|
||||
if (myDelegate instanceof DefaultProfileValidationSupportBundleStrategy) {
|
||||
myFlush = ()->((DefaultProfileValidationSupportBundleStrategy) myDelegate).flush();
|
||||
} else {
|
||||
myFlush = ()->{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources() {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
return myDelegate.fetchAllConformanceResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> List<T> fetchAllStructureDefinitions() {
|
||||
return toList(provideStructureDefinitionMap());
|
||||
return myDelegate.fetchAllStructureDefinitions();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends IBaseResource> List<T> fetchAllNonBaseStructureDefinitions() {
|
||||
return null;
|
||||
return myDelegate.fetchAllNonBaseStructureDefinitions();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchCodeSystem(String theSystem) {
|
||||
return fetchCodeSystemOrValueSet(theSystem, true);
|
||||
}
|
||||
|
||||
private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSystem) {
|
||||
synchronized (this) {
|
||||
Map<String, IBaseResource> codeSystems = myCodeSystems;
|
||||
Map<String, IBaseResource> valueSets = myValueSets;
|
||||
if (codeSystems == null || valueSets == null) {
|
||||
codeSystems = new HashMap<>();
|
||||
valueSets = new HashMap<>();
|
||||
|
||||
initializeResourceLists();
|
||||
for (String next : myTerminologyResources) {
|
||||
loadCodeSystems(codeSystems, valueSets, next);
|
||||
}
|
||||
|
||||
myCodeSystems = codeSystems;
|
||||
myValueSets = valueSets;
|
||||
}
|
||||
|
||||
// System can take the form "http://url|version"
|
||||
String system = theSystem;
|
||||
String version = null;
|
||||
int pipeIdx = system.indexOf('|');
|
||||
if (pipeIdx > 0) {
|
||||
version = system.substring(pipeIdx + 1);
|
||||
system = system.substring(0, pipeIdx);
|
||||
}
|
||||
|
||||
IBaseResource candidate;
|
||||
if (codeSystem) {
|
||||
candidate = codeSystems.get(system);
|
||||
} else {
|
||||
candidate = valueSets.get(system);
|
||||
}
|
||||
|
||||
if (candidate != null && isNotBlank(version) && !system.startsWith("http://hl7.org") && !system.startsWith("http://terminology.hl7.org")) {
|
||||
if (!StringUtils.equals(version, myCtx.newTerser().getSinglePrimitiveValueOrNull(candidate, "version"))) {
|
||||
candidate = null;
|
||||
}
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
return myDelegate.fetchCodeSystem(theSystem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchStructureDefinition(String theUrl) {
|
||||
String url = theUrl;
|
||||
if (!url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
if (url.indexOf('/') == -1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION + url;
|
||||
} else if (StringUtils.countMatches(url, '/') == 1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url;
|
||||
}
|
||||
}
|
||||
Map<String, IBaseResource> structureDefinitionMap = provideStructureDefinitionMap();
|
||||
IBaseResource retVal = structureDefinitionMap.get(url);
|
||||
if (retVal == null) {
|
||||
|
||||
if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
|
||||
/*
|
||||
* A few built-in R4 SearchParameters have the wrong casing for primitive
|
||||
* search parameters eg "value.as(String)" when it should be
|
||||
* "value.as(string)". This lets us be a bit lenient about this.
|
||||
*/
|
||||
if (myCtx.getVersion().getVersion() == FhirVersionEnum.R4 || myCtx.getVersion().getVersion() == FhirVersionEnum.R4B || myCtx.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||
String end = url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length());
|
||||
if (Character.isUpperCase(end.charAt(0))) {
|
||||
String newEnd = Character.toLowerCase(end.charAt(0)) + end.substring(1);
|
||||
String alternateUrl = URL_PREFIX_STRUCTURE_DEFINITION + newEnd;
|
||||
retVal = structureDefinitionMap.get(alternateUrl);
|
||||
if (retVal != null) {
|
||||
retVal = myCtx.newTerser().clone(retVal);
|
||||
myCtx.newTerser().setElement(retVal, "type", end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return retVal;
|
||||
return myDelegate.fetchStructureDefinition(theUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchValueSet(String theUrl) {
|
||||
IBaseResource retVal = fetchCodeSystemOrValueSet(theUrl, false);
|
||||
return retVal;
|
||||
return myDelegate.fetchValueSet(theUrl);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
myCodeSystems = null;
|
||||
myStructureDefinitions = null;
|
||||
myFlush.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -282,152 +134,6 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
return myCtx;
|
||||
}
|
||||
|
||||
private Map<String, IBaseResource> provideStructureDefinitionMap() {
|
||||
Map<String, IBaseResource> structureDefinitions = myStructureDefinitions;
|
||||
if (structureDefinitions == null) {
|
||||
structureDefinitions = new HashMap<>();
|
||||
|
||||
initializeResourceLists();
|
||||
for (String next : myStructureDefinitionResources) {
|
||||
loadStructureDefinitions(structureDefinitions, next);
|
||||
}
|
||||
|
||||
myStructureDefinitions = structureDefinitions;
|
||||
}
|
||||
return structureDefinitions;
|
||||
}
|
||||
|
||||
private void loadCodeSystems(Map<String, IBaseResource> theCodeSystems, Map<String, IBaseResource> theValueSets, String theClasspath) {
|
||||
ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath);
|
||||
InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
InputStreamReader reader = null;
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
reader = new InputStreamReader(inputStream, Constants.CHARSET_UTF8);
|
||||
List<IBaseResource> resources = parseBundle(reader);
|
||||
for (IBaseResource next : resources) {
|
||||
|
||||
RuntimeResourceDefinition nextDef = getFhirContext().getResourceDefinition(next);
|
||||
Map<String, IBaseResource> map = null;
|
||||
switch (nextDef.getName()) {
|
||||
case "CodeSystem":
|
||||
map = theCodeSystems;
|
||||
break;
|
||||
case "ValueSet":
|
||||
map = theValueSets;
|
||||
break;
|
||||
}
|
||||
|
||||
if (map != null) {
|
||||
String urlValueString = getConformanceResourceUrl(next);
|
||||
if (isNotBlank(urlValueString)) {
|
||||
map.put(urlValueString, next);
|
||||
}
|
||||
|
||||
switch (myCtx.getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
case DSTU2_HL7ORG:
|
||||
|
||||
IPrimitiveType<?> codeSystem = myCtx.newTerser().getSingleValueOrNull(next, "ValueSet.codeSystem.system", IPrimitiveType.class);
|
||||
if (codeSystem != null && isNotBlank(codeSystem.getValueAsString())) {
|
||||
theCodeSystems.put(codeSystem.getValueAsString(), next);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
case DSTU2_1:
|
||||
case DSTU3:
|
||||
case R4:
|
||||
case R5:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
ourLog.warn("Failure closing stream", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
|
||||
// Load built-in system
|
||||
|
||||
if (myCtx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
String storageCodeEnum = ClasspathUtil.loadResource("ca/uhn/fhir/context/support/HapiFhirStorageResponseCode.json");
|
||||
IBaseResource storageCodeCodeSystem = myCtx.newJsonParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(storageCodeEnum);
|
||||
String url = myCtx.newTerser().getSinglePrimitiveValueOrNull(storageCodeCodeSystem, "url");
|
||||
theCodeSystems.put(url, storageCodeCodeSystem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void loadStructureDefinitions(Map<String, IBaseResource> theCodeSystems, String theClasspath) {
|
||||
ourLog.info("Loading structure definitions from classpath: {}", theClasspath);
|
||||
|
||||
String packageUserData = null;
|
||||
if (myCtx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
packageUserData = "hl7.fhir." + myCtx.getVersion().getVersion().name().replace("DSTU", "R").toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
try (InputStream valueSetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath)) {
|
||||
if (valueSetText != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(valueSetText, Constants.CHARSET_UTF8)) {
|
||||
|
||||
List<IBaseResource> resources = parseBundle(reader);
|
||||
for (IBaseResource next : resources) {
|
||||
|
||||
String nextType = getFhirContext().getResourceType(next);
|
||||
if ("StructureDefinition".equals(nextType)) {
|
||||
|
||||
String url = getConformanceResourceUrl(next);
|
||||
if (isNotBlank(url)) {
|
||||
theCodeSystems.put(url, next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This is used by the validator to determine which package a given SD came from.
|
||||
// I don't love this use of magic strings but that's what is expected currently
|
||||
if (packageUserData != null) {
|
||||
next.setUserData("package", packageUserData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
} catch (IOException theE) {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
|
||||
private String getConformanceResourceUrl(IBaseResource theResource) {
|
||||
return getConformanceResourceUrl(getFhirContext(), theResource);
|
||||
}
|
||||
|
||||
private List<IBaseResource> parseBundle(InputStreamReader theReader) {
|
||||
IBaseResource parsedObject = getFhirContext().newXmlParser().parseResource(theReader);
|
||||
if (parsedObject instanceof IBaseBundle) {
|
||||
IBaseBundle bundle = (IBaseBundle) parsedObject;
|
||||
return BundleUtil.toListOfResources(getFhirContext(), bundle);
|
||||
} else {
|
||||
return Collections.singletonList(parsedObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getConformanceResourceUrl(FhirContext theFhirContext, IBaseResource theResource) {
|
||||
|
@ -440,8 +146,5 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
return urlValueString;
|
||||
}
|
||||
|
||||
static <T extends IBaseResource> List<T> toList(Map<String, IBaseResource> theMap) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>(theMap.values());
|
||||
return (List<T>) Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,430 @@
|
|||
/*-
|
||||
* #%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 ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.parser.LenientErrorHandler;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
class DefaultProfileValidationSupportBundleStrategy implements IValidationSupport {
|
||||
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION = "http://hl7.org/fhir/StructureDefinition/";
|
||||
private static final String URL_PREFIX_STRUCTURE_DEFINITION_BASE = "http://hl7.org/fhir/";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DefaultProfileValidationSupport.class);
|
||||
private final FhirContext myCtx;
|
||||
|
||||
private Map<String, IBaseResource> myCodeSystems;
|
||||
private Map<String, IBaseResource> myStructureDefinitions;
|
||||
private Map<String, IBaseResource> myValueSets;
|
||||
private List<String> myTerminologyResources;
|
||||
private List<String> myStructureDefinitionResources;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theFhirContext The context to use
|
||||
*/
|
||||
DefaultProfileValidationSupportBundleStrategy(FhirContext theFhirContext) {
|
||||
myCtx = theFhirContext;
|
||||
}
|
||||
|
||||
|
||||
private void initializeResourceLists() {
|
||||
|
||||
if (myTerminologyResources != null && myStructureDefinitionResources != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> terminologyResources = new ArrayList<>();
|
||||
List<String> structureDefinitionResources = new ArrayList<>();
|
||||
switch (getFhirContext().getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
case DSTU2_HL7ORG:
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml");
|
||||
Properties profileNameProperties = new Properties();
|
||||
try {
|
||||
profileNameProperties.load(DefaultProfileValidationSupport.class.getResourceAsStream("/org/hl7/fhir/instance/model/profile/profiles.properties"));
|
||||
for (Object nextKey : profileNameProperties.keySet()) {
|
||||
structureDefinitionResources.add("/org/hl7/fhir/instance/model/profile/" + nextKey);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException(Msg.code(1740) + e);
|
||||
}
|
||||
break;
|
||||
case DSTU2_1:
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu2016may/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu2016may/model/profile/profiles-others.xml");
|
||||
break;
|
||||
case DSTU3:
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/dstu3/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/dstu3/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R4:
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R4B:
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r4b/model/valueset/v3-codesystems.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r4b/model/extension/extension-definitions.xml");
|
||||
break;
|
||||
case R5:
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-resources.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-types.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/profile/profiles-others.xml");
|
||||
structureDefinitionResources.add("/org/hl7/fhir/r5/model/extension/extension-definitions.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/valuesets.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/v2-tables.xml");
|
||||
terminologyResources.add("/org/hl7/fhir/r5/model/valueset/v3-codesystems.xml");
|
||||
break;
|
||||
}
|
||||
|
||||
myTerminologyResources = terminologyResources;
|
||||
myStructureDefinitionResources = structureDefinitionResources;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources() {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
retVal.addAll(myCodeSystems.values());
|
||||
retVal.addAll(myStructureDefinitions.values());
|
||||
retVal.addAll(myValueSets.values());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> List<T> fetchAllStructureDefinitions() {
|
||||
return toList(provideStructureDefinitionMap());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends IBaseResource> List<T> fetchAllNonBaseStructureDefinitions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchCodeSystem(String theSystem) {
|
||||
return fetchCodeSystemOrValueSet(theSystem, true);
|
||||
}
|
||||
|
||||
private IBaseResource fetchCodeSystemOrValueSet(String theSystem, boolean codeSystem) {
|
||||
synchronized (this) {
|
||||
Map<String, IBaseResource> codeSystems = myCodeSystems;
|
||||
Map<String, IBaseResource> valueSets = myValueSets;
|
||||
if (codeSystems == null || valueSets == null) {
|
||||
codeSystems = new HashMap<>();
|
||||
valueSets = new HashMap<>();
|
||||
|
||||
initializeResourceLists();
|
||||
for (String next : myTerminologyResources) {
|
||||
loadCodeSystems(codeSystems, valueSets, next);
|
||||
}
|
||||
|
||||
myCodeSystems = codeSystems;
|
||||
myValueSets = valueSets;
|
||||
}
|
||||
|
||||
// System can take the form "http://url|version"
|
||||
String system = theSystem;
|
||||
String version = null;
|
||||
int pipeIdx = system.indexOf('|');
|
||||
if (pipeIdx > 0) {
|
||||
version = system.substring(pipeIdx + 1);
|
||||
system = system.substring(0, pipeIdx);
|
||||
}
|
||||
|
||||
IBaseResource candidate;
|
||||
if (codeSystem) {
|
||||
candidate = codeSystems.get(system);
|
||||
} else {
|
||||
candidate = valueSets.get(system);
|
||||
}
|
||||
|
||||
if (candidate != null && isNotBlank(version) && !system.startsWith("http://hl7.org") && !system.startsWith("http://terminology.hl7.org")) {
|
||||
if (!StringUtils.equals(version, myCtx.newTerser().getSinglePrimitiveValueOrNull(candidate, "version"))) {
|
||||
candidate = null;
|
||||
}
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchStructureDefinition(String theUrl) {
|
||||
String url = theUrl;
|
||||
if (!url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
if (url.indexOf('/') == -1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION + url;
|
||||
} else if (StringUtils.countMatches(url, '/') == 1) {
|
||||
url = URL_PREFIX_STRUCTURE_DEFINITION_BASE + url;
|
||||
}
|
||||
}
|
||||
Map<String, IBaseResource> structureDefinitionMap = provideStructureDefinitionMap();
|
||||
IBaseResource retVal = structureDefinitionMap.get(url);
|
||||
if (retVal == null) {
|
||||
|
||||
if (url.startsWith(URL_PREFIX_STRUCTURE_DEFINITION)) {
|
||||
|
||||
/*
|
||||
* A few built-in R4 SearchParameters have the wrong casing for primitive
|
||||
* search parameters eg "value.as(String)" when it should be
|
||||
* "value.as(string)". This lets us be a bit lenient about this.
|
||||
*/
|
||||
if (myCtx.getVersion().getVersion() == FhirVersionEnum.R4 || myCtx.getVersion().getVersion() == FhirVersionEnum.R4B || myCtx.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||
String end = url.substring(URL_PREFIX_STRUCTURE_DEFINITION.length());
|
||||
if (Character.isUpperCase(end.charAt(0))) {
|
||||
String newEnd = Character.toLowerCase(end.charAt(0)) + end.substring(1);
|
||||
String alternateUrl = URL_PREFIX_STRUCTURE_DEFINITION + newEnd;
|
||||
retVal = structureDefinitionMap.get(alternateUrl);
|
||||
if (retVal != null) {
|
||||
retVal = myCtx.newTerser().clone(retVal);
|
||||
myCtx.newTerser().setElement(retVal, "type", end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchValueSet(String theUrl) {
|
||||
IBaseResource retVal = fetchCodeSystemOrValueSet(theUrl, false);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
myCodeSystems = null;
|
||||
myStructureDefinitions = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FhirContext getFhirContext() {
|
||||
return myCtx;
|
||||
}
|
||||
|
||||
private Map<String, IBaseResource> provideStructureDefinitionMap() {
|
||||
Map<String, IBaseResource> structureDefinitions = myStructureDefinitions;
|
||||
if (structureDefinitions == null) {
|
||||
structureDefinitions = new HashMap<>();
|
||||
|
||||
initializeResourceLists();
|
||||
for (String next : myStructureDefinitionResources) {
|
||||
loadStructureDefinitions(structureDefinitions, next);
|
||||
}
|
||||
|
||||
myStructureDefinitions = structureDefinitions;
|
||||
}
|
||||
return structureDefinitions;
|
||||
}
|
||||
|
||||
private void loadCodeSystems(Map<String, IBaseResource> theCodeSystems, Map<String, IBaseResource> theValueSets, String theClasspath) {
|
||||
ourLog.info("Loading CodeSystem/ValueSet from classpath: {}", theClasspath);
|
||||
InputStream inputStream = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath);
|
||||
InputStreamReader reader = null;
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
reader = new InputStreamReader(inputStream, Constants.CHARSET_UTF8);
|
||||
List<IBaseResource> resources = parseBundle(reader);
|
||||
for (IBaseResource next : resources) {
|
||||
|
||||
RuntimeResourceDefinition nextDef = getFhirContext().getResourceDefinition(next);
|
||||
Map<String, IBaseResource> map = null;
|
||||
switch (nextDef.getName()) {
|
||||
case "CodeSystem":
|
||||
map = theCodeSystems;
|
||||
break;
|
||||
case "ValueSet":
|
||||
map = theValueSets;
|
||||
break;
|
||||
}
|
||||
|
||||
if (map != null) {
|
||||
String urlValueString = getConformanceResourceUrl(next);
|
||||
if (isNotBlank(urlValueString)) {
|
||||
map.put(urlValueString, next);
|
||||
}
|
||||
|
||||
switch (myCtx.getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
case DSTU2_HL7ORG:
|
||||
|
||||
IPrimitiveType<?> codeSystem = myCtx.newTerser().getSingleValueOrNull(next, "ValueSet.codeSystem.system", IPrimitiveType.class);
|
||||
if (codeSystem != null && isNotBlank(codeSystem.getValueAsString())) {
|
||||
theCodeSystems.put(codeSystem.getValueAsString(), next);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
case DSTU2_1:
|
||||
case DSTU3:
|
||||
case R4:
|
||||
case R4B:
|
||||
case R5:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
ourLog.warn("Failure closing stream", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
|
||||
// Load built-in system
|
||||
|
||||
if (myCtx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
String storageCodeEnum = ClasspathUtil.loadResource("ca/uhn/fhir/context/support/HapiFhirStorageResponseCode.json");
|
||||
IBaseResource storageCodeCodeSystem = myCtx.newJsonParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(storageCodeEnum);
|
||||
String url = myCtx.newTerser().getSinglePrimitiveValueOrNull(storageCodeCodeSystem, "url");
|
||||
theCodeSystems.put(url, storageCodeCodeSystem);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void loadStructureDefinitions(Map<String, IBaseResource> theCodeSystems, String theClasspath) {
|
||||
ourLog.info("Loading structure definitions from classpath: {}", theClasspath);
|
||||
|
||||
String packageUserData = null;
|
||||
if (myCtx.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
packageUserData = "hl7.fhir." + myCtx.getVersion().getVersion().name().replace("DSTU", "R").toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
try (InputStream valueSetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath)) {
|
||||
if (valueSetText != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(valueSetText, Constants.CHARSET_UTF8)) {
|
||||
|
||||
List<IBaseResource> resources = parseBundle(reader);
|
||||
for (IBaseResource next : resources) {
|
||||
|
||||
String nextType = getFhirContext().getResourceType(next);
|
||||
if ("StructureDefinition".equals(nextType)) {
|
||||
|
||||
String url = getConformanceResourceUrl(next);
|
||||
if (isNotBlank(url)) {
|
||||
theCodeSystems.put(url, next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This is used by the validator to determine which package a given SD came from.
|
||||
// I don't love this use of magic strings but that's what is expected currently
|
||||
if (packageUserData != null) {
|
||||
next.setUserData("package", packageUserData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
} catch (IOException theE) {
|
||||
ourLog.warn("Unable to load resource: {}", theClasspath);
|
||||
}
|
||||
}
|
||||
|
||||
private String getConformanceResourceUrl(IBaseResource theResource) {
|
||||
return DefaultProfileValidationSupport.getConformanceResourceUrl(getFhirContext(), theResource);
|
||||
}
|
||||
|
||||
private List<IBaseResource> parseBundle(InputStreamReader theReader) {
|
||||
IBaseResource parsedObject = getFhirContext().newXmlParser().parseResource(theReader);
|
||||
if (parsedObject instanceof IBaseBundle) {
|
||||
IBaseBundle bundle = (IBaseBundle) parsedObject;
|
||||
return BundleUtil.toListOfResources(getFhirContext(), bundle);
|
||||
} else {
|
||||
return Collections.singletonList(parsedObject);
|
||||
}
|
||||
}
|
||||
|
||||
static <T extends IBaseResource> List<T> toList(Map<String, IBaseResource> theMap) {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>(theMap.values());
|
||||
return (List<T>) Collections.unmodifiableList(retVal);
|
||||
}
|
||||
|
||||
}
|
|
@ -126,6 +126,16 @@ public interface IValidationSupport {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and return all possible search parameters
|
||||
*
|
||||
* @since 6.6.0
|
||||
*/
|
||||
@Nullable
|
||||
default <T extends IBaseResource> List<T> fetchAllSearchParameters() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and return all possible structure definitions
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.util;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
@ -171,6 +172,25 @@ public class ExtensionUtil {
|
|||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a resource or other structure that can have direct extensions,
|
||||
* pulls out any extensions that have the given theExtensionUrl and a primitive value type,
|
||||
* and returns a list of the string version of the extension values.
|
||||
*/
|
||||
public static List<String> getExtensionPrimitiveValues(IBaseHasExtensions theBase, String theExtensionUrl) {
|
||||
List<String> values = theBase
|
||||
.getExtension()
|
||||
.stream()
|
||||
.filter(t -> theExtensionUrl.equals(t.getUrl()))
|
||||
.filter(t -> t.getValue() instanceof IPrimitiveType<?>)
|
||||
.map(t->(IPrimitiveType<?>)t.getValue())
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all extensions that match the specified filter predicate
|
||||
*
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package ca.uhn.fhir.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class HapiExtensions {
|
||||
|
||||
/**
|
||||
|
@ -155,6 +157,9 @@ public class HapiExtensions {
|
|||
*/
|
||||
public static final String EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN_ELEMENT_NAME = "element-name";
|
||||
|
||||
public static final String EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE = "http://hl7.org/fhir/tools/CustomBaseResource";
|
||||
public static final String EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE = "http://hl7.org/fhir/tools/CustomTargetResource";
|
||||
|
||||
/**
|
||||
* Non instantiable
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*-
|
||||
* #%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;
|
||||
|
||||
public interface ILockable {
|
||||
|
||||
void lock();
|
||||
|
||||
}
|
|
@ -21,10 +21,13 @@ package ca.uhn.fhir.util;
|
|||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
|
@ -244,11 +247,7 @@ public class ReflectionUtil {
|
|||
@SuppressWarnings("unchecked")
|
||||
public static <T> T newInstanceOrReturnNull(String theClassName, Class<T> theType, Class<?>[] theArgTypes, Object[] theArgs) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(theClassName);
|
||||
if (!theType.isAssignableFrom(clazz)) {
|
||||
throw new ConfigurationException(Msg.code(1787) + theClassName + " is not assignable to " + theType);
|
||||
}
|
||||
return (T) clazz.getConstructor(theArgTypes).newInstance(theArgs);
|
||||
return newInstance(theClassName, theType, theArgTypes, theArgs);
|
||||
} catch (ConfigurationException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
@ -257,6 +256,20 @@ public class ReflectionUtil {
|
|||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static <T> T newInstance(String theClassName, Class<T> theType, Class<?>[] theArgTypes, Object[] theArgs) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(theClassName);
|
||||
if (!theType.isAssignableFrom(clazz)) {
|
||||
throw new ConfigurationException(Msg.code(1787) + theClassName + " is not assignable to " + theType);
|
||||
}
|
||||
return (T) clazz.getConstructor(theArgTypes).newInstance(theArgs);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
InvocationTargetException e) {
|
||||
throw new InternalErrorException(Msg.code(2330) + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean typeExists(String theName) {
|
||||
try {
|
||||
Class.forName(theName);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -27,13 +27,6 @@
|
|||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-sql-migrate</artifactId>
|
||||
|
|
|
@ -176,7 +176,6 @@ public abstract class BaseApp {
|
|||
|
||||
protected List<BaseCommand> provideCommands() {
|
||||
ArrayList<BaseCommand> commands = new ArrayList<>();
|
||||
commands.add(new RunServerCommand());
|
||||
commands.add(new ExampleDataUploader());
|
||||
commands.add(new ValidateCommand());
|
||||
commands.add(new ValidationDataUploader());
|
||||
|
|
|
@ -19,223 +19,12 @@
|
|||
*/
|
||||
package ca.uhn.fhir.cli;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.demo.ContextHolder;
|
||||
import ca.uhn.fhir.jpa.demo.FhirServerConfig;
|
||||
import ca.uhn.fhir.jpa.demo.FhirServerConfigDstu3;
|
||||
import ca.uhn.fhir.jpa.demo.FhirServerConfigR4;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
/**
|
||||
* @deprecated Will be removed after 6.6.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class RunServerCommand {
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.SocketException;
|
||||
|
||||
public class RunServerCommand extends BaseCommand {
|
||||
|
||||
private static final String OPTION_DISABLE_REFERENTIAL_INTEGRITY = "disable-referential-integrity";
|
||||
private static final String OPTION_ALLOW_EXTERNAL_REFS = "allow-external-refs";
|
||||
private static final String OPTION_REUSE_SEARCH_RESULTS_MILLIS = "reuse-search-results-milliseconds";
|
||||
private static final int DEFAULT_PORT = 8080;
|
||||
private static final String OPTION_P = "p";
|
||||
|
||||
// TODO: Don't use qualified names for loggers in HAPI CLI.
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RunServerCommand.class);
|
||||
public static final String RUN_SERVER_COMMAND = "run-server";
|
||||
private int myPort;
|
||||
|
||||
private Server myServer;
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return RUN_SERVER_COMMAND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
Options options = new Options();
|
||||
addFhirVersionOption(options);
|
||||
options.addOption(OPTION_P, "port", true, "The port to listen on (default is " + DEFAULT_PORT + ")");
|
||||
options.addOption(null, OPTION_ALLOW_EXTERNAL_REFS, false, "If this flag is set, the server will allow resources to be persisted contaning external resource references");
|
||||
options.addOption(null, OPTION_DISABLE_REFERENTIAL_INTEGRITY, false, "If this flag is set, the server will not enforce referential integrity");
|
||||
|
||||
addOptionalOption(options, "u", "url", "Url", "If this option is set, specifies the JDBC URL to use for the database connection");
|
||||
|
||||
Long defaultReuseSearchResults = JpaStorageSettings.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
|
||||
String defaultReuseSearchResultsStr = defaultReuseSearchResults == null ? "off" : String.valueOf(defaultReuseSearchResults);
|
||||
options.addOption(null, OPTION_REUSE_SEARCH_RESULTS_MILLIS, true, "The time in milliseconds within which the same results will be returned for multiple identical searches, or \"off\" (default is " + defaultReuseSearchResultsStr + ")");
|
||||
return options;
|
||||
}
|
||||
|
||||
private int parseOptionInteger(CommandLine theCommandLine, String opt, int defaultPort) throws ParseException {
|
||||
try {
|
||||
return Integer.parseInt(theCommandLine.getOptionValue(opt, Integer.toString(defaultPort)));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParseException(Msg.code(1558) + "Invalid value '" + theCommandLine.getOptionValue(opt) + "' (must be numeric)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CommandLine theCommandLine) throws ParseException {
|
||||
parseFhirContext(theCommandLine);
|
||||
|
||||
myPort = parseOptionInteger(theCommandLine, OPTION_P, DEFAULT_PORT);
|
||||
|
||||
if (theCommandLine.hasOption(OPTION_ALLOW_EXTERNAL_REFS)) {
|
||||
ourLog.info("Server is configured to allow external references");
|
||||
ContextHolder.setAllowExternalRefs(true);
|
||||
}
|
||||
|
||||
if (theCommandLine.hasOption(OPTION_DISABLE_REFERENTIAL_INTEGRITY)) {
|
||||
ourLog.info("Server is configured to not enforce referential integrity");
|
||||
ContextHolder.setDisableReferentialIntegrity(true);
|
||||
}
|
||||
|
||||
ContextHolder.setDatabaseUrl(theCommandLine.getOptionValue("u"));
|
||||
|
||||
String reuseSearchResults = theCommandLine.getOptionValue(OPTION_REUSE_SEARCH_RESULTS_MILLIS);
|
||||
if (reuseSearchResults != null) {
|
||||
if (reuseSearchResults.equals("off")) {
|
||||
ourLog.info("Server is configured to not reuse search results");
|
||||
ContextHolder.setReuseCachedSearchResultsForMillis(null);
|
||||
} else {
|
||||
try {
|
||||
long reuseSearchResultsMillis = Long.parseLong(reuseSearchResults);
|
||||
if (reuseSearchResultsMillis < 0) {
|
||||
throw new NumberFormatException(Msg.code(1559) + "expected a positive integer");
|
||||
}
|
||||
ourLog.info("Server is configured to reuse search results for " + String.valueOf(reuseSearchResultsMillis) + " milliseconds");
|
||||
ContextHolder.setReuseCachedSearchResultsForMillis(reuseSearchResultsMillis);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParseException(Msg.code(1560) + "Invalid value '" + reuseSearchResults + "' (must be a positive integer)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContextHolder.setCtx(getFhirContext());
|
||||
|
||||
ourLog.info("Preparing HAPI FHIR JPA server on port {}", myPort);
|
||||
File tempWarFile;
|
||||
try {
|
||||
tempWarFile = File.createTempFile("hapi-fhir", ".war");
|
||||
tempWarFile.deleteOnExit();
|
||||
|
||||
InputStream inStream = RunServerCommand.class.getResourceAsStream("/hapi-fhir-cli-jpaserver.war");
|
||||
OutputStream outStream = new BufferedOutputStream(new FileOutputStream(tempWarFile, false));
|
||||
IOUtils.copy(inStream, outStream);
|
||||
} catch (IOException e) {
|
||||
ourLog.error("Failed to create temporary file", e);
|
||||
return;
|
||||
}
|
||||
|
||||
final ContextLoaderListener cll = new ContextLoaderListener();
|
||||
|
||||
ourLog.info("Starting HAPI FHIR JPA server in {} mode", ContextHolder.getCtx().getVersion().getVersion());
|
||||
WebAppContext root = new WebAppContext();
|
||||
root.setAllowDuplicateFragmentNames(true);
|
||||
root.setWar(tempWarFile.getAbsolutePath());
|
||||
root.setParentLoaderPriority(true);
|
||||
root.setContextPath("/");
|
||||
root.addEventListener(new ServletContextListener() {
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent theSce) {
|
||||
theSce.getServletContext().setInitParameter(ContextLoader.CONTEXT_CLASS_PARAM, AnnotationConfigWebApplicationContext.class.getName());
|
||||
switch (ContextHolder.getCtx().getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
theSce.getServletContext().setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, FhirServerConfig.class.getName());
|
||||
break;
|
||||
case DSTU3:
|
||||
theSce.getServletContext().setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, FhirServerConfigDstu3.class.getName());
|
||||
break;
|
||||
case R4:
|
||||
theSce.getServletContext().setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, FhirServerConfigR4.class.getName());
|
||||
break;
|
||||
case DSTU2_1:
|
||||
case DSTU2_HL7ORG:
|
||||
break;
|
||||
}
|
||||
cll.contextInitialized(theSce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent theSce) {
|
||||
cll.contextDestroyed(theSce);
|
||||
}
|
||||
});
|
||||
|
||||
String path = ContextHolder.getPath();
|
||||
root.addServlet("ca.uhn.fhir.jpa.demo.JpaServerDemo", path + "*");
|
||||
|
||||
myServer = new Server(myPort);
|
||||
myServer.setHandler(root);
|
||||
try {
|
||||
myServer.start();
|
||||
} catch (SocketException e) {
|
||||
throw new CommandFailureException(Msg.code(1561) + "Server failed to start on port " + myPort + " because of the following error \"" + e.toString() + "\". Note that you can use the '-p' option to specify an alternate port.");
|
||||
} catch (Exception e) {
|
||||
ourLog.error("Server failed to start", e);
|
||||
throw new CommandFailureException(Msg.code(1562) + "Server failed to start", e);
|
||||
}
|
||||
|
||||
ourLog.info("Server started on port {}", myPort);
|
||||
ourLog.info("Web Testing UI : http://localhost:{}/", myPort);
|
||||
ourLog.info("Server Base URL: http://localhost:{}{}", myPort, path);
|
||||
|
||||
// Never quit.. We'll let the user ctrl-C their way out.
|
||||
loopForever();
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("InfiniteLoopStatement")
|
||||
private void loopForever() {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(DateUtils.MILLIS_PER_MINUTE);
|
||||
} catch (InterruptedException theE) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] theArgs) {
|
||||
|
||||
|
||||
Server server = new Server(22);
|
||||
String path = "../hapi-fhir-cli-jpaserver";
|
||||
WebAppContext webAppContext = new WebAppContext();
|
||||
webAppContext.setContextPath("/");
|
||||
webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml");
|
||||
webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-example");
|
||||
webAppContext.setParentLoaderPriority(true);
|
||||
|
||||
server.setHandler(webAppContext);
|
||||
try {
|
||||
server.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ourLog.info("Started");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandDescription() {
|
||||
return "Start a FHIR server which can be used for testing";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -24,19 +24,6 @@
|
|||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
|
@ -56,32 +43,6 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<type>war</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>target/classes</outputDirectory>
|
||||
<destFileName>hapi-fhir-cli-jpaserver.war</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<!-- other configurations here -->
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
|
|
|
@ -1,129 +0,0 @@
|
|||
/target
|
||||
/jpaserver_derby_files
|
||||
*.log
|
||||
ca.uhn.fhir.jpa.entity.ResourceTable/
|
||||
|
||||
# Created by https://www.gitignore.io
|
||||
|
||||
### Java ###
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
|
||||
### Maven ###
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
|
||||
|
||||
### Vim ###
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
*~
|
||||
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
# if you remove the above rule, at least ignore the following:
|
||||
|
||||
# User-specific stuff:
|
||||
# .idea/workspace.xml
|
||||
# .idea/tasks.xml
|
||||
# .idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# .idea/dataSources.ids
|
||||
# .idea/dataSources.xml
|
||||
# .idea/sqlDataSources.xml
|
||||
# .idea/dynamic.xml
|
||||
# .idea/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
# .idea/gradle.xml
|
||||
# .idea/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
# .idea/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
|
||||
|
||||
|
||||
### Eclipse ###
|
||||
*.pydevproject
|
||||
.metadata
|
||||
.gradle
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# Eclipse Core
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- Note: HAPI projects use the "hapi-fhir" POM as their base to provide easy management. You do not need to use this in your own projects, so the "parent" tag and it's contents below may be removed
|
||||
if you are using this file as a basis for your own project. -->
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-cli-jpaserver</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>HAPI FHIR - Command Line Client - Server WAR</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- This dependency includes the core HAPI-FHIR classes -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- This dependency includes the JPA server itself, which is packaged separately from the rest of HAPI FHIR -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- This dependency is used for the "FHIR Tester" web app overlay -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- HAPI-FHIR uses Logback for logging support. The logback library is included automatically by Maven as a part of the hapi-fhir-base dependency, but you also need to include a logging library. Logback
|
||||
is used here, but log4j would also be fine. -->
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Needed for JEE/Servlet support -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- If you are using HAPI narrative generation, you will need to include Thymeleaf as well. Otherwise the following can be omitted. -->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Used for CORS support -->
|
||||
|
||||
<!-- Spring Web is used to deploy the server to a web container. -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- You may not need this if you are deploying to an application server which provides database connection pools itself. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-dbcp2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- This example uses H2 embedded database. If you are using another database such as Mysql or Oracle, you may omit the following dependencies and replace them with an appropriate database client
|
||||
dependency for your database platform. -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Hibernate search Lucene backend -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate.search</groupId>
|
||||
<artifactId>hibernate-search-backend-lucene</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-phonetic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-backward-codecs</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- The following dependencies are only needed for automated unit tests, you do not neccesarily need them to run the example. -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>ph-schematron</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>Saxon-HE</artifactId>
|
||||
<groupId>net.sf.saxon</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<!-- Tells Maven to name the generated WAR file as hapi-fhir-jpaserver-example.war -->
|
||||
<finalName>hapi-fhir-cli-jpaserver</finalName>
|
||||
|
||||
<!-- The following is not required for the application to build, but allows you to test it by issuing "mvn jetty:run" from the command line. -->
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<webApp>
|
||||
<contextPath>/hapi-fhir-jpaserver-example</contextPath>
|
||||
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!-- The configuration here tells the WAR plugin to include the FHIR Tester overlay. You can omit it if you are not using that feature. -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Build-Time>${maven.build.timestamp}</Build-Time>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<overlays>
|
||||
<overlay>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
</overlay>
|
||||
</overlays>
|
||||
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
|
||||
<attachClasses>true</attachClasses>
|
||||
<packagingExcludes>
|
||||
WEB-INF/lib/Saxon-HE-*,
|
||||
WEB-INF/lib/hapi-*
|
||||
</packagingExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- This is to run the integration tests -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,31 +0,0 @@
|
|||
Running hapi-fhir-jpaserver-example in Tomcat from IntelliJ
|
||||
|
||||
Install Tomcat.
|
||||
|
||||
Make sure you have Tomcat set up in IntelliJ.
|
||||
File->Settings->Build, Execution, Deployment->Application Servers
|
||||
Click +
|
||||
Select "Tomcat Server"
|
||||
Enter the path to your tomcat deployment for both Tomcat Home (IntelliJ will fill in base directory for you)
|
||||
|
||||
Add a Run Configuration for running hapi-fhir-jpaserver-example under Tomcat
|
||||
Run->Edit Configurations
|
||||
Click the green +
|
||||
Select Tomcat Server, Local
|
||||
Change the name to whatever you wish
|
||||
Uncheck the "After launch" checkbox
|
||||
On the "Deployment" tab, click the green +
|
||||
Select "Artifact"
|
||||
Select "hapi-fhir-jpaserver-example:war"
|
||||
In "Application context" type /hapi
|
||||
|
||||
Run the configuration
|
||||
You should now have an "Application Servers" in the list of windows at the bottom.
|
||||
Click it.
|
||||
Select your server, and click the green triangle (or the bug if you want to debug)
|
||||
Wait for the console output to stop
|
||||
|
||||
Point your browser (or fiddler, or what have you) to
|
||||
http://localhost:8080/hapi/base/Patient
|
||||
|
||||
You should get an empty bundle back.
|
|
@ -1,97 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.hibernate.search.mapper.orm.cfg.HibernateOrmMapperSettings;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Configuration
|
||||
public class CommonConfig {
|
||||
|
||||
/**
|
||||
* Configure FHIR properties around the JPA server via this bean
|
||||
*/
|
||||
@Bean
|
||||
public JpaStorageSettings storageSettings() {
|
||||
JpaStorageSettings retVal = new JpaStorageSettings();
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following bean configures the database connection. The 'url' property value of "jdbc:h2:file:target./jpaserver_h2_files" indicates that the server should save resources in a
|
||||
* directory called "jpaserver_h2_files".
|
||||
* <p>
|
||||
* A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource.
|
||||
*/
|
||||
@Bean(destroyMethod = "close")
|
||||
public DataSource dataSource() {
|
||||
String url = "jdbc:h2:file:./target/jpaserver_h2_files";
|
||||
if (isNotBlank(ContextHolder.getDatabaseUrl())) {
|
||||
url = ContextHolder.getDatabaseUrl();
|
||||
}
|
||||
|
||||
BasicDataSource retVal = new BasicDataSource();
|
||||
retVal.setDriver(new org.h2.Driver());
|
||||
retVal.setUrl(url);
|
||||
retVal.setUsername("");
|
||||
retVal.setPassword("");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Properties jpaProperties() {
|
||||
Properties extraProperties = new Properties();
|
||||
|
||||
//Regular Hibernate Settings
|
||||
extraProperties.put("hibernate.dialect", HapiFhirH2Dialect.class.getName());
|
||||
extraProperties.put("hibernate.format_sql", "true");
|
||||
extraProperties.put("hibernate.show_sql", "false");
|
||||
extraProperties.put("hibernate.hbm2ddl.auto", "update");
|
||||
extraProperties.put("hibernate.jdbc.batch_size", "20");
|
||||
extraProperties.put("hibernate.cache.use_query_cache", "false");
|
||||
extraProperties.put("hibernate.cache.use_second_level_cache", "false");
|
||||
extraProperties.put("hibernate.cache.use_structured_entries", "false");
|
||||
extraProperties.put("hibernate.cache.use_minimal_puts", "false");
|
||||
extraProperties.put("hibernate.search.backend.type", "lucene");
|
||||
extraProperties.put(HibernateOrmMapperSettings.ENABLED, "false");
|
||||
extraProperties.put(Constants.HIBERNATE_INTEGRATION_ENVERS_ENABLED, storageSettings().isNonResourceDbHistoryEnabled());
|
||||
|
||||
return extraProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PartitionSettings partitionSettings() {
|
||||
return new PartitionSettings();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class ContextHolder {
|
||||
|
||||
private static boolean ourAllowExternalRefs;
|
||||
private static FhirContext ourCtx;
|
||||
private static boolean ourDisableReferentialIntegrity;
|
||||
private static String ourPath;
|
||||
private static Long ourReuseSearchResultsMillis;
|
||||
private static String ourDatabaseUrl;
|
||||
|
||||
static {
|
||||
ourReuseSearchResultsMillis = JpaStorageSettings.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS;
|
||||
}
|
||||
|
||||
public static FhirContext getCtx() {
|
||||
Validate.notNull(ourPath, "Context not set");
|
||||
return ourCtx;
|
||||
}
|
||||
|
||||
public static void setCtx(FhirContext theCtx) throws ParseException {
|
||||
switch (theCtx.getVersion().getVersion()) {
|
||||
case DSTU2:
|
||||
ourPath = "/baseDstu2/";
|
||||
break;
|
||||
case DSTU2_1:
|
||||
break;
|
||||
case DSTU3:
|
||||
ourPath = "/baseDstu3/";
|
||||
break;
|
||||
case R4:
|
||||
ourPath = "/baseR4/";
|
||||
break;
|
||||
case DSTU2_HL7ORG:
|
||||
default:
|
||||
throw new ParseException(Msg.code(1531) + "FHIR version not supported by this command: " + theCtx.getVersion().getVersion());
|
||||
}
|
||||
|
||||
ourCtx = theCtx;
|
||||
}
|
||||
|
||||
public static String getPath() {
|
||||
Validate.notNull(ourPath, "Context not set");
|
||||
return ourPath;
|
||||
}
|
||||
|
||||
public static Long getReuseCachedSearchResultsForMillis() {
|
||||
return ourReuseSearchResultsMillis;
|
||||
}
|
||||
|
||||
public static void setReuseCachedSearchResultsForMillis(Long reuseSearchResultsMillis) {
|
||||
ourReuseSearchResultsMillis = reuseSearchResultsMillis;
|
||||
}
|
||||
|
||||
public static boolean isAllowExternalRefs() {
|
||||
return ourAllowExternalRefs;
|
||||
}
|
||||
|
||||
public static void setAllowExternalRefs(boolean theAllowExternalRefs) {
|
||||
ourAllowExternalRefs = theAllowExternalRefs;
|
||||
}
|
||||
|
||||
public static boolean isDisableReferentialIntegrity() {
|
||||
return ourDisableReferentialIntegrity;
|
||||
}
|
||||
|
||||
public static void setDisableReferentialIntegrity(boolean theDisableReferentialIntegrity) {
|
||||
ourDisableReferentialIntegrity = theDisableReferentialIntegrity;
|
||||
}
|
||||
|
||||
public static String getDatabaseUrl() {
|
||||
return ourDatabaseUrl;
|
||||
}
|
||||
|
||||
public static void setDatabaseUrl(String theDatabaseUrl) {
|
||||
ourDatabaseUrl = theDatabaseUrl;
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.config.HapiJpaConfig;
|
||||
import ca.uhn.fhir.jpa.config.JpaDstu2Config;
|
||||
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement()
|
||||
@Import({CommonConfig.class, JpaDstu2Config.class, HapiJpaConfig.class})
|
||||
public class FhirServerConfig {
|
||||
|
||||
@Autowired
|
||||
private DataSource myDataSource;
|
||||
@Autowired()
|
||||
@Qualifier("jpaProperties")
|
||||
private Properties myJpaProperties;
|
||||
|
||||
/**
|
||||
* Configure FHIR properties around the JPA server via this bean
|
||||
*/
|
||||
@Bean
|
||||
public JpaStorageSettings storageSettings() {
|
||||
JpaStorageSettings retVal = new JpaStorageSettings();
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theConfigurableListableBeanFactory, FhirContext theFhirContext) {
|
||||
LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(theConfigurableListableBeanFactory, theFhirContext);
|
||||
retVal.setPersistenceUnitName("HAPI_PU");
|
||||
retVal.setDataSource(myDataSource);
|
||||
retVal.setJpaProperties(myJpaProperties);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do some fancy logging to create a nice access log that has details about each incoming request.
|
||||
*/
|
||||
public LoggingInterceptor loggingInterceptor() {
|
||||
LoggingInterceptor retVal = new LoggingInterceptor();
|
||||
retVal.setLoggerName("fhirtest.access");
|
||||
retVal.setMessageFormat(
|
||||
"Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]");
|
||||
retVal.setLogExceptions(true);
|
||||
retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interceptor adds some pretty syntax highlighting in responses when a browser is detected
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ResponseHighlighterInterceptor responseHighlighterInterceptor() {
|
||||
ResponseHighlighterInterceptor retVal = new ResponseHighlighterInterceptor();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IServerInterceptor subscriptionSecurityInterceptor() {
|
||||
SubscriptionsRequireManualActivationInterceptorDstu2 retVal = new SubscriptionsRequireManualActivationInterceptorDstu2();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager retVal = new JpaTransactionManager();
|
||||
retVal.setEntityManagerFactory(entityManagerFactory);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.config.HapiJpaConfig;
|
||||
import ca.uhn.fhir.jpa.config.dstu3.JpaDstu3Config;
|
||||
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* This class isn't used by default by the example, but
|
||||
* you can use it as a config if you want to support DSTU3
|
||||
* instead of DSTU2 in your server.
|
||||
* <p>
|
||||
* See https://github.com/hapifhir/hapi-fhir/issues/278
|
||||
*/
|
||||
@Configuration
|
||||
@EnableTransactionManagement()
|
||||
@Import({CommonConfig.class, JpaDstu3Config.class, HapiJpaConfig.class,})
|
||||
public class FhirServerConfigDstu3 {
|
||||
|
||||
@Autowired
|
||||
private DataSource myDataSource;
|
||||
@Autowired()
|
||||
@Qualifier("jpaProperties")
|
||||
private Properties myJpaProperties;
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theConfigurableListableBeanFactory, FhirContext theFhirContext) {
|
||||
LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(theConfigurableListableBeanFactory, theFhirContext);
|
||||
retVal.setPersistenceUnitName("HAPI_PU");
|
||||
retVal.setDataSource(myDataSource);
|
||||
retVal.setJpaProperties(myJpaProperties);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do some fancy logging to create a nice access log that has details about each incoming request.
|
||||
* @return
|
||||
*/
|
||||
public LoggingInterceptor loggingInterceptor() {
|
||||
LoggingInterceptor retVal = new LoggingInterceptor();
|
||||
retVal.setLoggerName("fhirtest.access");
|
||||
retVal.setMessageFormat(
|
||||
"Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]");
|
||||
retVal.setLogExceptions(true);
|
||||
retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interceptor adds some pretty syntax highlighting in responses when a browser is detected
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ResponseHighlighterInterceptor responseHighlighterInterceptor() {
|
||||
ResponseHighlighterInterceptor retVal = new ResponseHighlighterInterceptor();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IServerInterceptor subscriptionSecurityInterceptor() {
|
||||
SubscriptionsRequireManualActivationInterceptorDstu3 retVal = new SubscriptionsRequireManualActivationInterceptorDstu3();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager retVal = new JpaTransactionManager();
|
||||
retVal.setEntityManagerFactory(entityManagerFactory);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.config.HapiJpaConfig;
|
||||
import ca.uhn.fhir.jpa.config.r4.JpaR4Config;
|
||||
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorR4;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* This class isn't used by default by the example, but
|
||||
* you can use it as a config if you want to support DSTU3
|
||||
* instead of DSTU2 in your server.
|
||||
* <p>
|
||||
* See https://github.com/hapifhir/hapi-fhir/issues/278
|
||||
*/
|
||||
@Configuration
|
||||
@EnableTransactionManagement()
|
||||
@Import({CommonConfig.class, JpaR4Config.class, HapiJpaConfig.class})
|
||||
public class FhirServerConfigR4 {
|
||||
|
||||
@Autowired
|
||||
private DataSource myDataSource;
|
||||
@Autowired()
|
||||
@Qualifier("jpaProperties")
|
||||
private Properties myJpaProperties;
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(ConfigurableListableBeanFactory theConfigurableListableBeanFactory, FhirContext theFhirContext) {
|
||||
LocalContainerEntityManagerFactoryBean retVal = HapiEntityManagerFactoryUtil.newEntityManagerFactory(theConfigurableListableBeanFactory, theFhirContext);
|
||||
retVal.setPersistenceUnitName("HAPI_PU");
|
||||
retVal.setDataSource(myDataSource);
|
||||
retVal.setJpaProperties(myJpaProperties);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do some fancy logging to create a nice access log that has details about each incoming request.
|
||||
* @return
|
||||
*/
|
||||
public LoggingInterceptor loggingInterceptor() {
|
||||
LoggingInterceptor retVal = new LoggingInterceptor();
|
||||
retVal.setLoggerName("fhirtest.access");
|
||||
retVal.setMessageFormat(
|
||||
"Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]");
|
||||
retVal.setLogExceptions(true);
|
||||
retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interceptor adds some pretty syntax highlighting in responses when a browser is detected
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ResponseHighlighterInterceptor responseHighlighterInterceptor() {
|
||||
ResponseHighlighterInterceptor retVal = new ResponseHighlighterInterceptor();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IServerInterceptor subscriptionSecurityInterceptor() {
|
||||
SubscriptionsRequireManualActivationInterceptorR4 retVal = new SubscriptionsRequireManualActivationInterceptorR4();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Primary
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
|
||||
JpaTransactionManager retVal = new JpaTransactionManager();
|
||||
retVal.setEntityManagerFactory(entityManagerFactory);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.to.FhirTesterMvcConfig;
|
||||
import ca.uhn.fhir.to.TesterConfig;
|
||||
|
||||
//@formatter:off
|
||||
/**
|
||||
* This spring config file configures the web testing module. It serves two
|
||||
* purposes:
|
||||
* 1. It imports FhirTesterMvcConfig, which is the spring config for the
|
||||
* tester itself
|
||||
* 2. It tells the tester which server(s) to talk to, via the testerConfig()
|
||||
* method below
|
||||
*/
|
||||
@Configuration
|
||||
@Import(FhirTesterMvcConfig.class)
|
||||
public class FhirTesterConfig {
|
||||
|
||||
/**
|
||||
* This bean tells the testing webpage which servers it should configure itself
|
||||
* to communicate with. In this example we configure it to talk to the local
|
||||
* server, as well as one public server. If you are creating a project to
|
||||
* deploy somewhere else, you might choose to only put your own server's
|
||||
* address here.
|
||||
*
|
||||
* Note the use of the ${serverBase} variable below. This will be replaced with
|
||||
* the base URL as reported by the server itself. Often for a simple Tomcat
|
||||
* (or other container) installation, this will end up being something
|
||||
* like "http://localhost:8080/hapi-fhir-jpaserver-example". If you are
|
||||
* deploying your server to a place with a fully qualified domain name,
|
||||
* you might want to use that instead of using the variable.
|
||||
*/
|
||||
@Bean
|
||||
public TesterConfig testerConfig() {
|
||||
TesterConfig retVal = new TesterConfig();
|
||||
retVal
|
||||
.addServer()
|
||||
.withId("home")
|
||||
.withFhirVersion(ContextHolder.getCtx().getVersion().getVersion())
|
||||
.withBaseUrl("${serverBase}" + ContextHolder.getPath())
|
||||
.withName("Local Tester");
|
||||
|
||||
retVal
|
||||
.addServer()
|
||||
.withId("hapi")
|
||||
.withFhirVersion(FhirVersionEnum.DSTU2)
|
||||
.withBaseUrl("http://fhirtest.uhn.ca/baseDstu2")
|
||||
.withName("Public HAPI Test Server");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
//@formatter:on
|
|
@ -1,187 +0,0 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Command Line Client - Server WAR
|
||||
* %%
|
||||
* 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.jpa.demo;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
|
||||
import ca.uhn.fhir.jpa.config.JpaConfig;
|
||||
import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc;
|
||||
import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor;
|
||||
import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider;
|
||||
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
|
||||
import ca.uhn.fhir.jpa.provider.JpaSystemProvider;
|
||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
|
||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.ETagSupportEnum;
|
||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JpaServerDemo extends RestfulServer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private WebApplicationContext myAppCtx;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initialize() throws ServletException {
|
||||
super.initialize();
|
||||
|
||||
setFhirContext(ContextHolder.getCtx());
|
||||
|
||||
// Get the spring context from the web container (it's declared in web.xml)
|
||||
myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext();
|
||||
|
||||
/*
|
||||
* The hapi-fhir-server-resourceproviders-dev.xml file is a spring configuration
|
||||
* file which is automatically generated as a part of hapi-fhir-jpaserver-base and
|
||||
* contains bean definitions for a resource provider for each resource type
|
||||
*/
|
||||
String resourceProviderBeanName;
|
||||
FhirVersionEnum fhirVersion = ContextHolder.getCtx().getVersion().getVersion();
|
||||
switch (fhirVersion) {
|
||||
case DSTU2:
|
||||
resourceProviderBeanName = "myResourceProvidersDstu2";
|
||||
break;
|
||||
case DSTU3:
|
||||
resourceProviderBeanName = "myResourceProvidersDstu3";
|
||||
break;
|
||||
case R4:
|
||||
resourceProviderBeanName = "myResourceProvidersR4";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(Msg.code(1532));
|
||||
}
|
||||
|
||||
ResourceProviderFactory beans = myAppCtx.getBean(resourceProviderBeanName, ResourceProviderFactory.class);
|
||||
registerProviders(beans.createProviders());
|
||||
|
||||
/*
|
||||
* The system provider implements non-resource-type methods, such as
|
||||
* transaction, and global history.
|
||||
*/
|
||||
List<Object> systemProvider = new ArrayList<Object>();
|
||||
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
||||
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
||||
systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class));
|
||||
} else if (fhirVersion == FhirVersionEnum.R4) {
|
||||
systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class));
|
||||
systemProvider.add(myAppCtx.getBean(JpaConfig.GRAPHQL_PROVIDER_NAME));
|
||||
} else {
|
||||
throw new IllegalStateException(Msg.code(1533));
|
||||
}
|
||||
systemProvider.add(myAppCtx.getBean(JpaSystemProvider.class));
|
||||
registerProviders(systemProvider);
|
||||
|
||||
/*
|
||||
* The conformance provider exports the supported resources, search parameters, etc for
|
||||
* this server. The JPA version adds resource counts to the exported statement, so it
|
||||
* is a nice addition.
|
||||
*/
|
||||
if (fhirVersion == FhirVersionEnum.DSTU2) {
|
||||
IFhirSystemDao<Bundle, MetaDt> systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao,
|
||||
myAppCtx.getBean(JpaStorageSettings.class));
|
||||
confProvider.setImplementationDescription("Example Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.DSTU3) {
|
||||
IFhirSystemDao<org.hl7.fhir.dstu3.model.Bundle, org.hl7.fhir.dstu3.model.Meta> systemDao = myAppCtx
|
||||
.getBean("mySystemDaoDstu3", IFhirSystemDao.class);
|
||||
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao,
|
||||
myAppCtx.getBean(JpaStorageSettings.class), myAppCtx.getBean(ISearchParamRegistry.class));
|
||||
confProvider.setImplementationDescription("Example Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else if (fhirVersion == FhirVersionEnum.R4) {
|
||||
IFhirSystemDao<org.hl7.fhir.r4.model.Bundle, org.hl7.fhir.r4.model.Meta> systemDao = myAppCtx
|
||||
.getBean("mySystemDaoR4", IFhirSystemDao.class);
|
||||
IValidationSupport validationSupport = myAppCtx.getBean(IValidationSupport.class);
|
||||
JpaCapabilityStatementProvider confProvider = new JpaCapabilityStatementProvider(this, systemDao,
|
||||
myAppCtx.getBean(JpaStorageSettings.class), myAppCtx.getBean(ISearchParamRegistry.class), validationSupport);
|
||||
confProvider.setImplementationDescription("Example Server");
|
||||
setServerConformanceProvider(confProvider);
|
||||
} else {
|
||||
throw new IllegalStateException(Msg.code(1534));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable ETag Support (this is already the default)
|
||||
*/
|
||||
setETagSupport(ETagSupportEnum.ENABLED);
|
||||
|
||||
/*
|
||||
* This server tries to dynamically generate narratives
|
||||
*/
|
||||
FhirContext ctx = getFhirContext();
|
||||
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||
|
||||
/*
|
||||
* Default to XML and pretty printing
|
||||
*/
|
||||
setDefaultPrettyPrint(true);
|
||||
setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||
|
||||
/*
|
||||
* This is a simple paging strategy that keeps the last 10 searches in memory
|
||||
*/
|
||||
setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||
|
||||
// Register a CORS filter
|
||||
CorsInterceptor corsInterceptor = new CorsInterceptor();
|
||||
registerInterceptor(corsInterceptor);
|
||||
|
||||
JpaStorageSettings storageSettings = myAppCtx.getBean(JpaStorageSettings.class);
|
||||
storageSettings.setAllowExternalReferences(ContextHolder.isAllowExternalRefs());
|
||||
storageSettings.setEnforceReferentialIntegrityOnDelete(!ContextHolder.isDisableReferentialIntegrity());
|
||||
storageSettings.setEnforceReferentialIntegrityOnWrite(!ContextHolder.isDisableReferentialIntegrity());
|
||||
storageSettings.setReuseCachedSearchResultsForMillis(ContextHolder.getReuseCachedSearchResultsForMillis());
|
||||
|
||||
DaoRegistry daoRegistry = myAppCtx.getBean(DaoRegistry.class);
|
||||
IInterceptorBroadcaster interceptorBroadcaster = myAppCtx.getBean(IInterceptorBroadcaster.class);
|
||||
ThreadSafeResourceDeleterSvc threadSafeResourceDeleterSvc = myAppCtx.getBean(ThreadSafeResourceDeleterSvc.class);
|
||||
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(ctx, daoRegistry, interceptorBroadcaster, threadSafeResourceDeleterSvc);
|
||||
getInterceptorService().registerInterceptor(cascadingDeleteInterceptor);
|
||||
|
||||
getInterceptorService().registerInterceptor(new ResponseHighlighterInterceptor());
|
||||
|
||||
registerProvider(myAppCtx.getBean(BinaryAccessProvider.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
<configuration scan="true" scanPeriod="30 seconds">
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -1,67 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head th:include="tmpl-head :: head">
|
||||
<title>About This Server</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form action="" method="get" id="outerForm">
|
||||
<div th:replace="tmpl-navbar-top :: top" ></div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div th:replace="tmpl-navbar-left :: left" ></div>
|
||||
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-9 col-md-offset-3 main">
|
||||
|
||||
<div th:replace="tmpl-banner :: banner"></div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">About This Server</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="pull-right">
|
||||
<object data="img/fhirtest-architecture.svg" width="383" height="369" type="image/svg+xml"></object>
|
||||
</div>
|
||||
<p>
|
||||
This server provides a nearly complete implementation of the FHIR Specification
|
||||
using a 100% open source software stack. It is hosted by University Health Network.
|
||||
</p>
|
||||
<p>
|
||||
The architecture in use here is shown in the image on the right. This server is built
|
||||
from a number of modules of the
|
||||
<a href="https://github.com/hapifhir/hapi-fhir/">HAPI FHIR</a>
|
||||
project, which is a 100% open-source (Apache 2.0 Licensed) Java based
|
||||
implementation of the FHIR specification.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Data On This Server</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
This server is regularly loaded with a standard set of test data sourced
|
||||
from UHN's own testing environment. Do not use this server to store any data
|
||||
that you will need later, as we will be regularly resetting it.
|
||||
</p>
|
||||
<p>
|
||||
This is not a production server and it provides no privacy. Do not store any
|
||||
confidential data here.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div th:replace="tmpl-footer :: footer" ></div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<div th:fragment="footer">
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-1395874-6', 'auto');
|
||||
ga('require', 'displayfeatures');
|
||||
ga('require', 'linkid', 'linkid.js');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</div>
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<div th:fragment="banner" class="well">
|
||||
<p>
|
||||
This server is deployed using HAPI-FHIR CLI (Command Line Interface).
|
||||
</p>
|
||||
</div>
|
||||
</html>
|
|
@ -1,64 +0,0 @@
|
|||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ./xsd/web-app_3_0.xsd">
|
||||
|
||||
<!--
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
<context-param>
|
||||
<param-name>contextClass</param-name>
|
||||
<param-value>
|
||||
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
||||
</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
ca.uhn.fhir.jpa.demo.FhirServerConfig
|
||||
</param-value>
|
||||
</context-param>
|
||||
-->
|
||||
|
||||
<!-- Servlets -->
|
||||
|
||||
<servlet>
|
||||
<servlet-name>spring</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextClass</param-name>
|
||||
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>ca.uhn.fhir.jpa.demo.FhirTesterConfig</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
<servlet>
|
||||
<servlet-name>fhirServlet</servlet-name>
|
||||
<servlet-class>ca.uhn.fhir.jpa.demo.JpaServerDemo</servlet-class>
|
||||
<init-param>
|
||||
<param-name>ImplementationDescription</param-name>
|
||||
<param-value>FHIR JPA Server</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>FhirVersion</param-name>
|
||||
<param-value>DSTU2</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>fhirServlet</servlet-name>
|
||||
<url-pattern>/baseDstu2/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
-->
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>spring</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,389 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="2.2">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
||||
|
||||
Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
|
||||
|
||||
The contents of this file are subject to the terms of either the
|
||||
GNU General Public License Version 2 only ("GPL") or the Common
|
||||
Development and Distribution License("CDDL") (collectively, the
|
||||
"License"). You may not use this file except in compliance with
|
||||
the License. You can obtain a copy of the License at
|
||||
https://glassfish.dev.java.net/public/CDDL+GPL.html or
|
||||
glassfish/bootstrap/legal/LICENSE.txt. See the License for the
|
||||
specific language governing permissions and limitations under the
|
||||
License.
|
||||
|
||||
When distributing the software, include this License Header
|
||||
Notice in each file and include the License file at
|
||||
glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
|
||||
particular file as subject to the "Classpath" exception as
|
||||
provided by Sun in the GPL Version 2 section of the License file
|
||||
that accompanied this code. If applicable, add the following
|
||||
below the License Header, with the fields enclosed by brackets []
|
||||
replaced by your own identifying information:
|
||||
"Portions Copyrighted [year] [name of copyright owner]"
|
||||
|
||||
Contributor(s):
|
||||
|
||||
If you wish your version of this file to be governed by only the
|
||||
CDDL or only the GPL Version 2, indicate your decision by adding
|
||||
"[Contributor] elects to include this software in this
|
||||
distribution under the [CDDL or GPL Version 2] license." If you
|
||||
don't indicate a single choice of license, a recipient has the
|
||||
option to distribute your version of this file under either the
|
||||
CDDL, the GPL Version 2 or to extend the choice of license to its
|
||||
licensees as provided above. However, if you add GPL Version 2
|
||||
code and therefore, elected the GPL Version 2 license, then the
|
||||
option applies only if the new code is made subject to such
|
||||
option by the copyright holder.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
This is the XML Schema for the JSP 2.2 deployment descriptor
|
||||
types. The JSP 2.2 schema contains all the special
|
||||
structures and datatypes that are necessary to use JSP files
|
||||
from a web application.
|
||||
|
||||
The contents of this schema is used by the web-common_3_0.xsd
|
||||
file to define JSP specific content.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The following conventions apply to all Java EE
|
||||
deployment descriptor elements unless indicated otherwise.
|
||||
|
||||
- In elements that specify a pathname to a file within the
|
||||
same JAR file, relative filenames (i.e., those not
|
||||
starting with "/") are considered relative to the root of
|
||||
the JAR file's namespace. Absolute filenames (i.e., those
|
||||
starting with "/") also specify names in the root of the
|
||||
JAR file's namespace. In general, relative names are
|
||||
preferred. The exception is .war files where absolute
|
||||
names are preferred for consistency with the Servlet API.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:include schemaLocation="javaee_6.xsd"/>
|
||||
|
||||
|
||||
<!-- **************************************************** -->
|
||||
|
||||
<xsd:complexType name="jsp-configType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The jsp-configType is used to provide global configuration
|
||||
information for the JSP files in a web application. It has
|
||||
two subelements, taglib and jsp-property-group.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="taglib"
|
||||
type="javaee:taglibType"
|
||||
minOccurs="0"
|
||||
maxOccurs="unbounded"/>
|
||||
<xsd:element name="jsp-property-group"
|
||||
type="javaee:jsp-property-groupType"
|
||||
minOccurs="0"
|
||||
maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id"
|
||||
type="xsd:ID"/>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
<!-- **************************************************** -->
|
||||
|
||||
<xsd:complexType name="jsp-fileType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The jsp-file element contains the full path to a JSP file
|
||||
within the web application beginning with a `/'.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleContent>
|
||||
<xsd:restriction base="javaee:pathType"/>
|
||||
</xsd:simpleContent>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
<!-- **************************************************** -->
|
||||
|
||||
<xsd:complexType name="jsp-property-groupType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The jsp-property-groupType is used to group a number of
|
||||
files so they can be given global property information.
|
||||
All files so described are deemed to be JSP files. The
|
||||
following additional properties can be described:
|
||||
|
||||
- Control whether EL is ignored.
|
||||
- Control whether scripting elements are invalid.
|
||||
- Indicate pageEncoding information.
|
||||
- Indicate that a resource is a JSP document (XML).
|
||||
- Prelude and Coda automatic includes.
|
||||
- Control whether the character sequence #{ is allowed
|
||||
when used as a String literal.
|
||||
- Control whether template text containing only
|
||||
whitespaces must be removed from the response output.
|
||||
- Indicate the default contentType information.
|
||||
- Indicate the default buffering model for JspWriter
|
||||
- Control whether error should be raised for the use of
|
||||
undeclared namespaces in a JSP page.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:group ref="javaee:descriptionGroup"/>
|
||||
<xsd:element name="url-pattern"
|
||||
type="javaee:url-patternType"
|
||||
maxOccurs="unbounded"/>
|
||||
<xsd:element name="el-ignored"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
Can be used to easily set the isELIgnored
|
||||
property of a group of JSP pages. By default, the
|
||||
EL evaluation is enabled for Web Applications using
|
||||
a Servlet 2.4 or greater web.xml, and disabled
|
||||
otherwise.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="page-encoding"
|
||||
type="javaee:string"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The valid values of page-encoding are those of the
|
||||
pageEncoding page directive. It is a
|
||||
translation-time error to name different encodings
|
||||
in the pageEncoding attribute of the page directive
|
||||
of a JSP page and in a JSP configuration element
|
||||
matching the page. It is also a translation-time
|
||||
error to name different encodings in the prolog
|
||||
or text declaration of a document in XML syntax and
|
||||
in a JSP configuration element matching the document.
|
||||
It is legal to name the same encoding through
|
||||
mulitple mechanisms.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="scripting-invalid"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
Can be used to easily disable scripting in a
|
||||
group of JSP pages. By default, scripting is
|
||||
enabled.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="is-xml"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
If true, denotes that the group of resources
|
||||
that match the URL pattern are JSP documents,
|
||||
and thus must be interpreted as XML documents.
|
||||
If false, the resources are assumed to not
|
||||
be JSP documents, unless there is another
|
||||
property group that indicates otherwise.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="include-prelude"
|
||||
type="javaee:pathType"
|
||||
minOccurs="0"
|
||||
maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The include-prelude element is a context-relative
|
||||
path that must correspond to an element in the
|
||||
Web Application. When the element is present,
|
||||
the given path will be automatically included (as
|
||||
in an include directive) at the beginning of each
|
||||
JSP page in this jsp-property-group.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="include-coda"
|
||||
type="javaee:pathType"
|
||||
minOccurs="0"
|
||||
maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The include-coda element is a context-relative
|
||||
path that must correspond to an element in the
|
||||
Web Application. When the element is present,
|
||||
the given path will be automatically included (as
|
||||
in an include directive) at the end of each
|
||||
JSP page in this jsp-property-group.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="deferred-syntax-allowed-as-literal"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The character sequence #{ is reserved for EL expressions.
|
||||
Consequently, a translation error occurs if the #{
|
||||
character sequence is used as a String literal, unless
|
||||
this element is enabled (true). Disabled (false) by
|
||||
default.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="trim-directive-whitespaces"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
Indicates that template text containing only whitespaces
|
||||
must be removed from the response output. It has no
|
||||
effect on JSP documents (XML syntax). Disabled (false)
|
||||
by default.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="default-content-type"
|
||||
type="javaee:string"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The valid values of default-content-type are those of the
|
||||
contentType page directive. It specifies the default
|
||||
response contentType if the page directive does not include
|
||||
a contentType attribute.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="buffer"
|
||||
type="javaee:string"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The valid values of buffer are those of the
|
||||
buffer page directive. It specifies if buffering should be
|
||||
used for the output to response, and if so, the size of the
|
||||
buffer to use.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="error-on-undeclared-namespace"
|
||||
type="javaee:true-falseType"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The default behavior when a tag with unknown namespace is used
|
||||
in a JSP page (regular syntax) is to silently ignore it. If
|
||||
set to true, then an error must be raised during the translation
|
||||
time when an undeclared tag is used in a JSP page. Disabled
|
||||
(false) by default.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id"
|
||||
type="xsd:ID"/>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
<!-- **************************************************** -->
|
||||
|
||||
<xsd:complexType name="taglibType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The taglibType defines the syntax for declaring in
|
||||
the deployment descriptor that a tag library is
|
||||
available to the application. This can be done
|
||||
to override implicit map entries from TLD files and
|
||||
from the container.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="taglib-uri"
|
||||
type="javaee:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
A taglib-uri element describes a URI identifying a
|
||||
tag library used in the web application. The body
|
||||
of the taglib-uri element may be either an
|
||||
absolute URI specification, or a relative URI.
|
||||
There should be no entries in web.xml with the
|
||||
same taglib-uri value.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="taglib-location"
|
||||
type="javaee:pathType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
the taglib-location element contains the location
|
||||
(as a resource relative to the root of the web
|
||||
application) where to find the Tag Library
|
||||
Description file for the tag library.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id"
|
||||
type="xsd:ID"/>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
|
@ -1,272 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="3.0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
||||
|
||||
Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
|
||||
|
||||
The contents of this file are subject to the terms of either the
|
||||
GNU General Public License Version 2 only ("GPL") or the Common
|
||||
Development and Distribution License("CDDL") (collectively, the
|
||||
"License"). You may not use this file except in compliance with
|
||||
the License. You can obtain a copy of the License at
|
||||
https://glassfish.dev.java.net/public/CDDL+GPL.html or
|
||||
glassfish/bootstrap/legal/LICENSE.txt. See the License for the
|
||||
specific language governing permissions and limitations under the
|
||||
License.
|
||||
|
||||
When distributing the software, include this License Header
|
||||
Notice in each file and include the License file at
|
||||
glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
|
||||
particular file as subject to the "Classpath" exception as
|
||||
provided by Sun in the GPL Version 2 section of the License file
|
||||
that accompanied this code. If applicable, add the following
|
||||
below the License Header, with the fields enclosed by brackets []
|
||||
replaced by your own identifying information:
|
||||
"Portions Copyrighted [year] [name of copyright owner]"
|
||||
|
||||
Contributor(s):
|
||||
|
||||
If you wish your version of this file to be governed by only the
|
||||
CDDL or only the GPL Version 2, indicate your decision by adding
|
||||
"[Contributor] elects to include this software in this
|
||||
distribution under the [CDDL or GPL Version 2] license." If you
|
||||
don't indicate a single choice of license, a recipient has the
|
||||
option to distribute your version of this file under either the
|
||||
CDDL, the GPL Version 2 or to extend the choice of license to its
|
||||
licensees as provided above. However, if you add GPL Version 2
|
||||
code and therefore, elected the GPL Version 2 license, then the
|
||||
option applies only if the new code is made subject to such
|
||||
option by the copyright holder.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[[
|
||||
This is the XML Schema for the Servlet 3.0 deployment descriptor.
|
||||
The deployment descriptor must be named "WEB-INF/web.xml" in the
|
||||
web application's war file. All Servlet deployment descriptors
|
||||
must indicate the web application schema by using the Java EE
|
||||
namespace:
|
||||
|
||||
http://java.sun.com/xml/ns/javaee
|
||||
|
||||
and by indicating the version of the schema by
|
||||
using the version element as shown below:
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="..."
|
||||
version="3.0">
|
||||
...
|
||||
</web-app>
|
||||
|
||||
The instance documents may indicate the published version of
|
||||
the schema using the xsi:schemaLocation attribute for Java EE
|
||||
namespace with the following location:
|
||||
|
||||
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd
|
||||
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The following conventions apply to all Java EE
|
||||
deployment descriptor elements unless indicated otherwise.
|
||||
|
||||
- In elements that specify a pathname to a file within the
|
||||
same JAR file, relative filenames (i.e., those not
|
||||
starting with "/") are considered relative to the root of
|
||||
the JAR file's namespace. Absolute filenames (i.e., those
|
||||
starting with "/") also specify names in the root of the
|
||||
JAR file's namespace. In general, relative names are
|
||||
preferred. The exception is .war files where absolute
|
||||
names are preferred for consistency with the Servlet API.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:include schemaLocation="web-common_3_0.xsd"/>
|
||||
|
||||
|
||||
<!-- **************************************************** -->
|
||||
|
||||
<xsd:element name="web-app"
|
||||
type="javaee:web-appType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The web-app element is the root of the deployment
|
||||
descriptor for a web application. Note that the sub-elements
|
||||
of this element can be in the arbitrary order. Because of
|
||||
that, the multiplicity of the elements of distributable,
|
||||
session-config, welcome-file-list, jsp-config, login-config,
|
||||
and locale-encoding-mapping-list was changed from "?" to "*"
|
||||
in this schema. However, the deployment descriptor instance
|
||||
file must not contain multiple elements of session-config,
|
||||
jsp-config, and login-config. When there are multiple elements of
|
||||
welcome-file-list or locale-encoding-mapping-list, the container
|
||||
must concatenate the element contents. The multiple occurence
|
||||
of the element distributable is redundant and the container
|
||||
treats that case exactly in the same way when there is only
|
||||
one distributable.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:unique name="web-common-servlet-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The servlet element contains the name of a servlet.
|
||||
The name must be unique within the web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:servlet"/>
|
||||
<xsd:field xpath="javaee:servlet-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-filter-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The filter element contains the name of a filter.
|
||||
The name must be unique within the web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:filter"/>
|
||||
<xsd:field xpath="javaee:filter-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-ejb-local-ref-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The ejb-local-ref-name element contains the name of an EJB
|
||||
reference. The EJB reference is an entry in the web
|
||||
application's environment and is relative to the
|
||||
java:comp/env context. The name must be unique within
|
||||
the web application.
|
||||
|
||||
It is recommended that name is prefixed with "ejb/".
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:ejb-local-ref"/>
|
||||
<xsd:field xpath="javaee:ejb-ref-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-ejb-ref-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The ejb-ref-name element contains the name of an EJB
|
||||
reference. The EJB reference is an entry in the web
|
||||
application's environment and is relative to the
|
||||
java:comp/env context. The name must be unique within
|
||||
the web application.
|
||||
|
||||
It is recommended that name is prefixed with "ejb/".
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:ejb-ref"/>
|
||||
<xsd:field xpath="javaee:ejb-ref-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-resource-env-ref-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The resource-env-ref-name element specifies the name of
|
||||
a resource environment reference; its value is the
|
||||
environment entry name used in the web application code.
|
||||
The name is a JNDI name relative to the java:comp/env
|
||||
context and must be unique within a web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:resource-env-ref"/>
|
||||
<xsd:field xpath="javaee:resource-env-ref-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-message-destination-ref-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The message-destination-ref-name element specifies the name of
|
||||
a message destination reference; its value is the
|
||||
environment entry name used in the web application code.
|
||||
The name is a JNDI name relative to the java:comp/env
|
||||
context and must be unique within a web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:message-destination-ref"/>
|
||||
<xsd:field xpath="javaee:message-destination-ref-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-res-ref-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The res-ref-name element specifies the name of a
|
||||
resource manager connection factory reference. The name
|
||||
is a JNDI name relative to the java:comp/env context.
|
||||
The name must be unique within a web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:resource-ref"/>
|
||||
<xsd:field xpath="javaee:res-ref-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:unique name="web-common-env-entry-name-uniqueness">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The env-entry-name element contains the name of a web
|
||||
application's environment entry. The name is a JNDI
|
||||
name relative to the java:comp/env context. The name
|
||||
must be unique within a web application.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:env-entry"/>
|
||||
<xsd:field xpath="javaee:env-entry-name"/>
|
||||
</xsd:unique>
|
||||
<xsd:key name="web-common-role-name-key">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
A role-name-key is specified to allow the references
|
||||
from the security-role-refs.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:security-role"/>
|
||||
<xsd:field xpath="javaee:role-name"/>
|
||||
</xsd:key>
|
||||
<xsd:keyref name="web-common-role-name-references"
|
||||
refer="javaee:web-common-role-name-key">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
The keyref indicates the references from
|
||||
security-role-ref to a specified role-name.
|
||||
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:selector xpath="javaee:servlet/javaee:security-role-ref"/>
|
||||
<xsd:field xpath="javaee:role-link"/>
|
||||
</xsd:keyref>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,287 +0,0 @@
|
|||
<?xml version='1.0'?>
|
||||
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
|
||||
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns ="http://www.w3.org/1999/xhtml"
|
||||
xml:lang="en">
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
<h1>About the XML namespace</h1>
|
||||
|
||||
<div class="bodytext">
|
||||
<p>
|
||||
This schema document describes the XML namespace, in a form
|
||||
suitable for import by other schema documents.
|
||||
</p>
|
||||
<p>
|
||||
See <a href="http://www.w3.org/XML/1998/namespace.html">
|
||||
http://www.w3.org/XML/1998/namespace.html</a> and
|
||||
<a href="http://www.w3.org/TR/REC-xml">
|
||||
http://www.w3.org/TR/REC-xml</a> for information
|
||||
about this namespace.
|
||||
</p>
|
||||
<p>
|
||||
Note that local names in this namespace are intended to be
|
||||
defined only by the World Wide Web Consortium or its subgroups.
|
||||
The names currently defined in this namespace are listed below.
|
||||
They should not be used with conflicting semantics by any Working
|
||||
Group, specification, or document instance.
|
||||
</p>
|
||||
<p>
|
||||
See further below in this document for more information about <a
|
||||
href="#usage">how to refer to this schema document from your own
|
||||
XSD schema documents</a> and about <a href="#nsversioning">the
|
||||
namespace-versioning policy governing this schema document</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:attribute name="lang">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
|
||||
<h3>lang (as an attribute name)</h3>
|
||||
<p>
|
||||
denotes an attribute whose value
|
||||
is a language code for the natural language of the content of
|
||||
any element; its value is inherited. This name is reserved
|
||||
by virtue of its definition in the XML specification.</p>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<h4>Notes</h4>
|
||||
<p>
|
||||
Attempting to install the relevant ISO 2- and 3-letter
|
||||
codes as the enumerated possible values is probably never
|
||||
going to be a realistic possibility.
|
||||
</p>
|
||||
<p>
|
||||
See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
|
||||
http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
|
||||
and the IANA language subtag registry at
|
||||
<a href="http://www.iana.org/assignments/language-subtag-registry">
|
||||
http://www.iana.org/assignments/language-subtag-registry</a>
|
||||
for further information.
|
||||
</p>
|
||||
<p>
|
||||
The union allows for the 'un-declaration' of xml:lang with
|
||||
the empty string.
|
||||
</p>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:union memberTypes="xs:language">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value=""/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:union>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attribute name="space">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
|
||||
<h3>space (as an attribute name)</h3>
|
||||
<p>
|
||||
denotes an attribute whose
|
||||
value is a keyword indicating what whitespace processing
|
||||
discipline is intended for the content of the element; its
|
||||
value is inherited. This name is reserved by virtue of its
|
||||
definition in the XML specification.</p>
|
||||
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:NCName">
|
||||
<xs:enumeration value="default"/>
|
||||
<xs:enumeration value="preserve"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
|
||||
<h3>base (as an attribute name)</h3>
|
||||
<p>
|
||||
denotes an attribute whose value
|
||||
provides a URI to be used as the base for interpreting any
|
||||
relative URIs in the scope of the element on which it
|
||||
appears; its value is inherited. This name is reserved
|
||||
by virtue of its definition in the XML Base specification.</p>
|
||||
|
||||
<p>
|
||||
See <a
|
||||
href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
|
||||
for information about this attribute.
|
||||
</p>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attribute name="id" type="xs:ID">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
|
||||
<h3>id (as an attribute name)</h3>
|
||||
<p>
|
||||
denotes an attribute whose value
|
||||
should be interpreted as if declared to be of type ID.
|
||||
This name is reserved by virtue of its definition in the
|
||||
xml:id specification.</p>
|
||||
|
||||
<p>
|
||||
See <a
|
||||
href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
|
||||
for information about this attribute.
|
||||
</p>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attributeGroup name="specialAttrs">
|
||||
<xs:attribute ref="xml:base"/>
|
||||
<xs:attribute ref="xml:lang"/>
|
||||
<xs:attribute ref="xml:space"/>
|
||||
<xs:attribute ref="xml:id"/>
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div>
|
||||
|
||||
<h3>Father (in any context at all)</h3>
|
||||
|
||||
<div class="bodytext">
|
||||
<p>
|
||||
denotes Jon Bosak, the chair of
|
||||
the original XML Working Group. This name is reserved by
|
||||
the following decision of the W3C XML Plenary and
|
||||
XML Coordination groups:
|
||||
</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
In appreciation for his vision, leadership and
|
||||
dedication the W3C XML Plenary on this 10th day of
|
||||
February, 2000, reserves for Jon Bosak in perpetuity
|
||||
the XML name "xml:Father".
|
||||
</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div xml:id="usage" id="usage">
|
||||
<h2><a name="usage">About this schema document</a></h2>
|
||||
|
||||
<div class="bodytext">
|
||||
<p>
|
||||
This schema defines attributes and an attribute group suitable
|
||||
for use by schemas wishing to allow <code>xml:base</code>,
|
||||
<code>xml:lang</code>, <code>xml:space</code> or
|
||||
<code>xml:id</code> attributes on elements they define.
|
||||
</p>
|
||||
<p>
|
||||
To enable this, such a schema must import this schema for
|
||||
the XML namespace, e.g. as follows:
|
||||
</p>
|
||||
<pre>
|
||||
<schema . . .>
|
||||
. . .
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
|
||||
</pre>
|
||||
<p>
|
||||
or
|
||||
</p>
|
||||
<pre>
|
||||
<import namespace="http://www.w3.org/XML/1998/namespace"
|
||||
schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
|
||||
</pre>
|
||||
<p>
|
||||
Subsequently, qualified reference to any of the attributes or the
|
||||
group defined below will have the desired effect, e.g.
|
||||
</p>
|
||||
<pre>
|
||||
<type . . .>
|
||||
. . .
|
||||
<attributeGroup ref="xml:specialAttrs"/>
|
||||
</pre>
|
||||
<p>
|
||||
will define a type which will schema-validate an instance element
|
||||
with any of those attributes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<div id="nsversioning" xml:id="nsversioning">
|
||||
<h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
|
||||
<div class="bodytext">
|
||||
<p>
|
||||
In keeping with the XML Schema WG's standard versioning
|
||||
policy, this schema document will persist at
|
||||
<a href="http://www.w3.org/2009/01/xml.xsd">
|
||||
http://www.w3.org/2009/01/xml.xsd</a>.
|
||||
</p>
|
||||
<p>
|
||||
At the date of issue it can also be found at
|
||||
<a href="http://www.w3.org/2001/xml.xsd">
|
||||
http://www.w3.org/2001/xml.xsd</a>.
|
||||
</p>
|
||||
<p>
|
||||
The schema document at that URI may however change in the future,
|
||||
in order to remain compatible with the latest version of XML
|
||||
Schema itself, or with the XML namespace itself. In other words,
|
||||
if the XML Schema or XML namespaces change, the version of this
|
||||
document at <a href="http://www.w3.org/2001/xml.xsd">
|
||||
http://www.w3.org/2001/xml.xsd
|
||||
</a>
|
||||
will change accordingly; the version at
|
||||
<a href="http://www.w3.org/2009/01/xml.xsd">
|
||||
http://www.w3.org/2009/01/xml.xsd
|
||||
</a>
|
||||
will not change.
|
||||
</p>
|
||||
<p>
|
||||
Previous dated (and unchanging) versions of this schema
|
||||
document are at:
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="http://www.w3.org/2009/01/xml.xsd">
|
||||
http://www.w3.org/2009/01/xml.xsd</a></li>
|
||||
<li><a href="http://www.w3.org/2007/08/xml.xsd">
|
||||
http://www.w3.org/2007/08/xml.xsd</a></li>
|
||||
<li><a href="http://www.w3.org/2004/10/xml.xsd">
|
||||
http://www.w3.org/2004/10/xml.xsd</a></li>
|
||||
<li><a href="http://www.w3.org/2001/03/xml.xsd">
|
||||
http://www.w3.org/2001/03/xml.xsd</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
</xs:schema>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -16,7 +16,6 @@
|
|||
<name>HAPI FHIR - Command Line Client - Base Project</name>
|
||||
|
||||
<modules>
|
||||
<module>hapi-fhir-cli-jpaserver</module>
|
||||
<module>hapi-fhir-cli-api</module>
|
||||
<module>hapi-fhir-cli-app</module>
|
||||
</modules>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
*/
|
||||
package ca.uhn.hapi.converters.canonical;
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_10_40;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_10_50;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_14_40;
|
||||
|
@ -41,10 +44,13 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
|||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
|
||||
import org.hl7.fhir.dstu2.model.Resource;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
|
@ -52,12 +58,17 @@ import org.hl7.fhir.r4.model.ConceptMap;
|
|||
import org.hl7.fhir.r4.model.Parameters;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.PackageInformation;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
|
@ -83,14 +94,16 @@ public class VersionCanonicalizer {
|
|||
private static final BaseAdvisor_14_50 ADVISOR_14_50 = new BaseAdvisor_14_50(false);
|
||||
|
||||
private final IStrategy myStrategy;
|
||||
private final FhirContext myContext;
|
||||
|
||||
public VersionCanonicalizer(FhirContext theTargetContext) {
|
||||
this(theTargetContext.getVersion().getVersion());
|
||||
public VersionCanonicalizer(FhirVersionEnum theTargetVersion) {
|
||||
this(theTargetVersion.newContextCached());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EnhancedSwitchMigration"})
|
||||
public VersionCanonicalizer(FhirVersionEnum theTargetVersion) {
|
||||
switch (theTargetVersion) {
|
||||
public VersionCanonicalizer(FhirContext theTargetContext) {
|
||||
myContext = theTargetContext;
|
||||
FhirVersionEnum targetVersion = theTargetContext.getVersion().getVersion();
|
||||
switch (targetVersion) {
|
||||
case DSTU2:
|
||||
myStrategy = new Dstu2Strategy(false);
|
||||
break;
|
||||
|
@ -113,10 +126,12 @@ public class VersionCanonicalizer {
|
|||
myStrategy = new R5Strategy();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(Msg.code(193) + "Can't handle version: " + theTargetVersion);
|
||||
throw new IllegalStateException(Msg.code(193) + "Can't handle version: " + targetVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"EnhancedSwitchMigration"})
|
||||
|
||||
|
||||
/**
|
||||
* Canonical version: R5
|
||||
|
@ -125,6 +140,13 @@ public class VersionCanonicalizer {
|
|||
return myStrategy.capabilityStatementToCanonical(theCapabilityStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonical version: R5
|
||||
*/
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theCapabilityStatement) {
|
||||
return myStrategy.capabilityStatementFromCanonical(theCapabilityStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonical version: R4
|
||||
*/
|
||||
|
@ -176,8 +198,39 @@ public class VersionCanonicalizer {
|
|||
return myStrategy.conceptMapToCanonical(theConceptMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonical version: R5
|
||||
* <p>
|
||||
* Note that this method will look for any nonstandard resource types specified in
|
||||
* {@literal SearchParameter.base} or {@literal SearchParameter.target} and move them into
|
||||
* extensions with the URLs {@link HapiExtensions#EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE}
|
||||
* and {@link HapiExtensions#EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE} respectively. If any
|
||||
* nonstandard resource types are found, all resource types in the respective list are moved into
|
||||
* the extension (including standard types) and the source list is cleared.
|
||||
*/
|
||||
public <T extends IBaseResource> SearchParameter searchParameterToCanonical(T theSearchParameter) {
|
||||
return myStrategy.searchParameterToCanonical(theSearchParameter);
|
||||
|
||||
/*
|
||||
* The R4 model allows custom types to be put into SearchParameter.base and
|
||||
* SearchParameter.target because those fields use a simple CodeType. But
|
||||
* in R5 it uses an Enumeration, so it's not actually possible to put custom
|
||||
* resource types into those fields. This means that the version converter fails
|
||||
* with an exception unless we remove those values from those fields before
|
||||
* conversion. However, we don't want to affect the state of the originally
|
||||
* passed in resource since that may affect other things. So, we clone
|
||||
* it first. This is a pain in the butt, but there doesn't seem to be any
|
||||
* better option.
|
||||
*/
|
||||
T input = myContext.newTerser().clone(theSearchParameter);
|
||||
|
||||
List<String> baseExtensionValues = extractNonStandardSearchParameterListAndClearSourceIfAnyArePresent(input, "base");
|
||||
List<String> targetExtensionValues = extractNonStandardSearchParameterListAndClearSourceIfAnyArePresent(input, "target");
|
||||
|
||||
SearchParameter retVal = myStrategy.searchParameterToCanonical(input);
|
||||
|
||||
baseExtensionValues.forEach(t -> retVal.addExtension(HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE, new CodeType(t)));
|
||||
targetExtensionValues.forEach(t -> retVal.addExtension(HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE, new CodeType(t)));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public IBaseResource searchParameterFromCanonical(SearchParameter theSearchParameter) {
|
||||
|
@ -218,6 +271,28 @@ public class VersionCanonicalizer {
|
|||
return myStrategy.codeSystemToValidatorCanonical(theResource);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private List<String> extractNonStandardSearchParameterListAndClearSourceIfAnyArePresent(IBaseResource theSearchParameter, String theChildName) {
|
||||
|
||||
BaseRuntimeChildDefinition child = myContext.getResourceDefinition(theSearchParameter).getChildByName(theChildName);
|
||||
List<IBase> baseList = child.getAccessor().getValues(theSearchParameter);
|
||||
|
||||
List<String> baseExtensionValues = baseList
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(t -> t instanceof IPrimitiveType)
|
||||
.map(t -> (IPrimitiveType<?>) t)
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toList());
|
||||
if (baseExtensionValues.stream().allMatch(Enumerations.VersionIndependentResourceTypesAll::isValidCode)) {
|
||||
baseExtensionValues.clear();
|
||||
} else {
|
||||
baseList.clear();
|
||||
}
|
||||
return baseExtensionValues;
|
||||
}
|
||||
|
||||
private interface IStrategy {
|
||||
|
||||
CapabilityStatement capabilityStatementToCanonical(IBaseResource theCapabilityStatement);
|
||||
|
@ -251,6 +326,8 @@ public class VersionCanonicalizer {
|
|||
org.hl7.fhir.r5.model.CodeSystem codeSystemToValidatorCanonical(IBaseResource theResource);
|
||||
|
||||
IBaseResource searchParameterFromCanonical(SearchParameter theResource);
|
||||
|
||||
IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource);
|
||||
}
|
||||
|
||||
private static class Dstu2Strategy implements IStrategy {
|
||||
|
@ -278,7 +355,7 @@ public class VersionCanonicalizer {
|
|||
retVal.setSystem(coding.getSystem());
|
||||
retVal.setDisplay(coding.getDisplay());
|
||||
retVal.setVersion(coding.getVersion());
|
||||
retVal.setUserSelected( ! coding.getUserSelectedElement().isEmpty() && coding.getUserSelected() );
|
||||
retVal.setUserSelected(!coding.getUserSelectedElement().isEmpty() && coding.getUserSelected());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -407,6 +484,12 @@ public class VersionCanonicalizer {
|
|||
return reencodeFromHl7Org(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
Resource converted = VersionConvertorFactory_10_50.convertResource(theResource, ADVISOR_10_50);
|
||||
return (IBaseConformance) reencodeToHl7Org(converted);
|
||||
}
|
||||
|
||||
private Resource reencodeToHl7Org(IBaseResource theInput) {
|
||||
if (myHl7OrgStructures) {
|
||||
return (Resource) theInput;
|
||||
|
@ -504,6 +587,11 @@ public class VersionCanonicalizer {
|
|||
public IBaseResource searchParameterFromCanonical(SearchParameter theResource) {
|
||||
return VersionConvertorFactory_14_50.convertResource(theResource, ADVISOR_14_50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
return (IBaseConformance) VersionConvertorFactory_14_50.convertResource(theResource, ADVISOR_14_50);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Dstu3Strategy implements IStrategy {
|
||||
|
@ -587,6 +675,11 @@ public class VersionCanonicalizer {
|
|||
public IBaseResource searchParameterFromCanonical(SearchParameter theResource) {
|
||||
return VersionConvertorFactory_30_50.convertResource(theResource, ADVISOR_30_50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
return (IBaseConformance) VersionConvertorFactory_30_50.convertResource(theResource, ADVISOR_30_50);
|
||||
}
|
||||
}
|
||||
|
||||
private static class R4Strategy implements IStrategy {
|
||||
|
@ -670,6 +763,11 @@ public class VersionCanonicalizer {
|
|||
return VersionConvertorFactory_40_50.convertResource(theResource, ADVISOR_40_50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
return (IBaseConformance) VersionConvertorFactory_40_50.convertResource(theResource, ADVISOR_40_50);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class R4BStrategy implements IStrategy {
|
||||
|
@ -761,8 +859,12 @@ public class VersionCanonicalizer {
|
|||
return VersionConvertorFactory_43_50.convertResource(theResource, ADVISOR_43_50);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
return (IBaseConformance) VersionConvertorFactory_43_50.convertResource(theResource, ADVISOR_43_50);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class R5Strategy implements IStrategy {
|
||||
|
||||
|
@ -846,6 +948,11 @@ public class VersionCanonicalizer {
|
|||
return theResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseConformance capabilityStatementFromCanonical(CapabilityStatement theResource) {
|
||||
return theResource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,12 +2,28 @@ package ca.uhn.hapi.converters.canonical;
|
|||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeType;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.util.ExtensionUtil.getExtensionPrimitiveValues;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class VersionCanonicalizerTest {
|
||||
|
@ -31,4 +47,51 @@ class VersionCanonicalizerTest {
|
|||
assertEquals("http://foo", outputDstu2.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToCanonicalSearchParameter_NoCustomResourceType() {
|
||||
// Setup
|
||||
VersionCanonicalizer canonicalizer = new VersionCanonicalizer(FhirVersionEnum.R4);
|
||||
|
||||
org.hl7.fhir.r4.model.SearchParameter input = new org.hl7.fhir.r4.model.SearchParameter();
|
||||
input.addBase("Patient");
|
||||
input.addBase("Observation");
|
||||
input.addTarget("Organization");
|
||||
|
||||
// Test
|
||||
org.hl7.fhir.r5.model.SearchParameter actual = canonicalizer.searchParameterToCanonical(input);
|
||||
|
||||
// Verify
|
||||
assertThat(actual.getBase().stream().map(Enumeration::getCode).collect(Collectors.toList()), contains("Patient", "Observation"));
|
||||
assertThat(actual.getTarget().stream().map(Enumeration::getCode).collect(Collectors.toList()), contains("Organization"));
|
||||
assertThat(getExtensionPrimitiveValues(actual, HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE), empty());
|
||||
assertThat(getExtensionPrimitiveValues(actual, HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE), empty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToCanonicalSearchParameter_WithCustomResourceType() {
|
||||
// Setup
|
||||
VersionCanonicalizer canonicalizer = new VersionCanonicalizer(FhirVersionEnum.R4);
|
||||
|
||||
org.hl7.fhir.r4.model.SearchParameter input = new org.hl7.fhir.r4.model.SearchParameter();
|
||||
input.addBase("Base1");
|
||||
input.addBase("Base2");
|
||||
input.addTarget("Target1");
|
||||
input.addTarget("Target2");
|
||||
|
||||
// Test
|
||||
org.hl7.fhir.r5.model.SearchParameter actual = canonicalizer.searchParameterToCanonical(input);
|
||||
|
||||
// Verify
|
||||
assertThat(actual.getBase().stream().map(Enumeration::getCode).collect(Collectors.toList()), empty());
|
||||
assertThat(actual.getTarget().stream().map(Enumeration::getCode).collect(Collectors.toList()), empty());
|
||||
assertThat(getExtensionPrimitiveValues(actual, HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE), contains("Base1", "Base2"));
|
||||
assertThat(getExtensionPrimitiveValues(actual, HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE), contains("Target1", "Target2"));
|
||||
// Original shouldn't be modified
|
||||
assertThat(input.getBase().stream().map(CodeType::getCode).toList(), contains("Base1", "Base2"));
|
||||
assertThat(input.getTarget().stream().map(CodeType::getCode).toList(), contains("Target1", "Target2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 4727
|
||||
title: "The FHIR R5 definitions have been upgraded to the final FHIR R5
|
||||
release version."
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
type: remove
|
||||
issue: 4727
|
||||
title: "The HAPI FHIR CLI `run-server` command has been removed. This command
|
||||
was used to launch a HAPI FHIR JPA Server instance. The
|
||||
[hapi-fhir-jpaserver-starter](https://github.com/hapifhir/hapi-fhir-jpaserver-starter/)
|
||||
project has long since duplicated and improved on the CLI version of the
|
||||
launcher, and maintaining both was been a maintenance burden. Users of the
|
||||
CLI command are recommended to migrate to the starter project."
|
|
@ -26,6 +26,28 @@ Note also that after the release of the FHIR DSTU2 specification, the FHIR
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>HAPI FHIR 6.6.0</td>
|
||||
<td>JDK11</td>
|
||||
<td class="versions-table-cell-empty"></td>
|
||||
<td class="versions-table-cell-draft">1.0.2</td>
|
||||
<td class="versions-table-cell-release">1.4.0</td>
|
||||
<td class="versions-table-cell-draft">3.0.2</td>
|
||||
<td class="versions-table-cell-draft">4.0.1</td>
|
||||
<td class="versions-table-cell-draft">4.3.0</td>
|
||||
<td class="versions-table-cell-draft">5.0.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 6.4.0</td>
|
||||
<td>JDK11</td>
|
||||
<td class="versions-table-cell-empty"></td>
|
||||
<td class="versions-table-cell-draft">1.0.2</td>
|
||||
<td class="versions-table-cell-release">1.4.0</td>
|
||||
<td class="versions-table-cell-draft">3.0.2</td>
|
||||
<td class="versions-table-cell-draft">4.0.1</td>
|
||||
<td class="versions-table-cell-draft">4.3.0</td>
|
||||
<td class="versions-table-cell-release">5.0.0-ballot<span class="download-version-hash"><br/>9a044604c1</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 6.2.0</td>
|
||||
<td>JDK11</td>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -426,6 +426,11 @@
|
|||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.exparity</groupId>
|
||||
<artifactId>hamcrest-date</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
@ -70,7 +71,7 @@ public class JpaResourceDaoSearchParameter<T extends IBaseResource> extends Base
|
|||
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
|
||||
|
||||
org.hl7.fhir.r5.model.SearchParameter searchParameter = myVersionCanonicalizer.searchParameterToCanonical(theResource);
|
||||
List<String> base = theResource != null ? searchParameter.getBase().stream().map(CodeType::getCode).collect(Collectors.toList()) : null;
|
||||
List<String> base = theResource != null ? searchParameter.getBase().stream().map(Enumeration::getCode).collect(Collectors.toList()) : null;
|
||||
requestReindexForRelatedResources(reindex, base, theRequestDetails);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||
import javax.annotation.Nonnull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
@ -39,6 +40,8 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.exparity.hamcrest.date.DateMatchers.within;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
|
@ -105,7 +108,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
jobInstances.get(0).setReport(null);
|
||||
|
||||
setupTestEnabledNoBinaries(expectedRetentionHours, jobInstances);
|
||||
setupTestEnabledNoBinaries(jobInstances);
|
||||
|
||||
myBulkDataExportJobSchedulingHelper.purgeExpiredFiles();
|
||||
|
||||
|
@ -117,7 +120,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
}
|
||||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -128,7 +131,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
jobInstances.get(0).setReport("{garbage}");
|
||||
|
||||
setupTestEnabledNoBinaries(expectedRetentionHours, jobInstances);
|
||||
setupTestEnabledNoBinaries(jobInstances);
|
||||
|
||||
myBulkDataExportJobSchedulingHelper.purgeExpiredFiles();
|
||||
|
||||
|
@ -140,7 +143,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
}
|
||||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -163,7 +166,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
}
|
||||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -186,7 +189,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
}
|
||||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -210,7 +213,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -234,7 +237,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -261,7 +264,7 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
final Date cutoffDate = myCutoffCaptor.getValue();
|
||||
|
||||
assertEquals(DateUtils.truncate(computeDateFromConfig(expectedRetentionHours), Calendar.MINUTE), DateUtils.truncate(cutoffDate, Calendar.MINUTE));
|
||||
assertThat(cutoffDate, within(1, ChronoUnit.MINUTES, computeDateFromConfig(expectedRetentionHours)));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -280,8 +283,8 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
setupTest(true, theRetentionHours, theJobInstances, true);
|
||||
}
|
||||
|
||||
private void setupTestEnabledNoBinaries(int theRetentionHours, List<JobInstance> theJobInstances) {
|
||||
setupTest(true, theRetentionHours, theJobInstances, false);
|
||||
private void setupTestEnabledNoBinaries(List<JobInstance> theJobInstances) {
|
||||
setupTest(true, 1, theJobInstances, false);
|
||||
}
|
||||
|
||||
private void setupTest(boolean theIsEnabled, int theRetentionHours, List<JobInstance> theJobInstances, boolean theIsEnableBinaryMocks) {
|
||||
|
@ -296,11 +299,13 @@ public class BulkDataExportJobSchedulingHelperImplTest {
|
|||
|
||||
final Answer<List<JobInstance>> fetchInstancesAnswer = theInvocationOnMock -> {
|
||||
final TransactionCallback<List<JobInstance>> transactionCallback = theInvocationOnMock.getArgument(0);
|
||||
//noinspection DataFlowIssue
|
||||
return transactionCallback.doInTransaction(null);
|
||||
};
|
||||
|
||||
final Answer<Void> purgeExpiredJobsAnswer = theInvocationOnMock -> {
|
||||
final TransactionCallback<Optional<JobInstance>> transactionCallback = theInvocationOnMock.getArgument(0);
|
||||
//noinspection DataFlowIssue
|
||||
transactionCallback.doInTransaction(null);
|
||||
return null;
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -33,11 +33,15 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
|
||||
public class ReadOnlySearchParamCache {
|
||||
|
||||
// resourceName -> searchParamName -> searchparam
|
||||
|
@ -91,51 +95,58 @@ public class ReadOnlySearchParamCache {
|
|||
|
||||
Set<String> resourceNames = theFhirContext.getResourceTypes();
|
||||
|
||||
IBaseBundle allSearchParameterBundle = null;
|
||||
/*
|
||||
* For R4/R4B we include a Bundle of SearchParameters from the core spec in
|
||||
* hapi-fhir-validation-resources-r4/r4b
|
||||
*
|
||||
* For R5 we include the NPM core R5 packages in
|
||||
* hapi-fhir-validation-resources-r5, so we get them from it
|
||||
*/
|
||||
List<IBaseResource> searchParams = null;
|
||||
if (theFhirContext.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||
allSearchParameterBundle = (IBaseBundle) theFhirContext.newJsonParser().parseResource(ClasspathUtil.loadResourceAsStream("org/hl7/fhir/r4/model/sp/search-parameters.json"));
|
||||
IBaseBundle allSearchParameterBundle = (IBaseBundle) theFhirContext.newJsonParser().parseResource(ClasspathUtil.loadResourceAsStream("org/hl7/fhir/r4/model/sp/search-parameters.json"));
|
||||
searchParams = BundleUtil.toListOfResources(theFhirContext, allSearchParameterBundle);
|
||||
} else if (theFhirContext.getVersion().getVersion() == FhirVersionEnum.R4B) {
|
||||
allSearchParameterBundle = (IBaseBundle) theFhirContext.newXmlParser().parseResource(ClasspathUtil.loadResourceAsStream("org/hl7/fhir/r4b/model/sp/search-parameters.xml"));
|
||||
IBaseBundle allSearchParameterBundle = (IBaseBundle) theFhirContext.newXmlParser().parseResource(ClasspathUtil.loadResourceAsStream("org/hl7/fhir/r4b/model/sp/search-parameters.xml"));
|
||||
searchParams = BundleUtil.toListOfResources(theFhirContext, allSearchParameterBundle);
|
||||
} else if (theFhirContext.getVersion().getVersion() == FhirVersionEnum.R5) {
|
||||
allSearchParameterBundle = (IBaseBundle) theFhirContext.newXmlParser().parseResource(ClasspathUtil.loadResourceAsStream("org/hl7/fhir/r5/model/sp/search-parameters.xml"));
|
||||
searchParams = FhirContext.forR5Cached().getValidationSupport().fetchAllSearchParameters();
|
||||
}
|
||||
|
||||
if (allSearchParameterBundle != null) {
|
||||
// For each SearchParameter resource in the bundle of all search parameters defined in this version of FHIR
|
||||
for (IBaseResource next : BundleUtil.toListOfResources(theFhirContext, allSearchParameterBundle)) {
|
||||
RuntimeSearchParam nextCanonical = theCanonicalizer.canonicalizeSearchParameter(next);
|
||||
searchParams = defaultIfNull(searchParams, Collections.emptyList());
|
||||
for (IBaseResource next : searchParams) {
|
||||
RuntimeSearchParam nextCanonical = theCanonicalizer.canonicalizeSearchParameter(next);
|
||||
|
||||
if (nextCanonical != null) {
|
||||
if (nextCanonical != null) {
|
||||
|
||||
// Force status to ACTIVE - For whatever reason the R5 draft SPs ship with
|
||||
// a status of DRAFT which means the server doesn't actually apply them.
|
||||
// At least this was the case as of 2021-12-24 - JA
|
||||
nextCanonical = new RuntimeSearchParam(
|
||||
nextCanonical.getId(),
|
||||
nextCanonical.getUri(),
|
||||
nextCanonical.getName(),
|
||||
nextCanonical.getDescription(),
|
||||
nextCanonical.getPath(),
|
||||
nextCanonical.getParamType(),
|
||||
nextCanonical.getProvidesMembershipInCompartments(),
|
||||
nextCanonical.getTargets(),
|
||||
RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE,
|
||||
nextCanonical.getComboSearchParamType(),
|
||||
nextCanonical.getComponents(),
|
||||
nextCanonical.getBase());
|
||||
// Force status to ACTIVE - For whatever reason the R5 draft SPs ship with
|
||||
// a status of DRAFT which means the server doesn't actually apply them.
|
||||
// At least this was the case as of 2021-12-24 - JA
|
||||
nextCanonical = new RuntimeSearchParam(
|
||||
nextCanonical.getId(),
|
||||
nextCanonical.getUri(),
|
||||
nextCanonical.getName(),
|
||||
nextCanonical.getDescription(),
|
||||
nextCanonical.getPath(),
|
||||
nextCanonical.getParamType(),
|
||||
nextCanonical.getProvidesMembershipInCompartments(),
|
||||
nextCanonical.getTargets(),
|
||||
RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE,
|
||||
nextCanonical.getComboSearchParamType(),
|
||||
nextCanonical.getComponents(),
|
||||
nextCanonical.getBase());
|
||||
|
||||
Collection<String> base = nextCanonical.getBase();
|
||||
if (base.contains("Resource") || base.contains("DomainResource")) {
|
||||
base = resourceNames;
|
||||
}
|
||||
Collection<String> base = nextCanonical.getBase();
|
||||
if (base.contains("Resource") || base.contains("DomainResource")) {
|
||||
base = resourceNames;
|
||||
}
|
||||
|
||||
// Add it to our return value if permitted by the pattern parameters
|
||||
for (String nextResourceName : base) {
|
||||
ResourceSearchParams resourceSearchParams = retVal.myResourceNameToSpNameToSp.computeIfAbsent(nextResourceName, t -> new ResourceSearchParams(nextResourceName));
|
||||
String nextParamName = nextCanonical.getName();
|
||||
if (theSearchParamPatternsToInclude == null || searchParamMatchesAtLeastOnePattern(theSearchParamPatternsToInclude, nextResourceName, nextParamName)) {
|
||||
resourceSearchParams.addSearchParamIfAbsent(nextParamName, nextCanonical);
|
||||
}
|
||||
// Add it to our return value if permitted by the pattern parameters
|
||||
for (String nextResourceName : base) {
|
||||
ResourceSearchParams resourceSearchParams = retVal.myResourceNameToSpNameToSp.computeIfAbsent(nextResourceName, t -> new ResourceSearchParams(nextResourceName));
|
||||
String nextParamName = nextCanonical.getName();
|
||||
if (theSearchParamPatternsToInclude == null || searchParamMatchesAtLeastOnePattern(theSearchParamPatternsToInclude, nextResourceName, nextParamName)) {
|
||||
resourceSearchParams.addSearchParamIfAbsent(nextParamName, nextCanonical);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,36 +27,20 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.DatatypeUtil;
|
||||
import ca.uhn.fhir.util.ExtensionUtil;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import ca.uhn.fhir.util.PhoneticEncoderUtil;
|
||||
import ca.uhn.fhir.util.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
import org.hl7.fhir.dstu3.model.SearchParameter;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
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 org.hl7.fhir.instance.model.api.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.startsWith;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
@Service
|
||||
public class SearchParameterCanonicalizer {
|
||||
|
@ -69,6 +53,16 @@ public class SearchParameterCanonicalizer {
|
|||
myFhirContext = theFhirContext;
|
||||
}
|
||||
|
||||
private static Collection<String> toStrings(Collection<? extends IPrimitiveType<String>> theBase) {
|
||||
HashSet<String> retVal = new HashSet<>();
|
||||
for (IPrimitiveType<String> next : theBase) {
|
||||
if (isNotBlank(next.getValueAsString())) {
|
||||
retVal.add(next.getValueAsString());
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public RuntimeSearchParam canonicalizeSearchParameter(IBaseResource theSearchParameter) {
|
||||
RuntimeSearchParam retVal;
|
||||
switch (myFhirContext.getVersion().getVersion()) {
|
||||
|
@ -266,7 +260,23 @@ public class SearchParameterCanonicalizer {
|
|||
String name = terser.getSinglePrimitiveValueOrNull(theNextSp, "code");
|
||||
String description = terser.getSinglePrimitiveValueOrNull(theNextSp, "description");
|
||||
String path = terser.getSinglePrimitiveValueOrNull(theNextSp, "expression");
|
||||
List<String> base = terser.getValues(theNextSp, "base", IPrimitiveType.class).stream().map(t -> t.getValueAsString()).collect(Collectors.toList());
|
||||
|
||||
List<String> base = terser
|
||||
.getValues(theNextSp, "base", IPrimitiveType.class)
|
||||
.stream()
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.collect(Collectors.toList());
|
||||
if (theNextSp instanceof IBaseHasExtensions) {
|
||||
((IBaseHasExtensions) theNextSp)
|
||||
.getExtension()
|
||||
.stream()
|
||||
.filter(t -> HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_BASE_RESOURCE.equals(t.getUrl()))
|
||||
.filter(t -> t.getValue() instanceof IPrimitiveType)
|
||||
.map(t -> ((IPrimitiveType<?>) t.getValue()))
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.forEach(base::add);
|
||||
}
|
||||
|
||||
RestSearchParameterTypeEnum paramType = null;
|
||||
RuntimeSearchParam.RuntimeSearchParamStatusEnum status = null;
|
||||
|
@ -314,7 +324,23 @@ public class SearchParameterCanonicalizer {
|
|||
break;
|
||||
}
|
||||
Set<String> providesMembershipInCompartments = Collections.emptySet();
|
||||
Set<String> targets = terser.getValues(theNextSp, "target", IPrimitiveType.class).stream().map(t -> t.getValueAsString()).collect(Collectors.toSet());
|
||||
|
||||
Set<String> targets = terser
|
||||
.getValues(theNextSp, "target", IPrimitiveType.class)
|
||||
.stream()
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.collect(Collectors.toSet());
|
||||
if (theNextSp instanceof IBaseHasExtensions) {
|
||||
((IBaseHasExtensions) theNextSp)
|
||||
.getExtension()
|
||||
.stream()
|
||||
.filter(t -> HapiExtensions.EXTENSION_SEARCHPARAM_CUSTOM_TARGET_RESOURCE.equals(t.getUrl()))
|
||||
.filter(t -> t.getValue() instanceof IPrimitiveType)
|
||||
.map(t -> ((IPrimitiveType<?>) t.getValue()))
|
||||
.map(IPrimitiveType::getValueAsString)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.forEach(targets::add);
|
||||
}
|
||||
|
||||
if (isBlank(name) || isBlank(path) || paramType == null) {
|
||||
if ("_text".equals(name) || "_content".equals(name)) {
|
||||
|
@ -356,7 +382,6 @@ public class SearchParameterCanonicalizer {
|
|||
return new RuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, base);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts any extensions from the resource and populates an extension field in the
|
||||
*/
|
||||
|
@ -396,22 +421,11 @@ public class SearchParameterCanonicalizer {
|
|||
IPhoneticEncoder encoder = PhoneticEncoderUtil.getEncoder(stringValue);
|
||||
if (encoder != null) {
|
||||
theRuntimeSearchParam.setPhoneticEncoder(encoder);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ourLog.error("Invalid PhoneticEncoderEnum value '" + stringValue + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<String> toStrings(Collection<? extends IPrimitiveType<String>> theBase) {
|
||||
HashSet<String> retVal = new HashSet<>();
|
||||
for (IPrimitiveType<String> next : theBase) {
|
||||
if (isNotBlank(next.getValueAsString())) {
|
||||
retVal.add(next.getValueAsString());
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.registry;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SearchParameterCanonicalizerTest {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchParameterCanonicalizerTest.class);
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {false, true})
|
||||
public void testCanonicalizeSearchParameterWithCustomType(boolean theConvertToR5) {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/meal-chef");
|
||||
sp.setUrl("http://example.org/SearchParameter/meal-chef");
|
||||
sp.addBase("Meal");
|
||||
sp.addBase("Patient");
|
||||
sp.setCode("chef");
|
||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setExpression("Meal.chef | Observation.subject");
|
||||
sp.addTarget("Chef");
|
||||
sp.addTarget("Observation");
|
||||
|
||||
IBaseResource searchParamToCanonicalize = sp;
|
||||
SearchParameterCanonicalizer svc;
|
||||
if (theConvertToR5) {
|
||||
VersionCanonicalizer versionCanonicalizer = new VersionCanonicalizer(FhirContext.forR4Cached());
|
||||
searchParamToCanonicalize = versionCanonicalizer.searchParameterToCanonical(sp);
|
||||
FhirContext fhirContextR5 = FhirContext.forR5Cached();
|
||||
ourLog.info("R5 Subscription: {}", fhirContextR5.newJsonParser().setPrettyPrint(true).encodeResourceToString(searchParamToCanonicalize));
|
||||
svc = new SearchParameterCanonicalizer(fhirContextR5);
|
||||
} else {
|
||||
svc = new SearchParameterCanonicalizer(FhirContext.forR4Cached());
|
||||
}
|
||||
|
||||
RuntimeSearchParam output = svc.canonicalizeSearchParameter(searchParamToCanonicalize);
|
||||
assertEquals("chef", output.getName());
|
||||
assertEquals(RestSearchParameterTypeEnum.REFERENCE, output.getParamType());
|
||||
assertEquals(RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, output.getStatus());
|
||||
assertThat(output.getPathsSplit(), containsInAnyOrder("Meal.chef", "Observation.subject"));
|
||||
assertThat(output.getBase(), containsInAnyOrder("Meal", "Patient"));
|
||||
assertThat(output.getTargets(), contains("Chef", "Observation"));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -37,7 +37,6 @@
|
|||
<dependency>
|
||||
<groupId>org.exparity</groupId>
|
||||
<artifactId>hamcrest-date</artifactId>
|
||||
<version>2.0.7</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>*</artifactId>
|
||||
|
|
|
@ -16,8 +16,10 @@ public class FhirResourceDaoCustomTypeR4Test extends BaseJpaR4Test {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCustomTypeR4Test.class);
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
myFhirContext.setDefaultTypeForProfile(CustomObservationR4.PROFILE, CustomObservationR4.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -854,6 +854,11 @@ public class FhirResourceDaoR4ComboUniqueParamIT extends BaseComboParamsR4Test {
|
|||
|
||||
createUniqueIndexCoverageBeneficiary();
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(0, uniques.size(), uniques.toString());
|
||||
});
|
||||
|
||||
executeReindex("Coverage?");
|
||||
|
||||
runInTransaction(() -> {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.term.TermReindexingSvcImpl;
|
|||
import ca.uhn.fhir.jpa.test.Batch2JobHelper;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -158,7 +159,7 @@ public class FhirResourceDaoR5CodeSystemTest extends BaseJpaR5Test {
|
|||
|
||||
private IIdType createLargeCodeSystem(String theVersion) {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
cs.setContent(Enumerations.CodeSystemContentMode.COMPLETE);
|
||||
cs.setUrl("http://foo");
|
||||
if (theVersion != null) {
|
||||
cs.setVersion(theVersion);
|
||||
|
|
|
@ -259,7 +259,7 @@ public class FhirResourceDaoR5SearchNoFtTest extends BaseJpaR5Test {
|
|||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setExpression("Bundle.entry[0].resource.as(Composition).subject.resolve().as(Patient).identifier");
|
||||
sp.addBase("Bundle");
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.BUNDLE);
|
||||
ourLog.info("SP: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
|
|||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -35,7 +36,7 @@ public class FhirResourceDaoR5ValueSetMultiVersionTest extends BaseJpaR5Test {
|
|||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl(URL_MY_CODE_SYSTEM);
|
||||
codeSystem.setVersion(theVersion);
|
||||
codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
codeSystem.setContent(Enumerations.CodeSystemContentMode.COMPLETE);
|
||||
for (String codeSystemCode : theCodeSystemCodes) {
|
||||
codeSystem.addConcept().setCode(codeSystemCode);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public class SearchParamExtractorR5Test {
|
|||
appointment.setStart(new Date());
|
||||
appointment.setEnd(new Date());
|
||||
Appointment.AppointmentParticipantComponent participant = new Appointment.AppointmentParticipantComponent();
|
||||
participant.setStatus(Enumerations.ParticipationStatus.ACCEPTED);
|
||||
participant.setStatus(Appointment.ParticipationStatus.ACCEPTED);
|
||||
appointment.setParticipant(Collections.singletonList(participant));
|
||||
|
||||
|
||||
|
|
|
@ -154,10 +154,10 @@ public class UpliftedRefchainsAndChainedSortingR5Test extends BaseJpaR5Test {
|
|||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
||||
sp.setExpression("Bundle.entry[0].resource.as(Composition)");
|
||||
subjectSp.getBase().forEach(sp::addBase);
|
||||
subjectSp.getTargets().forEach(sp::addTarget);
|
||||
subjectSp.getBase().forEach(t->sp.addBase(Enumerations.VersionIndependentResourceTypesAll.fromCode(t)));
|
||||
subjectSp.getTargets().forEach(t->sp.addTarget(Enumerations.VersionIndependentResourceTypesAll.fromCode(t)));
|
||||
ourLog.info("SP: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
mySearchParameterDao.create(sp, mySrd);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
|
@ -1063,9 +1063,9 @@ public class UpliftedRefchainsAndChainedSortingR5Test extends BaseJpaR5Test {
|
|||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
||||
sp.setExpression(subjectSp.getPath());
|
||||
subjectSp.getBase().forEach(sp::addBase);
|
||||
subjectSp.getTargets().forEach(sp::addTarget);
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
subjectSp.getBase().forEach(t->sp.addBase(Enumerations.VersionIndependentResourceTypesAll.fromCode(t)));
|
||||
subjectSp.getTargets().forEach(t->sp.addTarget(Enumerations.VersionIndependentResourceTypesAll.fromCode(t)));
|
||||
mySearchParameterDao.create(sp, mySrd);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ResourceProviderR5CodeSystemTest extends BaseResourceProviderR5Test
|
|||
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
|
||||
parentChildCs.setName("Parent Child CodeSystem");
|
||||
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setContent(Enumerations.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
|
||||
|
||||
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
|
||||
|
@ -193,47 +193,59 @@ public class ResourceProviderR5CodeSystemTest extends BaseResourceProviderR5Test
|
|||
@Test
|
||||
public void testLookupOperationByCodeAndSystemBuiltInCode() {
|
||||
// First test with no version specified (should return the one and only version defined).
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named("lookup")
|
||||
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
|
||||
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
|
||||
.execute();
|
||||
{
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named("lookup")
|
||||
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
|
||||
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
|
||||
.execute();
|
||||
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param0 = respParam.getParameter().get(0);
|
||||
assertEquals("name", param0.getName());
|
||||
assertEquals("IdentifierType", ((StringType) param0.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param1 = respParam.getParameter().get(1);
|
||||
assertEquals("version", param1.getName());
|
||||
assertEquals("2.9.0", ((StringType) param1.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param2 = respParam.getParameter().get(2);
|
||||
assertEquals("display", param2.getName());
|
||||
assertEquals("Accession ID", ((StringType) param2.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param3 = respParam.getParameter().get(3);
|
||||
assertEquals("abstract", param3.getName());
|
||||
assertEquals(false, ((BooleanType) param3.getValue()).getValue());
|
||||
}
|
||||
|
||||
// Repeat with version specified.
|
||||
respParam = myClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named("lookup")
|
||||
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
|
||||
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
|
||||
.andParameter("version", new StringType("2.9"))
|
||||
.execute();
|
||||
{
|
||||
Parameters respParam = myClient
|
||||
.operation()
|
||||
.onType(CodeSystem.class)
|
||||
.named("lookup")
|
||||
.withParameter(Parameters.class, "code", new CodeType("ACSN"))
|
||||
.andParameter("system", new UriType("http://terminology.hl7.org/CodeSystem/v2-0203"))
|
||||
.andParameter("version", new StringType("2.9.0"))
|
||||
.execute();
|
||||
|
||||
resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam);
|
||||
ourLog.info(resp);
|
||||
|
||||
assertEquals("name", respParam.getParameter().get(0).getName());
|
||||
assertEquals("v2.0203", ((StringType) respParam.getParameter().get(0).getValue()).getValue());
|
||||
assertEquals("version", respParam.getParameter().get(1).getName());
|
||||
assertEquals("2.9", ((StringType) respParam.getParameter().get(1).getValue()).getValue());
|
||||
assertEquals("display", respParam.getParameter().get(2).getName());
|
||||
assertEquals("Accession ID", ((StringType) respParam.getParameter().get(2).getValue()).getValue());
|
||||
assertEquals("abstract", respParam.getParameter().get(3).getName());
|
||||
assertEquals(false, ((BooleanType) respParam.getParameter().get(3).getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param0 = respParam.getParameter().get(0);
|
||||
assertEquals("name", param0.getName());
|
||||
assertEquals("IdentifierType", ((StringType) param0.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param1 = respParam.getParameter().get(1);
|
||||
assertEquals("version", param1.getName());
|
||||
assertEquals("2.9.0", ((StringType) param1.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param2 = respParam.getParameter().get(2);
|
||||
assertEquals("display", param2.getName());
|
||||
assertEquals("Accession ID", ((StringType) param2.getValue()).getValue());
|
||||
Parameters.ParametersParameterComponent param3 = respParam.getParameter().get(3);
|
||||
assertEquals("abstract", param3.getName());
|
||||
assertEquals(false, ((BooleanType) param3.getValue()).getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProvi
|
|||
parentChildCs.setVersion("1");
|
||||
parentChildCs.setName("Parent Child CodeSystem 1");
|
||||
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setContent(Enumerations.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
|
||||
|
||||
CodeSystem.ConceptDefinitionComponent parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A");
|
||||
|
@ -68,7 +68,7 @@ public class ResourceProviderR5CodeSystemVersionedTest extends BaseResourceProvi
|
|||
parentChildCs.setName("Parent Child CodeSystem 2");
|
||||
parentChildCs.setUrl(SYSTEM_PARENTCHILD);
|
||||
parentChildCs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
parentChildCs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setContent(Enumerations.CodeSystemContentMode.COMPLETE);
|
||||
parentChildCs.setHierarchyMeaning(CodeSystem.CodeSystemHierarchyMeaning.ISA);
|
||||
|
||||
parentA = parentChildCs.addConcept().setCode("ParentA").setDisplay("Parent A v2");
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.hl7.fhir.r5.model.BooleanType;
|
|||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Bundle.HTTPVerb;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.hl7.fhir.r4.model.codesystems.HttpVerb;
|
|||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
|
|
|
@ -72,7 +72,6 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
.sorted()
|
||||
.toList();
|
||||
assertThat(indexInstances.toString(), indexInstances, contains(
|
||||
"_profile NO_CHANGE Reference true",
|
||||
"active NO_CHANGE Token true",
|
||||
"address NO_CHANGE String true",
|
||||
"address-city NO_CHANGE String true",
|
||||
|
@ -80,8 +79,6 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
"address-postalcode NO_CHANGE String true",
|
||||
"address-state NO_CHANGE String true",
|
||||
"address-use NO_CHANGE Token true",
|
||||
"age NO_CHANGE Number true",
|
||||
"birthOrderBoolean NO_CHANGE Token true",
|
||||
"birthdate NO_CHANGE Date true",
|
||||
"death-date NO_CHANGE Date true",
|
||||
"email NO_CHANGE Token true",
|
||||
|
@ -90,7 +87,6 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
"identifier NO_CHANGE Token true",
|
||||
"language NO_CHANGE Token true",
|
||||
"link NO_CHANGE Reference true",
|
||||
"mothersMaidenName NO_CHANGE String true",
|
||||
"organization NO_CHANGE Reference true",
|
||||
"part-agree NO_CHANGE Reference true",
|
||||
"phone NO_CHANGE Token true",
|
||||
|
@ -136,7 +132,7 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
Parameters outcome = (Parameters) mySvc.reindexDryRun(new SystemRequestDetails(), id, null);
|
||||
ourLog.info("Output:{}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
|
||||
Parameters.ParametersParameterComponent index = findSingleIndex(outcome, ResearchStudy.SP_RECRUITMENTTARGET, "NumberIndexes");
|
||||
Parameters.ParametersParameterComponent index = findSingleIndex(outcome, ResearchStudy.SP_RECRUITMENT_TARGET, "NumberIndexes");
|
||||
assertEquals("NO_CHANGE", getPartValue("Action", index));
|
||||
assertEquals("Number", getPartValue("Type", index));
|
||||
assertEquals("3", getPartValue("Value", index));
|
||||
|
@ -294,7 +290,7 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
IIdType p1id = myPatientDao.create(p1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
SearchParameter eyeColourSp = new SearchParameter();
|
||||
eyeColourSp.addBase("Patient");
|
||||
eyeColourSp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
eyeColourSp.setCode("eyecolour");
|
||||
eyeColourSp.setType(Enumerations.SearchParamType.STRING);
|
||||
eyeColourSp.setTitle("Eye Colour");
|
||||
|
@ -326,7 +322,7 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
sp.setCode("family");
|
||||
sp.setExpression("Patient.name.family + '|'");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
|
@ -335,14 +331,14 @@ public class InstanceReindexServiceImplR5Test extends BaseJpaR5Test {
|
|||
sp.setCode("given");
|
||||
sp.setExpression("Patient.name.given");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-names-and-gender");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-family");
|
||||
|
|
|
@ -31,14 +31,14 @@ public class SubscriptionTopicR5Test extends BaseSubscriptionsR5Test {
|
|||
@Test
|
||||
public void testRestHookSubscriptionTopicApplicationFhirJson() throws Exception {
|
||||
// WIP SR4B test update, delete, etc
|
||||
createEncounterSubscriptionTopic(Encounter.EncounterStatus.PLANNED, Encounter.EncounterStatus.COMPLETED, SubscriptionTopic.InteractionTrigger.CREATE);
|
||||
createEncounterSubscriptionTopic(Enumerations.EncounterStatus.PLANNED, Enumerations.EncounterStatus.COMPLETED, SubscriptionTopic.InteractionTrigger.CREATE);
|
||||
waitForRegisteredSubscriptionTopicCount(1);
|
||||
|
||||
Subscription subscription = createTopicSubscription(SUBSCRIPTION_TOPIC_TEST_URL);
|
||||
waitForActivatedSubscriptionCount(1);
|
||||
|
||||
assertEquals(0, getSystemProviderCount());
|
||||
Encounter sentEncounter = sendEncounterWithStatus(Encounter.EncounterStatus.COMPLETED, false);
|
||||
Encounter sentEncounter = sendEncounterWithStatus(Enumerations.EncounterStatus.COMPLETED, false);
|
||||
|
||||
await().until(() -> getSystemProviderCount() > 0);
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class SubscriptionTopicR5Test extends BaseSubscriptionsR5Test {
|
|||
validateSubscriptionStatus(subscription, sentEncounter, ss);
|
||||
|
||||
Encounter encounter = (Encounter) resources.get(1);
|
||||
assertEquals(Encounter.EncounterStatus.COMPLETED, encounter.getStatus());
|
||||
assertEquals(Enumerations.EncounterStatus.COMPLETED, encounter.getStatus());
|
||||
assertEquals(sentEncounter.getIdElement(), encounter.getIdElement());
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public class SubscriptionTopicR5Test extends BaseSubscriptionsR5Test {
|
|||
return postSubscription(subscription);
|
||||
}
|
||||
|
||||
private SubscriptionTopic createEncounterSubscriptionTopic(Encounter.EncounterStatus theFrom, Encounter.EncounterStatus theCurrent, SubscriptionTopic.InteractionTrigger... theInteractionTriggers) throws InterruptedException {
|
||||
private SubscriptionTopic createEncounterSubscriptionTopic(Enumerations.EncounterStatus theFrom, Enumerations.EncounterStatus theCurrent, SubscriptionTopic.InteractionTrigger... theInteractionTriggers) throws InterruptedException {
|
||||
SubscriptionTopic retval = new SubscriptionTopic();
|
||||
retval.setUrl(SUBSCRIPTION_TOPIC_TEST_URL);
|
||||
retval.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
|
@ -78,7 +78,7 @@ public class SubscriptionTopicR5Test extends BaseSubscriptionsR5Test {
|
|||
return retval;
|
||||
}
|
||||
|
||||
private Encounter sendEncounterWithStatus(Encounter.EncounterStatus theStatus, boolean theExpectDelivery) throws InterruptedException {
|
||||
private Encounter sendEncounterWithStatus(Enumerations.EncounterStatus theStatus, boolean theExpectDelivery) throws InterruptedException {
|
||||
Encounter encounter = new Encounter();
|
||||
encounter.setStatus(theStatus);
|
||||
|
||||
|
|
|
@ -675,29 +675,6 @@ public class RestHookTestR5IT extends BaseSubscriptionsR5Test {
|
|||
return createSubscriptionTopic(subscriptionTopic);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscriptionWithHeaders() throws Exception {
|
||||
createSubscriptionTopic();
|
||||
|
||||
// Add some headers, and we'll also turn back to requested status for fun
|
||||
Subscription subscription = createTopicSubscription();
|
||||
waitForActivatedSubscriptionCount(1);
|
||||
|
||||
subscription.addHeader("X-Foo: FOO");
|
||||
subscription.addHeader("X-Bar: BAR");
|
||||
updateResource(subscription, false);
|
||||
|
||||
Observation sentObservation = sendObservationExpectDelivery();
|
||||
|
||||
// Should see 1 subscription notification
|
||||
assertReceivedTransactionCount(1);
|
||||
Observation receivedObservation = assertBundleAndGetObservation(subscription, sentObservation);
|
||||
Assertions.assertEquals(Constants.CT_FHIR_JSON_NEW, getLastSystemProviderContentType());
|
||||
|
||||
assertThat(getLastSystemProviderHeaders(), hasItem("X-Foo: FOO"));
|
||||
assertThat(getLastSystemProviderHeaders(), hasItem("X-Bar: BAR"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableSubscription() throws Exception {
|
||||
createSubscriptionTopic();
|
||||
|
@ -792,7 +769,7 @@ public class RestHookTestR5IT extends BaseSubscriptionsR5Test {
|
|||
String criteria = "Observation?accessType=Catheter,PD%20Catheter";
|
||||
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.addBase("Observation");
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.OBSERVATION);
|
||||
sp.setCode("accessType");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setExpression("Observation.extension('Observation#accessType')");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*-
|
||||
* #%L
|
||||
* Smile CDR - CDR
|
||||
* %%
|
||||
* Copyright (C) 2016 - 2023 Smile CDR, Inc.
|
||||
* %%
|
||||
* All rights reserved.
|
||||
* #L%
|
||||
*/
|
||||
package ca.uhn.fhir.jpa.dao.validation;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is a custom resource class structure representing a Meal that was
|
||||
* prepared by a chef (Patient).
|
||||
*/
|
||||
@ResourceDef(name = "Meal", profile = "http://example.org/StructureDefinition/Meal")
|
||||
public class Meal extends DomainResource {
|
||||
|
||||
public static final Base[] EMPTY_BASE_ARRAY = new Base[0];
|
||||
|
||||
@Child(name = "identifier", min = 0, max = Child.MAX_UNLIMITED)
|
||||
private List<Identifier> myIdentifier;
|
||||
@Child(name = "name")
|
||||
private StringType myName;
|
||||
@Child(name = "chef", type = {Patient.class})
|
||||
private Reference myChef;
|
||||
|
||||
/**
|
||||
* By convention in HAPI FHIR, the getter for a repeating (List) field should create
|
||||
* the list if it isn't already initialized.
|
||||
*/
|
||||
public List<Identifier> getIdentifier() {
|
||||
if (myIdentifier == null) {
|
||||
myIdentifier = new ArrayList<>();
|
||||
}
|
||||
return myIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every field annotated with {@link Child @Child} needs a getter
|
||||
*/
|
||||
public StringType getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every non-List field annotated with {@link Child @Child} needs a setter too
|
||||
*/
|
||||
public void setName(StringType theName) {
|
||||
myName = theName;
|
||||
}
|
||||
|
||||
public Reference getChef() {
|
||||
return myChef;
|
||||
}
|
||||
|
||||
public void setChef(Reference theChef) {
|
||||
myChef = theChef;
|
||||
}
|
||||
|
||||
/**
|
||||
* All resource classes must implement the {@literal copy()} method.
|
||||
*/
|
||||
@Override
|
||||
public DomainResource copy() {
|
||||
Meal retVal = new Meal();
|
||||
super.copyValues(retVal);
|
||||
for (Identifier next : getIdentifier()) {
|
||||
retVal.getIdentifier().add(next.copy());
|
||||
}
|
||||
retVal.myName = myName != null ? myName.copy() : null;
|
||||
retVal.myChef = myChef != null ? myChef.copy() : null;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fhirType() {
|
||||
return "Meal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Base[] getProperty(int theHash, String theName, boolean theCheckValid) throws FHIRException {
|
||||
switch (theName) {
|
||||
case "identifier":
|
||||
return myIdentifier != null ? myIdentifier.toArray(EMPTY_BASE_ARRAY) : EMPTY_BASE_ARRAY;
|
||||
case "chef":
|
||||
return myChef != null ? new Base[]{myChef} : EMPTY_BASE_ARRAY;
|
||||
case "name":
|
||||
return myName != null ? new Base[]{myName} : EMPTY_BASE_ARRAY;
|
||||
default:
|
||||
return super.getProperty(theHash, theName, theCheckValid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceType getResourceType() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package ca.uhn.fhir.jpa.dao.validation;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class SearchParameterDaoValidatorTest {
|
||||
|
||||
@Spy
|
||||
private FhirContext ourCtx = FhirContext.forR4Cached();
|
||||
@Mock
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
@Spy
|
||||
private JpaStorageSettings myStorageSettings = new JpaStorageSettings();
|
||||
@InjectMocks
|
||||
private SearchParameterDaoValidator mySvc;
|
||||
|
||||
private VersionCanonicalizer myVersionCanonicalizer = new VersionCanonicalizer(ourCtx);
|
||||
|
||||
@Test
|
||||
public void testValidateSubscription() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-eyecolour");
|
||||
sp.setUrl("http://example.org/SearchParameter/patient-eyecolour");
|
||||
sp.addBase("Patient");
|
||||
sp.setCode("eyecolour");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setExpression("Patient.extension('http://foo')");
|
||||
sp.addTarget("Patient");
|
||||
|
||||
org.hl7.fhir.r5.model.SearchParameter canonicalSp = myVersionCanonicalizer.searchParameterToCanonical(sp);
|
||||
mySvc.validate(canonicalSp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateSubscriptionWithCustomType() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/meal-chef");
|
||||
sp.setUrl("http://example.org/SearchParameter/meal-chef");
|
||||
sp.addBase("Meal");
|
||||
sp.setCode("chef");
|
||||
sp.setType(Enumerations.SearchParamType.REFERENCE);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setExpression("Meal.chef");
|
||||
sp.addTarget("Chef");
|
||||
|
||||
org.hl7.fhir.r5.model.SearchParameter canonicalSp = myVersionCanonicalizer.searchParameterToCanonical(sp);
|
||||
mySvc.validate(canonicalSp);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.5.16-SNAPSHOT</version>
|
||||
<version>6.5.17-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue