Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2019-07-11 18:17:09 -04:00
commit dca55d054b
31 changed files with 1076 additions and 220 deletions

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.util;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.*;
public class ValidateUtil { public class ValidateUtil {
@ -37,7 +37,7 @@ public class ValidateUtil {
} }
/** /**
* Throws {@link IllegalArgumentException} if theValue is <= theMinimum * Throws {@link IllegalArgumentException} if theValue is < theMinimum
*/ */
public static void isGreaterThanOrEqualTo(long theValue, long theMinimum, String theMessage) { public static void isGreaterThanOrEqualTo(long theValue, long theMinimum, String theMessage) {
if (theValue < theMinimum) { if (theValue < theMinimum) {
@ -45,6 +45,12 @@ public class ValidateUtil {
} }
} }
public static void isNotBlankOrThrowIllegalArgument(String theString, String theMessage) {
if (isBlank(theString)) {
throw new IllegalArgumentException(theMessage);
}
}
public static void isNotBlankOrThrowInvalidRequest(String theString, String theMessage) { public static void isNotBlankOrThrowInvalidRequest(String theString, String theMessage) {
if (isBlank(theString)) { if (isBlank(theString)) {
throw new InvalidRequestException(theMessage); throw new InvalidRequestException(theMessage);
@ -57,6 +63,12 @@ public class ValidateUtil {
} }
} }
public static void isNotTooLongOrThrowIllegalArgument(String theString, int theMaxLength, String theMessage) {
if (length(theString) > theMaxLength) {
throw new IllegalArgumentException(theMessage);
}
}
public static void isTrueOrThrowInvalidRequest(boolean theSuccess, String theMessage) { public static void isTrueOrThrowInvalidRequest(boolean theSuccess, String theMessage) {
if (theSuccess == false) { if (theSuccess == false) {
throw new InvalidRequestException(theMessage); throw new InvalidRequestException(theMessage);

View File

@ -115,8 +115,9 @@ ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor.noParam=Note that cascadi
ca.uhn.fhir.jpa.provider.BaseJpaProvider.cantCombintAtAndSince=Unable to combine _at and _since parameters for history operation ca.uhn.fhir.jpa.provider.BaseJpaProvider.cantCombintAtAndSince=Unable to combine _at and _since parameters for history operation
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateCodeSystemUrl=Can not create multiple CodeSystem resources with CodeSystem.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1} ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateConceptMapUrl=Can not create multiple ConceptMap resources with ConceptMap.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateCodeSystemUri=Can not create multiple code systems with URI "{0}", already have one with resource ID: {1} ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.cannotCreateDuplicateValueSetUrl=Can not create multiple ValueSet resources with ValueSet.url "{0}", already have one with resource ID: {1}
ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted! ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl.expansionTooLarge=Expansion of ValueSet produced too many codes (maximum {0}) - Operation aborted!
ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1} ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils.failedToApplyPatch=Failed to apply JSON patch to {0}: {1}

View File

@ -145,6 +145,10 @@ public class DaoConfig {
private boolean myEnableInMemorySubscriptionMatching = true; private boolean myEnableInMemorySubscriptionMatching = true;
private boolean myEnforceReferenceTargetTypes = true; private boolean myEnforceReferenceTargetTypes = true;
private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC; private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
/**
* EXPERIMENTAL - Do not use in production! Do not change default of {@code false}!
*/
private boolean myPreExpandValueSetsExperimental = false;
/** /**
* Constructor * Constructor
@ -1600,6 +1604,34 @@ public class DaoConfig {
myModelConfig.setWebsocketContextPath(theWebsocketContextPath); myModelConfig.setWebsocketContextPath(theWebsocketContextPath);
} }
/**
* EXPERIMENTAL - Do not use in production!
* <p>
* If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
* future optimization of the $expand operation on large ValueSets.
* </p>
* <p>
* The default value for this setting is {@code false}.
* </p>
*/
public boolean isPreExpandValueSetsExperimental() {
return myPreExpandValueSetsExperimental;
}
/**
* EXPERIMENTAL - Do not use in production!
* <p>
* If set to {@code true}, ValueSets and expansions are stored in terminology tables. This is to facilitate
* future optimization of the $expand operation on large ValueSets.
* </p>
* <p>
* The default value for this setting is {@code false}.
* </p>
*/
public void setPreExpandValueSetsExperimental(boolean thePreExpandValueSetsExperimental) {
myPreExpandValueSetsExperimental = thePreExpandValueSetsExperimental;
}
public enum IndexEnabledEnum { public enum IndexEnabledEnum {
ENABLED, ENABLED,
DISABLED DISABLED

View File

@ -34,7 +34,7 @@ public interface ITermCodeSystemDao extends JpaRepository<TermCodeSystem, Long>
TermCodeSystem findByCodeSystemUri(@Param("code_system_uri") String theCodeSystemUri); TermCodeSystem findByCodeSystemUri(@Param("code_system_uri") String theCodeSystemUri);
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResourcePid = :resource_pid") @Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myResourcePid = :resource_pid")
TermCodeSystem findByResourcePid(@Param("resource_pid") Long theReourcePid); TermCodeSystem findByResourcePid(@Param("resource_pid") Long theResourcePid);
@Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCurrentVersion.myId = :csv_pid") @Query("SELECT cs FROM TermCodeSystem cs WHERE cs.myCurrentVersion.myId = :csv_pid")
Optional<TermCodeSystem> findWithCodeSystemVersionAsCurrentVersion(@Param("csv_pid") Long theCodeSystemVersionPid); Optional<TermCodeSystem> findWithCodeSystemVersionAsCurrentVersion(@Param("csv_pid") Long theCodeSystemVersionPid);

View File

@ -0,0 +1,35 @@
package ca.uhn.fhir.jpa.dao.data;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.entity.TermValueSetCode;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ITermValueSetCodeDao extends JpaRepository<TermValueSetCode, Long> {
@Query("DELETE FROM TermValueSetCode vsc WHERE vsc.myValueSet.myId = :pid")
@Modifying
void deleteTermValueSetCodesByValueSetId(@Param("pid") Long theValueSetId);
}

View File

@ -0,0 +1,43 @@
package ca.uhn.fhir.jpa.dao.data;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.entity.TermValueSet;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.Optional;
public interface ITermValueSetDao extends JpaRepository<TermValueSet, Long> {
@Query("DELETE FROM TermValueSet vs WHERE vs.myId = :pid")
@Modifying
void deleteTermValueSetById(@Param("pid") Long theId);
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myResourcePid = :resource_pid")
Optional<TermValueSet> findByResourcePid(@Param("resource_pid") Long theResourcePid);
@Query("SELECT vs FROM TermValueSet vs WHERE vs.myUrl = :url")
Optional<TermValueSet> findByUrl(@Param("url") String theUrl);
}

View File

@ -23,11 +23,15 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.LogicUtil; import ca.uhn.fhir.jpa.util.LogicUtil;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import org.apache.commons.codec.binary.StringUtils; import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext; import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport; import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
@ -37,6 +41,8 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetFilterComponent;
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator; import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -45,14 +51,18 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> { public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class); private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoValueSetDstu3.class);
@Autowired
private IHapiTerminologySvc myHapiTerminologySvc;
@Autowired @Autowired
@Qualifier("myJpaValidationSupportChainDstu3") @Qualifier("myJpaValidationSupportChainDstu3")
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@ -295,4 +305,26 @@ public class FhirResourceDaoValueSetDstu3 extends FhirResourceDaoDstu3<ValueSet>
// nothing // nothing
} }
@Override
protected ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (myDaoConfig.isPreExpandValueSetsExperimental()) {
if (retVal.getDeleted() == null) {
try {
ValueSet valueSet = (ValueSet) theResource;
org.hl7.fhir.r4.model.ValueSet converted = VersionConvertor_30_40.convertValueSet(valueSet);
myHapiTerminologySvc.storeTermValueSetAndChildren(retVal, converted);
} catch (FHIRException fe) {
throw new InternalErrorException(fe);
}
} else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal);
}
}
return retVal;
}
} }

View File

@ -74,6 +74,8 @@ public class ExpungeEverythingService {
counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceLink.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, ResourceLink.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchResult.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchResult.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchInclude.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, SearchInclude.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermValueSetCode.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermValueSet.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptParentChildLink.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptParentChildLink.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElementTarget.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElementTarget.class));
counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElement.class)); counter.addAndGet(doExpungeEverythingQuery(txTemplate, TermConceptMapGroupElement.class));

View File

@ -20,34 +20,43 @@ package ca.uhn.fhir.jpa.dao.r4;
* #L% * #L%
*/ */
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.Collections;
import java.util.List;
import org.apache.commons.codec.binary.StringUtils;
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.Enumerations.PublicationStatus;
import org.hl7.fhir.r4.model.ValueSet.*;
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.LogicUtil; import ca.uhn.fhir.jpa.util.LogicUtil;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import org.apache.commons.codec.binary.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetFilterComponent;
import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> { public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
@Autowired
private IHapiTerminologySvc myHapiTerminologySvc;
@Autowired @Autowired
@Qualifier("myJpaValidationSupportChainR4") @Qualifier("myJpaValidationSupportChainR4")
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
@ -296,4 +305,21 @@ public class FhirResourceDaoValueSetR4 extends FhirResourceDaoR4<ValueSet> imple
// nothing // nothing
} }
@Override
protected ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
if (myDaoConfig.isPreExpandValueSetsExperimental()) {
if (retVal.getDeleted() == null) {
ValueSet valueSet = (ValueSet) theResource;
myHapiTerminologySvc.storeTermValueSetAndChildren(retVal, valueSet);
} else {
myHapiTerminologySvc.deleteValueSetAndChildren(retVal);
}
}
return retVal;
}
} }

