Skip to content

Commit

Permalink
Fixes for databases and codesystems
Browse files Browse the repository at this point in the history
  • Loading branch information
JPercival committed Jun 5, 2020
1 parent a764ebc commit 4d3ebd9
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 75 deletions.
3 changes: 1 addition & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@
.project
examples
target
derby.log
!target/jpaserver_derby_files
derby.log
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package org.opencds.cqf.dstu3.providers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Expand Down Expand Up @@ -41,15 +47,15 @@ public CodeSystemUpdateProvider(IFhirResourceDao<ValueSet> valueSetDao,
@Operation(name = "$updateCodeSystems", idempotent = true)
public OperationOutcome updateCodeSystems() {
IBundleProvider valuesets = this.valueSetDao.search(new SearchParameterMap());
OperationOutcome response = new OperationOutcome();

OperationOutcome outcome;
for (IBaseResource valueSet : valuesets.getResources(0, valuesets.size())) {
outcome = this.performCodeSystemUpdate((ValueSet) valueSet);
if (outcome.hasIssue()) {
for (OperationOutcome.OperationOutcomeIssueComponent issue : outcome.getIssue()) {
response.addIssue(issue);
}
List<ValueSet> valueSets = valuesets.getResources(0, valuesets.size()).stream().map(x -> (ValueSet)x).collect(Collectors.toList());

OperationOutcome outcome = this.performCodeSystemUpdate(valueSets);

OperationOutcome response = new OperationOutcome();
if (outcome.hasIssue()) {
for (OperationOutcome.OperationOutcomeIssueComponent issue : outcome.getIssue()) {
response.addIssue(issue);
}
}

Expand All @@ -75,32 +81,55 @@ public OperationOutcome updateCodeSystems(@IdParam IdType theId) {
return responseBuilder.buildIssue("error", "notfound", "Unable to find Resource: " + theId.getId()).build();
}

return performCodeSystemUpdate(vs);
return performCodeSystemUpdate(Collections.singletonList(vs));
}

public OperationOutcome performCodeSystemUpdate(ValueSet vs) {
public OperationOutcome performCodeSystemUpdate(List<ValueSet> valueSets) {
OperationOutcomeBuilder responseBuilder = new OperationOutcomeBuilder();

List<String> codeSystems = new ArrayList<>();

// Possible for this to run out of memory with really large ValueSets and CodeSystems.
Map<String, Set<String>> codesBySystem = new HashMap<>();
for (var vs : valueSets){

if (vs.hasCompose() && vs.getCompose().hasInclude()) {
CodeSystem codeSystem;
for (ValueSet.ConceptSetComponent csc : vs.getCompose().getInclude()) {
if (!csc.hasSystem())
if (!csc.hasSystem() || !csc.hasConcept()){
continue;
}

codeSystem = getCodeSystemByUrl(csc.getSystem());
var system = csc.getSystem();
if (!codesBySystem.containsKey(system)){
codesBySystem.put(system, new HashSet<>());
}

if (!csc.hasConcept())
continue;
var codes = codesBySystem.get(system);

codes.addAll(csc.getConcept().stream().map(ValueSet.ConceptReferenceComponent::getCode)
.collect(Collectors.toList()));
}
}

updateCodeSystem(codeSystem.setUrl(csc.getSystem()), getUnionDistinctCodes(csc, codeSystem));
}

for(var entry : codesBySystem.entrySet()) {
var system = entry.getKey();
var codeSystem = getCodeSystemByUrl(system);
updateCodeSystem(codeSystem.setUrl(system), getUnionDistinctCodes(entry.getValue(), codeSystem));

codeSystems.add(codeSystem.getUrl());

codeSystems.add(codeSystem.getUrl());
}
}

return responseBuilder.buildIssue("information", "informational",
"Successfully updated the following CodeSystems: " + String.join(", ", codeSystems)).build();
if (codeSystems.size() > 0) {
return responseBuilder.buildIssue("information", "informational",
"Successfully updated the following CodeSystems: " + String.join(", ", codeSystems)).build();
}
else {
return responseBuilder.buildIssue("information", "informational",
"No code systems were updated").build();
}
}

/***
Expand Down Expand Up @@ -128,17 +157,15 @@ private CodeSystem getCodeSystemByUrl(String url) {
* @param codeSystem A CodeSystem resource
* @return List of distinct codes strings
*/
private List<String> getUnionDistinctCodes(ValueSet.ConceptSetComponent valueSetCodes, CodeSystem codeSystem) {
private Set<String> getUnionDistinctCodes(Set<String> valueSetCodes, CodeSystem codeSystem) {
if (!codeSystem.hasConcept()) {
return valueSetCodes.getConcept().stream().map(ValueSet.ConceptReferenceComponent::getCode)
.collect(Collectors.toList());
return valueSetCodes;
}
return Stream.concat(
valueSetCodes.getConcept().stream().map(ValueSet.ConceptReferenceComponent::getCode)
.collect(Collectors.toList()).stream(),
codeSystem.getConcept().stream().map(CodeSystem.ConceptDefinitionComponent::getCode)
.collect(Collectors.toList()).stream())
.distinct().collect(Collectors.toList());

valueSetCodes.addAll(codeSystem.getConcept().stream().map(CodeSystem.ConceptDefinitionComponent::getCode)
.collect(Collectors.toUnmodifiableSet()));

return valueSetCodes;
}

/***
Expand All @@ -147,7 +174,7 @@ private List<String> getUnionDistinctCodes(ValueSet.ConceptSetComponent valueSet
* @param codeSystem A CodeSystem resource
* @param codes List of (unique) code strings
*/
private void updateCodeSystem(CodeSystem codeSystem, List<String> codes) {
private void updateCodeSystem(CodeSystem codeSystem, Set<String> codes) {
codeSystem
.setConcept(codes.stream().map(x -> new CodeSystem.ConceptDefinitionComponent().setCode(x))
.collect(Collectors.toList()))
Expand All @@ -156,4 +183,4 @@ private void updateCodeSystem(CodeSystem codeSystem, List<String> codes) {
this.codeSystemDao.update(codeSystem);
}

}
}
112 changes: 106 additions & 6 deletions dstu3/src/main/resources/hapi.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,71 @@ server_address=http://localhost:8080/cqf-ruler-dstu3/fhir/
# setting above should also be changed.
server.base=/cqf-ruler-dstu3/fhir



enable_index_missing_fields=false
auto_create_placeholder_reference_targets=false
enforce_referential_integrity_on_write=false
enforce_referential_integrity_on_delete=false
default_encoding=JSON
etag_support=ENABLED
reuse_cached_search_results_millis=-1
reuse_cached_search_results_millis=60000
retain_cached_searches_mins=60
default_page_size=20
max_page_size=200
allow_override_default_search_params=true
allow_contains_searches=true
allow_multiple_delete=true
allow_external_references=true
allow_cascading_deletes=true
allow_placeholder_references=true
expunge_enabled=true
persistence_unit_name=HAPI_PU
logger.name=fhirtest.access
logger.format=Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]
logger.error_format=ERROR - ${requestVerb} ${requestUrl}
logger.log_exceptions=true
datasource.driver=org.apache.derby.jdbc.EmbeddedDriver
datasource.url=jdbc:derby:directory:target/jpaserver_derby_files_dstu3;create=true
datasource.driver=org.h2.Driver
datasource.url=jdbc:h2:file:./target/database/h2/dstu3
datasource.username=
datasource.password=
server.name=Local Tester
server.id=home
test.port=
hibernate.dialect=ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect

###################################################
# Binary Storage (104857600 = 100mb)
###################################################
max_binary_size=104857600

###################################################
# Validation
###################################################
# Should all incoming requests be validated
validation.requests.enabled=false
# Should outgoing responses be validated
validation.responses.enabled=false

###################################################
# Search Features
###################################################
filter_search.enabled=true
graphql.enabled=true
# See FhirPathFilterInterceptor
fhirpath_interceptor.enabled=false

###################################################
# Supported Resources
###################################################
# Enable the following property if you want to customize the
# list of resources that is supported by the server (i.e. to
# disable specific resources)
#supported_resource_types=Patient,Observation,Encounter

###################################################
# Database Settings
###################################################
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.search.model_mapping=ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory
hibernate.format_sql=false
hibernate.show_sql=false
Expand All @@ -45,8 +86,67 @@ hibernate.cache.use_second_level_cache=false
hibernate.cache.use_structured_entries=false
hibernate.cache.use_minimal_puts=false
hibernate.search.default.directory_provider=filesystem
hibernate.search.default.indexBase=target/lucenefiles_dstu3
hibernate.search.default.indexBase=target/lucenefiles
hibernate.search.lucene_version=LUCENE_CURRENT
tester.config.refuse_to_fetch_third_party_urls=false

##################################################
# ElasticSearch
# Note that using ElasticSearch is disabled by
# default and the server will use Lucene instead.
##################################################
elasticsearch.enabled=false
elasticsearch.rest_url=http://localhost:9200
elasticsearch.username=SomeUsername
elasticsearch.password=SomePassword
elasticsearch.required_index_status=YELLOW
elasticsearch.schema_management_strategy=CREATE
# Immediately refresh indexes after every write. This is very bad for
# performance, but can be helpful for testing.
elasticsearch.debug.refresh_after_write=false
elasticsearch.debug.pretty_print_json_log=false


##################################################
# Binary Storage Operations
##################################################
binary_storage.enabled=true

##################################################
# Bulk Data Specification
##################################################
bulk.export.enabled=true

##################################################
# CORS Settings
##################################################
cors.enabled=true
cors.allowed_origin=*
cors.allowCredentials=true
# Supports multiple, comma separated allowed origin entries
# cors.allowed_origin=http://localhost:8080,https://localhost:8080,https://fhirtest.uhn.ca
cors.allow_origin=*

##################################################
# Allowed Bundle Types for persistence (defaults are: COLLECTION,DOCUMENT,MESSAGE)
##################################################
#allowed_bundle_types=COLLECTION,DOCUMENT,MESSAGE,TRANSACTION,TRANSACTIONRESPONSE,BATCH,BATCHRESPONSE,HISTORY,SEARCHSET

##################################################
# Subscriptions
##################################################

# Enable REST Hook Subscription Channel
subscription.resthook.enabled=false

# Enable Email Subscription Channel
subscription.email.enabled=false
email.enabled=false
email.from=[email protected]
email.host=
email.port=0
email.username=
email.password=

# Enable Websocket Subscription Channel
subscription.websocket.enabled=false

Loading

0 comments on commit 4d3ebd9

Please sign in to comment.