More loinc work

This commit is contained in:
James Agnew 2018-03-22 07:16:16 -04:00
parent 308ac63a77
commit 45a16fe066
13 changed files with 91 additions and 76 deletions

View File

@ -5,9 +5,9 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao; import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.jpa.rp.dstu3.ActivityDefinitionResourceProvider; import ca.uhn.fhir.jpa.rp.dstu3.ActivityDefinitionResourceProvider;
import ca.uhn.fhir.jpa.rp.dstu3.MeasureResourceProvider; import ca.uhn.fhir.jpa.rp.dstu3.MeasureResourceProvider;
import ca.uhn.fhir.jpa.rp.dstu3.PlanDefinitionResourceProvider; import ca.uhn.fhir.jpa.rp.dstu3.PlanDefinitionResourceProvider;
@ -149,7 +149,7 @@ public class CdsServerExample extends RestfulServer {
* so it is a potential security vulnerability. Consider using an AuthorizationInterceptor * so it is a potential security vulnerability. Consider using an AuthorizationInterceptor
* with this feature. * with this feature.
*/ */
registerProvider(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); registerProvider(myAppCtx.getBean(TerminologyUploaderProvider.class));
} }
public IResourceProvider getProvider(String name) { public IResourceProvider getProvider(String name) {

View File

@ -8,7 +8,6 @@ import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
@ -79,7 +78,7 @@ public class JpaServerDemo extends RestfulServer {
systemProvider.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); systemProvider.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class));
} else if (fhirVersion == FhirVersionEnum.DSTU3) { } else if (fhirVersion == FhirVersionEnum.DSTU3) {
systemProvider.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); systemProvider.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class));
systemProvider.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class));
} else if (fhirVersion == FhirVersionEnum.R4) { } else if (fhirVersion == FhirVersionEnum.R4) {
systemProvider.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); systemProvider.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class));
systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class)); systemProvider.add(myAppCtx.getBean(TerminologyUploaderProvider.class));

View File

@ -188,7 +188,7 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
if (isNotBlank(next.getCode())) { if (isNotBlank(next.getCode())) {
TermConcept termConcept = new TermConcept(); TermConcept termConcept = new TermConcept();
termConcept.setCode(next.getCode()); termConcept.setCode(next.getCode());
termConcept.setCodeSystem(theCodeSystemVersion); termConcept.setCodeSystemVersion(theCodeSystemVersion);
termConcept.setDisplay(next.getDisplay()); termConcept.setDisplay(next.getDisplay());
termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA); termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA);
retVal.add(termConcept); retVal.add(termConcept);

View File

@ -161,7 +161,7 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
if (isNotBlank(next.getCode())) { if (isNotBlank(next.getCode())) {
TermConcept termConcept = new TermConcept(); TermConcept termConcept = new TermConcept();
termConcept.setCode(next.getCode()); termConcept.setCode(next.getCode());
termConcept.setCodeSystem(theCodeSystemVersion); termConcept.setCodeSystemVersion(theCodeSystemVersion);
termConcept.setDisplay(next.getDisplay()); termConcept.setDisplay(next.getDisplay());
termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA); termConcept.addChildren(toPersistedConcepts(next.getConcept(), theCodeSystemVersion), RelationshipTypeEnum.ISA);
retVal.add(termConcept); retVal.add(termConcept);

View File

@ -20,28 +20,15 @@ package ca.uhn.fhir.jpa.entity;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.CoverageIgnore;
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 javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import ca.uhn.fhir.util.CoverageIgnore;
//@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)
) )
@Entity() @Entity()
@ -54,17 +41,23 @@ public class TermCodeSystemVersion implements Serializable {
@Id() @Id()
@SequenceGenerator(name = "SEQ_CODESYSTEMVER_PID", sequenceName = "SEQ_CODESYSTEMVER_PID") @SequenceGenerator(name = "SEQ_CODESYSTEMVER_PID", sequenceName = "SEQ_CODESYSTEMVER_PID")
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CODESYSTEMVER_PID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEMVER_PID")
@Column(name = "PID") @Column(name = "PID")
private Long myId; private Long myId;
@OneToOne() @OneToOne()
@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)
private String myCodeSystemVersionId; private String myCodeSystemVersionId;
/**
* This was added in HAPI FHIR 3.3.0 and is nullable just to avoid migration
* issued. It should be made non-nullable at some point.
*/
@ManyToOne
@JoinColumn(name = "CODESYSTEM_PID", referencedColumnName = "PID", nullable = true)
private TermCodeSystem myCodeSystem;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@OneToOne(mappedBy = "myCurrentVersion", optional = true) @OneToOne(mappedBy = "myCurrentVersion", optional = true)
private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny; private TermCodeSystem myCodeSystemHavingThisVersionAsCurrentVersionIfAny;
@ -76,26 +69,6 @@ public class TermCodeSystemVersion implements Serializable {
super(); super();
} }
public Collection<TermConcept> getConcepts() {
if (myConcepts == null) {
myConcepts = new ArrayList<>();
}
return myConcepts;
}
public Long getPid() {
return myId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((myResource.getId() == null) ? 0 : myResource.getId().hashCode());
result = prime * result + ((myCodeSystemVersionId == null) ? 0 : myCodeSystemVersionId.hashCode());
return result;
}
@CoverageIgnore @CoverageIgnore
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
@ -125,20 +98,48 @@ public class TermCodeSystemVersion implements Serializable {
return true; return true;
} }
public ResourceTable getResource() { public TermCodeSystem getCodeSystem() {
return myResource; return myCodeSystem;
}
public void setCodeSystem(TermCodeSystem theCodeSystem) {
myCodeSystem = theCodeSystem;
} }
public String getCodeSystemVersionId() { public String getCodeSystemVersionId() {
return myCodeSystemVersionId; return myCodeSystemVersionId;
} }
public void setResource(ResourceTable theResource) {
myResource = theResource;
}
public void setCodeSystemVersionId(String theCodeSystemVersionId) { public void setCodeSystemVersionId(String theCodeSystemVersionId) {
myCodeSystemVersionId = theCodeSystemVersionId; myCodeSystemVersionId = theCodeSystemVersionId;
} }
public Collection<TermConcept> getConcepts() {
if (myConcepts == null) {
myConcepts = new ArrayList<>();
}
return myConcepts;
}
public Long getPid() {
return myId;
}
public ResourceTable getResource() {
return myResource;
}
public void setResource(ResourceTable theResource) {
myResource = theResource;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((myResource.getId() == null) ? 0 : myResource.getId().hashCode());
result = prime * result + ((myCodeSystemVersionId == null) ? 0 : myCodeSystemVersionId.hashCode());
return result;
}
} }

View File

@ -101,7 +101,7 @@ public class TermConcept implements Serializable {
} }
public TermConcept(TermCodeSystemVersion theCs, String theCode) { public TermConcept(TermCodeSystemVersion theCs, String theCode) {
setCodeSystem(theCs); setCodeSystemVersion(theCs);
setCode(theCode); setCode(theCode);
} }
@ -178,14 +178,14 @@ public class TermConcept implements Serializable {
myCode = theCode; myCode = theCode;
} }
public TermCodeSystemVersion getCodeSystem() { public TermCodeSystemVersion getCodeSystemVersion() {
return myCodeSystem; return myCodeSystem;
} }
public void setCodeSystem(TermCodeSystemVersion theCodeSystem) { public void setCodeSystemVersion(TermCodeSystemVersion theCodeSystemVersion) {
myCodeSystem = theCodeSystem; myCodeSystem = theCodeSystemVersion;
if (theCodeSystem.getPid() != null) { if (theCodeSystemVersion.getPid() != null) {
myCodeSystemVersionPid = theCodeSystem.getPid(); myCodeSystemVersionPid = theCodeSystemVersion.getPid();
} }
} }

View File

@ -408,7 +408,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
ourLog.info("Have processed {}/{} concepts ({}%)", theConceptsStack.size(), theTotalConcepts, (int) (pct * 100.0f)); ourLog.info("Have processed {}/{} concepts ({}%)", theConceptsStack.size(), theTotalConcepts, (int) (pct * 100.0f));
} }
theConcept.setCodeSystem(theCodeSystem); theConcept.setCodeSystemVersion(theCodeSystem);
theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED); theConcept.setIndexStatus(BaseHapiFhirDao.INDEX_STATUS_INDEXED);
if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) { if (theConceptsStack.size() <= myDaoConfig.getDeferIndexingForCodesystemsOfSize()) {
@ -436,10 +436,10 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
} }
private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) { private void populateVersion(TermConcept theNext, TermCodeSystemVersion theCodeSystemVersion) {
if (theNext.getCodeSystem() != null) { if (theNext.getCodeSystemVersion() != null) {
return; return;
} }
theNext.setCodeSystem(theCodeSystemVersion); theNext.setCodeSystemVersion(theCodeSystemVersion);
for (TermConceptParentChildLink next : theNext.getChildren()) { for (TermConceptParentChildLink next : theNext.getChildren()) {
populateVersion(next.getChild(), theCodeSystemVersion); populateVersion(next.getChild(), theCodeSystemVersion);
} }
@ -667,6 +667,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
throw new UnprocessableEntityException(msg); throw new UnprocessableEntityException(msg);
} }
} }
theCodeSystemVersion.setCodeSystem(codeSystem);
ourLog.info("Validating all codes in CodeSystem for storage (this can take some time for large sets)"); ourLog.info("Validating all codes in CodeSystem for storage (this can take some time for large sets)");
@ -753,8 +754,8 @@ 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.getCodeSystem() != null, "CodesystemValue is null"); ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystemVersion() != null, "CodesystemValue is null");
ValidateUtil.isTrueOrThrowInvalidRequest(theConcept.getCodeSystem() == 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())) {

View File

@ -237,7 +237,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvcImpl implemen
def.setDisplay(code.getDisplay()); def.setDisplay(code.getDisplay());
CodeValidationResult retVal = new CodeValidationResult(def); CodeValidationResult retVal = new CodeValidationResult(def);
retVal.setProperties(code.toValidationProperties()); retVal.setProperties(code.toValidationProperties());
retVal.setCodeSystemName(code.getCodeSystem().get); retVal.setCodeSystemName(code.getCodeSystemVersion().getCodeSystem().getName());
return retVal; return retVal;
} }

