Fix web testing UI regression
This commit is contained in:
parent
6b9f8ec487
commit
202a1ea885
|
@ -21,5 +21,5 @@ package ca.uhn.fhir.rest.api;
|
|||
*/
|
||||
|
||||
public enum RequestTypeEnum {
|
||||
CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, TRACE, TRACK
|
||||
CONNECT, DELETE, GET, OPTIONS, PATCH, POST, PUT, TRACE, TRACK, HEAD
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class BanUnsupportedHttpMethodsInterceptor extends InterceptorAdapter {
|
|||
myAllowedMethods.add(RequestTypeEnum.DELETE);
|
||||
myAllowedMethods.add(RequestTypeEnum.PUT);
|
||||
myAllowedMethods.add(RequestTypeEnum.POST);
|
||||
myAllowedMethods.add(RequestTypeEnum.HEAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -194,7 +194,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
private FhirContext myContext;
|
||||
|
||||
// @PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT")
|
||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
|
||||
|
@ -669,7 +668,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
}
|
||||
}
|
||||
|
||||
private String parseContentTextIntoWords(IBaseResource theResource) {
|
||||
public String parseContentTextIntoWords(IBaseResource theResource) {
|
||||
StringBuilder retVal = new StringBuilder();
|
||||
@SuppressWarnings("rawtypes")
|
||||
List<IPrimitiveType> childElements = getContext().newTerser().getAllPopulatedChildElementsOfType(theResource, IPrimitiveType.class);
|
||||
|
@ -686,6 +685,17 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
return retVal.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateFullTextFields(final IBaseResource theResource, ResourceTable theEntity) {
|
||||
if (theEntity.getDeleted() != null) {
|
||||
theEntity.setNarrativeTextParsedIntoWords(null);
|
||||
theEntity.setContentTextParsedIntoWords(null);
|
||||
} else {
|
||||
theEntity.setNarrativeTextParsedIntoWords(parseNarrativeTextIntoWords(theResource));
|
||||
theEntity.setContentTextParsedIntoWords(parseContentTextIntoWords(theResource));
|
||||
}
|
||||
}
|
||||
|
||||
private void populateResourceId(final IBaseResource theResource, BaseHasResource theEntity) {
|
||||
IIdType id = theEntity.getIdDt();
|
||||
if (getContext().getVersion().getVersion().isRi()) {
|
||||
|
@ -931,10 +941,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
throw new NotImplementedException("");
|
||||
}
|
||||
|
||||
public void setConfig(DaoConfig theConfig) {
|
||||
myConfig = theConfig;
|
||||
}
|
||||
|
||||
// protected MetaDt toMetaDt(Collection<TagDefinition> tagDefinitions) {
|
||||
// MetaDt retVal = new MetaDt();
|
||||
// for (TagDefinition next : tagDefinitions) {
|
||||
|
@ -953,6 +959,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
// return retVal;
|
||||
// }
|
||||
|
||||
public void setConfig(DaoConfig theConfig) {
|
||||
myConfig = theConfig;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setContext(FhirContext theContext) {
|
||||
myContext = theContext;
|
||||
|
@ -1273,8 +1283,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
theEntity.setResourceLinks(links);
|
||||
theEntity.setHasLinks(links.isEmpty() == false);
|
||||
theEntity.setIndexStatus(INDEX_STATUS_INDEXED);
|
||||
theEntity.setNarrativeTextParsedIntoWords(parseNarrativeTextIntoWords(theResource));
|
||||
theEntity.setContentTextParsedIntoWords(parseContentTextIntoWords(theResource));
|
||||
populateFullTextFields(theResource, theEntity);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -1397,53 +1406,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
return updateEntity(theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime);
|
||||
}
|
||||
|
||||
protected void validateDeleteConflictsEmptyOrThrowException(List<DeleteConflict> theDeleteConflicts) {
|
||||
if (theDeleteConflicts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
for (DeleteConflict next : theDeleteConflicts) {
|
||||
String msg = "Unable to delete " + next.getTargetId().toUnqualifiedVersionless().getValue()
|
||||
+ " because at least one resource has a reference to this resource. First reference found was resource " + next.getTargetId().toUnqualifiedVersionless().getValue() + " in path "
|
||||
+ next.getSourcePath();
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, OO_SEVERITY_ERROR, msg, null, "processing");
|
||||
}
|
||||
|
||||
throw new ResourceVersionConflictException("Delete failed because of constraint failure", oo);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked immediately before storing a new resource, or an update to an existing resource to allow the DAO to ensure that it is valid for persistence. By default, checks for the
|
||||
* "subsetted" tag and rejects resources which have it. Subclasses should call the superclass implementation to preserve this check.
|
||||
*
|
||||
* @param theResource
|
||||
* The resource that is about to be persisted
|
||||
* @param theEntityToSave
|
||||
* TODO
|
||||
*/
|
||||
protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) {
|
||||
Object tag = null;
|
||||
if (theResource instanceof IResource) {
|
||||
IResource res = (IResource) theResource;
|
||||
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(res);
|
||||
if (tagList != null) {
|
||||
tag = tagList.getTag(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE);
|
||||
}
|
||||
} else {
|
||||
IAnyResource res = (IAnyResource) theResource;
|
||||
tag = res.getMeta().getTag(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE);
|
||||
}
|
||||
|
||||
if (tag != null) {
|
||||
throw new UnprocessableEntityException("Resource contains the 'subsetted' tag, and must not be stored as it may contain a subset of available data");
|
||||
}
|
||||
|
||||
String resName = getContext().getResourceDefinition(theResource).getName();
|
||||
validateChildReferences(theResource, resName);
|
||||
|
||||
}
|
||||
|
||||
private void validateChildReferences(IBase theElement, String thePath) {
|
||||
if (theElement == null) {
|
||||
return;
|
||||
|
@ -1499,6 +1461,53 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
}
|
||||
}
|
||||
|
||||
protected void validateDeleteConflictsEmptyOrThrowException(List<DeleteConflict> theDeleteConflicts) {
|
||||
if (theDeleteConflicts.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBaseOperationOutcome oo = OperationOutcomeUtil.newInstance(getContext());
|
||||
for (DeleteConflict next : theDeleteConflicts) {
|
||||
String msg = "Unable to delete " + next.getTargetId().toUnqualifiedVersionless().getValue()
|
||||
+ " because at least one resource has a reference to this resource. First reference found was resource " + next.getTargetId().toUnqualifiedVersionless().getValue() + " in path "
|
||||
+ next.getSourcePath();
|
||||
OperationOutcomeUtil.addIssue(getContext(), oo, OO_SEVERITY_ERROR, msg, null, "processing");
|
||||
}
|
||||
|
||||
throw new ResourceVersionConflictException("Delete failed because of constraint failure", oo);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked immediately before storing a new resource, or an update to an existing resource to allow the DAO to ensure that it is valid for persistence. By default, checks for the
|
||||
* "subsetted" tag and rejects resources which have it. Subclasses should call the superclass implementation to preserve this check.
|
||||
*
|
||||
* @param theResource
|
||||
* The resource that is about to be persisted
|
||||
* @param theEntityToSave
|
||||
* TODO
|
||||
*/
|
||||
protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) {
|
||||
Object tag = null;
|
||||
if (theResource instanceof IResource) {
|
||||
IResource res = (IResource) theResource;
|
||||
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(res);
|
||||
if (tagList != null) {
|
||||
tag = tagList.getTag(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE);
|
||||
}
|
||||
} else {
|
||||
IAnyResource res = (IAnyResource) theResource;
|
||||
tag = res.getMeta().getTag(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE);
|
||||
}
|
||||
|
||||
if (tag != null) {
|
||||
throw new UnprocessableEntityException("Resource contains the 'subsetted' tag, and must not be stored as it may contain a subset of available data");
|
||||
}
|
||||
|
||||
String resName = getContext().getResourceDefinition(theResource).getName();
|
||||
validateChildReferences(theResource, resName);
|
||||
|
||||
}
|
||||
|
||||
protected static boolean isValidPid(IIdType theId) {
|
||||
if (theId == null || theId.getIdPart() == null) {
|
||||
return false;
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum.ResourceMetadataKeySupportingAnyResource;
|
||||
|
@ -70,4 +71,6 @@ public interface IDao {
|
|||
IBaseResource toResource(BaseHasResource theEntity, boolean theForHistoryOperation);
|
||||
|
||||
<R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity, boolean theForHistoryOperation);
|
||||
|
||||
void populateFullTextFields(IBaseResource theResource, ResourceTable theEntity);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,9 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3 {
|
|||
search = myValueSetDao.search(ValueSet.SP_URL, new UriParam(theUri));
|
||||
}
|
||||
} else if ("StructureDefinition".equals(resourceName)) {
|
||||
if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
|
||||
return null;
|
||||
}
|
||||
search = myStructureDefinitionDao.search(StructureDefinition.SP_URL, new UriParam(theUri));
|
||||
} else if ("Questionnaire".equals(resourceName)) {
|
||||
search = myQuestionnaireDao.search(IAnyResource.SP_RES_ID, new StringParam(id.getIdPart()));
|
||||
|
|
|
@ -77,7 +77,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
|||
@Index(name = "IDX_RES_DATE", columnList="RES_UPDATED"),
|
||||
@Index(name = "IDX_RES_LANG", columnList="RES_TYPE,RES_LANGUAGE"),
|
||||
@Index(name = "IDX_RES_PROFILE", columnList="RES_PROFILE"),
|
||||
@Index(name = "IDX_INDEXSTATUS", columnList="SP_INDEX_STATUS")
|
||||
@Index(name = "IDX_INDEXSTATUS", columnList="SP_INDEX_STATUS")
|
||||
})
|
||||
@AnalyzerDefs({
|
||||
@AnalyzerDef(name = "autocompleteEdgeAnalyzer",
|
||||
|
|
|
@ -220,6 +220,8 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
|||
@Autowired
|
||||
@Qualifier("myValueSetDaoDstu3")
|
||||
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
||||
@Autowired
|
||||
protected PlatformTransactionManager myTransactionMgr;
|
||||
@After()
|
||||
public void afterGrabCaches() {
|
||||
ourValueSetDao = myValueSetDao;
|
||||
|
|
|
@ -30,6 +30,9 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
|||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
|
@ -49,6 +52,36 @@ import ca.uhn.fhir.util.TestUtil;
|
|||
public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3SearchNoFtTest.class);
|
||||
|
||||
@Test
|
||||
public void testSearchWithRevIncludes() {
|
||||
final String methodName = "testSearchWithRevIncludes";
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionMgr);
|
||||
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
|
||||
IIdType pid = txTemplate.execute(new TransactionCallback<IIdType>() {
|
||||
|
||||
@Override
|
||||
public IIdType doInTransaction(TransactionStatus theStatus) {
|
||||
org.hl7.fhir.dstu3.model.Patient p = new org.hl7.fhir.dstu3.model.Patient();
|
||||
p.addName().addFamily(methodName);
|
||||
IIdType pid = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||
|
||||
org.hl7.fhir.dstu3.model.Condition c = new org.hl7.fhir.dstu3.model.Condition();
|
||||
c.getSubject().setReferenceElement(pid);
|
||||
myConditionDao.create(c);
|
||||
|
||||
return pid;
|
||||
}
|
||||
});
|
||||
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Patient.SP_RES_ID, new StringParam(pid.getIdPart()));
|
||||
map.addRevInclude(Condition.INCLUDE_PATIENT);
|
||||
IBundleProvider results = myPatientDao.search(map);
|
||||
List<IBaseResource> foundResources = results.getResources(0, results.size());
|
||||
assertEquals(Patient.class, foundResources.get(0).getClass());
|
||||
assertEquals(Condition.class, foundResources.get(1).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeSearch() {
|
||||
Subscription subs = new Subscription();
|
||||
|
@ -276,7 +309,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
@Test
|
||||
public void testHasParameter() {
|
||||
IIdType pid0, pid1;
|
||||
IIdType pid0;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
|
@ -287,7 +320,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
patient.addName().addFamily("Tester").addGiven("Joe");
|
||||
pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
|
@ -907,6 +940,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testSearchLastUpdatedParamWithComparator() throws InterruptedException {
|
||||
IIdType id0;
|
||||
|
@ -2339,7 +2373,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
ValueSet vs2 = new ValueSet();
|
||||
vs2.setUrl("http://hl7.org/foo/bar");
|
||||
IIdType id2 = myValueSetDao.create(vs2, mySrd).getId().toUnqualifiedVersionless();
|
||||
myValueSetDao.create(vs2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
IBundleProvider result;
|
||||
result = myValueSetDao.search(ValueSet.SP_URL, new UriParam("http://hl7.org/fhir/ValueSet/basic-resource-type"));
|
||||
|
|
|
@ -5,31 +5,25 @@ import static org.junit.Assert.assertThat;
|
|||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
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.IdType;
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.dstu3.model.OperationOutcome;
|
||||
import org.hl7.fhir.dstu3.model.Organization;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.StructureDefinition;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
||||
|
@ -40,6 +34,31 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateStructureDefinition() throws Exception {
|
||||
String input = IOUtils.toString(getClass().getResourceAsStream("/sd-david-dhtest7.json"), StandardCharsets.UTF_8);
|
||||
StructureDefinition sd = myFhirCtx.newJsonParser().parseResource(StructureDefinition.class, input);
|
||||
|
||||
|
||||
ourLog.info("Starting validation");
|
||||
try {
|
||||
myStructureDefinitionDao.validate(sd, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
} catch (PreconditionFailedException e) {
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
}
|
||||
ourLog.info("Done validation");
|
||||
|
||||
StopWatch sw = new StopWatch();
|
||||
ourLog.info("Starting validation");
|
||||
try {
|
||||
myStructureDefinitionDao.validate(sd, null, null, null, ValidationModeEnum.UPDATE, null, mySrd);
|
||||
} catch (PreconditionFailedException e) {
|
||||
// ok
|
||||
}
|
||||
ourLog.info("Done validation in {}ms", sw.getMillis());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
{
|
||||
"resourceType": "StructureDefinition",
|
||||
"id": "dhtest7",
|
||||
"meta": {
|
||||
"versionId": "2",
|
||||
"lastUpdated": "2016-09-01T03:05:36.257-04:00"
|
||||
},
|
||||
"url": "http://fhirtest.uhn.ca/baseDstu3/StructureDefinition/dhtest7",
|
||||
"name": "dhtest7",
|
||||
"status": "draft",
|
||||
"experimental": true,
|
||||
"description": "Base StructureDefinition for Basic Resource",
|
||||
"requirements": "Need some way to safely (without breaking interoperability) allow implementers to exchange content not supported by the initial set of declared resources.",
|
||||
"code": [
|
||||
{
|
||||
"system": "http://fhir.hl7.org.nz/NamingSystem/application",
|
||||
"code": "clinfhir"
|
||||
}
|
||||
],
|
||||
"kind": "resource",
|
||||
"abstract": false,
|
||||
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Basic",
|
||||
"derivation": "constraint",
|
||||
"snapshot": {
|
||||
"element": [
|
||||
{
|
||||
"path": "Basic",
|
||||
"short": "Resource for non-supported content",
|
||||
"definition": "Basic is used for handling concepts not yet defined in FHIR, narrative-only resources that don't map to an existing resource, and custom resources not appropriate for inclusion in the FHIR specification.",
|
||||
"alias": [
|
||||
"Z-resource",
|
||||
"Extension-resource",
|
||||
"Custom-resource"
|
||||
],
|
||||
"min": 0,
|
||||
"max": "*",
|
||||
"type": [
|
||||
{
|
||||
"code": "DomainResource"
|
||||
}
|
||||
],
|
||||
"isSummary": true,
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "Act, Entity or Role"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "infrastructure.structure"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.id",
|
||||
"definition": "Id",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"base": {
|
||||
"path": "Resource.id",
|
||||
"min": 0,
|
||||
"max": "1"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"code": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.meta",
|
||||
"definition": "The meta element",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"base": {
|
||||
"path": "Resource.meta",
|
||||
"min": 0,
|
||||
"max": "1"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"code": "Meta"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.text",
|
||||
"definition": "Narrative",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"base": {
|
||||
"path": "DomainResource.text",
|
||||
"min": 0,
|
||||
"max": "*"
|
||||
},
|
||||
"type": [
|
||||
{
|
||||
"code": "Narrative"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.identifier",
|
||||
"short": "Business identifier",
|
||||
"definition": "Identifier assigned to the resource for business purposes, outside the context of FHIR.",
|
||||
"min": 0,
|
||||
"max": "*",
|
||||
"type": [
|
||||
{
|
||||
"code": "Identifier"
|
||||
}
|
||||
],
|
||||
"isSummary": true,
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "./identifier"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.code",
|
||||
"short": "Kind of Resource",
|
||||
"definition": "Identifies the 'type' of resource - equivalent to the resource name for other resources.",
|
||||
"comments": "Because resource references will only be able to indicate 'Basic', the type of reference will need to be specified in a Profile identified as part of the resource. Refer to the resource notes section for information on appropriate terminologies for this code.",
|
||||
"requirements": "Must be able to distinguish different types of \"basic\" resources.",
|
||||
"min": 1,
|
||||
"max": "1",
|
||||
"type": [
|
||||
{
|
||||
"code": "CodeableConcept"
|
||||
}
|
||||
],
|
||||
"isModifier": true,
|
||||
"isSummary": true,
|
||||
"binding": {
|
||||
"strength": "example",
|
||||
"description": "Codes for identifying types of resources not yet defined by FHIR",
|
||||
"valueSetReference": {
|
||||
"reference": "http://hl7.org/fhir/ValueSet/basic-resource-type"
|
||||
}
|
||||
},
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "./code"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "what"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.subject",
|
||||
"short": "Identifies the focus of this resource",
|
||||
"definition": "Identifies the patient, practitioner, device or any other resource that is the \"focus\" of this resource.",
|
||||
"comments": "Optional as not all resources potential resources will have subjects. Resources associated with multiple subjects can handle this via extension.",
|
||||
"requirements": "Needed for partitioning the resource by Patient.",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"type": [
|
||||
{
|
||||
"code": "Reference",
|
||||
"profile": "http://hl7.org/fhir/StructureDefinition/Resource"
|
||||
}
|
||||
],
|
||||
"isSummary": true,
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "./participation[typeCode='SBJ'] (possibly through a ControlAct and Role)"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "who.focus"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.created",
|
||||
"short": "When created",
|
||||
"definition": "Identifies when the resource was first created.",
|
||||
"requirements": "Allows ordering resource instances by time.",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"type": [
|
||||
{
|
||||
"code": "date"
|
||||
}
|
||||
],
|
||||
"isSummary": true,
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "./participation[typeCode='AUT']/time (possibly through a ControlAct and Role)"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "when.recorded"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "Basic.author",
|
||||
"short": "Who created",
|
||||
"definition": "Indicates who was responsible for creating the resource instance.",
|
||||
"requirements": "Needed for partitioning the resource.",
|
||||
"min": 0,
|
||||
"max": "1",
|
||||
"type": [
|
||||
{
|
||||
"code": "Reference",
|
||||
"profile": "http://hl7.org/fhir/StructureDefinition/Practitioner"
|
||||
},
|
||||
{
|
||||
"code": "Reference",
|
||||
"profile": "http://hl7.org/fhir/StructureDefinition/Patient"
|
||||
},
|
||||
{
|
||||
"code": "Reference",
|
||||
"profile": "http://hl7.org/fhir/StructureDefinition/RelatedPerson"
|
||||
}
|
||||
],
|
||||
"isSummary": true,
|
||||
"mapping": [
|
||||
{
|
||||
"identity": "rim",
|
||||
"map": "./participation[typeCode='SUB'] (possibly through a ControlAct and Role)"
|
||||
},
|
||||
{
|
||||
"identity": "w5",
|
||||
"map": "who.author"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -10,11 +10,7 @@ import org.apache.commons.lang3.time.DateUtils;
|
|||
import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowire;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
|
@ -23,10 +19,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
|
||||
|
||||
|
@ -118,33 +112,6 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
return requestValidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean which validates outgoing responses
|
||||
*/
|
||||
@Bean
|
||||
@Lazy
|
||||
public ResponseValidatingInterceptor responseValidatingInterceptor() {
|
||||
ResponseValidatingInterceptor responseValidator = new ResponseValidatingInterceptor();
|
||||
responseValidator.setResponseHeaderValueNoIssues("Validation did not detect any issues");
|
||||
responseValidator.setFailOnSeverity(null);
|
||||
responseValidator.setAddResponseHeaderOnSeverity(null);
|
||||
responseValidator.setAddResponseOutcomeHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.METADATA);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.EXTENDED_OPERATION_SERVER);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.GET_PAGE);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.HISTORY_INSTANCE);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.HISTORY_SYSTEM);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.HISTORY_TYPE);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.SEARCH_SYSTEM);
|
||||
responseValidator.addExcludeOperationType(RestOperationTypeEnum.SEARCH_TYPE);
|
||||
responseValidator.addValidatorModule(instanceValidatorDstu3());
|
||||
responseValidator.setIgnoreValidatorExceptions(true);
|
||||
|
||||
return responseValidator;
|
||||
}
|
||||
|
||||
@Bean(autowire = Autowire.BY_TYPE)
|
||||
public IServerInterceptor subscriptionSecurityInterceptor() {
|
||||
return new SubscriptionsRequireManualActivationInterceptorDstu3();
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.containsString;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -11,6 +12,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpHead;
|
||||
import org.apache.http.client.methods.HttpOptions;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
|
@ -48,7 +50,7 @@ public class ServerFeaturesDstu2Test {
|
|||
public void testOptions() throws Exception {
|
||||
HttpOptions httpGet = new HttpOptions("http://localhost:" + ourPort + "");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
@ -60,7 +62,7 @@ public class ServerFeaturesDstu2Test {
|
|||
|
||||
httpGet = new HttpOptions("http://localhost:" + ourPort + "/");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
@ -76,7 +78,7 @@ public class ServerFeaturesDstu2Test {
|
|||
public void testOptionsForNonBasePath1() throws Exception {
|
||||
HttpOptions httpGet = new HttpOptions("http://localhost:" + ourPort + "/Foo");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
@ -90,7 +92,7 @@ public class ServerFeaturesDstu2Test {
|
|||
public void testOptionsForNonBasePath2() throws Exception {
|
||||
HttpOptions httpGet = new HttpOptions("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
@ -104,7 +106,7 @@ public class ServerFeaturesDstu2Test {
|
|||
public void testOptionsForNonBasePath3() throws Exception {
|
||||
HttpOptions httpGet = new HttpOptions("http://localhost:" + ourPort + "/metadata");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
ourLog.info(responseContent);
|
||||
|
@ -115,18 +117,30 @@ public class ServerFeaturesDstu2Test {
|
|||
public void testOptionsJson() throws Exception {
|
||||
HttpOptions httpGet = new HttpOptions("http://localhost:" + ourPort + "?_format=json");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("resourceType\":\"Conformance"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeadJson() throws Exception {
|
||||
HttpHead httpGet = new HttpHead("http://localhost:" + ourPort + "/Patient/123");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
assertEquals(null, status.getEntity());
|
||||
|
||||
ourLog.info(status.toString());
|
||||
|
||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.getFirstHeader("x-powered-by").getValue(), containsString("HAPI"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAndUnregisterResourceProviders() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("PRP1"));
|
||||
|
@ -140,7 +154,7 @@ public class ServerFeaturesDstu2Test {
|
|||
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
|
||||
status = ourClient.execute(httpGet);
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, containsString("PRP2"));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
|
@ -9,10 +11,7 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.methods.HttpTrace;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
|
@ -56,6 +55,19 @@ public class BanUnsupprtedHttpMethodsInterceptorDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeadJson() throws Exception {
|
||||
HttpHead httpGet = new HttpHead("http://localhost:" + ourPort + "/Patient/123");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
assertEquals(null, status.getEntity());
|
||||
|
||||
ourLog.info(status.toString());
|
||||
|
||||
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||
assertThat(status.getFirstHeader("x-powered-by").getValue(), containsString("HAPI"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHttpTrackNotEnabled() throws Exception {
|
||||
HttpRequestBase req = new HttpRequestBase() {
|
||||
|
|
|
@ -253,8 +253,8 @@
|
|||
<span class="glyphicon glyphicon-step-backward"></span>
|
||||
Prev Page
|
||||
</button>
|
||||
<script type="text/javascript">
|
||||
if (<th:block th:text="${riBundle.getLink('prev') == null}"/>) {
|
||||
<script type="text/javascript" th:inline="javascript">
|
||||
if ([[${riBundle.getLink('prev') == null}]]) {
|
||||
$('#page-prev-btn').prop('disabled', true);
|
||||
}
|
||||
$('#page-prev-btn').click(function() {
|
||||
|
@ -270,8 +270,8 @@
|
|||
<span class="glyphicon glyphicon-step-forward"></span>
|
||||
Next Page
|
||||
</button>
|
||||
<script type="text/javascript">
|
||||
if (<th:block th:text="${riBundle.getLink('next') == null}"/>) {
|
||||
<script type="text/javascript" th:inline="javascript">
|
||||
if ([[${riBundle.getLink('next') == null}]]) {
|
||||
$('#page-next-btn').prop('disabled', true);
|
||||
}
|
||||
$('#page-next-btn').click(function() {
|
||||
|
|
|
@ -12,6 +12,18 @@
|
|||
<![CDATA[<code>_include</code>]]> resources to the response bundle if they were
|
||||
referred to by a contained reosurce. Thanks to Neal Acharya for reporting!
|
||||
</action>
|
||||
<action type="fix">
|
||||
Fix regression in web testing UI where "prev" and "next" buttons don't work
|
||||
when showing a result bundle
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server should not attempt to resolve built-in FHIR StructureDefinitions from the
|
||||
database (this causes a significant performance hit when validating)
|
||||
</action>
|
||||
<action type="fix">
|
||||
BanUnsupportedHttpMethodsInterceptor was erroring out when a client
|
||||
attempts HTTP HEAD requests
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.0" date="2016-08-30">
|
||||
<action type="fix">
|
||||
|
|
|
@ -239,6 +239,18 @@ public DaoConfig daoConfig() {
|
|||
|
||||
</section>
|
||||
|
||||
<section name="Additional Information">
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.openhealthhub.org/t/hapi-terminology-server-uk-snomed-ct-import/592">This page</a>
|
||||
has information on loading national editions (UK specifically) of SNOMED CT files into
|
||||
the database.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<!--
|
||||
alter table hfj_res_link ALTER COLUMN "TARGET_RESOURCE_ID" NULL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue