All recreating code systems with previously used URL
This commit is contained in:
parent
2bb01451ea
commit
805fbad6ce
|
@ -35,7 +35,7 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValidationDataUploader.class);
|
||||
|
||||
private ArrayList<IIdType> myExcludes;
|
||||
private ArrayList<IIdType> myExcludes = new ArrayList<>();
|
||||
|
||||
private void filterBundle(ca.uhn.fhir.model.dstu2.resource.Bundle theBundle) {
|
||||
for (Iterator<Entry> iter = theBundle.getEntry().iterator(); iter.hasNext(); ) {
|
||||
|
@ -120,16 +120,8 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
}
|
||||
|
||||
FhirContext ctx = getSpecVersionContext(theCommandLine);
|
||||
if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU2) {
|
||||
uploadDefinitionsDstu2(targetServer, ctx);
|
||||
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||
uploadDefinitionsDstu3(targetServer, ctx);
|
||||
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||
uploadDefinitionsR4(targetServer, ctx);
|
||||
}
|
||||
|
||||
String exclude = theCommandLine.getOptionValue("e");
|
||||
myExcludes = new ArrayList<>();
|
||||
|
||||
if (isNotBlank(exclude)) {
|
||||
for (String next : exclude.split(",")) {
|
||||
if (isNotBlank(next)) {
|
||||
|
@ -140,6 +132,14 @@ public class ValidationDataUploader extends BaseCommand {
|
|||
}
|
||||
}
|
||||
|
||||
if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU2) {
|
||||
uploadDefinitionsDstu2(targetServer, ctx);
|
||||
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.DSTU3) {
|
||||
uploadDefinitionsDstu3(targetServer, ctx);
|
||||
} else if (ctx.getVersion().getVersion() == FhirVersionEnum.R4) {
|
||||
uploadDefinitionsR4(targetServer, ctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void uploadDefinitionsDstu2(String targetServer, FhirContext ctx) throws CommandFailureException {
|
||||
|
|
|
@ -20,28 +20,39 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.IdType;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
|
@ -50,6 +61,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
@Autowired
|
||||
private ITermCodeSystemVersionDao myCsvDao;
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemDao myCsDao;
|
||||
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTerminologySvc;
|
||||
|
||||
|
@ -165,8 +179,21 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete);
|
||||
|
||||
String codeSystemUrl = theResourceToDelete.getUrl();
|
||||
if (isNotBlank(codeSystemUrl)) {
|
||||
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
|
||||
if (persCs != null) {
|
||||
myTerminologySvc.deleteCodeSystem(persCs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<TermConcept>();
|
||||
ArrayList<TermConcept> retVal = new ArrayList<>();
|
||||
|
||||
for (ConceptDefinitionComponent next : theConcept) {
|
||||
if (isNotBlank(next.getCode())) {
|
||||
|
@ -191,10 +218,13 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||
|
||||
if (cs != null && isNotBlank(cs.getUrl())) {
|
||||
String codeSystemUrl = cs.getUrl();
|
||||
if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
|
||||
Long codeSystemResourcePid = retVal.getId();
|
||||
|
||||
if (retVal.getDeleted() != null) {
|
||||
// deleting
|
||||
} else if (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == null) {
|
||||
ourLog.info("CodeSystem {} has a status of {}, going to store concepts in terminology tables", retVal.getIdDt().getValue(), cs.getContentElement().getValueAsString());
|
||||
|
||||
Long codeSystemResourcePid = retVal.getId();
|
||||
TermCodeSystemVersion persCs = myCsvDao.findByCodeSystemResourceAndVersion(codeSystemResourcePid, retVal.getVersion());
|
||||
if (persCs != null) {
|
||||
ourLog.info("Code system version already exists in database");
|
||||
|
|
|
@ -20,28 +20,39 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.hl7.fhir.r4.hapi.ctx.ValidationSupportChain;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
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.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.r4.hapi.ctx.ValidationSupportChain;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode;
|
||||
import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
|
@ -49,10 +60,10 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||
|
||||
@Autowired
|
||||
private ITermCodeSystemVersionDao myCsvDao;
|
||||
|
||||
@Autowired
|
||||
private ITermCodeSystemDao myCsDao;
|
||||
@Autowired
|
||||
private IHapiTerminologySvc myTerminologySvc;
|
||||
|
||||
@Autowired
|
||||
private ValidationSupportChain myValidationSupport;
|
||||
|
||||
|
@ -165,6 +176,19 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete);
|
||||
|
||||
String codeSystemUrl = theResourceToDelete.getUrl();
|
||||
if (isNotBlank(codeSystemUrl)) {
|
||||
TermCodeSystem persCs = myCsDao.findByCodeSystemUri(codeSystemUrl);
|
||||
if (persCs != null) {
|
||||
myTerminologySvc.deleteCodeSystem(persCs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<TermConcept> toPersistedConcepts(List<ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<TermConcept>();
|
||||
|
||||
|
|
|
@ -20,69 +20,59 @@ package ca.uhn.fhir.jpa.entity;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
//@formatter:off
|
||||
@Table(name="TRM_CODESYSTEM", uniqueConstraints= {
|
||||
@UniqueConstraint(name="IDX_CS_CODESYSTEM", columnNames= {"CODE_SYSTEM_URI"})
|
||||
@Table(name = "TRM_CODESYSTEM", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "IDX_CS_CODESYSTEM", columnNames = {"CODE_SYSTEM_URI"})
|
||||
})
|
||||
@Entity()
|
||||
//@formatter:on
|
||||
public class TermCodeSystem implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name="CODE_SYSTEM_URI", nullable=false)
|
||||
@Column(name = "CODE_SYSTEM_URI", nullable = false)
|
||||
private String myCodeSystemUri;
|
||||
|
||||
@OneToOne()
|
||||
@JoinColumn(name="CURRENT_VERSION_PID", referencedColumnName="PID", nullable=true, foreignKey=@ForeignKey(name="FK_TRMCODESYSTEM_CURVER"))
|
||||
@JoinColumn(name = "CURRENT_VERSION_PID", referencedColumnName = "PID", nullable = true, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_CURVER"))
|
||||
private TermCodeSystemVersion myCurrentVersion;
|
||||
|
||||
@Id()
|
||||
@SequenceGenerator(name = "SEQ_CODESYSTEM_PID", sequenceName = "SEQ_CODESYSTEM_PID")
|
||||
@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_CODESYSTEM_PID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_CODESYSTEM_PID")
|
||||
@Column(name = "PID")
|
||||
private Long myPid;
|
||||
|
||||
@OneToOne()
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey=@ForeignKey(name="FK_TRMCODESYSTEM_RES"))
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", nullable = false, updatable = false, foreignKey = @ForeignKey(name = "FK_TRMCODESYSTEM_RES"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable=false, updatable=false)
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourcePid;
|
||||
|
||||
public String getCodeSystemUri() {
|
||||
return myCodeSystemUri;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion getCurrentVersion() {
|
||||
return myCurrentVersion;
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public void setCodeSystemUri(String theCodeSystemUri) {
|
||||
myCodeSystemUri = theCodeSystemUri;
|
||||
}
|
||||
|
||||
public TermCodeSystemVersion getCurrentVersion() {
|
||||
return myCurrentVersion;
|
||||
}
|
||||
|
||||
public void setCurrentVersion(TermCodeSystemVersion theCurrentVersion) {
|
||||
myCurrentVersion = theCurrentVersion;
|
||||
}
|
||||
|
||||
public Long getPid() {
|
||||
return myPid;
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public void setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
}
|
||||
|
|
|
@ -618,4 +618,15 @@ public abstract class BaseHapiTerminologySvc implements IHapiTerminologySvc {
|
|||
ourForceSaveDeferredAlwaysForUnitTest = theForceSaveDeferredAlwaysForUnitTest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteCodeSystem(TermCodeSystem theCodeSystem) {
|
||||
ourLog.info(" * Deleting code system {}", theCodeSystem.getPid());
|
||||
for (TermCodeSystemVersion next : myCodeSystemVersionDao.findByCodeSystemResource(theCodeSystem.getPid())) {
|
||||
myConceptParentChildLinkDao.deleteByCodeSystemVersion(next.getPid());
|
||||
myConceptDao.deleteByCodeSystemVersion(next.getPid());
|
||||
}
|
||||
myCodeSystemDao.delete(theCodeSystem.getPid());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,13 +20,12 @@ package ca.uhn.fhir.jpa.term;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.hapi.validation.IValidationSupport;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import java.util.List;
|
||||
|
||||
public class HapiTerminologySvcDstu2 extends BaseHapiTerminologySvc {
|
||||
|
||||
|
@ -46,5 +45,4 @@ public class HapiTerminologySvcDstu2 extends BaseHapiTerminologySvc {
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,12 +24,15 @@ import java.util.List;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystem;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
||||
public interface IHapiTerminologySvc {
|
||||
|
||||
void deleteCodeSystem(TermCodeSystem thePersCs);
|
||||
|
||||
Set<TermConcept> findCodesAbove(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);
|
||||
|
||||
Set<TermConcept> findCodesBelow(Long theCodeSystemResourcePid, Long theCodeSystemResourceVersionPid, String theCode);
|
||||
|
|
|
@ -28,6 +28,21 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3UpdateTest.class);
|
||||
|
||||
@Test
|
||||
public void testReCreateMatchResource() {
|
||||
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://foo");
|
||||
IIdType id = myCodeSystemDao.create(codeSystem).getId().toUnqualifiedVersionless();
|
||||
|
||||
myCodeSystemDao.delete(id);
|
||||
|
||||
codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://foo");
|
||||
myCodeSystemDao.update(codeSystem, "Patient?name=FAM").getId().toUnqualifiedVersionless();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndUpdateWithoutRequest() throws Exception {
|
||||
String methodName = "testUpdateByUrl";
|
||||
|
|
|
@ -28,6 +28,21 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UpdateTest.class);
|
||||
|
||||
@Test
|
||||
public void testReCreateMatchResource() {
|
||||
|
||||
CodeSystem codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://foo");
|
||||
IIdType id = myCodeSystemDao.create(codeSystem).getId().toUnqualifiedVersionless();
|
||||
|
||||
myCodeSystemDao.delete(id);
|
||||
|
||||
codeSystem = new CodeSystem();
|
||||
codeSystem.setUrl("http://foo");
|
||||
myCodeSystemDao.update(codeSystem, "Patient?name=FAM").getId().toUnqualifiedVersionless();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndUpdateWithoutRequest() throws Exception {
|
||||
String methodName = "testUpdateByUrl";
|
||||
|
|
|
@ -1,28 +1,7 @@
|
|||
package org.hl7.fhir.dstu3.hapi.validation;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||
|
@ -32,65 +11,185 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport.CodeValidationResult;
|
||||
import org.hl7.fhir.dstu3.model.Base;
|
||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.ContactPoint;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.RelatedPerson;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.dstu3.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.rules.TestWatcher;
|
||||
import org.junit.runner.Description;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class FhirInstanceValidatorDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorDstu3Test.class);
|
||||
private static DefaultProfileValidationSupport myDefaultValidationSupport = new DefaultProfileValidationSupport();
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorDstu3Test.class);
|
||||
private FhirInstanceValidator myInstanceVal;
|
||||
private IValidationSupport myMockSupport;
|
||||
|
||||
private Map<String, ValueSetExpansionComponent> mySupportedCodeSystemsForExpansion;
|
||||
private FhirValidator myVal;
|
||||
private ArrayList<String> myValidConcepts;
|
||||
private Set<String> myValidSystems = new HashSet<String>();
|
||||
@Rule
|
||||
public TestRule watcher = new TestWatcher() {
|
||||
protected void starting(Description description) {
|
||||
ourLog.info("Starting test: " + description.getMethodName());
|
||||
}
|
||||
};
|
||||
private FhirInstanceValidator myInstanceVal;
|
||||
private IValidationSupport myMockSupport;
|
||||
private Map<String, ValueSetExpansionComponent> mySupportedCodeSystemsForExpansion;
|
||||
private FhirValidator myVal;
|
||||
private ArrayList<String> myValidConcepts;
|
||||
private Set<String> myValidSystems = new HashSet<String>();
|
||||
|
||||
private void addValidConcept(String theSystem, String theCode) {
|
||||
myValidSystems.add(theSystem);
|
||||
myValidConcepts.add(theSystem + "___" + theCode);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void before() {
|
||||
myVal = ourCtx.newValidator();
|
||||
myVal.setValidateAgainstStandardSchema(false);
|
||||
myVal.setValidateAgainstStandardSchematron(false);
|
||||
|
||||
myMockSupport = mock(IValidationSupport.class);
|
||||
ValidationSupportChain validationSupport = new ValidationSupportChain(myMockSupport, myDefaultValidationSupport);
|
||||
myInstanceVal = new FhirInstanceValidator(validationSupport);
|
||||
|
||||
myVal.registerValidatorModule(myInstanceVal);
|
||||
|
||||
mySupportedCodeSystemsForExpansion = new HashMap<String, ValueSet.ValueSetExpansionComponent>();
|
||||
|
||||
myValidConcepts = new ArrayList<String>();
|
||||
|
||||
when(myMockSupport.expandValueSet(any(FhirContext.class), any(ConceptSetComponent.class))).thenAnswer(new Answer<ValueSetExpansionComponent>() {
|
||||
@Override
|
||||
public ValueSetExpansionComponent answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
ConceptSetComponent arg = (ConceptSetComponent) theInvocation.getArguments()[0];
|
||||
ValueSetExpansionComponent retVal = mySupportedCodeSystemsForExpansion.get(arg.getSystem());
|
||||
if (retVal == null) {
|
||||
retVal = myDefaultValidationSupport.expandValueSet(any(FhirContext.class), arg);
|
||||
}
|
||||
ourLog.debug("expandValueSet({}) : {}", new Object[]{theInvocation.getArguments()[0], retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.isCodeSystemSupported(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<Boolean>() {
|
||||
@Override
|
||||
public Boolean answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
boolean retVal = myValidSystems.contains(theInvocation.getArguments()[1]);
|
||||
ourLog.debug("isCodeSystemSupported({}) : {}", new Object[]{theInvocation.getArguments()[1], retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchResource(any(FhirContext.class), any(Class.class), any(String.class))).thenAnswer(new Answer<IBaseResource>() {
|
||||
@Override
|
||||
public IBaseResource answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource retVal;
|
||||
String id = (String) theInvocation.getArguments()[2];
|
||||
if ("Questionnaire/q_jon".equals(id)) {
|
||||
retVal = ourCtx.newJsonParser().parseResource(IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/q_jon.json")));
|
||||
} else {
|
||||
retVal = myDefaultValidationSupport.fetchResource((FhirContext) theInvocation.getArguments()[0], (Class<IBaseResource>) theInvocation.getArguments()[1], id);
|
||||
}
|
||||
ourLog.debug("fetchResource({}, {}) : {}", new Object[]{theInvocation.getArguments()[1], id, retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.validateCode(any(FhirContext.class), any(String.class), any(String.class), any(String.class))).thenAnswer(new Answer<CodeValidationResult>() {
|
||||
@Override
|
||||
public CodeValidationResult answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
FhirContext ctx = (FhirContext) theInvocation.getArguments()[0];
|
||||
String system = (String) theInvocation.getArguments()[1];
|
||||
String code = (String) theInvocation.getArguments()[2];
|
||||
CodeValidationResult retVal;
|
||||
if (myValidConcepts.contains(system + "___" + code)) {
|
||||
retVal = new CodeValidationResult(new ConceptDefinitionComponent(new CodeType(code)));
|
||||
} else {
|
||||
retVal = myDefaultValidationSupport.validateCode(ctx, system, code, (String) theInvocation.getArguments()[2]);
|
||||
}
|
||||
ourLog.debug("validateCode({}, {}, {}) : {}", new Object[]{system, code, (String) theInvocation.getArguments()[2], retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchCodeSystem(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<CodeSystem>() {
|
||||
@Override
|
||||
public CodeSystem answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
CodeSystem retVal = myDefaultValidationSupport.fetchCodeSystem((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
|
||||
ourLog.debug("fetchCodeSystem({}) : {}", new Object[]{(String) theInvocation.getArguments()[1], retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchStructureDefinition(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<StructureDefinition>() {
|
||||
@Override
|
||||
public StructureDefinition answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
StructureDefinition retVal = myDefaultValidationSupport.fetchStructureDefinition((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
|
||||
ourLog.debug("fetchStructureDefinition({}) : {}", new Object[]{(String) theInvocation.getArguments()[1], retVal});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchAllStructureDefinitions(any(FhirContext.class))).thenAnswer(new Answer<List<StructureDefinition>>() {
|
||||
@Override
|
||||
public List<StructureDefinition> answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
List<StructureDefinition> retVal = myDefaultValidationSupport.fetchAllStructureDefinitions((FhirContext) theInvocation.getArguments()[0]);
|
||||
ourLog.debug("fetchAllStructureDefinitions()", new Object[]{});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private Object defaultString(Integer theLocationLine) {
|
||||
return theLocationLine != null ? theLocationLine.toString() : "";
|
||||
}
|
||||
|
||||
private List<SingleValidationMessage> logResultsAndReturnAll(ValidationResult theOutput) {
|
||||
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
|
||||
|
||||
int index = 0;
|
||||
for (SingleValidationMessage next : theOutput.getMessages()) {
|
||||
ourLog.info("Result {}: {} - {}:{} {} - {}",
|
||||
new Object[]{index, next.getSeverity(), defaultString(next.getLocationLine()), defaultString(next.getLocationCol()), next.getLocationString(), next.getMessage()});
|
||||
index++;
|
||||
|
||||
retVal.add(next);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
|
||||
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
|
||||
|
||||
int index = 0;
|
||||
for (SingleValidationMessage next : theOutput.getMessages()) {
|
||||
ourLog.info("Result {}: {} - {} - {}", new Object[]{index, next.getSeverity(), next.getLocationString(), next.getMessage()});
|
||||
index++;
|
||||
|
||||
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
|
||||
retVal.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* See #531
|
||||
*/
|
||||
|
@ -120,46 +219,33 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #370
|
||||
*/
|
||||
@Test
|
||||
public void testValidateRelatedPerson() {
|
||||
public void testIsNoTerminologyChecks() {
|
||||
assertFalse(myInstanceVal.isNoTerminologyChecks());
|
||||
myInstanceVal.setNoTerminologyChecks(true);
|
||||
assertTrue(myInstanceVal.isNoTerminologyChecks());
|
||||
}
|
||||
|
||||
/*
|
||||
* Try with a code that is in http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
|
||||
* and therefore should validate
|
||||
*/
|
||||
RelatedPerson rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("c");
|
||||
@Test
|
||||
public void testValidateBigRawJsonResource() throws Exception {
|
||||
InputStream stream = FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/conformance.json.gz");
|
||||
stream = new GZIPInputStream(stream);
|
||||
String input = IOUtils.toString(stream);
|
||||
|
||||
ValidationResult results = myVal.validateWithResult(rp);
|
||||
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, empty());
|
||||
long start = System.currentTimeMillis();
|
||||
ValidationResult output = null;
|
||||
int passes = 1;
|
||||
for (int i = 0; i < passes; i++) {
|
||||
ourLog.info("Pass {}", i + 1);
|
||||
output = myVal.validateWithResult(input);
|
||||
}
|
||||
|
||||
/*
|
||||
* Code system is case insensitive, so try with capital C
|
||||
*/
|
||||
rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("C");
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
long per = delay / passes;
|
||||
|
||||
results = myVal.validateWithResult(rp);
|
||||
outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, empty());
|
||||
|
||||
/*
|
||||
* Now a bad code
|
||||
*/
|
||||
rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("GAGAGAGA");
|
||||
|
||||
results = myVal.validateWithResult(rp);
|
||||
outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, not(empty()));
|
||||
logResultsAndReturnAll(output);
|
||||
|
||||
ourLog.info("Took {} ms -- {}ms / pass", delay, per);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -197,21 +283,6 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
ourLog.info("Validated the following:\n{}", ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* FHIRPathEngine was throwing Error...
|
||||
*/
|
||||
@Test
|
||||
public void testValidateCrucibleCarePlan() throws Exception {
|
||||
org.hl7.fhir.dstu3.model.Bundle bundle;
|
||||
String name = "profiles-resources";
|
||||
ourLog.info("Uploading " + name);
|
||||
String vsContents;
|
||||
vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/crucible-condition.xml"), "UTF-8");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(vsContents);
|
||||
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidateBundleWithObservations() throws Exception {
|
||||
|
@ -241,6 +312,21 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* FHIRPathEngine was throwing Error...
|
||||
*/
|
||||
@Test
|
||||
public void testValidateCrucibleCarePlan() throws Exception {
|
||||
org.hl7.fhir.dstu3.model.Bundle bundle;
|
||||
String name = "profiles-resources";
|
||||
ourLog.info("Uploading " + name);
|
||||
String vsContents;
|
||||
vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/crucible-condition.xml"), "UTF-8");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(vsContents);
|
||||
List<SingleValidationMessage> errors = logResultsAndReturnNonInformationalOnes(output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateDocument() throws Exception {
|
||||
String vsContents = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/sample-document.xml"), "UTF-8");
|
||||
|
@ -250,184 +336,6 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertTrue(output.isSuccessful());
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference with only an identifier should be valid
|
||||
*/
|
||||
@Test
|
||||
public void testValidateReferenceWithIdentifierValid() throws Exception {
|
||||
Patient p = new Patient();
|
||||
p.getManagingOrganization().getIdentifier().setSystem("http://acme.org");
|
||||
p.getManagingOrganization().getIdentifier().setValue("foo");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(p);
|
||||
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertThat(nonInfo, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference with only an identifier should be valid
|
||||
*/
|
||||
@Test
|
||||
public void testValidateReferenceWithDisplayValid() throws Exception {
|
||||
Patient p = new Patient();
|
||||
p.getManagingOrganization().setDisplay("HELLO");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(p);
|
||||
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertThat(nonInfo, empty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void before() {
|
||||
myVal = ourCtx.newValidator();
|
||||
myVal.setValidateAgainstStandardSchema(false);
|
||||
myVal.setValidateAgainstStandardSchematron(false);
|
||||
|
||||
myMockSupport = mock(IValidationSupport.class);
|
||||
ValidationSupportChain validationSupport = new ValidationSupportChain(myMockSupport, myDefaultValidationSupport);
|
||||
myInstanceVal = new FhirInstanceValidator(validationSupport);
|
||||
|
||||
myVal.registerValidatorModule(myInstanceVal);
|
||||
|
||||
mySupportedCodeSystemsForExpansion = new HashMap<String, ValueSet.ValueSetExpansionComponent>();
|
||||
|
||||
myValidConcepts = new ArrayList<String>();
|
||||
|
||||
when(myMockSupport.expandValueSet(any(FhirContext.class), any(ConceptSetComponent.class))).thenAnswer(new Answer<ValueSetExpansionComponent>() {
|
||||
@Override
|
||||
public ValueSetExpansionComponent answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
ConceptSetComponent arg = (ConceptSetComponent) theInvocation.getArguments()[0];
|
||||
ValueSetExpansionComponent retVal = mySupportedCodeSystemsForExpansion.get(arg.getSystem());
|
||||
if (retVal == null) {
|
||||
retVal = myDefaultValidationSupport.expandValueSet(any(FhirContext.class), arg);
|
||||
}
|
||||
ourLog.debug("expandValueSet({}) : {}", new Object[] { theInvocation.getArguments()[0], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.isCodeSystemSupported(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<Boolean>() {
|
||||
@Override
|
||||
public Boolean answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
boolean retVal = myValidSystems.contains(theInvocation.getArguments()[1]);
|
||||
ourLog.debug("isCodeSystemSupported({}) : {}", new Object[] { theInvocation.getArguments()[1], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchResource(any(FhirContext.class), any(Class.class), any(String.class))).thenAnswer(new Answer<IBaseResource>() {
|
||||
@Override
|
||||
public IBaseResource answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
IBaseResource retVal;
|
||||
String id = (String) theInvocation.getArguments()[2];
|
||||
if ("Questionnaire/q_jon".equals(id)) {
|
||||
retVal = ourCtx.newJsonParser().parseResource(IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/q_jon.json")));
|
||||
} else {
|
||||
retVal = myDefaultValidationSupport.fetchResource((FhirContext) theInvocation.getArguments()[0], (Class<IBaseResource>) theInvocation.getArguments()[1], id);
|
||||
}
|
||||
ourLog.debug("fetchResource({}, {}) : {}", new Object[] { theInvocation.getArguments()[1], id, retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.validateCode(any(FhirContext.class), any(String.class), any(String.class), any(String.class))).thenAnswer(new Answer<CodeValidationResult>() {
|
||||
@Override
|
||||
public CodeValidationResult answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
FhirContext ctx = (FhirContext) theInvocation.getArguments()[0];
|
||||
String system = (String) theInvocation.getArguments()[1];
|
||||
String code = (String) theInvocation.getArguments()[2];
|
||||
CodeValidationResult retVal;
|
||||
if (myValidConcepts.contains(system + "___" + code)) {
|
||||
retVal = new CodeValidationResult(new ConceptDefinitionComponent(new CodeType(code)));
|
||||
} else {
|
||||
retVal = myDefaultValidationSupport.validateCode(ctx, system, code, (String) theInvocation.getArguments()[2]);
|
||||
}
|
||||
ourLog.debug("validateCode({}, {}, {}) : {}", new Object[] { system, code, (String) theInvocation.getArguments()[2], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchCodeSystem(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<CodeSystem>() {
|
||||
@Override
|
||||
public CodeSystem answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
CodeSystem retVal = myDefaultValidationSupport.fetchCodeSystem((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
|
||||
ourLog.debug("fetchCodeSystem({}) : {}", new Object[] { (String) theInvocation.getArguments()[1], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchStructureDefinition(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<StructureDefinition>() {
|
||||
@Override
|
||||
public StructureDefinition answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
StructureDefinition retVal = myDefaultValidationSupport.fetchStructureDefinition((FhirContext) theInvocation.getArguments()[0], (String) theInvocation.getArguments()[1]);
|
||||
ourLog.debug("fetchStructureDefinition({}) : {}", new Object[] { (String) theInvocation.getArguments()[1], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
when(myMockSupport.fetchAllStructureDefinitions(any(FhirContext.class))).thenAnswer(new Answer<List<StructureDefinition>>() {
|
||||
@Override
|
||||
public List<StructureDefinition> answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
List<StructureDefinition> retVal = myDefaultValidationSupport.fetchAllStructureDefinitions((FhirContext) theInvocation.getArguments()[0]);
|
||||
ourLog.debug("fetchAllStructureDefinitions()", new Object[] {});
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private Object defaultString(Integer theLocationLine) {
|
||||
return theLocationLine != null ? theLocationLine.toString() : "";
|
||||
}
|
||||
|
||||
private List<SingleValidationMessage> logResultsAndReturnAll(ValidationResult theOutput) {
|
||||
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
|
||||
|
||||
int index = 0;
|
||||
for (SingleValidationMessage next : theOutput.getMessages()) {
|
||||
ourLog.info("Result {}: {} - {}:{} {} - {}",
|
||||
new Object[] { index, next.getSeverity(), defaultString(next.getLocationLine()), defaultString(next.getLocationCol()), next.getLocationString(), next.getMessage() });
|
||||
index++;
|
||||
|
||||
retVal.add(next);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private List<SingleValidationMessage> logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
|
||||
List<SingleValidationMessage> retVal = new ArrayList<SingleValidationMessage>();
|
||||
|
||||
int index = 0;
|
||||
for (SingleValidationMessage next : theOutput.getMessages()) {
|
||||
ourLog.info("Result {}: {} - {} - {}", new Object[] { index, next.getSeverity(), next.getLocationString(), next.getMessage() });
|
||||
index++;
|
||||
|
||||
if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
|
||||
retVal.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateBigRawJsonResource() throws Exception {
|
||||
InputStream stream = FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/conformance.json.gz");
|
||||
stream = new GZIPInputStream(stream);
|
||||
String input = IOUtils.toString(stream);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
ValidationResult output = null;
|
||||
int passes = 1;
|
||||
for (int i = 0; i < passes; i++) {
|
||||
ourLog.info("Pass {}", i + 1);
|
||||
output = myVal.validateWithResult(input);
|
||||
}
|
||||
|
||||
long delay = System.currentTimeMillis() - start;
|
||||
long per = delay / passes;
|
||||
|
||||
logResultsAndReturnAll(output);
|
||||
|
||||
ourLog.info("Took {} ms -- {}ms / pass", delay, per);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateQuestionnaireResponse() throws IOException {
|
||||
String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/qr_jon.xml"));
|
||||
|
@ -448,6 +356,40 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(output.toString(), 0, output.getMessages().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawJsonResourceBadAttributes() {
|
||||
//@formatter:off
|
||||
String input =
|
||||
"{" +
|
||||
"\"resourceType\":\"Patient\"," +
|
||||
"\"id\":\"123\"," +
|
||||
"\"foo\":\"123\"" +
|
||||
"}";
|
||||
//@formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
assertEquals("/Patient", output.getMessages().get(0).getLocationString());
|
||||
assertEquals("Unrecognised property '@foo'", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawJsonResourceFromExamples() throws Exception {
|
||||
// @formatter:off
|
||||
String input = IOUtils.toString(FhirInstanceValidator.class.getResourceAsStream("/testscript-search.json"));
|
||||
// @formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
logResultsAndReturnNonInformationalOnes(output);
|
||||
// assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
// ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
// ourLog.info(output.getMessages().get(0).getMessage());
|
||||
// assertEquals("/foo", output.getMessages().get(0).getLocationString());
|
||||
// assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawJsonResourceWithUnknownExtension() {
|
||||
|
||||
|
@ -515,65 +457,6 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(ResultSeverityEnum.ERROR, output.getMessages().get(0).getSeverity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlWithMissingRootNamespace() {
|
||||
//@formatter:off
|
||||
String input = ""
|
||||
+ "<Patient>"
|
||||
+ " <text>"
|
||||
+ " <status value=\"generated\"/>"
|
||||
+ " <div xmlns=\"http://www.w3.org/1999/xhtml\">Some narrative</div>"
|
||||
+ " </text>"
|
||||
+ " <name>"
|
||||
+ " <use value=\"official\"/>"
|
||||
+ " <family value=\"Doe\"/>"
|
||||
+ " <given value=\"John\"/>"
|
||||
+ " </name>"
|
||||
+ " <gender value=\"male\"/>"
|
||||
+ " <birthDate value=\"1974-12-25\"/>"
|
||||
+ "</Patient>";
|
||||
//@formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
assertEquals("This cannot be parsed as a FHIR object (no namespace)", output.getMessages().get(0).getMessage());
|
||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawJsonResourceBadAttributes() {
|
||||
//@formatter:off
|
||||
String input =
|
||||
"{" +
|
||||
"\"resourceType\":\"Patient\"," +
|
||||
"\"id\":\"123\"," +
|
||||
"\"foo\":\"123\"" +
|
||||
"}";
|
||||
//@formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
assertEquals("/Patient", output.getMessages().get(0).getLocationString());
|
||||
assertEquals("Unrecognised property '@foo'", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawJsonResourceFromExamples() throws Exception {
|
||||
// @formatter:off
|
||||
String input = IOUtils.toString(FhirInstanceValidator.class.getResourceAsStream("/testscript-search.json"));
|
||||
// @formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
logResultsAndReturnNonInformationalOnes(output);
|
||||
// assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
// ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
// ourLog.info(output.getMessages().get(0).getMessage());
|
||||
// assertEquals("/foo", output.getMessages().get(0).getLocationString());
|
||||
// assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResource() {
|
||||
// @formatter:off
|
||||
|
@ -584,6 +467,21 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(output.toString(), 0, output.getMessages().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceBadAttributes() {
|
||||
//@formatter:off
|
||||
String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "<foo value=\"222\"/>"
|
||||
+ "</Patient>";
|
||||
//@formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
assertEquals("/f:Patient", output.getMessages().get(0).getLocationString());
|
||||
assertEquals("Undefined element 'foo\"", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceWithEmptyPrimitive() {
|
||||
// @formatter:off
|
||||
|
@ -627,18 +525,97 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testValidateRawXmlResourceBadAttributes() {
|
||||
public void testValidateRawXmlWithMissingRootNamespace() {
|
||||
//@formatter:off
|
||||
String input = "<Patient xmlns=\"http://hl7.org/fhir\">" + "<id value=\"123\"/>" + "<foo value=\"222\"/>"
|
||||
String input = ""
|
||||
+ "<Patient>"
|
||||
+ " <text>"
|
||||
+ " <status value=\"generated\"/>"
|
||||
+ " <div xmlns=\"http://www.w3.org/1999/xhtml\">Some narrative</div>"
|
||||
+ " </text>"
|
||||
+ " <name>"
|
||||
+ " <use value=\"official\"/>"
|
||||
+ " <family value=\"Doe\"/>"
|
||||
+ " <given value=\"John\"/>"
|
||||
+ " </name>"
|
||||
+ " <gender value=\"male\"/>"
|
||||
+ " <birthDate value=\"1974-12-25\"/>"
|
||||
+ "</Patient>";
|
||||
//@formatter:on
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
assertEquals(output.toString(), 1, output.getMessages().size());
|
||||
assertEquals("This cannot be parsed as a FHIR object (no namespace)", output.getMessages().get(0).getMessage());
|
||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
assertEquals("/f:Patient", output.getMessages().get(0).getLocationString());
|
||||
assertEquals("Undefined element 'foo\"", output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference with only an identifier should be valid
|
||||
*/
|
||||
@Test
|
||||
public void testValidateReferenceWithDisplayValid() throws Exception {
|
||||
Patient p = new Patient();
|
||||
p.getManagingOrganization().setDisplay("HELLO");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(p);
|
||||
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertThat(nonInfo, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference with only an identifier should be valid
|
||||
*/
|
||||
@Test
|
||||
public void testValidateReferenceWithIdentifierValid() throws Exception {
|
||||
Patient p = new Patient();
|
||||
p.getManagingOrganization().getIdentifier().setSystem("http://acme.org");
|
||||
p.getManagingOrganization().getIdentifier().setValue("foo");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(p);
|
||||
List<SingleValidationMessage> nonInfo = logResultsAndReturnNonInformationalOnes(output);
|
||||
assertThat(nonInfo, empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* See #370
|
||||
*/
|
||||
@Test
|
||||
public void testValidateRelatedPerson() {
|
||||
|
||||
/*
|
||||
* Try with a code that is in http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype
|
||||
* and therefore should validate
|
||||
*/
|
||||
RelatedPerson rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("c");
|
||||
|
||||
ValidationResult results = myVal.validateWithResult(rp);
|
||||
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, empty());
|
||||
|
||||
/*
|
||||
* Code system is case insensitive, so try with capital C
|
||||
*/
|
||||
rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("C");
|
||||
|
||||
results = myVal.validateWithResult(rp);
|
||||
outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, empty());
|
||||
|
||||
/*
|
||||
* Now a bad code
|
||||
*/
|
||||
rp = new RelatedPerson();
|
||||
rp.getPatient().setReference("Patient/1");
|
||||
rp.getRelationship().addCoding().setSystem("http://hl7.org/fhir/v2/0131").setCode("GAGAGAGA");
|
||||
|
||||
results = myVal.validateWithResult(rp);
|
||||
outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertThat(outcome, not(empty()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -760,6 +737,23 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceWithExampleBindingCodeValidationFailingNonLoinc() {
|
||||
Observation input = new Observation();
|
||||
|
||||
myInstanceVal.setValidationSupport(myMockSupport);
|
||||
addValidConcept("http://acme.org", "12345");
|
||||
|
||||
input.setStatus(ObservationStatus.FINAL);
|
||||
input.getCode().addCoding().setSystem("http://acme.org").setCode("9988877");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
List<SingleValidationMessage> errors = logResultsAndReturnAll(output);
|
||||
assertThat(errors.toString(), errors.size(), greaterThan(0));
|
||||
assertEquals("Unknown code: http://acme.org / 9988877", errors.get(0).getMessage());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceWithExampleBindingCodeValidationPassingLoinc() {
|
||||
Observation input = new Observation();
|
||||
|
@ -810,23 +804,6 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(errors.toString(), 0, errors.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceWithExampleBindingCodeValidationFailingNonLoinc() {
|
||||
Observation input = new Observation();
|
||||
|
||||
myInstanceVal.setValidationSupport(myMockSupport);
|
||||
addValidConcept("http://acme.org", "12345");
|
||||
|
||||
input.setStatus(ObservationStatus.FINAL);
|
||||
input.getCode().addCoding().setSystem("http://acme.org").setCode("9988877");
|
||||
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
List<SingleValidationMessage> errors = logResultsAndReturnAll(output);
|
||||
assertThat(errors.toString(), errors.size(), greaterThan(0));
|
||||
assertEquals("Unknown code: http://acme.org / 9988877", errors.get(0).getMessage());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceWithValuesetExpansionBad() {
|
||||
|
||||
|
@ -854,13 +831,6 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
assertEquals(0, all.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNoTerminologyChecks() {
|
||||
assertFalse(myInstanceVal.isNoTerminologyChecks());
|
||||
myInstanceVal.setNoTerminologyChecks(true);
|
||||
assertTrue(myInstanceVal.isNoTerminologyChecks());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidateStructureDefinition() throws IOException {
|
||||
|
@ -874,6 +844,17 @@ public class FhirInstanceValidatorDstu3Test {
|
|||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValueWithWhitespace() throws IOException {
|
||||
String input = IOUtils.toString(FhirInstanceValidatorDstu3Test.class.getResourceAsStream("/dstu3-rick-test.json"), Charsets.UTF_8);
|
||||
|
||||
ValidationResult results = myVal.validateWithResult(input);
|
||||
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
|
||||
assertEquals(1, outcome.size());
|
||||
assertThat(outcome.toString(), containsString("value should not start or finish with whitespace"));
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
myDefaultValidationSupport.flush();
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"resourceType": "CommunicationRequest",
|
||||
"id": "Christol0808",
|
||||
"meta": {
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2017-09-09T13:40:35.438-04:00"
|
||||
},
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Request for Encounter 08082017 Report</div>"
|
||||
},
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://hl7.org/fhir/us/attachments/StructureDefinition/attachment-type",
|
||||
"valueCodeableConcept": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "http://loinc.org",
|
||||
"code": "34133-1",
|
||||
"display": "Summarization of Encounter Note 08082017"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"identifier": [
|
||||
{
|
||||
"system": "http://www.jurisdiction.com/insurer/123456",
|
||||
"value": "AnthemChristol08082017",
|
||||
"_value": {
|
||||
"fhir_comments": [
|
||||
" this is the value to which the response will refer "
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"basedOn": [
|
||||
{
|
||||
"reference": "Claim/good-health-claim-1"
|
||||
}
|
||||
],
|
||||
"status": "active",
|
||||
"subject": {
|
||||
"reference": "Patient/good-health-patient-1"
|
||||
},
|
||||
"recipient": [
|
||||
{
|
||||
"reference": "Organization/good-health"
|
||||
}
|
||||
],
|
||||
"payload": [
|
||||
{
|
||||
"contentString": "Please provide the summarization of encounter note. "
|
||||
}
|
||||
],
|
||||
"occurrenceDateTime": "2017-09-09T08:01:10-08:00",
|
||||
"authoredOn": "2017-09-09T08:01:10-08:00",
|
||||
"sender": {
|
||||
"reference": "Organization/example-payer"
|
||||
}
|
||||
}
|
|
@ -361,6 +361,15 @@
|
|||
the returned
|
||||
<![CDATA[<code>Location</code>]]> header value as well
|
||||
</action>
|
||||
<action type="add">
|
||||
A new flag has been add to the CLI upload-definitions command
|
||||
"-e" which allows skipping particular resources
|
||||
</action>
|
||||
<action type="add">
|
||||
An issue in JPA server has been corrected where if a CodeSystem
|
||||
resource was deleted, it was not possible to create a new resource
|
||||
with the same URI as the previous one
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.5" date="2017-06-08">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue