From 836d4d051b38ba8f1553fabf4886f291bf576656 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 7 Sep 2017 20:33:19 -0700 Subject: [PATCH 1/2] Work on IG Pack uploading --- examples/pom.xml | 5 + .../main/java/example/GenomicsUploader.java | 61 ++++ .../support/IContextValidationSupport.java | 194 ++++++------ hapi-fhir-cli/hapi-fhir-cli-app/pom.xml | 5 + .../src/main/java/ca/uhn/fhir/cli/App.java | 1 + .../java/ca/uhn/fhir/cli/BaseCommand.java | 172 +++++++++-- .../ca/uhn/fhir/cli/ExampleDataUploader.java | 106 +------ .../java/ca/uhn/fhir/cli/IgPackUploader.java | 82 +++++ .../cli/LoadingValidationSupportDstu3.java | 18 +- .../fhir/cli/LoadingValidationSupportR4.java | 39 +-- .../src/test/java/InstallIgPackTest.java | 11 + .../src/test/java/ValidateTest.java | 3 - .../interceptor/LoggingInterceptor.java | 8 +- hapi-fhir-igpacks/pom.xml | 46 +++ .../main/java/parser/IgPackParserDstu3.java | 121 ++++++++ .../parser/IgPackValidationSupportDstu3.java | 104 +++++++ .../igpack/parser/IgPackParserDstu3Test.java | 30 ++ .../src/test/resources/logback-test.xml | 30 ++ .../resources/us-core-stu3-validator.pack | Bin 0 -> 285739 bytes .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 56 +++- .../java/ca/uhn/fhir/jpa/dao/DaoConfig.java | 56 +++- .../ca/uhn/fhir/jpa/dao/SearchBuilder.java | 50 ++-- .../FhirResourceDaoSearchParameterDstu3.java | 2 +- .../dao/dstu3/JpaValidationSupportDstu3.java | 78 ++--- .../r4/FhirResourceDaoSearchParameterR4.java | 2 +- .../jpa/dao/r4/JpaValidationSupportR4.java | 80 ++--- .../ResourceIndexedCompositeStringUnique.java | 2 + .../jpa/provider/BaseJpaSystemProvider.java | 1 + .../BaseJpaSystemProviderDstu2Plus.java | 19 +- .../jpa/term/HapiTerminologySvcDstu3.java | 5 + .../fhir/jpa/term/HapiTerminologySvcR4.java | 213 ++++++------- .../java/ca/uhn/fhir/jpa/util/StopWatch.java | 14 +- ...hirResourceDaoR4UniqueSearchParamTest.java | 282 ++++++++++++++++-- .../jpa/provider/r4/SystemProviderR4Test.java | 11 + .../ca/uhn/fhir/jpa/util/StopWatchTest.java | 12 + .../derby_maintenance.txt | 36 ++- .../DefaultProfileValidationSupport.java | 71 +++-- .../PrePopulatedValidationSupport.java | 90 +++--- .../validation/ValidationSupportChain.java | 55 ++-- .../DefaultProfileValidationSupport.java | 62 ++-- .../PrePopulatedValidationSupport.java | 52 ++-- .../validation/ValidationSupportChain.java | 226 +++++++------- .../ctx/DefaultProfileValidationSupport.java | 75 +++-- .../ctx/PrePopulatedValidationSupport.java | 52 ++-- .../r4/hapi/ctx/ValidationSupportChain.java | 26 +- .../rest/client/LoggingInterceptorTest.java | 2 +- pom.xml | 3 +- 47 files changed, 1842 insertions(+), 827 deletions(-) create mode 100644 examples/src/main/java/example/GenomicsUploader.java create mode 100644 hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/IgPackUploader.java create mode 100644 hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/InstallIgPackTest.java create mode 100644 hapi-fhir-igpacks/pom.xml create mode 100644 hapi-fhir-igpacks/src/main/java/parser/IgPackParserDstu3.java create mode 100644 hapi-fhir-igpacks/src/main/java/parser/IgPackValidationSupportDstu3.java create mode 100644 hapi-fhir-igpacks/src/test/java/ca/uhn/fhir/igpack/parser/IgPackParserDstu3Test.java create mode 100644 hapi-fhir-igpacks/src/test/resources/logback-test.xml create mode 100644 hapi-fhir-igpacks/src/test/resources/us-core-stu3-validator.pack diff --git a/examples/pom.xml b/examples/pom.xml index 1a0ee2bf0c1..5c9b74052b2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -35,6 +35,11 @@ hapi-fhir-structures-dstu3 ${project.version} + + ca.uhn.hapi.fhir + hapi-fhir-structures-r4 + ${project.version} + ca.uhn.hapi.fhir hapi-fhir-structures-hl7org-dstu2 diff --git a/examples/src/main/java/example/GenomicsUploader.java b/examples/src/main/java/example/GenomicsUploader.java new file mode 100644 index 00000000000..f7f87823905 --- /dev/null +++ b/examples/src/main/java/example/GenomicsUploader.java @@ -0,0 +1,61 @@ +package example; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; +import org.hl7.fhir.r4.model.Enumerations; +import org.hl7.fhir.r4.model.SearchParameter; + +public class GenomicsUploader { + + public static void main(String[] theArgs) { + FhirContext ctx = FhirContext.forR4(); + IGenericClient client = ctx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseR4"); + client.registerInterceptor(new LoggingInterceptor(false)); + + SearchParameter dnaSequenceVariantName = new SearchParameter(); + dnaSequenceVariantName.setId("SearchParameter/dnaSequenceVariantName"); + dnaSequenceVariantName.setStatus(Enumerations.PublicationStatus.ACTIVE); + dnaSequenceVariantName.addBase("Observation"); + dnaSequenceVariantName.setCode("dnaSequenceVariantName"); + dnaSequenceVariantName.setType(Enumerations.SearchParamType.TOKEN); + dnaSequenceVariantName.setTitle("DNASequenceVariantName"); + dnaSequenceVariantName.setExpression("Observation.extension('http://hl7.org/fhir/StructureDefinition/observation-geneticsDNASequenceVariantName')"); + dnaSequenceVariantName.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); + client.update().resource(dnaSequenceVariantName).execute(); + + SearchParameter dNAVariantId = new SearchParameter(); + dNAVariantId.setId("SearchParameter/dNAVariantId"); + dNAVariantId.setStatus(Enumerations.PublicationStatus.ACTIVE); + dNAVariantId.addBase("Observation"); + dNAVariantId.setCode("dnaVariantId"); + dNAVariantId.setType(Enumerations.SearchParamType.TOKEN); + dNAVariantId.setTitle("DNAVariantId"); + dNAVariantId.setExpression("Observation.extension('http://hl7.org/fhir/StructureDefinition/observation-geneticsDNAVariantId')"); + dNAVariantId.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); + client.update().resource(dNAVariantId).execute(); + + SearchParameter gene = new SearchParameter(); + gene.setId("SearchParameter/gene"); + gene.setStatus(Enumerations.PublicationStatus.ACTIVE); + gene.addBase("Observation"); + gene.setCode("gene"); + gene.setType(Enumerations.SearchParamType.TOKEN); + gene.setTitle("Gene"); + gene.setExpression("Observation.extension('http://hl7.org/fhir/StructureDefinition/observation-geneticsGene')"); + gene.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); + client.update().resource(gene).execute(); + + SearchParameter alleleName = new SearchParameter(); + alleleName.setId("SearchParameter/alleleName"); + alleleName.setStatus(Enumerations.PublicationStatus.ACTIVE); + alleleName.addBase("Observation"); + alleleName.setCode("alleleName"); + alleleName.setType(Enumerations.SearchParamType.TOKEN); + alleleName.setTitle("AlleleName"); + alleleName.setExpression("Observation.extension('http://hl7.org/fhir/StructureDefinition/observation-geneticsAlleleName')"); + alleleName.setXpathUsage(SearchParameter.XPathUsageType.NORMAL); + client.update().resource(alleleName).execute(); + } + +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IContextValidationSupport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IContextValidationSupport.java index 8a068739346..126efe344d8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IContextValidationSupport.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IContextValidationSupport.java @@ -20,117 +20,113 @@ package ca.uhn.fhir.context.support; * #L% */ -import java.util.List; - +import ca.uhn.fhir.context.FhirContext; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; +import java.util.List; public interface IContextValidationSupport { - /** - * Expands the given portion of a ValueSet - * - * @param theInclude - * The portion to include - * @return The expansion - */ - EVS_OUT expandValueSet(FhirContext theContext, EVS_IN theInclude); + /** + * Expands the given portion of a ValueSet + * + * @param theInclude The portion to include + * @return The expansion + */ + EVS_OUT expandValueSet(FhirContext theContext, EVS_IN theInclude); - /** - * Load and return all possible structure definitions - */ - List fetchAllStructureDefinitions(FhirContext theContext); + /** + * Load and return all conformance resources associated with this + * validation support module. This method may return null if it doesn't + * make sense for a given module. + */ + List fetchAllConformanceResources(FhirContext theContext); - - /** - * Fetch a code system by ID - * - * @param theSystem - * The code system - * @return The valueset (must not be null, but can be an empty ValueSet) - */ - CST fetchCodeSystem(FhirContext theContext, String theSystem); + /** + * Load and return all possible structure definitions + */ + List fetchAllStructureDefinitions(FhirContext theContext); - /** - * Loads a resource needed by the validation (a StructureDefinition, or a - * ValueSet) - * - * @param theContext - * The HAPI FHIR Context object current in use by the validator - * @param theClass - * The type of the resource to load - * @param theUri - * The resource URI - * @return Returns the resource, or null if no resource with the - * given URI can be found - */ - T fetchResource(FhirContext theContext, Class theClass, String theUri); + /** + * Fetch a code system by ID + * + * @param theSystem The code system + * @return The valueset (must not be null, but can be an empty ValueSet) + */ + CST fetchCodeSystem(FhirContext theContext, String theSystem); - SDT fetchStructureDefinition(FhirContext theCtx, String theUrl); + /** + * Loads a resource needed by the validation (a StructureDefinition, or a + * ValueSet) + * + * @param theContext The HAPI FHIR Context object current in use by the validator + * @param theClass The type of the resource to load + * @param theUri The resource URI + * @return Returns the resource, or null if no resource with the + * given URI can be found + */ + T fetchResource(FhirContext theContext, Class theClass, String theUri); - /** - * Returns true if codes in the given code system can be expanded - * or validated - * - * @param theSystem - * The URI for the code system, e.g. "http://loinc.org" - * @return Returns true if codes in the given code system can be - * validated - */ - boolean isCodeSystemSupported(FhirContext theContext, String theSystem); + SDT fetchStructureDefinition(FhirContext theCtx, String theUrl); -/** - * Validates that the given code exists and if possible returns a display - * name. This method is called to check codes which are found in "example" - * binding fields (e.g. Observation.code in the default profile. - * - * @param theCodeSystem - * The code system, e.g. "http://loinc.org" - * @param theCode - * The code, e.g. "1234-5" - * @param theDisplay - * The display name, if it should also be validated - * @return Returns a validation result object - */ - CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay); + /** + * Returns true if codes in the given code system can be expanded + * or validated + * + * @param theSystem The URI for the code system, e.g. "http://loinc.org" + * @return Returns true if codes in the given code system can be + * validated + */ + boolean isCodeSystemSupported(FhirContext theContext, String theSystem); + + /** + * Validates that the given code exists and if possible returns a display + * name. This method is called to check codes which are found in "example" + * binding fields (e.g. Observation.code in the default profile. + * + * @param theCodeSystem The code system, e.g. "http://loinc.org" + * @param theCode The code, e.g. "1234-5" + * @param theDisplay The display name, if it should also be validated + * @return Returns a validation result object + */ + CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay); public class CodeValidationResult { - private CDCT definition; - private String message; - private IST severity; - - public CodeValidationResult(CDCT theNext) { - this.definition = theNext; - } - - public CodeValidationResult(IST severity, String message) { - this.severity = severity; - this.message = message; - } - - public CodeValidationResult(IST severity, String message, CDCT definition) { - this.severity = severity; - this.message = message; - this.definition = definition; - } - - public CDCT asConceptDefinition() { - return definition; - } - - public String getMessage() { - return message; - } - - public IST getSeverity() { - return severity; - } - - public boolean isOk() { - return definition != null; - } - - } + private CDCT definition; + private String message; + private IST severity; + + public CodeValidationResult(CDCT theNext) { + this.definition = theNext; + } + + public CodeValidationResult(IST severity, String message) { + this.severity = severity; + this.message = message; + } + + public CodeValidationResult(IST severity, String message, CDCT definition) { + this.severity = severity; + this.message = message; + this.definition = definition; + } + + public CDCT asConceptDefinition() { + return definition; + } + + public String getMessage() { + return message; + } + + public IST getSeverity() { + return severity; + } + + public boolean isOk() { + return definition != null; + } + + } } diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index 320090b2643..3d68cdcca53 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -73,6 +73,11 @@ hapi-fhir-validation-resources-dstu3 ${project.version} + + ca.uhn.hapi.fhir + hapi-fhir-igpacks + ${project.version} + ch.qos.logback diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java index 4f882dfd986..5d34fbd0706 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/App.java @@ -41,6 +41,7 @@ public class App { ourCommands.add(new ValidationDataUploader()); ourCommands.add(new WebsocketSubscribeCommand()); ourCommands.add(new UploadTerminologyCommand()); + ourCommands.add(new IgPackUploader()); Collections.sort(ourCommands); } diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/BaseCommand.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/BaseCommand.java index d854871a5e2..62b8e99027d 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/BaseCommand.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/BaseCommand.java @@ -1,53 +1,99 @@ package ca.uhn.fhir.cli; -import org.apache.commons.cli.*; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.rest.client.api.IGenericClient; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.fusesource.jansi.Ansi; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; public abstract class BaseCommand implements Comparable { private static final String SPEC_DEFAULT_VERSION = "dstu3"; - + private static final Logger ourLog = LoggerFactory.getLogger(BaseCommand.class); private FhirContext myFhirCtx; public BaseCommand() { super(); } + protected void addFhirVersionOption(Options theOptions) { + Option opt = new Option("f", "fhirversion", true, "Spec version to upload (default is '" + SPEC_DEFAULT_VERSION + "')"); + opt.setRequired(false); + theOptions.addOption(opt); + } + @Override public int compareTo(BaseCommand theO) { return getCommandName().compareTo(theO.getCommandName()); } + private void downloadFileFromInternet(CloseableHttpResponse result, File localFile) throws IOException { + FileOutputStream buffer = FileUtils.openOutputStream(localFile); + try { + + long maxLength = result.getEntity().getContentLength(); + long nextLog = -1; + // ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[16384]; + while ((nRead = result.getEntity().getContent().read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + long fileSize = FileUtils.sizeOf(localFile); + if (fileSize > nextLog) { + System.err.print("\r" + Ansi.ansi().eraseLine()); + System.err.print(FileUtils.byteCountToDisplaySize(fileSize)); + if (maxLength > 0) { + System.err.print(" ["); + int stars = (int) (50.0f * ((float) fileSize / (float) maxLength)); + for (int i = 0; i < stars; i++) { + System.err.print("*"); + } + for (int i = stars; i < 50; i++) { + System.err.print(" "); + } + System.err.print("]"); + } + System.err.flush(); + nextLog += 100000; + } + } + buffer.flush(); + + System.err.println(); + System.err.flush(); + } finally { + IOUtils.closeQuietly(buffer); + } + } + public abstract String getCommandDescription(); public abstract String getCommandName(); public abstract Options getOptions(); - protected IGenericClient newClient(FhirContext ctx, String theBaseUrl) { - ctx.getRestfulClientFactory().setSocketTimeout(10 * 60 * 1000); - IGenericClient fhirClient = ctx.newRestfulGenericClient(theBaseUrl); - return fhirClient; - } - - public abstract void run(CommandLine theCommandLine) throws ParseException, Exception; - -// public FhirContext getFhirCtx() { -// if (myFhirCtx == null) { -// myFhirCtx = FhirContext.forDstu2(); -// } -// return myFhirCtx; -// } - - protected void addFhirVersionOption(Options theOptions) { - Option opt = new Option("f", "fhirversion", true, "Spec version to upload (default is '" + SPEC_DEFAULT_VERSION + "')"); - opt.setRequired(false); - theOptions.addOption(opt); - } - protected FhirContext getSpecVersionContext(CommandLine theCommandLine) throws ParseException { if (myFhirCtx == null) { String specVersion = theCommandLine.getOptionValue("f", SPEC_DEFAULT_VERSION); @@ -68,4 +114,82 @@ public abstract class BaseCommand implements Comparable { return myFhirCtx; } +// public FhirContext getFhirCtx() { +// if (myFhirCtx == null) { +// myFhirCtx = FhirContext.forDstu2(); +// } +// return myFhirCtx; +// } + + protected Collection loadFile(FhirContext theCtx, String theSpecUrl, String theFilepath, boolean theCacheFile) throws IOException { + String userHomeDir = System.getProperty("user.home"); + + File applicationDir = new File(userHomeDir + File.separator + "." + "hapi-fhir-cli"); + FileUtils.forceMkdir(applicationDir); + + Collection inputFiles; + if (isNotBlank(theFilepath)) { + ourLog.info("Loading from local path: {}", theFilepath); + + if (theFilepath.startsWith("~" + File.separator)) { + theFilepath = userHomeDir + theFilepath.substring(1); + } + + File suppliedFile = new File(FilenameUtils.normalize(theFilepath)); + + if (suppliedFile.isDirectory()) { + inputFiles = FileUtils.listFiles(suppliedFile, new String[]{"zip"}, false); + } else { + inputFiles = Collections.singletonList(suppliedFile); + } + + } else { + + File cacheDir = new File(applicationDir, "cache"); + FileUtils.forceMkdir(cacheDir); + + File inputFile = new File(cacheDir, "examples-json-" + theCtx.getVersion().getVersion() + ".zip"); + + Date cacheExpiryDate = DateUtils.addHours(new Date(), -12); + + if (!inputFile.exists() | (theCacheFile && FileUtils.isFileOlder(inputFile, cacheExpiryDate))) { + + File exampleFileDownloading = new File(cacheDir, "examples-json-" + theCtx.getVersion().getVersion() + ".zip.partial"); + + HttpGet get = new HttpGet(theSpecUrl); + CloseableHttpClient client = HttpClientBuilder.create().build(); + CloseableHttpResponse result = client.execute(get); + + if (result.getStatusLine().getStatusCode() != 200) { + throw new CommandFailureException("Got HTTP " + result.getStatusLine().getStatusCode() + " response code loading " + theSpecUrl); + } + + ourLog.info("Downloading from remote url: {}", theSpecUrl); + downloadFileFromInternet(result, exampleFileDownloading); + + FileUtils.deleteQuietly(inputFile); + FileUtils.moveFile(exampleFileDownloading, inputFile); + + if (!theCacheFile) { + inputFile.deleteOnExit(); + } + + ourLog.info("Successfully Loaded example pack ({})", FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(inputFile))); + IOUtils.closeQuietly(result.getEntity().getContent()); + } + + inputFiles = Collections.singletonList(inputFile); + + } + return inputFiles; + } + + protected IGenericClient newClient(FhirContext ctx, String theBaseUrl) { + ctx.getRestfulClientFactory().setSocketTimeout(10 * 60 * 1000); + IGenericClient fhirClient = ctx.newRestfulGenericClient(theBaseUrl); + return fhirClient; + } + + public abstract void run(CommandLine theCommandLine) throws ParseException, Exception; + } diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java index c88aca5aba2..f36ee10cabb 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/ExampleDataUploader.java @@ -127,79 +127,17 @@ public class ExampleDataUploader extends BaseCommand { boolean cacheFile = theCommandLine.hasOption('c'); - String userHomeDir = System.getProperty("user.home"); - - File applicationDir = new File(userHomeDir + File.separator + "." + "hapi-fhir-cli"); - FileUtils.forceMkdir(applicationDir); - - if (isNotBlank(filepath)) { - ourLog.info("Loading from local path: {}", filepath); - - if (filepath.startsWith("~" + File.separator)) { - filepath = userHomeDir + filepath.substring(1); - } - - File suppliedFile = new File(FilenameUtils.normalize(filepath)); - - if (suppliedFile.isDirectory()) { - Collection inputFiles; - inputFiles = FileUtils.listFiles(suppliedFile, new String[]{"zip"}, false); - - for (File inputFile : inputFiles) { - IBaseBundle bundle = getBundleFromFile(limit, inputFile, ctx); - processBundle(ctx, bundle); - sendBundleToTarget(targetServer, ctx, bundle); - } - } else { - IBaseBundle bundle = getBundleFromFile(limit, suppliedFile, ctx); - processBundle(ctx, bundle); - sendBundleToTarget(targetServer, ctx, bundle); - } - - } else { - - File cacheDir = new File(applicationDir, "cache"); - FileUtils.forceMkdir(cacheDir); - - File inputFile = new File(cacheDir, "examples-json-" + ctx.getVersion().getVersion() + ".zip"); - - Date cacheExpiryDate = DateUtils.addHours(new Date(), -12); - - if (!inputFile.exists() | (cacheFile && FileUtils.isFileOlder(inputFile, cacheExpiryDate))) { - - File exampleFileDownloading = new File(cacheDir, "examples-json-" + ctx.getVersion().getVersion() + ".zip.partial"); - - HttpGet get = new HttpGet(specUrl); - CloseableHttpClient client = HttpClientBuilder.create().build(); - CloseableHttpResponse result = client.execute(get); - - if (result.getStatusLine().getStatusCode() != 200) { - throw new CommandFailureException("Got HTTP " + result.getStatusLine().getStatusCode() + " response code loading " + specUrl); - } - - ourLog.info("Downloading from remote url: {}", specUrl); - downloadFileFromInternet(result, exampleFileDownloading); - - FileUtils.deleteQuietly(inputFile); - FileUtils.moveFile(exampleFileDownloading, inputFile); - - if (!cacheFile) { - inputFile.deleteOnExit(); - } - - ourLog.info("Successfully Loaded example pack ({})", FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(inputFile))); - IOUtils.closeQuietly(result.getEntity().getContent()); - } + Collection inputFiles = loadFile(ctx, specUrl, filepath, cacheFile); + for (File inputFile : inputFiles) { IBaseBundle bundle = getBundleFromFile(limit, inputFile, ctx); processBundle(ctx, bundle); - sendBundleToTarget(targetServer, ctx, bundle); - } } + private IBaseBundle getBundleFromFile(Integer theLimit, File theSuppliedFile, FhirContext theCtx) throws ParseException, IOException { switch (theCtx.getVersion().getVersion()) { case DSTU2: @@ -791,43 +729,5 @@ public class ExampleDataUploader extends BaseCommand { return bundle; } - private void downloadFileFromInternet(CloseableHttpResponse result, File localFile) throws IOException { - FileOutputStream buffer = FileUtils.openOutputStream(localFile); - try { - - long maxLength = result.getEntity().getContentLength(); - long nextLog = -1; - // ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - byte[] data = new byte[16384]; - while ((nRead = result.getEntity().getContent().read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - long fileSize = FileUtils.sizeOf(localFile); - if (fileSize > nextLog) { - System.err.print("\r" + Ansi.ansi().eraseLine()); - System.err.print(FileUtils.byteCountToDisplaySize(fileSize)); - if (maxLength > 0) { - System.err.print(" ["); - int stars = (int) (50.0f * ((float) fileSize / (float) maxLength)); - for (int i = 0; i < stars; i++) { - System.err.print("*"); - } - for (int i = stars; i < 50; i++) { - System.err.print(" "); - } - System.err.print("]"); - } - System.err.flush(); - nextLog += 100000; - } - } - buffer.flush(); - - System.err.println(); - System.err.flush(); - } finally { - IOUtils.closeQuietly(buffer); - } - } } diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/IgPackUploader.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/IgPackUploader.java new file mode 100644 index 00000000000..bb3440f7e1f --- /dev/null +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/IgPackUploader.java @@ -0,0 +1,82 @@ +package ca.uhn.fhir.cli; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import parser.IgPackParserDstu3; +import parser.IgPackValidationSupportDstu3; + +import java.io.File; +import java.io.FileInputStream; +import java.util.Collection; + +public class IgPackUploader extends BaseCommand { + private static final Logger ourLog = LoggerFactory.getLogger(IgPackUploader.class); + + @Override + public String getCommandDescription() { + return "Uploads an Implementation Guide Validation Pack"; + } + + @Override + public String getCommandName() { + return "upload-igpack"; + } + + @Override + public Options getOptions() { + Options options = new Options(); + addFhirVersionOption(options); + + Option opt = new Option("t", "target", true, "Base URL for the target server (e.g. \"http://example.com/fhir\")"); + opt.setRequired(false); + options.addOption(opt); + + opt = new Option("u", "url", true, "The URL to the validation.pack file, e.g. http://hl7.org/fhir/us/core/validator.pack"); + opt.setRequired(true); + options.addOption(opt); + + return options; + } + + @Override + public void run(CommandLine theCommandLine) throws ParseException, Exception { + FhirContext ctx = getSpecVersionContext(theCommandLine); + + String targetServer = theCommandLine.getOptionValue("t"); + IGenericClient client = ctx.newRestfulGenericClient(targetServer); + + String url = theCommandLine.getOptionValue("u"); + + Collection files = loadFile(ctx, url, null, false); + for (File nextFile : files) { + switch (ctx.getVersion().getVersion()) { + case DSTU3: + IgPackParserDstu3 packParser = new IgPackParserDstu3(ctx); + IValidationSupport ig = packParser.parseIg(new FileInputStream(nextFile), nextFile.getName()); + Iterable conformanceResources = ig.fetchAllConformanceResources(ctx); + for (IBaseResource nextResource : conformanceResources) { + String nextResourceUrl = ((IPrimitiveType)ctx.newTerser().getSingleValueOrNull(nextResource, "url")).getValueAsString(); + ourLog.info("Uploading resource: {}", nextResourceUrl); + client + .update() + .resource(nextResource) + .conditional() + .and(StructureDefinition.URL.matches().value(nextResourceUrl)) + .execute(); + } + default: + throw new ParseException("This command does not support FHIR version " + ctx.getVersion().getVersion()); + } + } + } +} diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportDstu3.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportDstu3.java index ff9eca35cd8..6331acef87b 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportDstu3.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportDstu3.java @@ -1,8 +1,9 @@ package ca.uhn.fhir.cli; -import java.util.Collections; -import java.util.List; - +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.client.api.IGenericClient; +import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; +import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.StructureDefinition; @@ -10,10 +11,8 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.client.api.IGenericClient; -import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; -import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; +import java.util.Collections; +import java.util.List; public class LoadingValidationSupportDstu3 implements IValidationSupport { @@ -26,6 +25,11 @@ public class LoadingValidationSupportDstu3 implements IValidationSupport { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + return null; + } + @Override public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { return null; diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportR4.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportR4.java index f04edfa13ea..a065ef2386a 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportR4.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/main/java/ca/uhn/fhir/cli/LoadingValidationSupportR4.java @@ -1,30 +1,38 @@ package ca.uhn.fhir.cli; -import java.util.Collections; -import java.util.List; - -import org.hl7.fhir.r4.model.CodeSystem; -import org.hl7.fhir.r4.model.StructureDefinition; -import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; -import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent; -import org.hl7.fhir.instance.model.api.IBaseResource; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; +import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent; + +import java.util.Collections; +import java.util.List; public class LoadingValidationSupportR4 implements org.hl7.fhir.r4.hapi.ctx.IValidationSupport { - private FhirContext myCtx = FhirContext.forR4(); - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LoadingValidationSupportR4.class); + private FhirContext myCtx = FhirContext.forR4(); @Override public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + return null; + } + + @Override + public List fetchAllStructureDefinitions(FhirContext theContext) { + return Collections.emptyList(); + } + @Override public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { return null; @@ -34,10 +42,10 @@ public class LoadingValidationSupportR4 implements org.hl7.fhir.r4.hapi.ctx.IVal public T fetchResource(FhirContext theContext, Class theClass, String theUri) { String resName = myCtx.getResourceDefinition(theClass).getName(); ourLog.info("Attempting to fetch {} at URL: {}", resName, theUri); - + myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); IGenericClient client = myCtx.newRestfulGenericClient("http://example.com"); - + T result; try { result = client.read(theClass, theUri); @@ -63,9 +71,4 @@ public class LoadingValidationSupportR4 implements org.hl7.fhir.r4.hapi.ctx.IVal return null; } - @Override - public List fetchAllStructureDefinitions(FhirContext theContext) { - return Collections.emptyList(); - } - } diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/InstallIgPackTest.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/InstallIgPackTest.java new file mode 100644 index 00000000000..70d05ee5f67 --- /dev/null +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/InstallIgPackTest.java @@ -0,0 +1,11 @@ +import org.junit.Test; + +public class InstallIgPackTest { + + @Test + public void testInstallIgPack() { + + } + + +} diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/ValidateTest.java b/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/ValidateTest.java index 0025053d860..d15f687c70e 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/ValidateTest.java +++ b/hapi-fhir-cli/hapi-fhir-cli-app/src/test/java/ValidateTest.java @@ -13,12 +13,9 @@ public class ValidateTest { @Test public void testValidateLocalProfile() { -// String profilePath = ValidateTest.class.getResource("/uslab-patient.profile.xml").getFile(); String resourcePath = ValidateTest.class.getResource("/patient-uslab-example1.xml").getFile(); -// ourLog.info(profilePath); ourLog.info(resourcePath); -// App.main(new String[] {"validate", "-p", "-n", resourcePath, "-l", profilePath}); App.main(new String[] {"validate", "-p", "-n", resourcePath}); } diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java index 4d7ecc760ea..d25efc8871f 100644 --- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java +++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java @@ -26,6 +26,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.Constants; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.Validate; @@ -107,7 +108,12 @@ public class LoggingInterceptor implements IClientInterceptor { */ List locationHeaders = theResponse.getHeaders(Constants.HEADER_LOCATION); if (locationHeaders != null && locationHeaders.size() > 0) { - respLocation = " (Location: " + locationHeaders.get(0) + ")"; + String locationValue = locationHeaders.get(0); + IdDt locationValueId = new IdDt(locationValue); + if (locationValueId.hasBaseUrl() && locationValueId.hasIdPart()) { + locationValue = locationValueId.toUnqualified().getValue(); + } + respLocation = " (" + locationValue + ")"; } myLog.info("Client response: {}{}", message, respLocation); } diff --git a/hapi-fhir-igpacks/pom.xml b/hapi-fhir-igpacks/pom.xml new file mode 100644 index 00000000000..02a758e9903 --- /dev/null +++ b/hapi-fhir-igpacks/pom.xml @@ -0,0 +1,46 @@ + + + + hapi-deployable-pom + ca.uhn.hapi.fhir + 3.0.0-SNAPSHOT + ../hapi-deployable-pom/pom.xml + + 4.0.0 + + hapi-fhir-igpacks + + + + ca.uhn.hapi.fhir + hapi-fhir-base + ${project.version} + + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-base + ${project.version} + + + + ca.uhn.hapi.fhir + hapi-fhir-structures-dstu3 + ${project.version} + true + + + + ch.qos.logback + logback-classic + + + + + + + + + + diff --git a/hapi-fhir-igpacks/src/main/java/parser/IgPackParserDstu3.java b/hapi-fhir-igpacks/src/main/java/parser/IgPackParserDstu3.java new file mode 100644 index 00000000000..dca92fa0a25 --- /dev/null +++ b/hapi-fhir-igpacks/src/main/java/parser/IgPackParserDstu3.java @@ -0,0 +1,121 @@ +package parser; + + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.jpa.util.StopWatch; +import ca.uhn.fhir.rest.api.Constants; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import org.apache.commons.lang3.Validate; +import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; +import org.hl7.fhir.dstu3.model.IdType; +import org.hl7.fhir.dstu3.model.ImplementationGuide; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +public class IgPackParserDstu3 { + + private static final Logger ourLog = LoggerFactory.getLogger(IgPackParserDstu3.class); + private final FhirContext myCtx; + + public IgPackParserDstu3(FhirContext theCtx) { + FhirVersionEnum expectedVersion = FhirVersionEnum.DSTU3; + Validate.isTrue(theCtx.getVersion().getVersion() == expectedVersion, "theCtx is not for the correct version, expecting " + expectedVersion); + + myCtx = theCtx; + } + + private IBaseResource findResource(Map theCandidateResources, IIdType theId) { + IBaseResource retVal = theCandidateResources.get(theId.toUnqualifiedVersionless().getValue()); + if (retVal == null) { + throw new InternalErrorException("Unknown reference in ImplementationGuide: " + theId); + } + return retVal; + } + + /** + * @param theIgInputStream The "validator.pack" ZIP file + * @param theDescription A description (just used for logs) + */ + public IValidationSupport parseIg(InputStream theIgInputStream, String theDescription) { + Validate.notNull(theIgInputStream, "theIdInputStream must not be null"); + + ourLog.info("Parsing IGPack: {}", theDescription); + StopWatch sw = new StopWatch(); + + ZipInputStream zipInputStream = new ZipInputStream(theIgInputStream); + ZipEntry entry; + try { + + Map candidateResources = new HashMap<>(); + Map igResources = new HashMap<>(); + + while ((entry = zipInputStream.getNextEntry()) != null) { + if (entry.getName().endsWith(".json")) { + InputStreamReader nextReader = new InputStreamReader(zipInputStream, Constants.CHARSET_UTF8); + IBaseResource parsed = myCtx.newJsonParser().parseResource(nextReader); + candidateResources.put(entry.getName(), parsed); + } + } + + ourLog.info("Parsed {} candidateResources in {}ms", candidateResources.size(), sw.getMillis()); + + String igResourceName = "ImplementationGuide-ig.json"; + ImplementationGuide ig = (ImplementationGuide) candidateResources.get(igResourceName); + + if (ig == null) { + throw new InternalErrorException("IG Pack '" + theDescription + "' does not contain a resource named: " + igResourceName); + } + +// ourLog.info(myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(ig)); + + HashMap newCandidateResources = new HashMap<>(); + for (IBaseResource next : candidateResources.values()) { + newCandidateResources.put(next.getIdElement().toUnqualifiedVersionless().getValue(), next); + } + candidateResources = newCandidateResources; + + for (ImplementationGuide.ImplementationGuidePackageComponent nextPackage : ig.getPackage()) { + ourLog.info("Processing package {}", nextPackage.getName()); + + for (ImplementationGuide.ImplementationGuidePackageResourceComponent nextResource : nextPackage.getResource()) { + if (isNotBlank(nextResource.getSourceReference().getReference())) { + IdType id = new IdType(nextResource.getSourceReference().getReference()); + if (isNotBlank(id.getResourceType())) { + switch (id.getResourceType()) { + case "CodeSystem": + case "ConceptMap": + case "StructureDefinition": + case "ValueSet": + IBaseResource resource = findResource(candidateResources, id); + igResources.put(id.toUnqualifiedVersionless(), resource); + break; + } + } + } + } + + } + + ourLog.info("IG contains {} resources", igResources.size()); + return new IgPackValidationSupportDstu3(igResources); + + } catch (Exception e) { + throw new InternalErrorException("Failure while parsing IG: " + e); + } + + + } + +} diff --git a/hapi-fhir-igpacks/src/main/java/parser/IgPackValidationSupportDstu3.java b/hapi-fhir-igpacks/src/main/java/parser/IgPackValidationSupportDstu3.java new file mode 100644 index 00000000000..c0cd82d0312 --- /dev/null +++ b/hapi-fhir-igpacks/src/main/java/parser/IgPackValidationSupportDstu3.java @@ -0,0 +1,104 @@ +package parser; + +import ca.uhn.fhir.context.FhirContext; +import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; +import org.hl7.fhir.dstu3.model.CodeSystem; +import org.hl7.fhir.dstu3.model.ConceptMap; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class IgPackValidationSupportDstu3 implements IValidationSupport { + private final Map myIgResources; + + public IgPackValidationSupportDstu3(Map theIgResources) { + myIgResources = theIgResources; + } + + @Override + public ValueSet.ValueSetExpansionComponent expandValueSet(FhirContext theContext, ValueSet.ConceptSetComponent theInclude) { + return null; + } + + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + return new ArrayList<>(myIgResources.values()); + } + + + @Override + public List fetchAllStructureDefinitions(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + for (Map.Entry next : myIgResources.entrySet()) { + if (next.getKey().getResourceType().equals("StructureDefinition")) { + retVal.add((StructureDefinition) next.getValue()); + } + } + return retVal; + } + + @Override + public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { + return fetchResource(theContext, CodeSystem.class, theSystem); + } + + @Override + public T fetchResource(FhirContext theContext, Class theClass, String theUri) { + for (Map.Entry next : myIgResources.entrySet()) { + if (theClass.equals(CodeSystem.class)) { + if (theClass.isAssignableFrom(next.getValue().getClass())) { + CodeSystem sd = ((CodeSystem) next.getValue()); + if (sd.getUrl().equals(theUri)) { + return (T) sd; + } + } + } + if (theClass.equals(ConceptMap.class)) { + if (theClass.isAssignableFrom(next.getValue().getClass())) { + ConceptMap sd = ((ConceptMap) next.getValue()); + if (sd.getUrl().equals(theUri)) { + return (T) sd; + } + } + } + if (theClass.equals(StructureDefinition.class)) { + if (theClass.isAssignableFrom(next.getValue().getClass())) { + StructureDefinition sd = ((StructureDefinition) next.getValue()); + if (sd.getUrl().equals(theUri)) { + return (T) sd; + } + } + } + if (theClass.equals(ValueSet.class)) { + if (theClass.isAssignableFrom(next.getValue().getClass())) { + ValueSet sd = ((ValueSet) next.getValue()); + if (sd.getUrl().equals(theUri)) { + return (T) sd; + } + } + } + } + + return null; + } + + @Override + public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { + return fetchResource(theCtx, StructureDefinition.class, theUrl); + } + + @Override + public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) { + return false; + } + + @Override + public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { + return null; + } +} diff --git a/hapi-fhir-igpacks/src/test/java/ca/uhn/fhir/igpack/parser/IgPackParserDstu3Test.java b/hapi-fhir-igpacks/src/test/java/ca/uhn/fhir/igpack/parser/IgPackParserDstu3Test.java new file mode 100644 index 00000000000..4dc8244f659 --- /dev/null +++ b/hapi-fhir-igpacks/src/test/java/ca/uhn/fhir/igpack/parser/IgPackParserDstu3Test.java @@ -0,0 +1,30 @@ +package ca.uhn.fhir.igpack.parser; + + +import ca.uhn.fhir.context.FhirContext; +import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import parser.IgPackParserDstu3; + +import static org.junit.Assert.*; + +public class IgPackParserDstu3Test { + private static final Logger ourLog = LoggerFactory.getLogger(IgPackParserDstu3Test.class); + + @Test + public void testParseIg() { + + FhirContext ctx = FhirContext.forDstu3(); + IgPackParserDstu3 igParser = new IgPackParserDstu3(ctx); + + IValidationSupport result = igParser.parseIg(IgPackParserDstu3Test.class.getResourceAsStream("/us-core-stu3-validator.pack"), "US-Core STU3"); + + assertNotNull(result.fetchResource(ctx, ValueSet.class, "http://hl7.org/fhir/us/core/ValueSet/simple-language")); + assertEquals(50, result.fetchAllConformanceResources(ctx).size()); + } + +} diff --git a/hapi-fhir-igpacks/src/test/resources/logback-test.xml b/hapi-fhir-igpacks/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..e5cbbb9c22e --- /dev/null +++ b/hapi-fhir-igpacks/src/test/resources/logback-test.xml @@ -0,0 +1,30 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%file:%line] - %msg%n + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-igpacks/src/test/resources/us-core-stu3-validator.pack b/hapi-fhir-igpacks/src/test/resources/us-core-stu3-validator.pack new file mode 100644 index 0000000000000000000000000000000000000000..3c027fe61c60e81a80944ef8c86b51f89748d773 GIT binary patch literal 285739 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

{# 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 AasU7T literal 0 HcmV?d00001 diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index e750cbb110b..a31753e9529 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -243,16 +243,20 @@ public abstract class BaseHapiFhirDao implements IDao { if (nextParam.getParamName().equals(nextCompositeOf.getName())) { IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType(); String value = nextParamAsClientParam.getValueAsQueryToken(getContext()); - value = UrlUtil.escape(value); - nextChoicesList.add(key + "=" + value); + if (isNotBlank(value)) { + value = UrlUtil.escape(value); + nextChoicesList.add(key + "=" + value); + } } } } if (linksForCompositePart != null) { for (ResourceLink nextLink : linksForCompositePart) { String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue(); - value = UrlUtil.escape(value); - nextChoicesList.add(key + "=" + value); + if (isNotBlank(value)) { + value = UrlUtil.escape(value); + nextChoicesList.add(key + "=" + value); + } } } } @@ -260,7 +264,9 @@ public abstract class BaseHapiFhirDao implements IDao { Set queryStringsToPopulate = extractCompositeStringUniquesValueChains(theEntity.getResourceType(), partsChoices); for (String nextQueryString : queryStringsToPopulate) { - compositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString)); + if (isNotBlank(nextQueryString)) { + compositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString)); + } } } @@ -1562,7 +1568,7 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setParamsUriPopulated(uriParams.isEmpty() == false); theEntity.setParamsCoords(coordsParams); theEntity.setParamsCoordsPopulated(coordsParams.isEmpty() == false); - theEntity.setParamsCompositeStringUnique(compositeStringUniques); +// theEntity.setParamsCompositeStringUnique(compositeStringUniques); theEntity.setParamsCompositeStringUniquePresent(compositeStringUniques.isEmpty() == false); theEntity.setResourceLinks(links); theEntity.setHasLinks(links.isEmpty() == false); @@ -1715,11 +1721,24 @@ public abstract class BaseHapiFhirDao implements IDao { theEntity.setResourceLinks(links); // Store composite string uniques - for (ResourceIndexedCompositeStringUnique next : existingCompositeStringUniques) { - myEntityManager.remove(next); - } - for (ResourceIndexedCompositeStringUnique next : compositeStringUniques) { - myEntityManager.persist(next); + if (getConfig().isUniqueIndexesEnabled()) { + for (ResourceIndexedCompositeStringUnique next : existingCompositeStringUniques) { + if (!compositeStringUniques.contains(next)) { + myEntityManager.remove(next); + } + } + for (ResourceIndexedCompositeStringUnique next : compositeStringUniques) { + if (!existingCompositeStringUniques.contains(next)) { + if (myConfig.isUniqueIndexesCheckedBeforeSave()) { + ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString()); + if (existing != null) { + throw new PreconditionFailedException("Can not create resource of type " + theEntity.getResourceType() + " as it would create a duplicate index matching query: " + next.getIndexString() + " (existing index belongs to " + existing.getResource().getIdDt().toUnqualifiedVersionless().getValue() + ")"); + } + } + ourLog.debug("Persisting unique index: {}", next); + myEntityManager.persist(next); + } + } } theEntity.toString(); @@ -1897,6 +1916,21 @@ public abstract class BaseHapiFhirDao implements IDao { */ public static Set extractCompositeStringUniquesValueChains(String theResourceType, List> thePartsChoices) { + for (List next : thePartsChoices) { + for (Iterator iter = next.iterator(); iter.hasNext(); ) { + if (isBlank(iter.next())) { + iter.remove(); + } + } + if (next.isEmpty()) { + return Collections.emptySet(); + } + } + + if (thePartsChoices.isEmpty()) { + return Collections.emptySet(); + } + Collections.sort(thePartsChoices, new Comparator>() { @Override public int compare(List o1, List o2) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index 734a7f92c8e..be2fc9c3aac 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -75,10 +75,64 @@ public class DaoConfig { private boolean myDeleteStaleSearches = true; private boolean myEnforceReferentialIntegrityOnDelete = true; + private boolean myUniqueIndexesEnabled = true; + /** + * If set to true (default is true), indexes will be + * created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}. + * This is a HAPI FHIR specific extension which can be used to specify that no more than one + * resource can exist which matches a given criteria, using a database constraint to + * enforce this. + */ + public boolean isUniqueIndexesEnabled() { + return myUniqueIndexesEnabled; + } + + /** + * If set to true (default is true), indexes will be + * created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}. + * This is a HAPI FHIR specific extension which can be used to specify that no more than one + * resource can exist which matches a given criteria, using a database constraint to + * enforce this. + */ + public void setUniqueIndexesEnabled(boolean theUniqueIndexesEnabled) { + myUniqueIndexesEnabled = theUniqueIndexesEnabled; + } + + /** + * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this + * setting is set to true (default is true) the system + * will test for the existence of a particular unique index value prior to saving + * a new one. + *

+ * This causes friendlier error messages to be generated, but adds an + * extra round-trip to the database for eavh save so it can cause + * a small performance hit. + *

+ */ + public boolean isUniqueIndexesCheckedBeforeSave() { + return myUniqueIndexesCheckedBeforeSave; + } + + /** + * When using {@link #setUniqueIndexesEnabled(boolean) unique indexes}, if this + * setting is set to true (default is true) the system + * will test for the existence of a particular unique index value prior to saving + * a new one. + *

+ * This causes friendlier error messages to be generated, but adds an + * extra round-trip to the database for eavh save so it can cause + * a small performance hit. + *

+ */ + public void setUniqueIndexesCheckedBeforeSave(boolean theUniqueIndexesCheckedBeforeSave) { + myUniqueIndexesCheckedBeforeSave = theUniqueIndexesCheckedBeforeSave; + } + + private boolean myUniqueIndexesCheckedBeforeSave = true; private boolean myEnforceReferentialIntegrityOnWrite = true; - private int myEverythingIncludesFetchPageSize = 50; + /** * update setter javadoc if default changes */ diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java index eace417ea9b..d9d36c3f608 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java @@ -1258,33 +1258,35 @@ public class SearchBuilder implements ISearchBuilder { * Check if there is a unique key associated with the set * of parameters passed in */ - if (myParams.getIncludes().isEmpty()) { - if (myParams.getRevIncludes().isEmpty()) { - if (myParams.getEverythingMode() == null) { - if (myParams.isAllParametersHaveNoModifier()) { - Set paramNames = theParams.keySet(); - if (paramNames.isEmpty() == false) { - List searchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, paramNames); - if (searchParams.size() > 0) { - List> params = new ArrayList<>(); - for (Entry>> nextParamNameToValues : theParams.entrySet()) { - String nextParamName = nextParamNameToValues.getKey(); - nextParamName = UrlUtil.escape(nextParamName); - for (List nextAnd : nextParamNameToValues.getValue()) { - ArrayList nextValueList = new ArrayList<>(); - params.add(nextValueList); - for (IQueryParameterType nextOr : nextAnd) { - String nextOrValue = nextOr.getValueAsQueryToken(myContext); - nextOrValue = UrlUtil.escape(nextOrValue); - nextValueList.add(nextParamName + "=" + nextOrValue); + if (myCallingDao.getConfig().isUniqueIndexesEnabled()) { + if (myParams.getIncludes().isEmpty()) { + if (myParams.getRevIncludes().isEmpty()) { + if (myParams.getEverythingMode() == null) { + if (myParams.isAllParametersHaveNoModifier()) { + Set paramNames = theParams.keySet(); + if (paramNames.isEmpty() == false) { + List searchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, paramNames); + if (searchParams.size() > 0) { + List> params = new ArrayList<>(); + for (Entry>> nextParamNameToValues : theParams.entrySet()) { + String nextParamName = nextParamNameToValues.getKey(); + nextParamName = UrlUtil.escape(nextParamName); + for (List nextAnd : nextParamNameToValues.getValue()) { + ArrayList nextValueList = new ArrayList<>(); + params.add(nextValueList); + for (IQueryParameterType nextOr : nextAnd) { + String nextOrValue = nextOr.getValueAsQueryToken(myContext); + nextOrValue = UrlUtil.escape(nextOrValue); + nextValueList.add(nextParamName + "=" + nextOrValue); + } } } + + Set uniqueQueryStrings = BaseHapiFhirDao.extractCompositeStringUniquesValueChains(myResourceName, params); + ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.UNIQUE_INDEX; + return new UniqueIndexIterator(uniqueQueryStrings); + } - - Set uniqueQueryStrings = BaseHapiFhirDao.extractCompositeStringUniquesValueChains(myResourceName, params); - ourLastHandlerMechanismForUnitTest = HandlerTypeEnum.UNIQUE_INDEX; - return new UniqueIndexIterator(uniqueQueryStrings); - } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java index 01b06e06048..911ec59a14a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java @@ -58,7 +58,7 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3 fetchAllConformanceResources(FhirContext theContext) { + return null; + } + + @Override + @Transactional(value = TxType.SUPPORTS) + public List fetchAllStructureDefinitions(FhirContext theContext) { + return Collections.emptyList(); + } + @Override public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { return fetchResource(theCtx, CodeSystem.class, theSystem); @@ -103,7 +111,7 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3 { params = new SearchParameterMap(); params.setLoadSynchronousUpTo(1); params.add(ValueSet.SP_URL, new UriParam(theUri)); - search = myValueSetDao.search(params); + search = myValueSetDao.search(params); } } else { SearchParameterMap params = new SearchParameterMap(); @@ -145,28 +153,20 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3 { } @Override - @Transactional(value=TxType.SUPPORTS) + public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { + return fetchResource(theCtx, StructureDefinition.class, theUrl); + } + + @Override + @Transactional(value = TxType.SUPPORTS) public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) { return false; } @Override - @Transactional(value=TxType.SUPPORTS) + @Transactional(value = TxType.SUPPORTS) public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) { return null; } - - @Override - public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { - return fetchResource(theCtx, StructureDefinition.class, theUrl); - } - - - @Override - @Transactional(value=TxType.SUPPORTS) - public List fetchAllStructureDefinitions(FhirContext theContext) { - return Collections.emptyList(); - } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java index d76ea7a5140..20070c88268 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoSearchParameterR4.java @@ -60,7 +60,7 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4 fetchAllConformanceResources(FhirContext theContext) { + return null; + } + + @Override + @Transactional(value = TxType.SUPPORTS) + public List fetchAllStructureDefinitions(FhirContext theContext) { + return Collections.emptyList(); + } + @Override public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { return fetchResource(theCtx, CodeSystem.class, theSystem); @@ -103,7 +111,7 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4 { params = new SearchParameterMap(); params.setLoadSynchronousUpTo(1); params.add(ValueSet.SP_URL, new UriParam(theUri)); - search = myValueSetDao.search(params); + search = myValueSetDao.search(params); } } else { SearchParameterMap params = new SearchParameterMap(); @@ -145,28 +153,20 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4 { } @Override - @Transactional(value=TxType.SUPPORTS) + public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { + return fetchResource(theCtx, StructureDefinition.class, theUrl); + } + + @Override + @Transactional(value = TxType.SUPPORTS) public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) { return false; } @Override - @Transactional(value=TxType.SUPPORTS) + @Transactional(value = TxType.SUPPORTS) public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) { return null; } - - @Override - public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { - return fetchResource(theCtx, StructureDefinition.class, theUrl); - } - - - @Override - @Transactional(value=TxType.SUPPORTS) - public List fetchAllStructureDefinitions(FhirContext theContext) { - return Collections.emptyList(); - } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedCompositeStringUnique.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedCompositeStringUnique.java index 3f7c7f4a0a7..3a44fafebfd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedCompositeStringUnique.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedCompositeStringUnique.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.entity; +import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.builder.*; import org.hl7.fhir.r4.model.Resource; @@ -88,6 +89,7 @@ public class ResourceIndexedCompositeStringUnique implements Comparable extends BaseJpaProvider { public static final String MARK_ALL_RESOURCES_FOR_REINDEXING = "$mark-all-resources-for-reindexing"; + public static final String PERFORM_REINDEXING_PASS = "$perform-reindexing-pass"; private IFhirSystemDao myDao; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java index 37897210d11..e8ad50fbc6f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java @@ -30,11 +30,9 @@ import ca.uhn.fhir.util.ParametersUtil; public abstract class BaseJpaSystemProviderDstu2Plus extends BaseJpaSystemProvider { - //@formatter:off @Operation(name=MARK_ALL_RESOURCES_FOR_REINDEXING, idempotent=true, returnParameters= { @OperationParam(name="status") }) - //@formatter:on public IBaseResource markAllResourcesForReindexing() { int count = getDao().markAllResourcesForReindexing(); @@ -42,9 +40,22 @@ public abstract class BaseJpaSystemProviderDstu2Plus extends BaseJpaSyste IPrimitiveType string = ParametersUtil.createString(getContext(), "Marked " + count + " resources"); ParametersUtil.addParameterToParameters(getContext(), retVal, string, "status"); - + + return retVal; + } + + @Operation(name=PERFORM_REINDEXING_PASS, idempotent=true, returnParameters= { + @OperationParam(name="status") + }) + public IBaseResource performReindexingPass() { + int count = getDao().performReindexingPass(1000); + + IBaseParameters retVal = ParametersUtil.newInstance(getContext()); + + IPrimitiveType string = ParametersUtil.createString(getContext(), "Indexed " + count + " resources"); + ParametersUtil.addParameterToParameters(getContext(), retVal, string, "status"); + return retVal; } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java index 57cbbec2c73..a8ac39a2600 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcDstu3.java @@ -254,6 +254,11 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I return retVal; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + return null; + } + @Override public List expandValueSet(String theValueSet) { ValueSet source = new ValueSet(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java index 990d7d60750..45189318700 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/HapiTerminologySvcR4.java @@ -1,5 +1,43 @@ package ca.uhn.fhir.jpa.term; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.jpa.dao.DaoMethodOutcome; +import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.jpa.entity.ResourceTable; +import ca.uhn.fhir.jpa.entity.TermCodeSystem; +import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion; +import ca.uhn.fhir.jpa.entity.TermConcept; +import ca.uhn.fhir.jpa.util.StopWatch; +import ca.uhn.fhir.rest.api.server.RequestDetails; +import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.util.CoverageIgnore; +import ca.uhn.fhir.util.UrlUtil; +import org.apache.lucene.search.Query; +import org.hibernate.search.jpa.FullTextEntityManager; +import org.hibernate.search.jpa.FullTextQuery; +import org.hibernate.search.query.dsl.BooleanJunction; +import org.hibernate.search.query.dsl.QueryBuilder; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext; +import org.hl7.fhir.r4.hapi.ctx.IValidationSupport; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; +import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.ValueSet; +import org.hl7.fhir.r4.model.ValueSet.*; +import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome; +import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -12,9 +50,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; * 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. @@ -22,36 +60,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; * limitations under the License. * #L% */ -import java.util.*; - -import org.apache.lucene.search.Query; -import org.hibernate.search.jpa.FullTextEntityManager; -import org.hibernate.search.jpa.FullTextQuery; -import org.hibernate.search.query.dsl.BooleanJunction; -import org.hibernate.search.query.dsl.QueryBuilder; -import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext; -import org.hl7.fhir.r4.hapi.ctx.IValidationSupport; -import org.hl7.fhir.r4.model.*; -import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; -import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; -import org.hl7.fhir.r4.model.ValueSet.*; -import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.jpa.dao.*; -import ca.uhn.fhir.jpa.entity.*; -import ca.uhn.fhir.jpa.util.StopWatch; -import ca.uhn.fhir.rest.api.server.RequestDetails; -import ca.uhn.fhir.rest.server.exceptions.*; -import ca.uhn.fhir.util.CoverageIgnore; -import ca.uhn.fhir.util.UrlUtil; public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IValidationSupport, IHapiTerminologySvcR4 { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HapiTerminologySvcR4.class); @@ -63,6 +71,15 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal @Autowired private IValidationSupport myValidationSupport; + private void addAllChildren(String theSystemString, ConceptDefinitionComponent theCode, List theListToPopulate) { + if (isNotBlank(theCode.getCode())) { + theListToPopulate.add(new VersionIndependentConcept(theSystemString, theCode.getCode())); + } + for (ConceptDefinitionComponent nextChild : theCode.getConcept()) { + addAllChildren(theSystemString, nextChild, theListToPopulate); + } + } + private void addCodeIfNotAlreadyAdded(String system, ValueSetExpansionComponent retVal, Set addedCodes, TermConcept nextConcept) { if (addedCodes.add(nextConcept.getCode())) { ValueSetExpansionContainsComponent contains = retVal.addContains(); @@ -72,36 +89,20 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal } } - @Override - protected List findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) { - ArrayList retVal = new ArrayList(); - CodeSystem system = myValidationSupport.fetchCodeSystem(myContext, theSystem); - if (system != null) { - findCodesBelow(system, theSystem, theCode, retVal); - } - return retVal; + private void addDisplayFilterExact(QueryBuilder qb, BooleanJunction bool, ConceptSetFilterComponent nextFilter) { + bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery()); } - private void findCodesBelow(CodeSystem theSystem, String theSystemString, String theCode, List theListToPopulate) { - List conceptList = theSystem.getConcept(); - findCodesBelow(theSystemString, theCode, theListToPopulate, conceptList); - } - - private void findCodesBelow(String theSystemString, String theCode, List theListToPopulate, List conceptList) { - for (ConceptDefinitionComponent next : conceptList) { - if (theCode.equals(next.getCode())) { - addAllChildren(theSystemString, next, theListToPopulate); - } else { - findCodesBelow(theSystemString, theCode, theListToPopulate, next.getConcept()); - } - } - } - - private void findCodesAbove(CodeSystem theSystem, String theSystemString, String theCode, List theListToPopulate) { - List conceptList = theSystem.getConcept(); - for (ConceptDefinitionComponent next : conceptList) { - addTreeIfItContainsCode(theSystemString, next, theCode, theListToPopulate); - } + private void addDisplayFilterInexact(QueryBuilder qb, BooleanJunction bool, ConceptSetFilterComponent nextFilter) { + Query textQuery = qb + .phrase() + .withSlop(2) + .onField("myDisplay").boostedTo(4.0f) + .andField("myDisplayEdgeNGram").boostedTo(2.0f) + // .andField("myDisplayNGram").boostedTo(1.0f) + // .andField("myDisplayPhonetic").boostedTo(0.5f) + .sentence(nextFilter.getValue().toLowerCase()).createQuery(); + bool.must(textQuery); } private boolean addTreeIfItContainsCode(String theSystemString, ConceptDefinitionComponent theNext, String theCode, List theListToPopulate) { @@ -118,41 +119,6 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal return false; } - private void addAllChildren(String theSystemString, ConceptDefinitionComponent theCode, List theListToPopulate) { - if (isNotBlank(theCode.getCode())) { - theListToPopulate.add(new VersionIndependentConcept(theSystemString, theCode.getCode())); - } - for (ConceptDefinitionComponent nextChild : theCode.getConcept()) { - addAllChildren(theSystemString, nextChild, theListToPopulate); - } - } - - @Override - protected List findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) { - ArrayList retVal = new ArrayList(); - CodeSystem system = myValidationSupport.fetchCodeSystem(myContext, theSystem); - if (system != null) { - findCodesAbove(system, theSystem, theCode, retVal); - } - return retVal; - } - - private void addDisplayFilterExact(QueryBuilder qb, BooleanJunction bool, ConceptSetFilterComponent nextFilter) { - bool.must(qb.phrase().onField("myDisplay").sentence(nextFilter.getValue()).createQuery()); - } - - private void addDisplayFilterInexact(QueryBuilder qb, BooleanJunction bool, ConceptSetFilterComponent nextFilter) { - Query textQuery = qb - .phrase() - .withSlop(2) - .onField("myDisplay").boostedTo(4.0f) - .andField("myDisplayEdgeNGram").boostedTo(2.0f) - // .andField("myDisplayNGram").boostedTo(1.0f) - // .andField("myDisplayPhonetic").boostedTo(0.5f) - .sentence(nextFilter.getValue().toLowerCase()).createQuery(); - bool.must(textQuery); - } - @Override public ValueSetExpansionComponent expandValueSet(FhirContext theContext, ConceptSetComponent theInclude) { String system = theInclude.getSystem(); @@ -204,8 +170,8 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal if (isBlank(nextFilter.getValue()) || nextFilter.getOp() == null || isBlank(nextFilter.getProperty())) { throw new InvalidRequestException("Invalid filter, must have fields populated: property op value"); } - - + + if (nextFilter.getProperty().equals("display:exact") && nextFilter.getOp() == FilterOperator.EQUAL) { addDisplayFilterExact(qb, bool, nextFilter); } else if ("display".equals(nextFilter.getProperty()) && nextFilter.getOp() == FilterOperator.EQUAL) { @@ -232,12 +198,12 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal jpaQuery.setMaxResults(1000); StopWatch sw = new StopWatch(); - + @SuppressWarnings("unchecked") List result = jpaQuery.getResultList(); - + ourLog.info("Expansion completed in {}ms", sw.getMillis()); - + for (TermConcept nextConcept : result) { addCodeIfNotAlreadyAdded(system, retVal, addedCodes, nextConcept); } @@ -278,6 +244,11 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + return null; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return Collections.emptyList(); @@ -300,6 +271,48 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal return null; } + private void findCodesAbove(CodeSystem theSystem, String theSystemString, String theCode, List theListToPopulate) { + List conceptList = theSystem.getConcept(); + for (ConceptDefinitionComponent next : conceptList) { + addTreeIfItContainsCode(theSystemString, next, theCode, theListToPopulate); + } + } + + @Override + protected List findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) { + ArrayList retVal = new ArrayList(); + CodeSystem system = myValidationSupport.fetchCodeSystem(myContext, theSystem); + if (system != null) { + findCodesAbove(system, theSystem, theCode, retVal); + } + return retVal; + } + + private void findCodesBelow(CodeSystem theSystem, String theSystemString, String theCode, List theListToPopulate) { + List conceptList = theSystem.getConcept(); + findCodesBelow(theSystemString, theCode, theListToPopulate, conceptList); + } + + private void findCodesBelow(String theSystemString, String theCode, List theListToPopulate, List conceptList) { + for (ConceptDefinitionComponent next : conceptList) { + if (theCode.equals(next.getCode())) { + addAllChildren(theSystemString, next, theListToPopulate); + } else { + findCodesBelow(theSystemString, theCode, theListToPopulate, next.getConcept()); + } + } + } + + @Override + protected List findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) { + ArrayList retVal = new ArrayList(); + CodeSystem system = myValidationSupport.fetchCodeSystem(myContext, theSystem); + if (system != null) { + findCodesBelow(system, theSystem, theCode, retVal); + } + return retVal; + } + @Override public boolean isCodeSystemSupported(FhirContext theContext, String theSystem) { return super.supportsSystem(theSystem); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StopWatch.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StopWatch.java index f1389e3d39c..414de7e53be 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StopWatch.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/StopWatch.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.jpa.util; +import org.apache.commons.lang3.time.DateUtils; + import java.util.Date; /* @@ -72,9 +74,15 @@ public class StopWatch { static public String formatMillis(long val) { StringBuilder buf = new StringBuilder(20); - append(buf, "", 2, ((val % 3600000) / 60000)); - append(buf, ":", 2, ((val % 60000) / 1000)); - append(buf, ".", 3, (val % 1000)); + if (val >= DateUtils.MILLIS_PER_DAY) { + append(buf, "", 1, ((val / DateUtils.MILLIS_PER_DAY))); + append(buf, "d", 2, ((val % DateUtils.MILLIS_PER_DAY) / DateUtils.MILLIS_PER_HOUR)); + } else { + append(buf, "", 2, ((val % DateUtils.MILLIS_PER_DAY) / DateUtils.MILLIS_PER_HOUR)); + } + append(buf, ":", 2, ((val % DateUtils.MILLIS_PER_HOUR) / DateUtils.MILLIS_PER_MINUTE)); + append(buf, ":", 2, ((val % DateUtils.MILLIS_PER_MINUTE) / DateUtils.MILLIS_PER_SECOND)); + append(buf, ".", 3, (val % DateUtils.MILLIS_PER_SECOND)); return buf.toString(); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java index 99e4eb030d8..0e3af0f029f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java @@ -35,6 +35,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { @After public void after() { myDaoConfig.setDefaultSearchParamsCanBeOverridden(new DaoConfig().isDefaultSearchParamsCanBeOverridden()); + myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave()); } @Before @@ -118,6 +119,58 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { mySearchParamRegsitry.forceRefresh(); } + private void createUniqueObservationSubjectDateCode() { + SearchParameter sp = new SearchParameter(); + sp.setId("SearchParameter/obs-subject"); + sp.setType(Enumerations.SearchParamType.REFERENCE); + sp.setCode("subject"); + sp.setExpression("Observation.subject"); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Observation"); + sp.addTarget("Patient"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/obs-effective"); + sp.setType(Enumerations.SearchParamType.DATE); + sp.setCode("date"); + sp.setExpression("Observation.effective"); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Observation"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/obs-code"); + sp.setType(Enumerations.SearchParamType.TOKEN); + sp.setCode("code"); + sp.setExpression("Observation.code"); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Observation"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/observation-subject-date-code"); + sp.setType(Enumerations.SearchParamType.COMPOSITE); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Observation"); + sp.setExpression("Observation.code"); + sp.addComponent() + .setExpression("Observation") + .setDefinition(new Reference("SearchParameter/obs-subject")); + sp.addComponent() + .setExpression("Observation") + .setDefinition(new Reference("SearchParameter/obs-effective")); + sp.addComponent() + .setExpression("Observation") + .setDefinition(new Reference("SearchParameter/obs-code")); + sp.addExtension() + .setUrl(JpaConstants.EXT_SP_UNIQUE) + .setValue(new BooleanType(true)); + mySearchParameterDao.update(sp); + + mySearchParamRegsitry.forceRefresh(); + } + @Test public void testDetectUniqueSearchParams() { createUniqueBirthdateAndGenderSps(); @@ -131,9 +184,61 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { assertEquals("gender", params.get(0).getCompositeOf().get(1).getName()); } + @Test + public void testDuplicateUniqueValuesAreReIndexed() { + + Patient pt1 = new Patient(); + pt1.setActive(true); + IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + /* + * Both of the following resources will match the unique index we'll + * create afterward. So we can create them both, but then when we create + * the unique index that matches them both that's a problem... + */ + + Observation obs = new Observation(); + obs.getCode().addCoding().setSystem("foo").setCode("bar"); + obs.setSubject(new Reference(pt1.getIdElement().toUnqualifiedVersionless().getValue())); + obs.setEffective(new DateTimeType("2011-01-01")); + IIdType id2 = myObservationDao.create(obs).getId().toUnqualifiedVersionless(); + + obs = new Observation(); + obs.getCode().addCoding().setSystem("foo").setCode("bar"); + obs.setSubject(new Reference(pt1.getIdElement().toUnqualifiedVersionless().getValue())); + obs.setEffective(new DateTimeType("2011-01-01")); + IIdType id3 = myObservationDao.create(obs).getId().toUnqualifiedVersionless(); + + ourLog.info("ID1: {} - ID2: {} - ID3: {}", id1, id2, id3); + + createUniqueObservationSubjectDateCode(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + mySystemDao.performReindexingPass(1000); + + List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString()); + + myResourceIndexedCompositeStringUniqueDao.deleteAll(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + mySystemDao.performReindexingPass(1000); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString()); + + } @Test - public void testDuplicateUniqueValuesAreRejected() { + public void testDuplicateUniqueValuesAreRejectedWithChecking_TestingDisabled() { + myDaoConfig.setUniqueIndexesCheckedBeforeSave(false); + createUniqueBirthdateAndGenderSps(); Patient pt1 = new Patient(); @@ -147,26 +252,10 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { } catch (JpaSystemException e) { // good } - - Patient pt2 = new Patient(); - pt2.setGender(Enumerations.AdministrativeGender.MALE); - IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless(); - - pt2 = new Patient(); - pt2.setId(id2); - pt2.setGender(Enumerations.AdministrativeGender.MALE); - pt2.setBirthDateElement(new DateType("2011-01-01")); - try { - myPatientDao.update(pt2); - fail(); - } catch (JpaSystemException e) { - // good - } - } @Test - public void testUniqueValuesAreIndexed_DateAndToken() { + public void testDuplicateUniqueValuesAreRejectedWithChecking_TestingEnabled() { createUniqueBirthdateAndGenderSps(); Patient pt1 = new Patient(); @@ -174,10 +263,12 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { pt1.setBirthDateElement(new DateType("2011-01-01")); IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); - List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); - assertEquals(1, uniques.size()); - assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); - assertEquals("Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale", uniques.get(0).getIndexString()); + try { + myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + fail(); + } catch (PreconditionFailedException e) { + assertEquals("Can not create resource of type Patient as it would create a duplicate index matching query: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale (existing index belongs to Patient/" + id1.getIdPart() + ")", e.getMessage()); + } } @Test @@ -204,7 +295,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { assertEquals(SearchBuilder.HandlerTypeEnum.UNIQUE_INDEX, SearchBuilder.getLastHandlerMechanismForUnitTest()); } - @Test + @Test public void testSearchUsingUniqueComposite() { createUniqueBirthdateAndGenderSps(); @@ -255,6 +346,51 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { } + @Test + public void testUniqueValuesAreIndexed_DateAndToken() { + createUniqueBirthdateAndGenderSps(); + + Patient pt1 = new Patient(); + pt1.setGender(Enumerations.AdministrativeGender.MALE); + pt1.setBirthDateElement(new DateType("2011-01-01")); + IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale", uniques.get(0).getIndexString()); + } + + @Test + public void testUniqueValuesAreIndexed_RefAndDateAndToken() { + createUniqueObservationSubjectDateCode(); + + List uniques; + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + Patient pt1 = new Patient(); + pt1.setActive(true); + IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + Observation obs = new Observation(); + obs.getCode().addCoding().setSystem("foo").setCode("bar"); + obs.setSubject(new Reference(pt1.getIdElement().toUnqualifiedVersionless().getValue())); + obs.setEffective(new DateTimeType("2011-01-01")); + IIdType id2 = myObservationDao.create(obs).getId().toUnqualifiedVersionless(); + + Patient pt2 = new Patient(); + pt2.setActive(false); + IIdType id3 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + ourLog.info("ID1: {} - ID2: {} - ID3: {}", id1, id2, id3); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString()); + } + @Test public void testUniqueValuesAreIndexed_StringAndReference() { createUniqueNameAndManagingOrganizationSps(); @@ -287,6 +423,106 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { assertEquals("Patient?name=GIVEN2&organization=Organization%2FORG", uniques.get(2).getIndexString()); } + @Test + public void testUniqueValuesAreNotIndexedIfNotAllParamsAreFound_DateAndToken() { + createUniqueBirthdateAndGenderSps(); + + Patient pt; + List uniques; + + pt = new Patient(); + pt.setGender(Enumerations.AdministrativeGender.MALE); + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + pt = new Patient(); + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + pt = new Patient(); + pt.setBirthDateElement(new DateType()); + pt.setGender(Enumerations.AdministrativeGender.MALE); + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + } + + @Test + public void testUniqueValuesAreNotIndexedIfNotAllParamsAreFound_StringAndReference() { + createUniqueNameAndManagingOrganizationSps(); + + Organization org = new Organization(); + org.setId("Organization/ORG"); + org.setName("ORG"); + myOrganizationDao.update(org); + + List uniques; + Patient pt; + + pt = new Patient(); + pt.setManagingOrganization(new Reference("Organization/ORG")); + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + pt = new Patient(); + pt.addName() + .setFamily("FAMILY1") + .addGiven("GIVEN1") + .addGiven("GIVEN2") + .addGiven("GIVEN2"); // GIVEN2 happens twice + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + + pt = new Patient(); + pt.setActive(true); + myPatientDao.create(pt).getId().toUnqualifiedVersionless(); + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 0, uniques.size()); + } + + @Test + public void testUniqueValuesAreReIndexed() { + createUniqueObservationSubjectDateCode(); + + Patient pt1 = new Patient(); + pt1.setActive(true); + IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + Observation obs = new Observation(); + obs.getCode().addCoding().setSystem("foo").setCode("bar"); + obs.setSubject(new Reference(pt1.getIdElement().toUnqualifiedVersionless().getValue())); + obs.setEffective(new DateTimeType("2011-01-01")); + IIdType id2 = myObservationDao.create(obs).getId().toUnqualifiedVersionless(); + + Patient pt2 = new Patient(); + pt2.setActive(false); + myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + + List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString()); + + myResourceIndexedCompositeStringUniqueDao.deleteAll(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString()); + + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java index 0a26b2caf46..c00286c6825 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java @@ -362,6 +362,17 @@ public class SystemProviderR4Test extends BaseJpaR4Test { } finally { IOUtils.closeQuietly(http);; } + + get = new HttpGet(ourServerBase + "/$perform-reindexing-pass"); + http = ourHttpClient.execute(get); + try { + String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8); + ourLog.info(output); + assertEquals(200, http.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(http);; + } + } @Transactional(propagation = Propagation.NEVER) diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/StopWatchTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/StopWatchTest.java index 1e1eafe10fb..54a2ed29e27 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/StopWatchTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/StopWatchTest.java @@ -3,10 +3,12 @@ package ca.uhn.fhir.jpa.util; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.Date; +import org.apache.commons.lang3.time.DateUtils; import org.junit.Test; public class StopWatchTest { @@ -46,4 +48,14 @@ public class StopWatchTest { assertThat(string, startsWith("00:00")); } + @Test + public void testFormatMillis() throws Exception { + assertEquals("00:00:01.000", StopWatch.formatMillis(DateUtils.MILLIS_PER_SECOND)); + assertEquals("00:01:00.000", StopWatch.formatMillis(DateUtils.MILLIS_PER_MINUTE)); + assertEquals("01:00:00.000", StopWatch.formatMillis(DateUtils.MILLIS_PER_HOUR)); + assertEquals("1d00:00:00.000", StopWatch.formatMillis(DateUtils.MILLIS_PER_DAY)); + assertEquals("2d00:00:00.000", StopWatch.formatMillis(DateUtils.MILLIS_PER_DAY*2)); + assertEquals("2d00:00:00.001", StopWatch.formatMillis((DateUtils.MILLIS_PER_DAY*2)+1)); + } + } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/derby_maintenance.txt b/hapi-fhir-jpaserver-uhnfhirtest/derby_maintenance.txt index 3646c2ac1b7..21e69afe88a 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/derby_maintenance.txt +++ b/hapi-fhir-jpaserver-uhnfhirtest/derby_maintenance.txt @@ -44,12 +44,34 @@ delete from hfj_forced_id where resource_pid = 16940; delete from hfj_resource where res_id = 16940; +# Drop all tables +drop table hfj_history_tag cascade constraints; +drop table hfj_res_ver cascade constraints; +drop table hfj_forced_id cascade constraints; +drop table hfj_res_link cascade constraints; +drop table hfj_res_link cascade constraints; +drop table hfj_spidx_coords cascade constraints; +drop table hfj_spidx_date cascade constraints; +drop table hfj_spidx_number cascade constraints; +drop table hfj_spidx_quantity cascade constraints; +drop table hfj_spidx_string cascade constraints; +drop table hfj_spidx_token cascade constraints; +drop table hfj_spidx_uri cascade constraints; +drop table hfj_res_tag cascade constraints; +drop table hfj_search_result cascade constraints; +drop table hfj_res_param_present cascade constraints; +drop table hfj_resource cascade constraints; +drop table hfj_idx_cmp_string_uniq cascade constraints; +drop table hfj_search cascade constraints; +drop table hfj_search_include cascade constraints; +drop table hfj_search_parm cascade constraints; +drop table hfj_subscription cascade constraints; +drop table hfj_subscription_flag_res cascade constraints; +drop table hfj_tag_def cascade constraints; +drop table trm_codesystem cascade constraints; +drop table trm_codesystem_var cascade constraints; +drop table trm_concept cascade constraints; +drop table trm_concept_pc_link cascade constraints; +drop table trm_concept_property cascade constraints; -delete from hfj_res_link where src_resource_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815) or target_resource_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); -delete from hfj_spidx_date where res_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); -delete from hfj_spidx_string where res_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); -delete from hfj_spidx_token where res_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); -delete from hfj_search_result where resource_pid in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); -delete from hfj_resource where res_id in ( 156618, 1092 , 1114 , 1139 , 1140 , 1141, 1142 , 1143 , 1144 , 1146 , 1147, 1148, 1062912, 1062916, 1062918, 1062919, 1062922, 1062929, 1062930, 1062934, 1062939, 1062940, 1062944, 1062949, 1062955, 1062957, 1062958, 1062959, 1062966, 1062969, 1062975, 1062976, 1062979, 1062981, 1062985, 1062987, 1062992, 1063002, 1063005, 1063007, 1063013, 1063016, 1063018, 1063020, 1063022, 1063062, 1063068, 1063075, 1063078, 1063080, 1063083, 1063084, 1063091, 1063095, 1063096, 1063098, 1107579, 1107591, 1107598, 1107761, 1107705, 1107748, 1109361, 1109388, 1109378, 1109399, 1109400, 1109401, 1109403, 1109404, 1109406, 1109409, 1109411, 1109414, 1109417, 1109418, 1109421, 1109427, 1109428, 1109429, 1109431, 1109432, 1109433, 1109891, 1109893, 1109947, 1179553, 1182781, 1182788, 1182791, 1182792, 1182795, 1182798, 1182801, 1182806, 1182811, 1182815); - diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java index 80e48d618cf..b5fe1903fb6 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java @@ -1,32 +1,22 @@ package org.hl7.fhir.dstu2016may.hapi.validation; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - +import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; import org.apache.commons.lang3.Validate; -import org.hl7.fhir.dstu2016may.model.Bundle; +import org.hl7.fhir.dstu2016may.model.*; import org.hl7.fhir.dstu2016may.model.Bundle.BundleEntryComponent; -import org.hl7.fhir.dstu2016may.model.CodeSystem; import org.hl7.fhir.dstu2016may.model.CodeSystem.ConceptDefinitionComponent; -import org.hl7.fhir.dstu2016may.model.DomainResource; import org.hl7.fhir.dstu2016may.model.OperationOutcome.IssueSeverity; -import org.hl7.fhir.dstu2016may.model.StructureDefinition; -import org.hl7.fhir.dstu2016may.model.ValueSet; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; public class DefaultProfileValidationSupport implements IValidationSupport { @@ -55,6 +45,15 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return retVal; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return new ArrayList(provideStructureDefinitionMap(theContext).values()); @@ -219,25 +218,6 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return structureDefinitions; } - @Override - public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { - CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); - if (cs != null) { - boolean caseSensitive = true; - if (cs.hasCaseSensitive()) { - caseSensitive = cs.getCaseSensitive(); - } - - CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); - - if (retVal != null) { - return retVal; - } - } - - return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); - } - private CodeValidationResult testIfConceptIsInList(String theCode, List conceptList, boolean theCaseSensitive) { String code = theCode; if (theCaseSensitive == false) { @@ -269,4 +249,23 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return retVal; } + @Override + public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { + CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); + if (cs != null) { + boolean caseSensitive = true; + if (cs.hasCaseSensitive()) { + caseSensitive = cs.getCaseSensitive(); + } + + CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); + + if (retVal != null) { + return retVal; + } + } + + return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); + } + } diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/PrePopulatedValidationSupport.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/PrePopulatedValidationSupport.java index f8cfa70d28e..8771c1609ef 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/PrePopulatedValidationSupport.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/PrePopulatedValidationSupport.java @@ -1,10 +1,6 @@ package org.hl7.fhir.dstu2016may.hapi.validation; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import ca.uhn.fhir.context.FhirContext; import org.apache.commons.lang3.Validate; import org.hl7.fhir.dstu2016may.model.CodeSystem; import org.hl7.fhir.dstu2016may.model.StructureDefinition; @@ -13,7 +9,10 @@ import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * This class is an implementation of {@link IValidationSupport} which may be pre-populated @@ -29,30 +28,25 @@ public class PrePopulatedValidationSupport implements IValidationSupport { * Constructor */ public PrePopulatedValidationSupport() { - myStructureDefinitions = new HashMap(); - myValueSets = new HashMap(); - myCodeSystems = new HashMap(); + myStructureDefinitions = new HashMap(); + myValueSets = new HashMap(); + myCodeSystems = new HashMap(); } - - + /** - * Add a new StructureDefinition resource which will be available to the validator. Note that - * {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this - * value will be used as the logical URL. + * Constructor + * + * @param theStructureDefinitions The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and + * values are the resource itself. + * @param theValueSets The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. + * @param theCodeSystems The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. */ - public void addStructureDefinition(StructureDefinition theStructureDefinition) { - Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value"); - myStructureDefinitions.put(theStructureDefinition.getUrl(), theStructureDefinition); - } - - /** - * Add a new ValueSet resource which will be available to the validator. Note that - * {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this - * value will be used as the logical URL. - */ - public void addValueSet(ValueSet theValueSet) { - Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value"); - myValueSets.put(theValueSet.getUrl(), theValueSet); + public PrePopulatedValidationSupport(Map theStructureDefinitions, Map theValueSets, Map theCodeSystems) { + myStructureDefinitions = theStructureDefinitions; + myValueSets = theValueSets; + myCodeSystems = theCodeSystems; } /** @@ -66,22 +60,23 @@ public class PrePopulatedValidationSupport implements IValidationSupport { } /** - * Constructor - * - * @param theStructureDefinitions - * The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and - * values are the resource itself. - * @param theValueSets - * The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. - * @param theCodeSystems - * The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. + * Add a new StructureDefinition resource which will be available to the validator. Note that + * {@link StructureDefinition#getUrl() the URL field) in this resource must contain a value as this + * value will be used as the logical URL. */ - public PrePopulatedValidationSupport(Map theStructureDefinitions, Map theValueSets, Map theCodeSystems) { - myStructureDefinitions = theStructureDefinitions; - myValueSets = theValueSets; - myCodeSystems = theCodeSystems; + public void addStructureDefinition(StructureDefinition theStructureDefinition) { + Validate.notBlank(theStructureDefinition.getUrl(), "theStructureDefinition.getUrl() must not return a value"); + myStructureDefinitions.put(theStructureDefinition.getUrl(), theStructureDefinition); + } + + /** + * Add a new ValueSet resource which will be available to the validator. Note that + * {@link ValueSet#getUrl() the URL field) in this resource must contain a value as this + * value will be used as the logical URL. + */ + public void addValueSet(ValueSet theValueSet) { + Validate.notBlank(theValueSet.getUrl(), "theValueSet.getUrl() must not return a value"); + myValueSets.put(theValueSet.getUrl(), theValueSet); } @Override @@ -89,6 +84,15 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return new ArrayList(myStructureDefinitions.values()); @@ -129,4 +133,4 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } -} \ No newline at end of file +} diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/ValidationSupportChain.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/ValidationSupportChain.java index 409e1d0b1e4..11889dba553 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/ValidationSupportChain.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/ValidationSupportChain.java @@ -1,19 +1,18 @@ package org.hl7.fhir.dstu2016may.hapi.validation; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +import ca.uhn.fhir.context.FhirContext; import org.hl7.fhir.dstu2016may.model.CodeSystem; import org.hl7.fhir.dstu2016may.model.StructureDefinition; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.commons.lang3.StringUtils.isBlank; public class ValidationSupportChain implements IValidationSupport { @@ -52,6 +51,32 @@ public class ValidationSupportChain implements IValidationSupport { return myChain.get(0).expandValueSet(theCtx, theInclude); } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + List retVal = new ArrayList<>(); + for (IValidationSupport next : myChain) { + List candidates = next.fetchAllConformanceResources(theContext); + if (candidates != null) { + retVal.addAll(candidates); + } + } + return retVal; + } + + @Override + public List fetchAllStructureDefinitions(FhirContext theContext) { + ArrayList retVal = new ArrayList(); + Set urls = new HashSet(); + for (IValidationSupport nextSupport : myChain) { + for (StructureDefinition next : nextSupport.fetchAllStructureDefinitions(theContext)) { + if (isBlank(next.getUrl()) || urls.add(next.getUrl())) { + retVal.add(next); + } + } + } + return retVal; + } + @Override public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { for (IValidationSupport next : myChain) { @@ -105,18 +130,4 @@ public class ValidationSupportChain implements IValidationSupport { return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay); } - @Override - public List fetchAllStructureDefinitions(FhirContext theContext) { - ArrayList retVal = new ArrayList(); - Set urls= new HashSet(); - for (IValidationSupport nextSupport : myChain) { - for (StructureDefinition next : nextSupport.fetchAllStructureDefinitions(theContext)) { - if (isBlank(next.getUrl()) || urls.add(next.getUrl())) { - retVal.add(next); - } - } - } - return retVal; - } - } diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java index d88b0a2fefd..a674072a212 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/DefaultProfileValidationSupport.java @@ -1,11 +1,6 @@ package org.hl7.fhir.dstu3.hapi.validation; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; - +import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; @@ -19,7 +14,11 @@ import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; -import ca.uhn.fhir.context.FhirContext; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; public class DefaultProfileValidationSupport implements IValidationSupport { @@ -52,6 +51,15 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return retVal; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return new ArrayList(provideStructureDefinitionMap(theContext).values()); @@ -94,7 +102,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (theClass.equals(StructureDefinition.class)) { return (T) fetchStructureDefinition(theContext, theUri); } - + if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) { return (T) fetchValueSet(theContext, theUri); } @@ -195,25 +203,6 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return structureDefinitions; } - @Override - public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { - CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); - if (cs != null) { - boolean caseSensitive = true; - if (cs.hasCaseSensitive()) { - caseSensitive = cs.getCaseSensitive(); - } - - CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); - - if (retVal != null) { - return retVal; - } - } - - return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); - } - private CodeValidationResult testIfConceptIsInList(String theCode, List conceptList, boolean theCaseSensitive) { String code = theCode; if (theCaseSensitive == false) { @@ -245,4 +234,23 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return retVal; } + @Override + public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { + CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); + if (cs != null) { + boolean caseSensitive = true; + if (cs.hasCaseSensitive()) { + caseSensitive = cs.getCaseSensitive(); + } + + CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); + + if (retVal != null) { + return retVal; + } + } + + return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); + } + } diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PrePopulatedValidationSupport.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PrePopulatedValidationSupport.java index 08820d6c862..1914426daa7 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PrePopulatedValidationSupport.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/PrePopulatedValidationSupport.java @@ -1,19 +1,21 @@ package org.hl7.fhir.dstu3.hapi.validation; -import static org.apache.commons.lang3.StringUtils.isNotBlank; +import ca.uhn.fhir.context.FhirContext; +import org.apache.commons.lang3.Validate; +import org.hl7.fhir.dstu3.model.CodeSystem; +import org.hl7.fhir.dstu3.model.MetadataResource; +import org.hl7.fhir.dstu3.model.StructureDefinition; +import org.hl7.fhir.dstu3.model.ValueSet; +import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; +import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; +import org.hl7.fhir.instance.model.api.IBaseResource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang3.Validate; -import org.hl7.fhir.dstu3.model.*; -import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; -import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; -import org.hl7.fhir.instance.model.api.IBaseResource; - -import ca.uhn.fhir.context.FhirContext; +import static org.apache.commons.lang3.StringUtils.isNotBlank; /** * This class is an implementation of {@link IValidationSupport} which may be pre-populated @@ -29,23 +31,20 @@ public class PrePopulatedValidationSupport implements IValidationSupport { * Constructor */ public PrePopulatedValidationSupport() { - myStructureDefinitions = new HashMap(); - myValueSets = new HashMap(); - myCodeSystems = new HashMap(); + myStructureDefinitions = new HashMap<>(); + myValueSets = new HashMap<>(); + myCodeSystems = new HashMap<>(); } /** * Constructor - * - * @param theStructureDefinitions - * The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and - * values are the resource itself. - * @param theValueSets - * The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. - * @param theCodeSystems - * The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. + * + * @param theStructureDefinitions The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and + * values are the resource itself. + * @param theValueSets The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. + * @param theCodeSystems The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. */ public PrePopulatedValidationSupport(Map theStructureDefinitions, Map theValueSets, Map theCodeSystems) { myStructureDefinitions = theStructureDefinitions; @@ -131,6 +130,15 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return new ArrayList(myStructureDefinitions.values()); @@ -171,4 +179,4 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } -} \ No newline at end of file +} diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/ValidationSupportChain.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/ValidationSupportChain.java index d7e0d60f469..e859f81746e 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/ValidationSupportChain.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/validation/ValidationSupportChain.java @@ -1,131 +1,143 @@ package org.hl7.fhir.dstu3.hapi.validation; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +import ca.uhn.fhir.context.FhirContext; import org.hl7.fhir.dstu3.model.CodeSystem; import org.hl7.fhir.dstu3.model.StructureDefinition; import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.instance.model.api.IBaseResource; -import ca.uhn.fhir.context.FhirContext; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.commons.lang3.StringUtils.isBlank; public class ValidationSupportChain implements IValidationSupport { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationSupportChain.class); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationSupportChain.class); - private List myChain; + private List myChain; - /** - * Constructor - */ - public ValidationSupportChain() { - myChain = new ArrayList(); - } + /** + * Constructor + */ + public ValidationSupportChain() { + myChain = new ArrayList(); + } - /** - * Constructor - */ - public ValidationSupportChain(IValidationSupport... theValidationSupportModules) { - this(); - for (IValidationSupport next : theValidationSupportModules) { - if (next != null) { - myChain.add(next); - } - } - } + /** + * Constructor + */ + public ValidationSupportChain(IValidationSupport... theValidationSupportModules) { + this(); + for (IValidationSupport next : theValidationSupportModules) { + if (next != null) { + myChain.add(next); + } + } + } - public void addValidationSupport(IValidationSupport theValidationSupport) { - myChain.add(theValidationSupport); - } + public void addValidationSupport(IValidationSupport theValidationSupport) { + myChain.add(theValidationSupport); + } - @Override - public ValueSetExpansionComponent expandValueSet(FhirContext theCtx, ConceptSetComponent theInclude) { - for (IValidationSupport next : myChain) { - if (next.isCodeSystemSupported(theCtx, theInclude.getSystem())) { - return next.expandValueSet(theCtx, theInclude); - } - } - return myChain.get(0).expandValueSet(theCtx, theInclude); - } + @Override + public ValueSetExpansionComponent expandValueSet(FhirContext theCtx, ConceptSetComponent theInclude) { + for (IValidationSupport next : myChain) { + if (next.isCodeSystemSupported(theCtx, theInclude.getSystem())) { + return next.expandValueSet(theCtx, theInclude); + } + } + return myChain.get(0).expandValueSet(theCtx, theInclude); + } - @Override - public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { - for (IValidationSupport next : myChain) { - CodeSystem retVal = next.fetchCodeSystem(theCtx, theSystem); - if (retVal != null) { - return retVal; - } - } - return null; - } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + List retVal = new ArrayList<>(); + for (IValidationSupport next : myChain) { + List candidates = next.fetchAllConformanceResources(theContext); + if (candidates != null) { + retVal.addAll(candidates); + } + } + return retVal; + } - @Override - public T fetchResource(FhirContext theContext, Class theClass, String theUri) { - for (IValidationSupport next : myChain) { - T retVal = next.fetchResource(theContext, theClass, theUri); - if (retVal != null) { - return retVal; - } - } - return null; - } + @Override + public List fetchAllStructureDefinitions(FhirContext theContext) { + ArrayList retVal = new ArrayList(); + Set urls = new HashSet(); + for (IValidationSupport nextSupport : myChain) { + for (StructureDefinition next : nextSupport.fetchAllStructureDefinitions(theContext)) { + if (isBlank(next.getUrl()) || urls.add(next.getUrl())) { + retVal.add(next); + } + } + } + return retVal; + } - @Override - public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { - for (IValidationSupport next : myChain) { - StructureDefinition retVal = next.fetchStructureDefinition(theCtx, theUrl); - if (retVal != null) { - return retVal; - } - } - return null; - } + @Override + public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { + for (IValidationSupport next : myChain) { + CodeSystem retVal = next.fetchCodeSystem(theCtx, theSystem); + if (retVal != null) { + return retVal; + } + } + return null; + } - @Override - public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) { - for (IValidationSupport next : myChain) { - if (next.isCodeSystemSupported(theCtx, theSystem)) { - return true; - } - } - return false; - } + @Override + public T fetchResource(FhirContext theContext, Class theClass, String theUri) { + for (IValidationSupport next : myChain) { + T retVal = next.fetchResource(theContext, theClass, theUri); + if (retVal != null) { + return retVal; + } + } + return null; + } - @Override - public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) { - - ourLog.info("Validating code {} in chain with {} items", theCode, myChain.size()); - - for (IValidationSupport next : myChain) { - if (next.isCodeSystemSupported(theCtx, theCodeSystem)) { - CodeValidationResult result = next.validateCode(theCtx, theCodeSystem, theCode, theDisplay); - ourLog.info("Chain item {} returned outcome {}", next, result.isOk()); - return result; - } else { - ourLog.info("Chain item {} does not support code system {}", next, theCodeSystem); - } - } - return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay); - } + @Override + public StructureDefinition fetchStructureDefinition(FhirContext theCtx, String theUrl) { + for (IValidationSupport next : myChain) { + StructureDefinition retVal = next.fetchStructureDefinition(theCtx, theUrl); + if (retVal != null) { + return retVal; + } + } + return null; + } + + @Override + public boolean isCodeSystemSupported(FhirContext theCtx, String theSystem) { + for (IValidationSupport next : myChain) { + if (next.isCodeSystemSupported(theCtx, theSystem)) { + return true; + } + } + return false; + } + + @Override + public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) { + + ourLog.info("Validating code {} in chain with {} items", theCode, myChain.size()); + + for (IValidationSupport next : myChain) { + if (next.isCodeSystemSupported(theCtx, theCodeSystem)) { + CodeValidationResult result = next.validateCode(theCtx, theCodeSystem, theCode, theDisplay); + ourLog.info("Chain item {} returned outcome {}", next, result.isOk()); + return result; + } else { + ourLog.info("Chain item {} does not support code system {}", next, theCodeSystem); + } + } + return myChain.get(0).validateCode(theCtx, theCodeSystem, theCode, theDisplay); + } - @Override - public List fetchAllStructureDefinitions(FhirContext theContext) { - ArrayList retVal = new ArrayList(); - Set urls= new HashSet(); - for (IValidationSupport nextSupport : myChain) { - for (StructureDefinition next : nextSupport.fetchAllStructureDefinitions(theContext)) { - if (isBlank(next.getUrl()) || urls.add(next.getUrl())) { - retVal.add(next); - } - } - } - return retVal; - } } diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java index 1961fa84b46..120e25e8567 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/DefaultProfileValidationSupport.java @@ -1,11 +1,6 @@ package org.hl7.fhir.r4.hapi.ctx; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.*; - +import ca.uhn.fhir.context.FhirContext; import org.apache.commons.io.Charsets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; @@ -14,10 +9,16 @@ import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; -import org.hl7.fhir.r4.model.ValueSet.*; +import org.hl7.fhir.r4.model.ValueSet.ConceptReferenceComponent; +import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; +import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; -import ca.uhn.fhir.context.FhirContext; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; public class DefaultProfileValidationSupport implements IValidationSupport { @@ -51,10 +52,20 @@ public class DefaultProfileValidationSupport implements IValidationSupport { } @Override - public List fetchAllStructureDefinitions(FhirContext theContext) { - return new ArrayList(provideStructureDefinitionMap(theContext).values()); + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; } + @Override + public List fetchAllStructureDefinitions(FhirContext theContext) { + return new ArrayList<>(provideStructureDefinitionMap(theContext).values()); + } + + @Override public CodeSystem fetchCodeSystem(FhirContext theContext, String theSystem) { return (CodeSystem) fetchCodeSystemOrValueSet(theContext, theSystem, true); @@ -65,8 +76,8 @@ public class DefaultProfileValidationSupport implements IValidationSupport { Map codeSystems = myCodeSystems; Map valueSets = myValueSets; if (codeSystems == null || valueSets == null) { - codeSystems = new HashMap(); - valueSets = new HashMap(); + codeSystems = new HashMap<>(); + valueSets = new HashMap<>(); loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/r4/model/valueset/valuesets.xml"); loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/r4/model/valueset/v2-tables.xml"); @@ -92,7 +103,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (theClass.equals(StructureDefinition.class)) { return (T) fetchStructureDefinition(theContext, theUri); } - + if (theClass.equals(ValueSet.class) || theUri.startsWith(URL_PREFIX_VALUE_SET)) { return (T) fetchValueSet(theContext, theUri); } @@ -193,25 +204,6 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return structureDefinitions; } - @Override - public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { - CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); - if (cs != null) { - boolean caseSensitive = true; - if (cs.hasCaseSensitive()) { - caseSensitive = cs.getCaseSensitive(); - } - - CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); - - if (retVal != null) { - return retVal; - } - } - - return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); - } - private CodeValidationResult testIfConceptIsInList(String theCode, List conceptList, boolean theCaseSensitive) { String code = theCode; if (theCaseSensitive == false) { @@ -243,4 +235,23 @@ public class DefaultProfileValidationSupport implements IValidationSupport { return retVal; } + @Override + public CodeValidationResult validateCode(FhirContext theContext, String theCodeSystem, String theCode, String theDisplay) { + CodeSystem cs = fetchCodeSystem(theContext, theCodeSystem); + if (cs != null) { + boolean caseSensitive = true; + if (cs.hasCaseSensitive()) { + caseSensitive = cs.getCaseSensitive(); + } + + CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); + + if (retVal != null) { + return retVal; + } + } + + return new CodeValidationResult(IssueSeverity.WARNING, "Unknown code: " + theCodeSystem + " / " + theCode); + } + } diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/PrePopulatedValidationSupport.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/PrePopulatedValidationSupport.java index 7545997ff31..92807c4f6c3 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/PrePopulatedValidationSupport.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/PrePopulatedValidationSupport.java @@ -1,16 +1,21 @@ package org.hl7.fhir.r4.hapi.ctx; -import static org.apache.commons.lang3.StringUtils.isNotBlank; - -import java.util.*; - +import ca.uhn.fhir.context.FhirContext; import org.apache.commons.lang3.Validate; import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.r4.model.*; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.MetadataResource; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent; -import ca.uhn.fhir.context.FhirContext; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; /** * This class is an implementation of {@link IValidationSupport} which may be pre-populated @@ -26,23 +31,21 @@ public class PrePopulatedValidationSupport implements IValidationSupport { * Constructor */ public PrePopulatedValidationSupport() { - myStructureDefinitions = new HashMap(); - myValueSets = new HashMap(); - myCodeSystems = new HashMap(); + myStructureDefinitions = new HashMap<>(); + myValueSets = new HashMap<>(); + myCodeSystems = new HashMap<>(); } + /** * Constructor - * - * @param theStructureDefinitions - * The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and - * values are the resource itself. - * @param theValueSets - * The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. - * @param theCodeSystems - * The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are - * the resource itself. + * + * @param theStructureDefinitions The StructureDefinitions to be returned by this module. Keys are the logical URL for the resource, and + * values are the resource itself. + * @param theValueSets The ValueSets to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. + * @param theCodeSystems The CodeSystems to be returned by this module. Keys are the logical URL for the resource, and values are + * the resource itself. */ public PrePopulatedValidationSupport(Map theStructureDefinitions, Map theValueSets, Map theCodeSystems) { myStructureDefinitions = theStructureDefinitions; @@ -128,6 +131,15 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + ArrayList retVal = new ArrayList<>(); + retVal.addAll(myCodeSystems.values()); + retVal.addAll(myStructureDefinitions.values()); + retVal.addAll(myValueSets.values()); + return retVal; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { return new ArrayList(myStructureDefinitions.values()); @@ -168,4 +180,4 @@ public class PrePopulatedValidationSupport implements IValidationSupport { return null; } -} \ No newline at end of file +} diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/ValidationSupportChain.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/ValidationSupportChain.java index 64d29bf119f..0ab5873784d 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/ValidationSupportChain.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/hapi/ctx/ValidationSupportChain.java @@ -1,16 +1,18 @@ package org.hl7.fhir.r4.hapi.ctx; -import static org.apache.commons.lang3.StringUtils.isBlank; - -import java.util.*; - +import ca.uhn.fhir.context.FhirContext; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.CodeSystem; import org.hl7.fhir.r4.model.StructureDefinition; import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent; -import ca.uhn.fhir.context.FhirContext; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.commons.lang3.StringUtils.isBlank; public class ValidationSupportChain implements IValidationSupport { @@ -51,7 +53,19 @@ public class ValidationSupportChain implements IValidationSupport { return myChain.get(0).expandValueSet(theCtx, theInclude); } - @Override + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + List retVal = new ArrayList<>(); + for (IValidationSupport next : myChain) { + List candidates = next.fetchAllConformanceResources(theContext); + if (candidates != null) { + retVal.addAll(candidates); + } + } + return retVal; + } + + @Override public CodeSystem fetchCodeSystem(FhirContext theCtx, String theSystem) { for (IValidationSupport next : myChain) { CodeSystem retVal = next.fetchCodeSystem(theCtx, theSystem); diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/LoggingInterceptorTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/LoggingInterceptorTest.java index d6bfee274a6..6e7f3c6d413 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/LoggingInterceptorTest.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/client/LoggingInterceptorTest.java @@ -85,7 +85,7 @@ public class LoggingInterceptorTest { System.out.flush(); return formattedMessage.contains("Client request: GET http://localhost:" + ourPort + "/Patient/1 HTTP/1.1") || - formattedMessage.contains("Client response: HTTP 200 OK (Location: http://localhost:" + ourPort + "/Patient/1/_history/1)"); + formattedMessage.contains("Client response: HTTP 200 OK (Patient/1/_history/1)"); } })); } diff --git a/pom.xml b/pom.xml index 8eedd207397..a859dfaafab 100644 --- a/pom.xml +++ b/pom.xml @@ -1828,6 +1828,7 @@ example-projects/hapi-fhir-base-example-embedded-ws example-projects/hapi-fhir-standalone-overlay-example hapi-fhir-jacoco + hapi-fhir-igpacks @@ -1875,6 +1876,4 @@ - - From 736e037b1a98ca23ffccdf3c563b85a6516473d4 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Sat, 9 Sep 2017 09:53:51 -0700 Subject: [PATCH 2/2] Ongoing work on subscriptions --- .../main/java/example/ValidatorExamples.java | 6 + .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 13 +- .../jpa/dao/dstu3/FhirSystemDaoDstu3.java | 1 + .../uhn/fhir/jpa/dao/r4/FhirSystemDaoR4.java | 1 + .../BaseSubscriptionInterceptor.java | 106 ++++--- ...scriptionDeliveringRestHookSubscriber.java | 79 ++--- .../fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java | 3 + ...ResourceDaoDstu3UniqueSearchParamTest.java | 182 ++++++++++- .../ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java | 3 + ...irResourceDaoCreatePlaceholdersR4Test.java | 39 ++- ...hirResourceDaoR4UniqueSearchParamTest.java | 290 ++++++++++++++++++ .../subscription/RestHookTestDstu2Test.java | 6 +- ...nterceptorRegisteredToDaoConfigR4Test.java | 6 +- 13 files changed, 635 insertions(+), 100 deletions(-) diff --git a/examples/src/main/java/example/ValidatorExamples.java b/examples/src/main/java/example/ValidatorExamples.java index e171d6f2774..e6d721c124c 100644 --- a/examples/src/main/java/example/ValidatorExamples.java +++ b/examples/src/main/java/example/ValidatorExamples.java @@ -214,6 +214,12 @@ public class ValidatorExamples { return null; } + @Override + public List fetchAllConformanceResources(FhirContext theContext) { + // TODO: implement + return null; + } + @Override public List fetchAllStructureDefinitions(FhirContext theContext) { // TODO: implement diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index a31753e9529..e7b22e678e7 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -165,11 +165,6 @@ public abstract class BaseHapiFhirDao implements IDao { @Autowired private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao; - private void autoCreateResource(T theResource) { - IFhirResourceDao dao = (IFhirResourceDao) getDao(theResource.getClass()); - dao.create(theResource); - } - protected void clearRequestAsProcessingSubRequest(ServletRequestDetails theRequestDetails) { if (theRequestDetails != null) { theRequestDetails.getUserData().remove(PROCESSING_SUB_REQUEST); @@ -423,10 +418,12 @@ public abstract class BaseHapiFhirDao implements IDao { if (getConfig().isAutoCreatePlaceholderReferenceTargets()) { IBaseResource newResource = missingResourceDef.newInstance(); newResource.setId(resName + "/" + id); - autoCreateResource(newResource); + IFhirResourceDao placeholderResourceDao = (IFhirResourceDao) getDao(newResource.getClass()); + ourLog.info("Automatically creating empty placeholder resource: {}", newResource.getIdElement().getValue()); + valueOf = placeholderResourceDao.update(newResource).getEntity().getId(); + } else { + throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); } - - throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPathsUnsplit); } ResourceTable target = myEntityManager.find(ResourceTable.class, valueOf); RuntimeResourceDefinition targetResourceDef = getContext().getResourceDefinition(type); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java index 033d7d85a8c..767bb9fa0ac 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3.java @@ -662,6 +662,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao { String nextReplacementIdPart = nextReplacementId.getValueAsString(); if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) { matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart); + matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart); } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4.java index 396675b1e5b..05918c2e8f2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/r4/FhirSystemDaoR4.java @@ -662,6 +662,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao { String nextReplacementIdPart = nextReplacementId.getValueAsString(); if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) { matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart); + matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart); } } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java index c6171e21a29..59a5bf08189 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionInterceptor.java @@ -46,10 +46,7 @@ import org.springframework.transaction.support.TransactionSynchronizationManager import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.*; public abstract class BaseSubscriptionInterceptor extends ServerOperationInterceptorAdapter { @@ -63,13 +60,15 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce private static final Integer MAX_SUBSCRIPTION_RESULTS = 1000; private SubscribableChannel myProcessingChannel; private SubscribableChannel myDeliveryChannel; - private ExecutorService myExecutor; + private ExecutorService myProcessingExecutor; private int myExecutorThreadCount; private SubscriptionActivatingSubscriber mySubscriptionActivatingSubscriber; private MessageHandler mySubscriptionCheckingSubscriber; private ConcurrentHashMap myIdToSubscription = new ConcurrentHashMap<>(); private Logger ourLog = LoggerFactory.getLogger(BaseSubscriptionInterceptor.class); - private BlockingQueue myExecutorQueue; + private ThreadPoolExecutor myDeliveryExecutor; + private LinkedBlockingQueue myProcessingExecutorQueue; + private LinkedBlockingQueue myDeliveryExecutorQueue; /** * Constructor @@ -89,8 +88,8 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce myDeliveryChannel = theDeliveryChannel; } - public BlockingQueue getExecutorQueueForUnitTests() { - return myExecutorQueue; + public int getExecutorQueueSizeForUnitTests() { + return myProcessingExecutorQueue.size() + myDeliveryExecutorQueue.size(); } public int getExecutorThreadCount() { @@ -157,42 +156,73 @@ public abstract class BaseSubscriptionInterceptor extends ServerOperationInterce @PostConstruct public void postConstruct() { - myExecutorQueue = new LinkedBlockingQueue<>(1000); + { + myProcessingExecutorQueue = new LinkedBlockingQueue<>(1000); - RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() { - @Override - public void rejectedExecution(Runnable theRunnable, ThreadPoolExecutor theExecutor) { - ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", myExecutorQueue.size()); - StopWatch sw = new StopWatch(); - try { - myExecutorQueue.put(theRunnable); - } catch (InterruptedException theE) { - throw new RejectedExecutionException("Task " + theRunnable.toString() + - " rejected from " + theE.toString()); + RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable theRunnable, ThreadPoolExecutor theExecutor) { + ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", myProcessingExecutorQueue.size()); + StopWatch sw = new StopWatch(); + try { + myProcessingExecutorQueue.put(theRunnable); + } catch (InterruptedException theE) { + throw new RejectedExecutionException("Task " + theRunnable.toString() + + " rejected from " + theE.toString()); + } + ourLog.info("Slot become available after {}ms", sw.getMillis()); } - ourLog.info("Slot become available after {}ms", sw.getMillis()); - } - }; - ThreadFactory threadFactory = new BasicThreadFactory.Builder() - .namingPattern("subscription-%d") - .daemon(false) - .priority(Thread.NORM_PRIORITY) - .build(); - myExecutor = new ThreadPoolExecutor( - 1, - getExecutorThreadCount(), - 0L, - TimeUnit.MILLISECONDS, - myExecutorQueue, - threadFactory, - rejectedExecutionHandler); - + }; + ThreadFactory threadFactory = new BasicThreadFactory.Builder() + .namingPattern("subscription-proc-%d") + .daemon(false) + .priority(Thread.NORM_PRIORITY) + .build(); + myProcessingExecutor = new ThreadPoolExecutor( + 1, + getExecutorThreadCount(), + 0L, + TimeUnit.MILLISECONDS, + myProcessingExecutorQueue, + threadFactory, + rejectedExecutionHandler); + } + { + myDeliveryExecutorQueue = new LinkedBlockingQueue<>(1000); + BasicThreadFactory threadFactory = new BasicThreadFactory.Builder() + .namingPattern("subscription-delivery-%d") + .daemon(false) + .priority(Thread.NORM_PRIORITY) + .build(); + RejectedExecutionHandler rejectedExecutionHandler2 = new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable theRunnable, ThreadPoolExecutor theExecutor) { + ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", myDeliveryExecutorQueue.size()); + StopWatch sw = new StopWatch(); + try { + myDeliveryExecutorQueue.put(theRunnable); + } catch (InterruptedException theE) { + throw new RejectedExecutionException("Task " + theRunnable.toString() + + " rejected from " + theE.toString()); + } + ourLog.info("Slot become available after {}ms", sw.getMillis()); + } + }; + myDeliveryExecutor = new ThreadPoolExecutor( + 1, + getExecutorThreadCount(), + 0L, + TimeUnit.MILLISECONDS, + myDeliveryExecutorQueue, + threadFactory, + rejectedExecutionHandler2); + } if (getProcessingChannel() == null) { - setProcessingChannel(new ExecutorSubscribableChannel(myExecutor)); + setProcessingChannel(new ExecutorSubscribableChannel(myProcessingExecutor)); } if (getDeliveryChannel() == null) { - setDeliveryChannel(new ExecutorSubscribableChannel(myExecutor)); + setDeliveryChannel(new ExecutorSubscribableChannel(myDeliveryExecutor)); } if (mySubscriptionActivatingSubscriber == null) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringRestHookSubscriber.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringRestHookSubscriber.java index e90d11cb5e1..74eb06262ff 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringRestHookSubscriber.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionDeliveringRestHookSubscriber.java @@ -21,12 +21,14 @@ package ca.uhn.fhir.jpa.subscription; */ import ca.uhn.fhir.jpa.dao.IFhirResourceDao; +import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor; import ca.uhn.fhir.rest.gclient.IClientExecutable; import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.r4.model.Subscription; @@ -78,44 +80,51 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionSu if (!(theMessage.getPayload() instanceof ResourceDeliveryMessage)) { return; } + try { + ResourceDeliveryMessage msg = (ResourceDeliveryMessage) theMessage.getPayload(); - ResourceDeliveryMessage msg = (ResourceDeliveryMessage) theMessage.getPayload(); - - if (!subscriptionTypeApplies(getContext(), msg.getSubscription())) { - return; - } - - IBaseResource subscription = msg.getSubscription(); - - - // Grab the endpoint from the subscription - IPrimitiveType endpoint = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_ENDPOINT, IPrimitiveType.class); - String endpointUrl = endpoint.getValueAsString(); - - // Grab the payload type (encoding mimetype) from the subscription - IPrimitiveType payload = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_PAYLOAD, IPrimitiveType.class); - String payloadString = payload.getValueAsString(); - if (payloadString.contains(";")) { - payloadString = payloadString.substring(0, payloadString.indexOf(';')); - } - payloadString = payloadString.trim(); - EncodingEnum payloadType = EncodingEnum.forContentType(payloadString); - payloadType = ObjectUtils.defaultIfNull(payloadType, EncodingEnum.XML); - - // Create the client request - getContext().getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); - IGenericClient client = getContext().newRestfulGenericClient(endpointUrl); - - // Additional headers specified in the subscription - List headers = getContext().newTerser().getValues(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_HEADER, IPrimitiveType.class); - for (IPrimitiveType next : headers) { - if (isNotBlank(next.getValueAsString())) { - client.registerInterceptor(new SimpleRequestHeaderInterceptor(next.getValueAsString())); + if (!subscriptionTypeApplies(getContext(), msg.getSubscription())) { + return; } + + IBaseResource subscription = msg.getSubscription(); + + + // Grab the endpoint from the subscription + IPrimitiveType endpoint = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_ENDPOINT, IPrimitiveType.class); + String endpointUrl = endpoint != null ? endpoint.getValueAsString() : null; + + // Grab the payload type (encoding mimetype) from the subscription + IPrimitiveType payload = getContext().newTerser().getSingleValueOrNull(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_PAYLOAD, IPrimitiveType.class); + String payloadString = payload != null ? payload.getValueAsString() : null; + payloadString = StringUtils.defaultString(payloadString, Constants.CT_FHIR_XML_NEW); + if (payloadString.contains(";")) { + payloadString = payloadString.substring(0, payloadString.indexOf(';')); + } + payloadString = payloadString.trim(); + EncodingEnum payloadType = EncodingEnum.forContentType(payloadString); + payloadType = ObjectUtils.defaultIfNull(payloadType, EncodingEnum.XML); + + // Create the client request + getContext().getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); + IGenericClient client = null; + if (isNotBlank(endpointUrl)) { + client = getContext().newRestfulGenericClient(endpointUrl); + + // Additional headers specified in the subscription + List headers = getContext().newTerser().getValues(subscription, BaseSubscriptionInterceptor.SUBSCRIPTION_HEADER, IPrimitiveType.class); + for (IPrimitiveType next : headers) { + if (isNotBlank(next.getValueAsString())) { + client.registerInterceptor(new SimpleRequestHeaderInterceptor(next.getValueAsString())); + } + } + } + + deliverPayload(msg, subscription, payloadType, client); + } catch (Exception e) { + ourLog.error("Failure handling subscription payload", e); + throw new MessagingException(theMessage, "Failure handling subscription payload", e); } - - deliverPayload(msg, subscription, payloadType, client); - } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java index ec4388df2a2..27457016c2f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java @@ -57,6 +57,9 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest { private static JpaValidationSupportChainDstu3 ourJpaValidationSupportChainDstu3; private static IFhirResourceDaoValueSet ourValueSetDao; + @Autowired + @Qualifier("myCoverageDaoDstu3") + protected IFhirResourceDao myCoverageDao; @Autowired protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao; @Autowired diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java index 7845f330ae3..fa685325792 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java @@ -9,6 +9,7 @@ import ca.uhn.fhir.jpa.util.JpaConstants; import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.TokenParam; +import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.util.TestUtil; import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus; @@ -36,6 +37,185 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test myDaoConfig.setDefaultSearchParamsCanBeOverridden(new DaoConfig().isDefaultSearchParamsCanBeOverridden()); } + + + @Test + public void testIndexTransactionWithMatchUrl() { + Patient pt2 = new Patient(); + pt2.setGender(Enumerations.AdministrativeGender.MALE); + pt2.setBirthDateElement(new DateType("2011-01-02")); + IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless(); + + Coverage cov = new Coverage(); + cov.getBeneficiary().setReference(id2.getValue()); + cov.addIdentifier().setSystem("urn:foo:bar").setValue("123"); + IIdType id3 = myCoverageDao.create(cov).getId().toUnqualifiedVersionless(); + + createUniqueIndexCoverageBeneficiary(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + + List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Coverage/" + id3.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Coverage?beneficiary=Patient%2F" + id2.getIdPart() + "&identifier=urn%3Afoo%3Abar%7C123", uniques.get(0).getIndexString()); + + + } + + + @Test + public void testIndexTransactionWithMatchUrl2() { + createUniqueIndexCoverageBeneficiary(); + + String input = "{\n" + + " \"resourceType\": \"Bundle\",\n" + + " \"type\": \"transaction\",\n" + + " \"entry\": [\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Patient\",\n" + + " \"identifier\": [\n" + + " {\n" + + " \"use\": \"official\",\n" + + " \"type\": {\n" + + " \"coding\": [\n" + + " {\n" + + " \"system\": \"http://hl7.org/fhir/v2/0203\",\n" + + " \"code\": \"MR\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"system\": \"FOOORG:FOOSITE:patientid:MR:R\",\n" + + " \"value\": \"007811959\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Patient?identifier=FOOORG%3AFOOSITE%3Apatientid%3AMR%3AR%7C007811959%2CFOOORG%3AFOOSITE%3Apatientid%3AMR%3AB%7C000929990%2CFOOORG%3AFOOSITE%3Apatientid%3API%3APH%7C00589363%2Chttp%3A%2F%2Fhl7.org%2Ffhir%2Fsid%2Fus-ssn%7C657-01-8133\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:b58ff639-11d1-4dac-942f-abf4f9a625d7\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Coverage\",\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"FOOORG:FOOSITE:coverage:planId\",\n" + + " \"value\": \"0403-010101\"\n" + + " }\n" + + " ],\n" + + " \"beneficiary\": {\n" + + " \"reference\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\"\n" + + " }\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Coverage?beneficiary=urn%3Auuid%3Ad2a46176-8e15-405d-bbda-baea1a9dc7f3&identifier=FOOORG%3AFOOSITE%3Acoverage%3AplanId%7C0403-010101\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:13f5da1a-6601-4c1a-82c9-41527be23fa0\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Coverage\",\n" + + " \"contained\": [\n" + + " {\n" + + " \"resourceType\": \"RelatedPerson\",\n" + + " \"id\": \"1\",\n" + + " \"name\": [\n" + + " {\n" + + " \"family\": \"SMITH\",\n" + + " \"given\": [\n" + + " \"FAKER\"\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"resourceType\": \"Organization\",\n" + + " \"id\": \"2\",\n" + + " \"name\": \"MEDICAID\"\n" + + " }\n" + + " ],\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"FOOORG:FOOSITE:coverage:planId\",\n" + + " \"value\": \"0404-010101\"\n" + + " }\n" + + " ],\n" + + " \"policyHolder\": {\n" + + " \"reference\": \"#1\"\n" + + " },\n" + + " \"beneficiary\": {\n" + + " \"reference\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\"\n" + + " },\n" + + " \"payor\": [\n" + + " {\n" + + " \"reference\": \"#2\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Coverage?beneficiary=urn%3Auuid%3Ad2a46176-8e15-405d-bbda-baea1a9dc7f3&identifier=FOOORG%3AFOOSITE%3Acoverage%3AplanId%7C0404-010101\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + Bundle inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, input); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inputBundle)); + mySystemDao.transaction(mySrd, inputBundle); + + inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, input); + mySystemDao.transaction(mySrd, inputBundle); + + } + + + private void createUniqueIndexCoverageBeneficiary() { + SearchParameter sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-beneficiary"); + sp.setCode("beneficiary"); + sp.setExpression("Coverage.beneficiary"); + sp.setType(Enumerations.SearchParamType.REFERENCE); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-identifier"); + sp.setCode("identifier"); + sp.setExpression("Coverage.identifier"); + sp.setType(Enumerations.SearchParamType.TOKEN); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-beneficiary-identifier"); + sp.setCode("coverage-beneficiary-identifier"); + sp.setExpression("Coverage.beneficiary"); + sp.setType(Enumerations.SearchParamType.COMPOSITE); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + sp.addComponent() + .setExpression("Coverage") + .setDefinition(new Reference("/SearchParameter/coverage-beneficiary")); + sp.addComponent() + .setExpression("Coverage") + .setDefinition(new Reference("/SearchParameter/coverage-identifier")); + sp.addExtension() + .setUrl(JpaConstants.EXT_SP_UNIQUE) + .setValue(new BooleanType(true)); + mySearchParameterDao.update(sp); + mySearchParamRegsitry.forceRefresh(); + } + + @Before public void before() { myDaoConfig.setDefaultSearchParamsCanBeOverridden(true); @@ -143,7 +323,7 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test try { myPatientDao.create(pt1).getId().toUnqualifiedVersionless(); fail(); - } catch (JpaSystemException e) { + } catch (PreconditionFailedException e) { // good } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java index 3891ab361ef..56f2307a016 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java @@ -146,6 +146,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest { @Qualifier("myPatientDaoR4") protected IFhirResourceDaoPatient myPatientDao; @Autowired + @Qualifier("myCoverageDaoR4") + protected IFhirResourceDao myCoverageDao; + @Autowired @Qualifier("myPractitionerDaoR4") protected IFhirResourceDao myPractitionerDao; @Autowired diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCreatePlaceholdersR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCreatePlaceholdersR4Test.java index 71aa00512fe..b74c2aadebb 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCreatePlaceholdersR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoCreatePlaceholdersR4Test.java @@ -83,12 +83,32 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test { Observation o = new Observation(); o.setStatus(ObservationStatus.FINAL); o.getSubject().setReference("Patient/FOO"); - try { - myObservationDao.create(o, mySrd); - fail(); - } catch (InvalidRequestException e) { - assertEquals("Resource Patient/FOO not found, specified in path: Observation.subject", e.getMessage()); - } + myObservationDao.create(o, mySrd); + } + + @Test + public void testCreateWithMultiplePlaceholders() { + myDaoConfig.setAutoCreatePlaceholderReferenceTargets(true); + + Task task = new Task(); + task.addNote().setText("A note"); + task.addPartOf().setReference("Task/AAA"); + task.addPartOf().setReference("Task/AAA"); + task.addPartOf().setReference("Task/AAA"); + IIdType id = myTaskDao.create(task).getId().toUnqualifiedVersionless(); + + task = myTaskDao.read(id); + assertEquals(3, task.getPartOf().size()); + assertEquals("Task/AAA", task.getPartOf().get(0).getReference()); + assertEquals("Task/AAA", task.getPartOf().get(1).getReference()); + assertEquals("Task/AAA", task.getPartOf().get(2).getReference()); + + SearchParameterMap params = new SearchParameterMap(); + params.add(Task.SP_PART_OF, new ReferenceParam("Task/AAA")); + List found = toUnqualifiedVersionlessIdValues(myTaskDao.search(params)); + assertThat(found, contains(id.getValue())); + + } @Test @@ -123,12 +143,7 @@ public class FhirResourceDaoCreatePlaceholdersR4Test extends BaseJpaR4Test { o.setId(id); o.setStatus(ObservationStatus.FINAL); o.getSubject().setReference("Patient/FOO"); - try { - myObservationDao.update(o, mySrd); - fail(); - } catch (InvalidRequestException e) { - assertEquals("Resource Patient/FOO not found, specified in path: Observation.subject", e.getMessage()); - } + myObservationDao.update(o, mySrd); } @AfterClass diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java index 0e3af0f029f..2eac41113c5 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java @@ -22,6 +22,7 @@ import org.springframework.orm.jpa.JpaSystemException; import java.util.Collections; import java.util.List; +import java.util.UUID; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; @@ -346,6 +347,182 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { } + + private void createUniqueIndexCoverageBeneficiary() { + SearchParameter sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-beneficiary"); + sp.setCode("beneficiary"); + sp.setExpression("Coverage.beneficiary"); + sp.setType(Enumerations.SearchParamType.REFERENCE); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-identifier"); + sp.setCode("identifier"); + sp.setExpression("Coverage.identifier"); + sp.setType(Enumerations.SearchParamType.TOKEN); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + mySearchParameterDao.update(sp); + + sp = new SearchParameter(); + sp.setId("SearchParameter/coverage-beneficiary-identifier"); + sp.setCode("coverage-beneficiary-identifier"); + sp.setExpression("Coverage.beneficiary"); + sp.setType(Enumerations.SearchParamType.COMPOSITE); + sp.setStatus(PublicationStatus.ACTIVE); + sp.addBase("Coverage"); + sp.addComponent() + .setExpression("Coverage") + .setDefinition(new Reference("/SearchParameter/coverage-beneficiary")); + sp.addComponent() + .setExpression("Coverage") + .setDefinition(new Reference("/SearchParameter/coverage-identifier")); + sp.addExtension() + .setUrl(JpaConstants.EXT_SP_UNIQUE) + .setValue(new BooleanType(true)); + mySearchParameterDao.update(sp); + mySearchParamRegsitry.forceRefresh(); + } + + @Test + public void testIndexTransactionWithMatchUrl() { + Patient pt2 = new Patient(); + pt2.setGender(Enumerations.AdministrativeGender.MALE); + pt2.setBirthDateElement(new DateType("2011-01-02")); + IIdType id2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless(); + + Coverage cov = new Coverage(); + cov.getBeneficiary().setReference(id2.getValue()); + cov.addIdentifier().setSystem("urn:foo:bar").setValue("123"); + IIdType id3 = myCoverageDao.create(cov).getId().toUnqualifiedVersionless(); + + createUniqueIndexCoverageBeneficiary(); + + mySystemDao.markAllResourcesForReindexing(); + mySystemDao.performReindexingPass(1000); + + List uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(uniques.toString(), 1, uniques.size()); + assertEquals("Coverage/" + id3.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Coverage?beneficiary=Patient%2F" + id2.getIdPart() + "&identifier=urn%3Afoo%3Abar%7C123", uniques.get(0).getIndexString()); + + + } + + @Test + public void testIndexTransactionWithMatchUrl2() { + createUniqueIndexCoverageBeneficiary(); + + String input = "{\n" + + " \"resourceType\": \"Bundle\",\n" + + " \"type\": \"transaction\",\n" + + " \"entry\": [\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Patient\",\n" + + " \"identifier\": [\n" + + " {\n" + + " \"use\": \"official\",\n" + + " \"type\": {\n" + + " \"coding\": [\n" + + " {\n" + + " \"system\": \"http://hl7.org/fhir/v2/0203\",\n" + + " \"code\": \"MR\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"system\": \"FOOORG:FOOSITE:patientid:MR:R\",\n" + + " \"value\": \"007811959\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Patient?identifier=FOOORG%3AFOOSITE%3Apatientid%3AMR%3AR%7C007811959%2CFOOORG%3AFOOSITE%3Apatientid%3AMR%3AB%7C000929990%2CFOOORG%3AFOOSITE%3Apatientid%3API%3APH%7C00589363%2Chttp%3A%2F%2Fhl7.org%2Ffhir%2Fsid%2Fus-ssn%7C657-01-8133\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:b58ff639-11d1-4dac-942f-abf4f9a625d7\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Coverage\",\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"FOOORG:FOOSITE:coverage:planId\",\n" + + " \"value\": \"0403-010101\"\n" + + " }\n" + + " ],\n" + + " \"beneficiary\": {\n" + + " \"reference\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\"\n" + + " }\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Coverage?beneficiary=urn%3Auuid%3Ad2a46176-8e15-405d-bbda-baea1a9dc7f3&identifier=FOOORG%3AFOOSITE%3Acoverage%3AplanId%7C0403-010101\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"fullUrl\": \"urn:uuid:13f5da1a-6601-4c1a-82c9-41527be23fa0\",\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Coverage\",\n" + + " \"contained\": [\n" + + " {\n" + + " \"resourceType\": \"RelatedPerson\",\n" + + " \"id\": \"1\",\n" + + " \"name\": [\n" + + " {\n" + + " \"family\": \"SMITH\",\n" + + " \"given\": [\n" + + " \"FAKER\"\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"resourceType\": \"Organization\",\n" + + " \"id\": \"2\",\n" + + " \"name\": \"MEDICAID\"\n" + + " }\n" + + " ],\n" + + " \"identifier\": [\n" + + " {\n" + + " \"system\": \"FOOORG:FOOSITE:coverage:planId\",\n" + + " \"value\": \"0404-010101\"\n" + + " }\n" + + " ],\n" + + " \"policyHolder\": {\n" + + " \"reference\": \"#1\"\n" + + " },\n" + + " \"beneficiary\": {\n" + + " \"reference\": \"urn:uuid:d2a46176-8e15-405d-bbda-baea1a9dc7f3\"\n" + + " },\n" + + " \"payor\": [\n" + + " {\n" + + " \"reference\": \"#2\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"request\": {\n" + + " \"method\": \"PUT\",\n" + + " \"url\": \"/Coverage?beneficiary=urn%3Auuid%3Ad2a46176-8e15-405d-bbda-baea1a9dc7f3&identifier=FOOORG%3AFOOSITE%3Acoverage%3AplanId%7C0404-010101\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + Bundle inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, input); + ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(inputBundle)); + mySystemDao.transaction(mySrd, inputBundle); + + inputBundle = myFhirCtx.newJsonParser().parseResource(Bundle.class, input); + mySystemDao.transaction(mySrd, inputBundle); + + } + + @Test public void testUniqueValuesAreIndexed_DateAndToken() { createUniqueBirthdateAndGenderSps(); @@ -423,6 +600,119 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test { assertEquals("Patient?name=GIVEN2&organization=Organization%2FORG", uniques.get(2).getIndexString()); } + @Test + public void testUniqueValuesAreIndexed_StringAndReference_UsingConditional() { + createUniqueNameAndManagingOrganizationSps(); + List uniques; + + Organization org = new Organization(); + org.setId("Organization/ORG"); + org.setName("ORG"); + myOrganizationDao.update(org); + + Patient pt1 = new Patient(); + pt1.addName().setFamily("FAMILY1"); + pt1.setManagingOrganization(new Reference("Organization/ORG")); + IIdType id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization.name=ORG").getId().toUnqualifiedVersionless(); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(1, uniques.size()); + assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Patient?name=FAMILY1&organization=Organization%2FORG", uniques.get(0).getIndexString()); + + // Again + + pt1 = new Patient(); + pt1.addName().setFamily("FAMILY1"); + pt1.setManagingOrganization(new Reference("Organization/ORG")); + id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization.name=ORG").getId().toUnqualifiedVersionless(); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(1, uniques.size()); + assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Patient?name=FAMILY1&organization=Organization%2FORG", uniques.get(0).getIndexString()); + } + + @Test + public void testUniqueValuesAreIndexed_StringAndReference_UsingConditionalInTransaction() { + createUniqueNameAndManagingOrganizationSps(); + List uniques; + + Organization org = new Organization(); + org.setId("Organization/ORG"); + org.setName("ORG"); + myOrganizationDao.update(org); + + Bundle bundle = new Bundle(); + bundle.setType(Bundle.BundleType.TRANSACTION); + + String orgId = "urn:uuid:" + UUID.randomUUID().toString(); + org = new Organization(); + org.setName("ORG"); + bundle + .addEntry() + .setResource(org) + .setFullUrl(orgId) + .getRequest() + .setMethod(Bundle.HTTPVerb.PUT) + .setUrl("/Organization?name=ORG"); + + Patient pt1 = new Patient(); + pt1.addName().setFamily("FAMILY1"); + pt1.setManagingOrganization(new Reference(orgId)); + bundle + .addEntry() + .setResource(pt1) + .getRequest() + .setMethod(Bundle.HTTPVerb.PUT) + .setUrl("/Patient?name=FAMILY1&organization=" + orgId.replace(":", "%3A")); + + Bundle resp = mySystemDao.transaction(mySrd, bundle); + + IIdType id1 = new IdType(resp.getEntry().get(1).getResponse().getLocation()); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(1, uniques.size()); + assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Patient?name=FAMILY1&organization=Organization%2FORG", uniques.get(0).getIndexString()); + + // Again + + bundle = new Bundle(); + bundle.setType(Bundle.BundleType.TRANSACTION); + + orgId = IdType.newRandomUuid().getValue(); + org = new Organization(); + org.setName("ORG"); + bundle + .addEntry() + .setResource(org) + .setFullUrl(orgId) + .getRequest() + .setMethod(Bundle.HTTPVerb.PUT) + .setUrl("/Organization?name=ORG"); + + pt1 = new Patient(); + pt1.addName().setFamily("FAMILY1"); + pt1.setManagingOrganization(new Reference(orgId)); + bundle + .addEntry() + .setResource(pt1) + .getRequest() + .setMethod(Bundle.HTTPVerb.PUT) + .setUrl("/Patient?name=FAMILY1&organization=" + orgId); + + resp = mySystemDao.transaction(mySrd, bundle); + + id1 = new IdType(resp.getEntry().get(1).getResponse().getLocation()); + + uniques = myResourceIndexedCompositeStringUniqueDao.findAll(); + assertEquals(1, uniques.size()); + assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue()); + assertEquals("Patient?name=FAMILY1&organization=Organization%2FORG", uniques.get(0).getIndexString()); + + } + @Test public void testUniqueValuesAreNotIndexedIfNotAllParamsAreFound_DateAndToken() { createUniqueBirthdateAndGenderSps(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java index 0ebff63348e..f4cf91d0867 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestDstu2Test.java @@ -281,11 +281,11 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test { } public static void waitForQueueToDrain(BaseSubscriptionInterceptor theRestHookSubscriptionInterceptor) throws InterruptedException { - ourLog.info("QUEUE HAS {} ITEMS", theRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); - while (theRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size() > 0) { + ourLog.info("QUEUE HAS {} ITEMS", theRestHookSubscriptionInterceptor.getExecutorQueueSizeForUnitTests()); + while (theRestHookSubscriptionInterceptor.getExecutorQueueSizeForUnitTests() > 0) { Thread.sleep(50); } - ourLog.info("QUEUE HAS {} ITEMS", theRestHookSubscriptionInterceptor.getExecutorQueueForUnitTests().size()); + ourLog.info("QUEUE HAS {} ITEMS", theRestHookSubscriptionInterceptor.getExecutorQueueSizeForUnitTests()); } private void waitForQueueToDrain() throws InterruptedException { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java index 240f26ec3a5..48c54cdedee 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/r4/RestHookTestWithInterceptorRegisteredToDaoConfigR4Test.java @@ -84,11 +84,11 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigR4Test extends Base } private void waitForQueueToDrain() throws InterruptedException { - ourLog.info("QUEUE HAS {} ITEMS", getRestHookSubscriptionInterceptor().getExecutorQueueForUnitTests().size()); - while (getRestHookSubscriptionInterceptor().getExecutorQueueForUnitTests().size() > 0) { + ourLog.info("QUEUE HAS {} ITEMS", getRestHookSubscriptionInterceptor().getExecutorQueueSizeForUnitTests()); + while (getRestHookSubscriptionInterceptor().getExecutorQueueSizeForUnitTests() > 0) { Thread.sleep(250); } - ourLog.info("QUEUE HAS {} ITEMS", getRestHookSubscriptionInterceptor().getExecutorQueueForUnitTests().size()); + ourLog.info("QUEUE HAS {} ITEMS", getRestHookSubscriptionInterceptor().getExecutorQueueSizeForUnitTests()); } private Observation sendObservation(String code, String system) throws InterruptedException {