View File

@ -21,13 +21,16 @@ package ca.uhn.fhir.jpa.entity;
*/ */
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import static org.apache.commons.lang3.StringUtils.left; import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
//@formatter:off //@formatter:off
@Table(name = "TRM_CODESYSTEM", uniqueConstraints = { @Table(name = "TRM_CODESYSTEM", uniqueConstraints = {
@ -37,9 +40,11 @@ import static org.apache.commons.lang3.StringUtils.left;
//@formatter:on //@formatter:on
public class TermCodeSystem implements Serializable { public class TermCodeSystem implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final int CS_NAME_LENGTH = 200;
@Column(name = "CODE_SYSTEM_URI", nullable = false) private static final int MAX_NAME_LENGTH = 200;
static final int MAX_URL_LENGTH = 200;
@Column(name = "CODE_SYSTEM_URI", nullable = false, length = MAX_URL_LENGTH)
private String myCodeSystemUri; private String myCodeSystemUri;
@OneToOne() @OneToOne()
@ -55,7 +60,7 @@ public class TermCodeSystem implements Serializable {
private ResourceTable myResource; private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false) @Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid; private Long myResourcePid;
@Column(name = "CS_NAME", nullable = true) @Column(name = "CS_NAME", nullable = true, length = MAX_NAME_LENGTH)
private String myName; private String myName;
public String getCodeSystemUri() { public String getCodeSystemUri() {
@ -66,16 +71,21 @@ public class TermCodeSystem implements Serializable {
return myName; return myName;
} }
public void setCodeSystemUri(String theCodeSystemUri) { public TermCodeSystem setCodeSystemUri(@Nonnull String theCodeSystemUri) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCodeSystemUri, "theCodeSystemUri must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCodeSystemUri, MAX_URL_LENGTH,
"URI exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theCodeSystemUri));
myCodeSystemUri = theCodeSystemUri; myCodeSystemUri = theCodeSystemUri;
return this;
} }
public TermCodeSystemVersion getCurrentVersion() { public TermCodeSystemVersion getCurrentVersion() {
return myCurrentVersion; return myCurrentVersion;
} }
public void setCurrentVersion(TermCodeSystemVersion theCurrentVersion) { public TermCodeSystem setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
myCurrentVersion = theCurrentVersion; myCurrentVersion = theCurrentVersion;
return this;
} }
public Long getPid() { public Long getPid() {
@ -86,12 +96,14 @@ public class TermCodeSystem implements Serializable {
return myResource; return myResource;
} }
public void setName(String theName) { public TermCodeSystem setName(String theName) {
myName = left(theName, CS_NAME_LENGTH); myName = left(theName, MAX_NAME_LENGTH);
return this;
} }
public void setResource(ResourceTable theResource) { public TermCodeSystem setResource(ResourceTable theResource) {
myResource = theResource; myResource = theResource;
return this;
} }
@Override @Override

View File

@ -22,12 +22,15 @@ package ca.uhn.fhir.jpa.entity;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ValidateUtil;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import static org.apache.commons.lang3.StringUtils.length;
//@formatter:off //@formatter:off
@Table(name = "TRM_CODESYSTEM_VER" @Table(name = "TRM_CODESYSTEM_VER"
// Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this) // Note, we used to have a constraint named IDX_CSV_RESOURCEPID_AND_VER (don't reuse this)
@ -37,6 +40,8 @@ import java.util.Collection;
public class TermCodeSystemVersion implements Serializable { public class TermCodeSystemVersion implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
static final int MAX_VERSION_LENGTH = 200;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem") @OneToMany(fetch = FetchType.LAZY, mappedBy = "myCodeSystem")
private Collection<TermConcept> myConcepts; private Collection<TermConcept> myConcepts;
@ -50,7 +55,7 @@ public class TermCodeSystemVersion implements Serializable {
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID")) @JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_CODESYSVER_RES_ID"))
private ResourceTable myResource; private ResourceTable myResource;
@Column(name = "CS_VERSION_ID", nullable = true, updatable = false) @Column(name = "CS_VERSION_ID", nullable = true, updatable = false, length = MAX_VERSION_LENGTH)
private String myCodeSystemVersionId; private String myCodeSystemVersionId;
/** /**
* This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration * This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
@ -104,16 +109,21 @@ public class TermCodeSystemVersion implements Serializable {
return myCodeSystem; return myCodeSystem;
} }
public void setCodeSystem(TermCodeSystem theCodeSystem) { public TermCodeSystemVersion setCodeSystem(TermCodeSystem theCodeSystem) {
myCodeSystem = theCodeSystem; myCodeSystem = theCodeSystem;
return this;
} }
public String getCodeSystemVersionId() { public String getCodeSystemVersionId() {
return myCodeSystemVersionId; return myCodeSystemVersionId;
} }
public void setCodeSystemVersionId(String theCodeSystemVersionId) { public TermCodeSystemVersion setCodeSystemVersionId(String theCodeSystemVersionId) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(
theCodeSystemVersionId, MAX_VERSION_LENGTH,
"Version ID exceeds maximum length (" + MAX_VERSION_LENGTH + "): " + length(theCodeSystemVersionId));
myCodeSystemVersionId = theCodeSystemVersionId; myCodeSystemVersionId = theCodeSystemVersionId;
return this;
} }
public Collection<TermConcept> getConcepts() { public Collection<TermConcept> getConcepts() {
@ -131,8 +141,9 @@ public class TermCodeSystemVersion implements Serializable {
return myResource; return myResource;
} }
public void setResource(ResourceTable theResource) { public TermCodeSystemVersion setResource(ResourceTable theResource) {
myResource = theResource; myResource = theResource;
return this;
} }
@Override @Override

View File

@ -1,25 +1,5 @@
package ca.uhn.fhir.jpa.entity; package ca.uhn.fhir.jpa.entity;
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.search.annotations.*;
import org.hl7.fhir.r4.model.Coding;
import javax.annotation.Nonnull;
import javax.persistence.*;
import javax.persistence.Index;
import java.io.Serializable;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/* /*
* #%L * #%L
* HAPI FHIR JPA Server * HAPI FHIR JPA Server
@ -40,6 +20,27 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.support.IContextValidationSupport;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.search.DeferConceptIndexingInterceptor;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.search.annotations.*;
import org.hl7.fhir.r4.model.Coding;
import javax.annotation.Nonnull;
import javax.persistence.Index;
import javax.persistence.*;
import java.io.Serializable;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Indexed(interceptor = DeferConceptIndexingInterceptor.class) @Indexed(interceptor = DeferConceptIndexingInterceptor.class)
@Table(name = "TRM_CONCEPT", uniqueConstraints = { @Table(name = "TRM_CONCEPT", uniqueConstraints = {
@ -49,16 +50,17 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
@Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED") @Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED")
}) })
public class TermConcept implements Serializable { public class TermConcept implements Serializable {
public static final int CODE_LENGTH = 500;
protected static final int MAX_DESC_LENGTH = 400;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class);
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
static final int MAX_CODE_LENGTH = 500;
static final int MAX_DESC_LENGTH = 400;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = {}) @OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = {})
private Collection<TermConceptParentChildLink> myChildren; private Collection<TermConceptParentChildLink> myChildren;
@Column(name = "CODE", length = CODE_LENGTH, nullable = false) @Column(name = "CODE", nullable = false, length = MAX_CODE_LENGTH)
@Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),}) @Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),})
private String myCode; private String myCode;
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
@ -70,7 +72,7 @@ public class TermConcept implements Serializable {
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false) @Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
@Fields({@Field(name = "myCodeSystemVersionPid")}) @Fields({@Field(name = "myCodeSystemVersionPid")})
private long myCodeSystemVersionPid; private long myCodeSystemVersionPid;
@Column(name = "DISPLAY", length = MAX_DESC_LENGTH, nullable = true) @Column(name = "DISPLAY", nullable = true, length = MAX_DESC_LENGTH)
@Fields({ @Fields({
@Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")), @Field(name = "myDisplay", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "standardAnalyzer")),
@Field(name = "myDisplayEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteEdgeAnalyzer")), @Field(name = "myDisplayEdgeNGram", index = org.hibernate.search.annotations.Index.YES, store = Store.NO, analyze = Analyze.YES, analyzer = @Analyzer(definition = "autocompleteEdgeAnalyzer")),
@ -187,20 +189,24 @@ public class TermConcept implements Serializable {
return myCode; return myCode;
} }
public void setCode(String theCode) { public TermConcept setCode(@Nonnull String theCode) {
ValidateUtil.isNotBlankOrThrowInvalidRequest(theCode, "Code must not be null or empty"); ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, MAX_CODE_LENGTH,
"Code exceeds maximum length (" + MAX_CODE_LENGTH + "): " + length(theCode));
myCode = theCode; myCode = theCode;
return this;
} }
public TermCodeSystemVersion getCodeSystemVersion() { public TermCodeSystemVersion getCodeSystemVersion() {
return myCodeSystem; return myCodeSystem;
} }
public void setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) { public TermConcept setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
myCodeSystem = theCodeSystemVersion; myCodeSystem = theCodeSystemVersion;
if (theCodeSystemVersion.getPid() != null) { if (theCodeSystemVersion.getPid() != null) {
myCodeSystemVersionPid = theCodeSystemVersion.getPid(); myCodeSystemVersionPid = theCodeSystemVersion.getPid();
} }
return this;
} }
public List<Coding> getCodingProperties(String thePropertyName) { public List<Coding> getCodingProperties(String thePropertyName) {
@ -231,10 +237,7 @@ public class TermConcept implements Serializable {
} }
public TermConcept setDisplay(String theDisplay) { public TermConcept setDisplay(String theDisplay) {
myDisplay = theDisplay; myDisplay = left(theDisplay, MAX_DESC_LENGTH);
if (isNotBlank(theDisplay) && theDisplay.length() > MAX_DESC_LENGTH) {
myDisplay = myDisplay.substring(0, MAX_DESC_LENGTH);
}
return this; return this;
} }
@ -246,8 +249,9 @@ public class TermConcept implements Serializable {
return myIndexStatus; return myIndexStatus;
} }
public void setIndexStatus(Long theIndexStatus) { public TermConcept setIndexStatus(Long theIndexStatus) {
myIndexStatus = theIndexStatus; myIndexStatus = theIndexStatus;
return this;
} }
public String getParentPidsAsString() { public String getParentPidsAsString() {
@ -272,8 +276,9 @@ public class TermConcept implements Serializable {
return mySequence; return mySequence;
} }
public void setSequence(Integer theSequence) { public TermConcept setSequence(Integer theSequence) {
mySequence = theSequence; mySequence = theSequence;
return this;
} }
public List<String> getStringProperties(String thePropertyName) { public List<String> getStringProperties(String thePropertyName) {
@ -300,8 +305,9 @@ public class TermConcept implements Serializable {
return myUpdated; return myUpdated;
} }
public void setUpdated(Date theUpdated) { public TermConcept setUpdated(Date theUpdated) {
myUpdated = theUpdated; myUpdated = theUpdated;
return this;
} }
@Override @Override
@ -355,8 +361,9 @@ public class TermConcept implements Serializable {
myParentPids = b.toString(); myParentPids = b.toString();
} }
public void setParentPids(String theParentPids) { public TermConcept setParentPids(String theParentPids) {
myParentPids = theParentPids; myParentPids = theParentPids;
return this;
} }
@Override @Override

View File

@ -20,16 +20,24 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.ValidateUtil;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_DESIG", uniqueConstraints = { @Table(name = "TRM_CONCEPT_DESIG", uniqueConstraints = {
}, indexes = { }, indexes = {
}) })
public class TermConceptDesignation implements Serializable { public class TermConceptDesignation implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final int MAX_LENGTH = 500;
@ManyToOne @ManyToOne
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT")) @JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTDESIG_CONCEPT"))
private TermConcept myConcept; private TermConcept myConcept;
@ -38,15 +46,15 @@ public class TermConceptDesignation implements Serializable {
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_DESIG_PID")
@Column(name = "PID") @Column(name = "PID")
private Long myId; private Long myId;
@Column(name = "LANG", length = 500, nullable = true) @Column(name = "LANG", nullable = true, length = MAX_LENGTH)
private String myLanguage; private String myLanguage;
@Column(name = "USE_SYSTEM", length = 500, nullable = true) @Column(name = "USE_SYSTEM", nullable = true, length = MAX_LENGTH)
private String myUseSystem; private String myUseSystem;
@Column(name = "USE_CODE", length = 500, nullable = true) @Column(name = "USE_CODE", nullable = true, length = MAX_LENGTH)
private String myUseCode; private String myUseCode;
@Column(name = "USE_DISPLAY", length = 500, nullable = true) @Column(name = "USE_DISPLAY", nullable = true, length = MAX_LENGTH)
private String myUseDisplay; private String myUseDisplay;
@Column(name = "VAL", length = 500, nullable = false) @Column(name = "VAL", nullable = false, length = MAX_LENGTH)
private String myValue; private String myValue;
/** /**
* TODO: Make this non-null * TODO: Make this non-null
@ -62,6 +70,8 @@ public class TermConceptDesignation implements Serializable {
} }
public TermConceptDesignation setLanguage(String theLanguage) { public TermConceptDesignation setLanguage(String theLanguage) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theLanguage, MAX_LENGTH,
"Language exceeds maximum length (" + MAX_LENGTH + "): " + length(theLanguage));
myLanguage = theLanguage; myLanguage = theLanguage;
return this; return this;
} }
@ -71,6 +81,8 @@ public class TermConceptDesignation implements Serializable {
} }
public TermConceptDesignation setUseCode(String theUseCode) { public TermConceptDesignation setUseCode(String theUseCode) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUseCode, MAX_LENGTH,
"Use code exceeds maximum length (" + MAX_LENGTH + "): " + length(theUseCode));
myUseCode = theUseCode; myUseCode = theUseCode;
return this; return this;
} }
@ -80,7 +92,7 @@ public class TermConceptDesignation implements Serializable {
} }
public TermConceptDesignation setUseDisplay(String theUseDisplay) { public TermConceptDesignation setUseDisplay(String theUseDisplay) {
myUseDisplay = theUseDisplay; myUseDisplay = left(theUseDisplay, MAX_LENGTH);
return this; return this;
} }
@ -89,6 +101,9 @@ public class TermConceptDesignation implements Serializable {
} }
public TermConceptDesignation setUseSystem(String theUseSystem) { public TermConceptDesignation setUseSystem(String theUseSystem) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUseSystem, MAX_LENGTH,
"Use system exceeds maximum length (" + MAX_LENGTH + "): " + length(theUseSystem));
myUseSystem = theUseSystem; myUseSystem = theUseSystem;
return this; return this;
} }
@ -97,7 +112,10 @@ public class TermConceptDesignation implements Serializable {
return myValue; return myValue;
} }
public TermConceptDesignation setValue(String theValue) { public TermConceptDesignation setValue(@Nonnull String theValue) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theValue, "theValue must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theValue, MAX_LENGTH,
"Value exceeds maximum length (" + MAX_LENGTH + "): " + length(theValue));
myValue = theValue; myValue = theValue;
return this; return this;
} }

View File

@ -21,19 +21,27 @@ package ca.uhn.fhir.jpa.entity;
*/ */
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = { @Table(name = "TRM_CONCEPT_MAP", uniqueConstraints = {
@UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL"}) @UniqueConstraint(name = "IDX_CONCEPT_MAP_URL", columnNames = {"URL"})
}) })
public class TermConceptMap implements Serializable { public class TermConceptMap implements Serializable {
private static final long serialVersionUID = 1L;
static final int MAX_URL_LENGTH = 200;
@Id() @Id()
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID") @SequenceGenerator(name = "SEQ_CONCEPT_MAP_PID", sequenceName = "SEQ_CONCEPT_MAP_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_PID")
@ -47,13 +55,13 @@ public class TermConceptMap implements Serializable {
@Column(name = "RES_ID", insertable = false, updatable = false) @Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid; private Long myResourcePid;
@Column(name = "SOURCE_URL", nullable = true, length = 200) @Column(name = "SOURCE_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String mySource; private String mySource;
@Column(name = "TARGET_URL", nullable = true, length = 200) @Column(name = "TARGET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String myTarget; private String myTarget;
@Column(name = "URL", length = 200, nullable = false) @Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
private String myUrl; private String myUrl;
@OneToMany(mappedBy = "myConceptMap") @OneToMany(mappedBy = "myConceptMap")
@ -75,47 +83,58 @@ public class TermConceptMap implements Serializable {
return myResource; return myResource;
} }
public void setResource(ResourceTable resource) { public TermConceptMap setResource(ResourceTable theResource) {
myResource = resource; myResource = theResource;
return this;
} }
public Long getResourcePid() { public Long getResourcePid() {
return myResourcePid; return myResourcePid;
} }
public void setResourcePid(Long resourcePid) { public TermConceptMap setResourcePid(Long theResourcePid) {
myResourcePid = resourcePid; myResourcePid = theResourcePid;
return this;
} }
public String getSource() { public String getSource() {
return mySource; return mySource;
} }
public void setSource(String source) { public TermConceptMap setSource(String theSource) {
mySource = source; ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSource, TermValueSet.MAX_URL_LENGTH,
"Source exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theSource));
mySource = theSource;
return this;
} }
public String getTarget() { public String getTarget() {
return myTarget; return myTarget;
} }
public void setTarget(String target) { public TermConceptMap setTarget(String theTarget) {
myTarget = target; ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTarget, TermValueSet.MAX_URL_LENGTH,
"Target exceeds maximum length (" + TermValueSet.MAX_URL_LENGTH + "): " + length(theTarget));
myTarget = theTarget;
return this;
} }
public String getUrl() { public String getUrl() {
return myUrl; return myUrl;
} }
public void setUrl(String theUrl) { public TermConceptMap setUrl(@Nonnull String theUrl) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUrl, MAX_URL_LENGTH,
"URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl));
myUrl = theUrl; myUrl = theUrl;
return this;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId) .append("myId", myId)
.append("myResource", myResource.toString())
.append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)")) .append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
.append("myResourcePid", myResourcePid) .append("myResourcePid", myResourcePid)
.append("mySource", mySource) .append("mySource", mySource)

View File

@ -20,17 +20,23 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_MAP_GROUP") @Table(name = "TRM_CONCEPT_MAP_GROUP")
public class TermConceptMapGroup implements Serializable { public class TermConceptMapGroup implements Serializable {
private static final long serialVersionUID = 1L;
@Id() @Id()
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GROUP_PID", sequenceName = "SEQ_CONCEPT_MAP_GROUP_PID") @SequenceGenerator(name = "SEQ_CONCEPT_MAP_GROUP_PID", sequenceName = "SEQ_CONCEPT_MAP_GROUP_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GROUP_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GROUP_PID")
@ -41,36 +47,37 @@ public class TermConceptMapGroup implements Serializable {
@JoinColumn(name = "CONCEPT_MAP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGROUP_CONCEPTMAP")) @JoinColumn(name = "CONCEPT_MAP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGROUP_CONCEPTMAP"))
private TermConceptMap myConceptMap; private TermConceptMap myConceptMap;
@Column(name = "SOURCE_URL", nullable = false, length = 200) @Column(name = "SOURCE_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
private String mySource; private String mySource;
@Column(name = "SOURCE_VERSION", length = 100) @Column(name = "SOURCE_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
private String mySourceVersion; private String mySourceVersion;
@Column(name = "TARGET_URL", nullable = false, length = 200) @Column(name = "TARGET_URL", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
private String myTarget; private String myTarget;
@Column(name = "TARGET_VERSION", length = 100) @Column(name = "TARGET_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
private String myTargetVersion; private String myTargetVersion;
@OneToMany(mappedBy = "myConceptMapGroup") @OneToMany(mappedBy = "myConceptMapGroup")
private List<TermConceptMapGroupElement> myConceptMapGroupElements; private List<TermConceptMapGroupElement> myConceptMapGroupElements;
@Column(name= "CONCEPT_MAP_URL", length = 200, nullable = true) @Column(name= "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
private String myConceptMapUrl; private String myConceptMapUrl;
@Column(name= "SOURCE_VS", length = 200, nullable = true) @Column(name= "SOURCE_VS", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String mySourceValueSet; private String mySourceValueSet;
@Column(name= "TARGET_VS", length = 200, nullable = true) @Column(name= "TARGET_VS", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String myTargetValueSet; private String myTargetValueSet;
public TermConceptMap getConceptMap() { public TermConceptMap getConceptMap() {
return myConceptMap; return myConceptMap;
} }
public void setConceptMap(TermConceptMap theTermConceptMap) { public TermConceptMapGroup setConceptMap(TermConceptMap theTermConceptMap) {
myConceptMap = theTermConceptMap; myConceptMap = theTermConceptMap;
return this;
} }
public List<TermConceptMapGroupElement> getConceptMapGroupElements() { public List<TermConceptMapGroupElement> getConceptMapGroupElements() {
@ -96,8 +103,12 @@ public class TermConceptMapGroup implements Serializable {
return mySource; return mySource;
} }
public void setSource(String theSource) { public TermConceptMapGroup setSource(@Nonnull String theSource) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theSource, "theSource must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSource, TermCodeSystem.MAX_URL_LENGTH,
"Source exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSource));
this.mySource = theSource; this.mySource = theSource;
return this;
} }
public String getSourceValueSet() { public String getSourceValueSet() {
@ -111,16 +122,23 @@ public class TermConceptMapGroup implements Serializable {
return mySourceVersion; return mySourceVersion;
} }
public void setSourceVersion(String theSourceVersion) { public TermConceptMapGroup setSourceVersion(String theSourceVersion) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSourceVersion, TermCodeSystemVersion.MAX_VERSION_LENGTH,
"Source version ID exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): " + length(theSourceVersion));
mySourceVersion = theSourceVersion; mySourceVersion = theSourceVersion;
return this;
} }
public String getTarget() { public String getTarget() {
return myTarget; return myTarget;
} }
public void setTarget(String theTarget) { public TermConceptMapGroup setTarget(@Nonnull String theTarget) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theTarget, "theTarget must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTarget, TermCodeSystem.MAX_URL_LENGTH,
"Target exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theTarget));
this.myTarget = theTarget; this.myTarget = theTarget;
return this;
} }
public String getTargetValueSet() { public String getTargetValueSet() {
@ -134,13 +152,16 @@ public class TermConceptMapGroup implements Serializable {
return myTargetVersion; return myTargetVersion;
} }
public void setTargetVersion(String theTargetVersion) { public TermConceptMapGroup setTargetVersion(String theTargetVersion) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theTargetVersion, TermCodeSystemVersion.MAX_VERSION_LENGTH,
"Target version ID exceeds maximum length (" + TermCodeSystemVersion.MAX_VERSION_LENGTH + "): " + length(theTargetVersion));
myTargetVersion = theTargetVersion; myTargetVersion = theTargetVersion;
return this;
} }
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId) .append("myId", myId)
.append(myConceptMap != null ? ("myConceptMap - id=" + myConceptMap.getId()) : ("myConceptMap=(null)")) .append(myConceptMap != null ? ("myConceptMap - id=" + myConceptMap.getId()) : ("myConceptMap=(null)"))
.append("mySource", mySource) .append("mySource", mySource)

View File

@ -20,22 +20,28 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import org.apache.commons.lang3.Validate; import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_MAP_GRP_ELEMENT", indexes = { @Table(name = "TRM_CONCEPT_MAP_GRP_ELEMENT", indexes = {
@Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE") @Index(name = "IDX_CNCPT_MAP_GRP_CD", columnList = "SOURCE_CODE")
}) })
public class TermConceptMapGroupElement implements Serializable { public class TermConceptMapGroupElement implements Serializable {
private static final long serialVersionUID = 1L;
@Id() @Id()
@SequenceGenerator(name = "SEQ_CONCEPT_MAP_GRP_ELM_PID", sequenceName = "SEQ_CONCEPT_MAP_GRP_ELM_PID") @SequenceGenerator(name = "SEQ_CONCEPT_MAP_GRP_ELM_PID", sequenceName = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GRP_ELM_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_MAP_GRP_ELM_PID")
@ -46,7 +52,7 @@ public class TermConceptMapGroupElement implements Serializable {
@JoinColumn(name = "CONCEPT_MAP_GROUP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP")) @JoinColumn(name = "CONCEPT_MAP_GROUP_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGELEMENT_GROUP"))
private TermConceptMapGroup myConceptMapGroup; private TermConceptMapGroup myConceptMapGroup;
@Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.CODE_LENGTH) @Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
private String myCode; private String myCode;
@Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DESC_LENGTH) @Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DESC_LENGTH)
@ -55,33 +61,37 @@ public class TermConceptMapGroupElement implements Serializable {
@OneToMany(mappedBy = "myConceptMapGroupElement") @OneToMany(mappedBy = "myConceptMapGroupElement")
private List<TermConceptMapGroupElementTarget> myConceptMapGroupElementTargets; private List<TermConceptMapGroupElementTarget> myConceptMapGroupElementTargets;
@Column(name = "CONCEPT_MAP_URL", length = 200) @Column(name = "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
private String myConceptMapUrl; private String myConceptMapUrl;
@Column(name = "SYSTEM_URL", length = 200) @Column(name = "SYSTEM_URL", nullable = true, length = TermCodeSystem.MAX_URL_LENGTH)
private String mySystem; private String mySystem;
@Column(name = "SYSTEM_VERSION", length = 200) @Column(name = "SYSTEM_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
private String mySystemVersion; private String mySystemVersion;
@Column(name = "VALUESET_URL", length = 200) @Column(name = "VALUESET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String myValueSet; private String myValueSet;
public String getCode() { public String getCode() {
return myCode; return myCode;
} }
public void setCode(String theCode) { public TermConceptMapGroupElement setCode(@Nonnull String theCode) {
Validate.notBlank(theCode, "theCode must not be blank"); ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
myCode = theCode; myCode = theCode;
return this;
} }
public TermConceptMapGroup getConceptMapGroup() { public TermConceptMapGroup getConceptMapGroup() {
return myConceptMapGroup; return myConceptMapGroup;
} }
public void setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) { public TermConceptMapGroupElement setConceptMapGroup(TermConceptMapGroup theTermConceptMapGroup) {
myConceptMapGroup = theTermConceptMapGroup; myConceptMapGroup = theTermConceptMapGroup;
return this;
} }
public List<TermConceptMapGroupElementTarget> getConceptMapGroupElementTargets() { public List<TermConceptMapGroupElementTarget> getConceptMapGroupElementTargets() {
@ -103,8 +113,9 @@ public class TermConceptMapGroupElement implements Serializable {
return myDisplay; return myDisplay;
} }
public void setDisplay(String theDisplay) { public TermConceptMapGroupElement setDisplay(String theDisplay) {
myDisplay = theDisplay; myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH);
return this;
} }
public Long getId() { public Long getId() {
@ -158,7 +169,7 @@ public class TermConceptMapGroupElement implements Serializable {
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId) .append("myId", myId)
.append(myConceptMapGroup != null ? ("myConceptMapGroup - id=" + myConceptMapGroup.getId()) : ("myConceptMapGroup=(null)")) .append(myConceptMapGroup != null ? ("myConceptMapGroup - id=" + myConceptMapGroup.getId()) : ("myConceptMapGroup=(null)"))
.append("myCode", myCode) .append("myCode", myCode)

View File

@ -20,20 +20,28 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence; import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_MAP_GRP_ELM_TGT", indexes = { @Table(name = "TRM_CONCEPT_MAP_GRP_ELM_TGT", indexes = {
@Index(name = "IDX_CNCPT_MP_GRP_ELM_TGT_CD", columnList = "TARGET_CODE") @Index(name = "IDX_CNCPT_MP_GRP_ELM_TGT_CD", columnList = "TARGET_CODE")
}) })
public class TermConceptMapGroupElementTarget implements Serializable { public class TermConceptMapGroupElementTarget implements Serializable {
private static final long serialVersionUID = 1L;
static final int MAX_EQUIVALENCE_LENGTH = 50;
@Id() @Id()
@SequenceGenerator(name = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID", sequenceName = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID") @SequenceGenerator(name = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID", sequenceName = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CNCPT_MAP_GRP_ELM_TGT_PID")
@ -44,31 +52,38 @@ public class TermConceptMapGroupElementTarget implements Serializable {
@JoinColumn(name = "CONCEPT_MAP_GRP_ELM_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGETARGET_ELEMENT")) @JoinColumn(name = "CONCEPT_MAP_GRP_ELM_PID", nullable = false, referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_TCMGETARGET_ELEMENT"))
private TermConceptMapGroupElement myConceptMapGroupElement; private TermConceptMapGroupElement myConceptMapGroupElement;
@Column(name = "TARGET_CODE", nullable = false, length = TermConcept.CODE_LENGTH) @Column(name = "TARGET_CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
private String myCode; private String myCode;
@Column(name = "TARGET_DISPLAY", length = TermConcept.MAX_DESC_LENGTH) @Column(name = "TARGET_DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH)
private String myDisplay; private String myDisplay;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = "TARGET_EQUIVALENCE", length = 50) @Column(name = "TARGET_EQUIVALENCE", nullable = true, length = MAX_EQUIVALENCE_LENGTH)
private ConceptMapEquivalence myEquivalence; private ConceptMapEquivalence myEquivalence;
@Column(name = "CONCEPT_MAP_URL", length = 200) @Column(name = "CONCEPT_MAP_URL", nullable = true, length = TermConceptMap.MAX_URL_LENGTH)
private String myConceptMapUrl; private String myConceptMapUrl;
@Column(name = "SYSTEM_URL", length = 200)
@Column(name = "SYSTEM_URL", nullable = true, length = TermCodeSystem.MAX_URL_LENGTH)
private String mySystem; private String mySystem;
@Column(name = "SYSTEM_VERSION", length = 200)
@Column(name = "SYSTEM_VERSION", nullable = true, length = TermCodeSystemVersion.MAX_VERSION_LENGTH)
private String mySystemVersion; private String mySystemVersion;
@Column(name = "VALUESET_URL", length = 200)
@Column(name = "VALUESET_URL", nullable = true, length = TermValueSet.MAX_URL_LENGTH)
private String myValueSet; private String myValueSet;
public String getCode() { public String getCode() {
return myCode; return myCode;
} }
public void setCode(String theCode) { public TermConceptMapGroupElementTarget setCode(@Nonnull String theCode) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
myCode = theCode; myCode = theCode;
return this;
} }
public TermConceptMapGroupElement getConceptMapGroupElement() { public TermConceptMapGroupElement getConceptMapGroupElement() {
@ -90,16 +105,18 @@ public class TermConceptMapGroupElementTarget implements Serializable {
return myDisplay; return myDisplay;
} }
public void setDisplay(String theDisplay) { public TermConceptMapGroupElementTarget setDisplay(String theDisplay) {
myDisplay = theDisplay; myDisplay = theDisplay;
return this;
} }
public ConceptMapEquivalence getEquivalence() { public ConceptMapEquivalence getEquivalence() {
return myEquivalence; return myEquivalence;
} }
public void setEquivalence(ConceptMapEquivalence theEquivalence) { public TermConceptMapGroupElementTarget setEquivalence(ConceptMapEquivalence theEquivalence) {
myEquivalence = theEquivalence; myEquivalence = theEquivalence;
return this;
} }
public Long getId() { public Long getId() {
@ -155,7 +172,7 @@ public class TermConceptMapGroupElementTarget implements Serializable {
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId) .append("myId", myId)
.append(myConceptMapGroupElement != null ? ("myConceptMapGroupElement - id=" + myConceptMapGroupElement.getId()) : ("myConceptMapGroupElement=(null)")) .append(myConceptMapGroupElement != null ? ("myConceptMapGroupElement - id=" + myConceptMapGroupElement.getId()) : ("myConceptMapGroupElement=(null)"))
.append("myCode", myCode) .append("myCode", myCode)

View File

@ -20,21 +20,9 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
@Entity @Entity
@Table(name = "TRM_CONCEPT_PC_LINK") @Table(name = "TRM_CONCEPT_PC_LINK")
public class TermConceptParentChildLink implements Serializable { public class TermConceptParentChildLink implements Serializable {
@ -136,20 +124,24 @@ public class TermConceptParentChildLink implements Serializable {
return result; return result;
} }
public void setChild(TermConcept theChild) { public TermConceptParentChildLink setChild(TermConcept theChild) {
myChild = theChild; myChild = theChild;
return this;
} }
public void setCodeSystem(TermCodeSystemVersion theCodeSystem) { public TermConceptParentChildLink setCodeSystem(TermCodeSystemVersion theCodeSystem) {
myCodeSystem = theCodeSystem; myCodeSystem = theCodeSystem;
return this;
} }
public void setParent(TermConcept theParent) { public TermConceptParentChildLink setParent(TermConcept theParent) {
myParent = theParent; myParent = theParent;
return this;
} }
public void setRelationshipType(RelationshipTypeEnum theRelationshipType) { public TermConceptParentChildLink setRelationshipType(RelationshipTypeEnum theRelationshipType) {
myRelationshipType = theRelationshipType; myRelationshipType = theRelationshipType;
return this;
} }
public enum RelationshipTypeEnum { public enum RelationshipTypeEnum {

View File

@ -20,21 +20,29 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import javax.annotation.Nonnull;
import javax.persistence.*; import javax.persistence.*;
import java.io.Serializable; import java.io.Serializable;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Entity @Entity
@Table(name = "TRM_CONCEPT_PROPERTY", uniqueConstraints = { @Table(name = "TRM_CONCEPT_PROPERTY", uniqueConstraints = {
}, indexes = { }, indexes = {
}) })
public class TermConceptProperty implements Serializable { public class TermConceptProperty implements Serializable {
static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final int MAX_LENGTH = 500;
static final int MAX_PROPTYPE_ENUM_LENGTH = 6;
@ManyToOne @ManyToOne
@JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT")) @JoinColumn(name = "CONCEPT_PID", referencedColumnName = "PID", foreignKey = @ForeignKey(name = "FK_CONCEPTPROP_CONCEPT"))
private TermConcept myConcept; private TermConcept myConcept;
@ -51,22 +59,22 @@ public class TermConceptProperty implements Serializable {
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PROP_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CONCEPT_PROP_PID")
@Column(name = "PID") @Column(name = "PID")
private Long myId; private Long myId;
@Column(name = "PROP_KEY", length = 500, nullable = false) @Column(name = "PROP_KEY", nullable = false, length = MAX_LENGTH)
@NotBlank @NotBlank
private String myKey; private String myKey;
@Column(name = "PROP_VAL", length = 500, nullable = true) @Column(name = "PROP_VAL", nullable = true, length = MAX_LENGTH)
private String myValue; private String myValue;
@Column(name = "PROP_TYPE", length = MAX_PROPTYPE_ENUM_LENGTH, nullable = false) @Column(name = "PROP_TYPE", nullable = false, length = MAX_PROPTYPE_ENUM_LENGTH)
private TermConceptPropertyTypeEnum myType; private TermConceptPropertyTypeEnum myType;
/** /**
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING} * Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
*/ */
@Column(name = "PROP_CODESYSTEM", length = 500, nullable = true) @Column(name = "PROP_CODESYSTEM", length = MAX_LENGTH, nullable = true)
private String myCodeSystem; private String myCodeSystem;
/** /**
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING} * Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
*/ */
@Column(name = "PROP_DISPLAY", length = 500, nullable = true) @Column(name = "PROP_DISPLAY", length = MAX_LENGTH, nullable = true)
private String myDisplay; private String myDisplay;
/** /**
@ -80,6 +88,8 @@ public class TermConceptProperty implements Serializable {
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING} * Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
*/ */
public TermConceptProperty setCodeSystem(String theCodeSystem) { public TermConceptProperty setCodeSystem(String theCodeSystem) {
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCodeSystem, MAX_LENGTH,
"Property code system exceeds maximum length (" + MAX_LENGTH + "): " + length(theCodeSystem));
myCodeSystem = theCodeSystem; myCodeSystem = theCodeSystem;
return this; return this;
} }
@ -95,7 +105,7 @@ public class TermConceptProperty implements Serializable {
* Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING} * Relevant only for properties of type {@link TermConceptPropertyTypeEnum#CODING}
*/ */
public TermConceptProperty setDisplay(String theDisplay) { public TermConceptProperty setDisplay(String theDisplay) {
myDisplay = theDisplay; myDisplay = left(theDisplay, MAX_LENGTH);
return this; return this;
} }
@ -103,15 +113,20 @@ public class TermConceptProperty implements Serializable {
return myKey; return myKey;
} }
public void setKey(String theKey) { public TermConceptProperty setKey(@Nonnull String theKey) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theKey, "theKey must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theKey, MAX_LENGTH,
"Code exceeds maximum length (" + MAX_LENGTH + "): " + length(theKey));
myKey = theKey; myKey = theKey;
return this;
} }
public TermConceptPropertyTypeEnum getType() { public TermConceptPropertyTypeEnum getType() {
return myType; return myType;
} }
public TermConceptProperty setType(TermConceptPropertyTypeEnum theType) { public TermConceptProperty setType(@Nonnull TermConceptPropertyTypeEnum theType) {
Validate.notNull(theType);
myType = theType; myType = theType;
return this; return this;
} }
@ -128,8 +143,9 @@ public class TermConceptProperty implements Serializable {
* This will contain the value for a {@link TermConceptPropertyTypeEnum#STRING string} * This will contain the value for a {@link TermConceptPropertyTypeEnum#STRING string}
* property, and the code for a {@link TermConceptPropertyTypeEnum#CODING coding} property. * property, and the code for a {@link TermConceptPropertyTypeEnum#CODING coding} property.
*/ */
public void setValue(String theValue) { public TermConceptProperty setValue(String theValue) {
myValue = theValue; myValue = left(theValue, MAX_LENGTH);
return this;
} }
public TermConceptProperty setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) { public TermConceptProperty setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
@ -137,8 +153,9 @@ public class TermConceptProperty implements Serializable {
return this; return this;
} }
public void setConcept(TermConcept theConcept) { public TermConceptProperty setConcept(TermConcept theConcept) {
myConcept = theConcept; myConcept = theConcept;
return this;
} }
@Override @Override

View File

@ -0,0 +1,144 @@
package ca.uhn.fhir.jpa.entity;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Table(name = "TRM_VALUESET", uniqueConstraints = {
@UniqueConstraint(name = "IDX_VALUESET_URL", columnNames = {"URL"})
})
@Entity()
public class TermValueSet implements Serializable {
private static final long serialVersionUID = 1L;
private static final int MAX_NAME_LENGTH = 200;
static final int MAX_URL_LENGTH = 200;
@Id()
@SequenceGenerator(name = "SEQ_VALUESET_PID", sequenceName = "SEQ_VALUESET_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_PID")
@Column(name = "PID")
private Long myId;
@Column(name = "URL", nullable = false, length = MAX_URL_LENGTH)
private String myUrl;
@OneToOne()
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMVALUESET_RES"))
private ResourceTable myResource;
@Column(name = "RES_ID", insertable = false, updatable = false)
private Long myResourcePid;
@Column(name = "NAME", nullable = true, length = MAX_NAME_LENGTH)
private String myName;
@OneToMany(mappedBy = "myValueSet")
private List<TermValueSetCode> myCodes;
public Long getId() {
return myId;
}
public String getUrl() {
return myUrl;
}
public TermValueSet setUrl(@Nonnull String theUrl) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theUrl, "theUrl must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theUrl, MAX_URL_LENGTH,
"URL exceeds maximum length (" + MAX_URL_LENGTH + "): " + length(theUrl));
myUrl = theUrl;
return this;
}
public ResourceTable getResource() {
return myResource;
}
public TermValueSet setResource(ResourceTable theResource) {
myResource = theResource;
return this;
}
public String getName() {
return myName;
}
public TermValueSet setName(String theName) {
myName = left(theName, MAX_NAME_LENGTH);
return this;
}
public List<TermValueSetCode> getCodes() {
if (myCodes == null) {
myCodes = new ArrayList<>();
}
return myCodes;
}
@Override
public boolean equals(Object theO) {
if (this == theO) return true;
if (!(theO instanceof TermValueSet)) return false;
TermValueSet that = (TermValueSet) theO;
return new EqualsBuilder()
.append(getUrl(), that.getUrl())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getUrl())
.toHashCode();
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId)
.append("myUrl", myUrl)
.append(myResource != null ? ("myResource=" + myResource.toString()) : ("myResource=(null)"))
.append("myResourcePid", myResourcePid)
.append("myName", myName)
.append(myCodes != null ? ("myCodes - size=" + myCodes.size()) : ("myCodes=(null)"))
.toString();
}
}

View File

@ -0,0 +1,166 @@
package ca.uhn.fhir.jpa.entity;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2019 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import javax.annotation.Nonnull;
import javax.persistence.*;
import java.io.Serializable;
import static org.apache.commons.lang3.StringUtils.left;
import static org.apache.commons.lang3.StringUtils.length;
@Table(name = "TRM_VALUESET_CODE", indexes = {
@Index(name = "IDX_VALUESET_CODE_CS_CD", columnList = "SYSTEM, CODE")
})
@Entity()
public class TermValueSetCode implements Serializable {
private static final long serialVersionUID = 1L;
@Id()
@SequenceGenerator(name = "SEQ_VALUESET_CODE_PID", sequenceName = "SEQ_VALUESET_CODE_PID")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_VALUESET_CODE_PID")
@Column(name = "PID")
private Long myId;
@ManyToOne()
@JoinColumn(name = "VALUESET_PID", referencedColumnName = "PID", nullable = false, foreignKey = @ForeignKey(name = "FK_TRM_VALUESET_PID"))
private TermValueSet myValueSet;
@Transient
private String myValueSetUrl;
@Transient
private String myValueSetName;
@Column(name = "SYSTEM", nullable = false, length = TermCodeSystem.MAX_URL_LENGTH)
private String mySystem;
@Column(name = "CODE", nullable = false, length = TermConcept.MAX_CODE_LENGTH)
private String myCode;
@Column(name = "DISPLAY", nullable = true, length = TermConcept.MAX_DESC_LENGTH)
private String myDisplay;
public Long getId() {
return myId;
}
public TermValueSet getValueSet() {
return myValueSet;
}
public TermValueSetCode setValueSet(TermValueSet theValueSet) {
myValueSet = theValueSet;
return this;
}
public String getValueSetUrl() {
if (myValueSetUrl == null) {
myValueSetUrl = getValueSet().getUrl();
}
return myValueSetUrl;
}
public String getValueSetName() {
if (myValueSetName == null) {
myValueSetName = getValueSet().getName();
}
return myValueSetName;
}
public String getSystem() {
return mySystem;
}
public TermValueSetCode setSystem(@Nonnull String theSystem) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theSystem, "theSystem must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theSystem, TermCodeSystem.MAX_URL_LENGTH,
"System exceeds maximum length (" + TermCodeSystem.MAX_URL_LENGTH + "): " + length(theSystem));
mySystem = theSystem;
return this;
}
public String getCode() {
return myCode;
}
public TermValueSetCode setCode(@Nonnull String theCode) {
ValidateUtil.isNotBlankOrThrowIllegalArgument(theCode, "theCode must not be null or empty");
ValidateUtil.isNotTooLongOrThrowIllegalArgument(theCode, TermConcept.MAX_CODE_LENGTH,
"Code exceeds maximum length (" + TermConcept.MAX_CODE_LENGTH + "): " + length(theCode));
myCode = theCode;
return this;
}
public String getDisplay() {
return myDisplay;
}
public TermValueSetCode setDisplay(String theDisplay) {
myDisplay = left(theDisplay, TermConcept.MAX_DESC_LENGTH);
return this;
}
@Override
public boolean equals(Object theO) {
if (this == theO) return true;
if (!(theO instanceof TermValueSetCode)) return false;
TermValueSetCode that = (TermValueSetCode) theO;
return new EqualsBuilder()
.append(getValueSetUrl(), that.getValueSetUrl())
.append(getSystem(), that.getSystem())
.append(getCode(), that.getCode())
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getValueSetUrl())
.append(getSystem())
.append(getCode())
.toHashCode();
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("myId", myId)
.append(myValueSet != null ? ("myValueSet - id=" + myValueSet.getId()) : ("myValueSet=(null)"))
.append("myValueSetUrl", this.getValueSetUrl())
.append("myValueSetName", this.getValueSetName())
.append("mySystem", mySystem)
.append("myCode", myCode)
.append("myDisplay", myDisplay)
.toString();
}
}

View File

@ -119,6 +119,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
@Autowired @Autowired
protected ITermConceptDesignationDao myConceptDesignationDao; protected ITermConceptDesignationDao myConceptDesignationDao;
@Autowired @Autowired
protected ITermValueSetDao myValueSetDao;
@Autowired
protected ITermValueSetCodeDao myValueSetCodeDao;
@Autowired
protected FhirContext myContext; protected FhirContext myContext;
@PersistenceContext(type = PersistenceContextType.TRANSACTION) @PersistenceContext(type = PersistenceContextType.TRANSACTION)
protected EntityManager myEntityManager; protected EntityManager myEntityManager;
@ -388,6 +392,31 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
deleteConceptMap(theResourceTable); deleteConceptMap(theResourceTable);
} }
public void deleteValueSet(ResourceTable theResourceTable) {
// Get existing entity so it can be deleted.
Optional<TermValueSet> optionalExistingTermValueSetById = myValueSetDao.findByResourcePid(theResourceTable.getId());
if (optionalExistingTermValueSetById.isPresent()) {
TermValueSet existingTermValueSet = optionalExistingTermValueSetById.get();
ourLog.info("Deleting existing TermValueSet {} and its children...", existingTermValueSet.getId());
myValueSetCodeDao.deleteTermValueSetCodesByValueSetId(existingTermValueSet.getId());
myValueSetDao.deleteTermValueSetById(existingTermValueSet.getId());
ourLog.info("Done deleting existing TermValueSet {} and its children.", existingTermValueSet.getId());
ourLog.info("Flushing...");
myValueSetCodeDao.flush();
myValueSetDao.flush();
ourLog.info("Done flushing.");
}
}
@Override
@Transactional
public void deleteValueSetAndChildren(ResourceTable theResourceTable) {
deleteValueSet(theResourceTable);
}
private <T> void doDelete(String theDescriptor, Supplier<Slice<T>> theLoader, Supplier<Integer> theCounter, JpaRepository<T, ?> theDao) { private <T> void doDelete(String theDescriptor, Supplier<Slice<T>> theLoader, Supplier<Integer> theCounter, JpaRepository<T, ?> theDao) {
int count; int count;
ourLog.info(" * Deleting {}", theDescriptor); ourLog.info(" * Deleting {}", theDescriptor);
@ -690,7 +719,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
private void expandWithoutHibernateSearch(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) { private void expandWithoutHibernateSearch(ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, ValueSet.ConceptSetComponent theInclude, String theSystem, boolean theAdd, AtomicInteger theCodeCounter) {
ourLog.trace("Hibernate search is not enabled"); ourLog.trace("Hibernate search is not enabled");
Validate.isTrue(theExpansionComponent.getParameter().isEmpty(), "Can not exapnd ValueSet with parameters - Hibernate Search is not enabled on this server."); Validate.isTrue(theExpansionComponent.getParameter().isEmpty(), "Can not expand ValueSet with parameters - Hibernate Search is not enabled on this server.");
Validate.isTrue(theInclude.getFilter().isEmpty(), "Can not expand ValueSet with filters - Hibernate Search is not enabled on this server."); Validate.isTrue(theInclude.getFilter().isEmpty(), "Can not expand ValueSet with filters - Hibernate Search is not enabled on this server.");
Validate.isTrue(isNotBlank(theSystem), "Can not expand ValueSet without explicit system - Hibernate Search is not enabled on this server."); Validate.isTrue(isNotBlank(theSystem), "Can not expand ValueSet without explicit system - Hibernate Search is not enabled on this server.");
@ -1144,7 +1173,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
myCodeSystemDao.save(codeSystem); myCodeSystemDao.save(codeSystem);
} else { } else {
if (!ObjectUtil.equals(codeSystem.getResource().getId(), theCodeSystemVersion.getResource().getId())) { if (!ObjectUtil.equals(codeSystem.getResource().getId(), theCodeSystemVersion.getResource().getId())) {
String msg = myContext.getLocalizer().getMessage(BaseHapiTerminologySvcImpl.class, "cannotCreateDuplicateCodeSystemUri", theSystemUri, String msg = myContext.getLocalizer().getMessage(BaseHapiTerminologySvcImpl.class, "cannotCreateDuplicateCodeSystemUrl", theSystemUri,
codeSystem.getResource().getIdDt().toUnqualifiedVersionless().getValue()); codeSystem.getResource().getIdDt().toUnqualifiedVersionless().getValue());
throw new UnprocessableEntityException(msg); throw new UnprocessableEntityException(msg);
} }
@ -1310,7 +1339,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget); myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
if (codesSaved++ % 250 == 0) { if (codesSaved++ % 250 == 0) {
ourLog.info("Have saved {} codes in conceptmap", codesSaved); ourLog.info("Have saved {} codes in ConceptMap", codesSaved);
myConceptMapGroupElementTargetDao.flush(); myConceptMapGroupElementTargetDao.flush();
} }
} }
@ -1334,6 +1363,69 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
ourLog.info("Done storing TermConceptMap."); ourLog.info("Done storing TermConceptMap.");
} }
@Override
@Transactional
public void storeTermValueSetAndChildren(ResourceTable theResourceTable, ValueSet theValueSet) {
ourLog.info("Storing TermValueSet {}", theValueSet.getIdElement().getValue());
ValidateUtil.isTrueOrThrowInvalidRequest(theResourceTable != null, "No resource supplied");
ValidateUtil.isNotBlankOrThrowUnprocessableEntity(theValueSet.getUrl(), "ValueSet has no value for ValueSet.url");
TermValueSet termValueSet = new TermValueSet();
termValueSet.setResource(theResourceTable);
termValueSet.setUrl(theValueSet.getUrl());
termValueSet.setName(theValueSet.hasName() ? theValueSet.getName() : null);
// We delete old versions; we don't support versioned ValueSets.
deleteValueSet(theResourceTable);
/*
* Do the upload.
*/
String url = termValueSet.getUrl();
Optional<TermValueSet> optionalExistingTermValueSetByUrl = myValueSetDao.findByUrl(url);
if (!optionalExistingTermValueSetByUrl.isPresent()) {
myValueSetDao.save(termValueSet);
int codesSaved = 0;
ValueSet expandedValueSet = expandValueSet(theValueSet);
if (expandedValueSet.hasExpansion()) {
if (expandedValueSet.getExpansion().hasTotal() && expandedValueSet.getExpansion().getTotal() > 0) {
TermValueSetCode code;
for (ValueSet.ValueSetExpansionContainsComponent contains : expandedValueSet.getExpansion().getContains()) {
ValidateUtil.isNotBlankOrThrowInvalidRequest(contains.getSystem(), "ValueSet contains a code with no system value");
ValidateUtil.isNotBlankOrThrowInvalidRequest(contains.getCode(), "ValueSet contains a code with no code value");
code = new TermValueSetCode();
code.setValueSet(termValueSet);
code.setSystem(contains.getSystem());
code.setCode(contains.getCode());
code.setDisplay(contains.hasDisplay() ? contains.getDisplay() : null);
myValueSetCodeDao.save(code);
if (codesSaved++ % 250 == 0) {
ourLog.info("Have pre-expanded {} codes in ValueSet", codesSaved);
myValueSetCodeDao.flush();
}
}
}
}
} else {
TermValueSet existingTermValueSet = optionalExistingTermValueSetByUrl.get();
String msg = myContext.getLocalizer().getMessage(
BaseHapiTerminologySvcImpl.class,
"cannotCreateDuplicateValueSetUrl",
url,
existingTermValueSet.getResource().getIdDt().toUnqualifiedVersionless().getValue());
throw new UnprocessableEntityException(msg);
}
ourLog.info("Done storing TermValueSet.");
}
@Override @Override
public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) { public IFhirResourceDaoCodeSystem.SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB) {
VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA); VersionIndependentConcept conceptA = toConcept(theCodeA, theSystem, theCodingA);
@ -1581,9 +1673,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, ArrayList<String> theConceptsStack, private int validateConceptForStorage(TermConcept theConcept, TermCodeSystemVersion theCodeSystem, ArrayList<String> theConceptsStack,
IdentityHashMap<TermConcept, Object> theAllConcepts) { IdentityHashMap<TermConcept, Object> theAllConcepts) {
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() != null, "CodesystemValue is null"); ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() != null, "CodeSystemVersion is null");
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() == theCodeSystem, "CodeSystems are not equal"); ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() == theCodeSystem, "CodeSystems are not equal");
ValidateUtil.isNotBlankOrThrowInvalidRequest(theConcept.getCode(), "Codesystem contains a code with no code value"); ValidateUtil.isNotBlankOrThrowInvalidRequest(theConcept.getCode(), "CodeSystem contains a code with no code value");
if (theConceptsStack.contains(theConcept.getCode())) { if (theConceptsStack.contains(theConcept.getCode())) {
throw new InvalidRequestException("CodeSystem contains circular reference around code " + theConcept.getCode()); throw new InvalidRequestException("CodeSystem contains circular reference around code " + theConcept.getCode());

View File

@ -81,8 +81,12 @@ public interface IHapiTerminologySvc {
void deleteConceptMapAndChildren(ResourceTable theResourceTable); void deleteConceptMapAndChildren(ResourceTable theResourceTable);
void deleteValueSetAndChildren(ResourceTable theResourceTable);
void storeTermConceptMapAndChildren(ResourceTable theResourceTable, ConceptMap theConceptMap); void storeTermConceptMapAndChildren(ResourceTable theResourceTable, ConceptMap theConceptMap);
void storeTermValueSetAndChildren(ResourceTable theResourceTable, ValueSet theValueSet);
boolean supportsSystem(String theCodeSystem); boolean supportsSystem(String theCodeSystem);
List<TermConceptMapGroupElementTarget> translate(TranslationRequest theTranslationRequest); List<TermConceptMapGroupElementTarget> translate(TranslationRequest theTranslationRequest);

View File

@ -1,31 +1,13 @@
package ca.uhn.fhir.jpa.dao.dstu3; package ca.uhn.fhir.jpa.dao.dstu3;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsStringIgnoringCase;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.util.*;
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.ValueSet.*;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem.LookupCodeResult;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.model.entity.*; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParam;
@ -35,6 +17,25 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult; import ca.uhn.fhir.validation.ValidationResult;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceCategory;
import org.hl7.fhir.dstu3.model.AllergyIntolerance.AllergyIntoleranceClinicalStatus;
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptReferenceComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.FilterOperator;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
@ -226,7 +227,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
myCodeSystemDao.create(codeSystem, mySrd); myCodeSystemDao.create(codeSystem, mySrd);
fail(); fail();
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage()); assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
} }
} }

View File

@ -118,6 +118,10 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("myCodeSystemDaoR4") @Qualifier("myCodeSystemDaoR4")
protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao; protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
@Autowired @Autowired
protected ITermCodeSystemDao myTermCodeSystemDao;
@Autowired
protected ITermCodeSystemVersionDao myTermCodeSystemVersionDao;
@Autowired
@Qualifier("myCompartmentDefinitionDaoR4") @Qualifier("myCompartmentDefinitionDaoR4")
protected IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao; protected IFhirResourceDao<CompartmentDefinition> myCompartmentDefinitionDao;
@Autowired @Autowired
@ -287,6 +291,10 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("myValueSetDaoR4") @Qualifier("myValueSetDaoR4")
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao; protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
@Autowired @Autowired
protected ITermValueSetDao myTermValueSetDao;
@Autowired
protected ITermValueSetCodeDao myTermValueSetCodeDao;
@Autowired
protected ITermConceptMapDao myTermConceptMapDao; protected ITermConceptMapDao myTermConceptMapDao;
@Autowired @Autowired
protected ITermConceptMapGroupElementTargetDao myTermConceptMapGroupElementTargetDao; protected ITermConceptMapGroupElementTargetDao myTermConceptMapGroupElementTargetDao;

View File

@ -222,7 +222,7 @@ public class FhirResourceDaoR4TerminologyTest extends BaseJpaR4Test {
myCodeSystemDao.create(codeSystem, mySrd); myCodeSystemDao.create(codeSystem, mySrd);
fail(); fail();
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage()); assertEquals("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage());
} }
} }