View File

@ -389,7 +389,7 @@ public class TerminologyLoaderSvcImpl implements IHapiTerminologyLoaderSvc {
if (concept == null) { if (concept == null) {
concept = new TermConcept(); concept = new TermConcept();
id2concept.put(id, concept); id2concept.put(id, concept);
concept.setCodeSystem(codeSystemVersion); concept.setCodeSystemVersion(codeSystemVersion);
} }
return concept; return concept;
} }

View File

@ -39,7 +39,7 @@ public class LoincHierarchyHandler implements IRecordHandler {
TermConcept retVal = myCode2Concept.get(theCode); TermConcept retVal = myCode2Concept.get(theCode);
if (retVal == null) { if (retVal == null) {
retVal = new TermConcept(); retVal = new TermConcept();
retVal.setCodeSystem(myCodeSystemVersion); retVal.setCodeSystemVersion(myCodeSystemVersion);
retVal.setCode(theCode); retVal.setCode(theCode);
retVal.setDisplay(theDisplay); retVal.setDisplay(theDisplay);
myCode2Concept.put(theCode, retVal); myCode2Concept.put(theCode, retVal);

View File

@ -5,9 +5,7 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test; import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.convertors.VersionConvertor_30_40; import org.hl7.fhir.convertors.VersionConvertor_30_40;
import org.hl7.fhir.dstu3.model.StringType; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.dstu3.model.Parameters;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
@ -16,10 +14,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test { public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
@ -73,6 +73,21 @@ public class TerminologyLoaderSvcIntegrationDstu3Test extends BaseJpaDstu3Test {
Parameters parameters = VersionConvertor_30_40.convertParameters(parametersR4); Parameters parameters = VersionConvertor_30_40.convertParameters(parametersR4);
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parameters)); ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parameters));
assertEquals("SYSTEM", this.<CodeType>getPropertyPart(parameters, "property", "code").get().getValueAsString());
assertEquals("Heart", this.<CodeType>getPropertyPart(parameters, "property", "value").get().getValueAsString());
}
private <T extends Type> Optional<T> getPropertyPart(Parameters theParameters, String thePropName, String thePart) {
return theParameters
.getParameter()
.stream()
.filter(t -> t.getName().equals(thePropName))
.flatMap(t -> t.getPart().stream())
.filter(t -> t.getName().equals(thePart))
.map(t -> (T)t.getValue())
.findFirst();
} }
private Set<String> toExpandedCodes(ValueSet theExpanded) { private Set<String> toExpandedCodes(ValueSet theExpanded) {

View File

@ -49,12 +49,12 @@ public class TerminologySvcImplDstu3Test extends BaseJpaDstu3Test {
cs.setResource(table); cs.setResource(table);
TermConcept parent = new TermConcept(); TermConcept parent = new TermConcept();
parent.setCodeSystem(cs); parent.setCodeSystemVersion(cs);
parent.setCode("parent"); parent.setCode("parent");
cs.getConcepts().add(parent); cs.getConcepts().add(parent);
TermConcept child = new TermConcept(); TermConcept child = new TermConcept();
child.setCodeSystem(cs); child.setCodeSystemVersion(cs);
child.setCode("child"); child.setCode("child");
parent.addChild(child, RelationshipTypeEnum.ISA); parent.addChild(child, RelationshipTypeEnum.ISA);

View File

@ -8,7 +8,6 @@ import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider; import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
@ -121,7 +120,7 @@ public class TestRestfulServer extends RestfulServer {
JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class)); JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class));
confProvider.setImplementationDescription(implDesc); confProvider.setImplementationDescription(implDesc);
setServerConformanceProvider(confProvider); setServerConformanceProvider(confProvider);
plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); plainProviders.add(myAppCtx.getBean(TerminologyUploaderProvider.class));
break; break;
} }
case "R4": { case "R4": {