View File

@ -1,34 +1,20 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import static org.hamcrest.Matchers.containsString; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult;
import static org.hamcrest.Matchers.not; import ca.uhn.fhir.util.TestUtil;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.UriType;
import org.hl7.fhir.r4.model.ValueSet;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.*;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet.ValidateCodeResult; import java.io.IOException;
import ca.uhn.fhir.util.TestUtil;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test { public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
@ -224,7 +210,7 @@ public class FhirResourceDaoR4ValueSetTest extends BaseJpaR4Test {
@Test @Test
public void testValiedateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() { public void testValidateCodeAgainstBuiltInValueSetAndCodeSystemWithValidCode() {
IPrimitiveType<String> display = null; IPrimitiveType<String> display = null;
Coding coding = null; Coding coding = null;
CodeableConcept codeableConcept = null; CodeableConcept codeableConcept = null;

View File

@ -177,7 +177,7 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs); myTermSvc.storeNewCodeSystemVersion(table.getId(), CS_URL, "SYSTEM NAME", cs);
fail(); fail();
} catch (UnprocessableEntityException e) { } catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/")); assertThat(e.getMessage(), containsString("Can not create multiple CodeSystem resources with CodeSystem.url \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/"));
} }
} }

View File

@ -2,17 +2,12 @@ package ca.uhn.fhir.jpa.term;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.entity.TermConceptMap; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElement;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.CanonicalType; import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence; import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r4.model.UriType;
import org.junit.*; import org.junit.*;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -21,6 +16,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -31,6 +27,8 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Rule @Rule
public final ExpectedException expectedException = ExpectedException.none(); public final ExpectedException expectedException = ExpectedException.none();
private IIdType myConceptMapId; private IIdType myConceptMapId;
private IIdType myExtensionalCsId;
private IIdType myExtensionalVsId;
@Before @Before
public void before() { public void before() {
@ -40,6 +38,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@After @After
public void after() { public void after() {
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences()); myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setPreExpandValueSetsExperimental(new DaoConfig().isPreExpandValueSetsExperimental());
} }
private void createAndPersistConceptMap() { private void createAndPersistConceptMap() {
@ -56,6 +55,39 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
}); });
} }
private void loadAndPersistCodeSystemAndValueSet() throws IOException {
loadAndPersistCodeSystem();
loadAndPersistValueSet();
}
private void loadAndPersistCodeSystem() throws IOException {
CodeSystem codeSystem = loadResourceFromClasspath(CodeSystem.class, "/extensional-case-3-cs.xml");
persistCodeSystem(codeSystem);
}
private void persistCodeSystem(CodeSystem theCodeSystem) {
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
myExtensionalCsId = myCodeSystemDao.create(theCodeSystem, mySrd).getId().toUnqualifiedVersionless();
}
});
}
private void loadAndPersistValueSet() throws IOException {
ValueSet valueSet = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
persistValueSet(valueSet);
}
private void persistValueSet(ValueSet theValueSet) {
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
myExtensionalVsId = myValueSetDao.create(theValueSet, mySrd).getId().toUnqualifiedVersionless();
}
});
}
@Test @Test
public void testCreateConceptMapWithMissingSourceSystem() { public void testCreateConceptMapWithMissingSourceSystem() {
ConceptMap conceptMap = new ConceptMap(); ConceptMap conceptMap = new ConceptMap();
@ -137,6 +169,16 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
} }
@Test
public void testDuplicateCodeSystemUrls() throws Exception {
loadAndPersistCodeSystem();
expectedException.expect(UnprocessableEntityException.class);
expectedException.expectMessage("Can not create multiple CodeSystem resources with CodeSystem.url \"http://acme.org\", already have one with resource ID: CodeSystem/" + myExtensionalCsId.getIdPart());
loadAndPersistCodeSystem();
}
@Test @Test
public void testDuplicateConceptMapUrls() { public void testDuplicateConceptMapUrls() {
createAndPersistConceptMap(); createAndPersistConceptMap();
@ -147,6 +189,19 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
createAndPersistConceptMap(); createAndPersistConceptMap();
} }
@Test
public void testDuplicateValueSetUrls() throws Exception {
myDaoConfig.setPreExpandValueSetsExperimental(true);
// DM 2019-03-05 - We pre-load our custom CodeSystem otherwise pre-expansion of the ValueSet will fail.
loadAndPersistCodeSystemAndValueSet();
expectedException.expect(UnprocessableEntityException.class);
expectedException.expectMessage("Can not create multiple ValueSet resources with ValueSet.url \"http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2\", already have one with resource ID: ValueSet/" + myExtensionalVsId.getIdPart());
loadAndPersistValueSet();
}
@Test @Test
public void testStoreTermConceptMapAndChildren() { public void testStoreTermConceptMapAndChildren() {
createAndPersistConceptMap(); createAndPersistConceptMap();
@ -325,6 +380,63 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
}); });
} }
@Test
public void testStoreTermValueSetAndChildren() throws Exception {
myDaoConfig.setPreExpandValueSetsExperimental(true);
loadAndPersistCodeSystemAndValueSet();
CodeSystem codeSystem = myCodeSystemDao.read(myExtensionalCsId);
ourLog.info("CodeSystem:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(codeSystem));
ValueSet valueSet = myValueSetDao.read(myExtensionalVsId);
ourLog.info("ValueSet:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(valueSet));
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
Optional<TermValueSet> optionalValueSetByResourcePid = myTermValueSetDao.findByResourcePid(myExtensionalVsId.getIdPartAsLong());
assertTrue(optionalValueSetByResourcePid.isPresent());
Optional<TermValueSet> optionalValueSetByUrl = myTermValueSetDao.findByUrl("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2");
assertTrue(optionalValueSetByUrl.isPresent());
TermValueSet valueSet = optionalValueSetByUrl.get();
assertSame(optionalValueSetByResourcePid.get(), valueSet);
ourLog.info("ValueSet:\n" + valueSet.toString());
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", valueSet.getUrl());
assertEquals("Terminology Services Connectation #1 Extensional case #2", valueSet.getName());
assertEquals(codeSystem.getConcept().size(), valueSet.getCodes().size());
TermValueSetCode code = valueSet.getCodes().get(0);
ourLog.info("Code:\n" + code.toString());
assertEquals("http://acme.org", code.getSystem());
assertEquals("8450-9", code.getCode());
assertEquals("Systolic blood pressure--expiration", code.getDisplay());
code = valueSet.getCodes().get(1);
ourLog.info("Code:\n" + code.toString());
assertEquals("http://acme.org", code.getSystem());
assertEquals("11378-7", code.getCode());
assertEquals("Systolic blood pressure at First encounter", code.getDisplay());
// ...
code = valueSet.getCodes().get(22);
ourLog.info("Code:\n" + code.toString());
assertEquals("http://acme.org", code.getSystem());
assertEquals("8491-3", code.getCode());
assertEquals("Systolic blood pressure 1 hour minimum", code.getDisplay());
code = valueSet.getCodes().get(23);
ourLog.info("Code:\n" + code.toString());
assertEquals("http://acme.org", code.getSystem());
assertEquals("8492-1", code.getCode());
assertEquals("Systolic blood pressure 8 hour minimum", code.getDisplay());
}
});
}
@Test @Test
public void testTranslateByCodeSystemsAndSourceCodeOneToMany() { public void testTranslateByCodeSystemsAndSourceCodeOneToMany() {
createAndPersistConceptMap(); createAndPersistConceptMap();

View File

@ -75,6 +75,41 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
.renameColumn("mySystem", "SYSTEM_URL") .renameColumn("mySystem", "SYSTEM_URL")
.renameColumn("mySystemVersion", "SYSTEM_VERSION") .renameColumn("mySystemVersion", "SYSTEM_VERSION")
.renameColumn("myValueSet", "VALUESET_URL"); .renameColumn("myValueSet", "VALUESET_URL");
// TermValueSet
version.startSectionWithMessage("Processing table: TRM_VALUESET");
version.addIdGenerator("SEQ_VALUESET_PID");
Builder.BuilderAddTableByColumns termValueSetTable = version.addTableByColumns("TRM_VALUESET", "PID");
termValueSetTable.addColumn("PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
termValueSetTable.addColumn("URL").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING);
termValueSetTable
.addIndex("IDX_VALUESET_URL")
.unique(true)
.withColumns("URL");
termValueSetTable.addColumn("RES_ID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
termValueSetTable
.addForeignKey("FK_TRMVALUESET_RES")
.toColumn("RES_ID")
.references("HFJ_RESOURCE", "RES_ID");
termValueSetTable.addColumn("NAME").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING);
// TermValueSetCode
version.startSectionWithMessage("Processing table: TRM_VALUESET_CODE");
version.addIdGenerator("SEQ_VALUESET_CODE_PID");
Builder.BuilderAddTableByColumns termValueSetCodeTable = version.addTableByColumns("TRM_VALUESET_CODE", "PID");
termValueSetCodeTable.addColumn("PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
termValueSetCodeTable.addColumn("VALUESET_PID").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.LONG);
termValueSetCodeTable
.addForeignKey("FK_TRM_VALUESET_PID")
.toColumn("VALUESET_PID")
.references("TRM_VALUESET", "PID");
termValueSetCodeTable.addColumn("SYSTEM").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING);
termValueSetCodeTable.addColumn("CODE").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING);
termValueSetCodeTable
.addIndex("IDX_VALUESET_CODE_CS_CD")
.unique(false)
.withColumns("SYSTEM", "CODE");
termValueSetCodeTable.addColumn("DISPLAY").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING);
} }

View File

@ -276,7 +276,7 @@ public DaoConfig daoConfig() {
If the client knows that they will only want a small number of results If the client knows that they will only want a small number of results
(for example, a UI containing 20 results is being shown and the client (for example, a UI containing 20 results is being shown and the client
knows that they will never load the next page of results) the client knows that they will never load the next page of results) the client
may also use the <code>nostore</code> directive along with a HAPI FHIR may also use the <code>no-store</code> directive along with a HAPI FHIR
extension called <code>max-results</code> in order to specify that extension called <code>max-results</code> in order to specify that
only the given number of results should be fetched. This directive only the given number of results should be fetched. This directive
disabled paging entirely for the request and causes the request to disabled paging entirely for the request and causes the request to
@ -285,7 +285,7 @@ public DaoConfig daoConfig() {
</p> </p>
<div class="source"> <div class="source">
<pre> <pre>
Cache-Control: nostore, max-results=20 Cache-Control: no-store, max-results=20
</pre> </pre>
</div> </div>