Correctly handle custom types in programatic access to JPA
This commit is contained in:
parent
090f079442
commit
eba136d706
|
@ -694,13 +694,16 @@ public class FhirContext {
|
|||
* The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be
|
||||
* <code>null</code> or empty.
|
||||
* @param theClass
|
||||
* The resource type. Must not be <code>null</code> or empty.
|
||||
* The resource type, or <code>null</code> to clear any existing type
|
||||
*/
|
||||
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
||||
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
||||
Validate.notNull(theClass, "theProfile must not be null");
|
||||
if (theClass == null) {
|
||||
myDefaultTypeForProfile.remove(theProfile);
|
||||
} else {
|
||||
myDefaultTypeForProfile.put(theProfile, theClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||
|
|
|
@ -733,6 +733,17 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
extractTagsRi((IAnyResource) theResource, theEntity, allDefs);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||
if (def.isStandardType() == false) {
|
||||
String profile = def.getResourceProfile("");
|
||||
if (isNotBlank(profile)) {
|
||||
TagDefinition tag = getTag(TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null);
|
||||
allDefs.add(tag);
|
||||
theEntity.addTag(tag);
|
||||
theEntity.setHasTags(true);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<ResourceTag> existingTags = new ArrayList<ResourceTag>();
|
||||
if (theEntity.isHasTags()) {
|
||||
existingTags.addAll(theEntity.getTags());
|
||||
|
@ -1003,9 +1014,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
@Override
|
||||
public IBaseResource toResource(BaseHasResource theEntity, boolean theForHistoryOperation) {
|
||||
RuntimeResourceDefinition type = myContext.getResourceDefinition(theEntity.getResourceType());
|
||||
return toResource(type.getImplementingClass(), theEntity, theForHistoryOperation);
|
||||
Class<? extends IBaseResource> resourceType = type.getImplementingClass();
|
||||
return toResource(resourceType, theEntity, theForHistoryOperation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity, boolean theForHistoryOperation) {
|
||||
String resourceText = null;
|
||||
|
@ -1022,14 +1035,34 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the appropriate custom type if one is specified in the context
|
||||
*/
|
||||
Class<R> resourceType = theResourceType;
|
||||
if (myContext.hasDefaultTypeForProfile()) {
|
||||
for (BaseTag nextTag : theEntity.getTags()) {
|
||||
if (nextTag.getTag().getTagType() == TagTypeEnum.PROFILE) {
|
||||
String profile = nextTag.getTag().getCode();
|
||||
if (isNotBlank(profile)) {
|
||||
Class<? extends IBaseResource> newType = myContext.getDefaultTypeForProfile(profile);
|
||||
if (newType != null && theResourceType.isAssignableFrom(newType)) {
|
||||
ourLog.debug("Using custom type {} for profile: {}", newType.getName(), profile);
|
||||
resourceType = (Class<R>) newType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IParser parser = theEntity.getEncoding().newParser(getContext(theEntity.getFhirVersion()));
|
||||
R retVal;
|
||||
try {
|
||||
retVal = parser.parseResource(theResourceType, resourceText);
|
||||
retVal = parser.parseResource(resourceType, resourceText);
|
||||
} catch (Exception e) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("Failed to parse database resource[");
|
||||
b.append(theResourceType);
|
||||
b.append(resourceType);
|
||||
b.append("/");
|
||||
b.append(theEntity.getIdDt().getIdPart());
|
||||
b.append(" (pid ");
|
||||
|
@ -1045,10 +1078,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||
|
||||
if (retVal instanceof IResource) {
|
||||
IResource res = (IResource) retVal;
|
||||
retVal = populateResourceMetadataHapi(theResourceType, theEntity, theForHistoryOperation, res);
|
||||
retVal = populateResourceMetadataHapi(resourceType, theEntity, theForHistoryOperation, res);
|
||||
} else {
|
||||
IAnyResource res = (IAnyResource) retVal;
|
||||
retVal = populateResourceMetadataRi(theResourceType, theEntity, theForHistoryOperation, res);
|
||||
retVal = populateResourceMetadataRi(resourceType, theEntity, theForHistoryOperation, res);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.Observation;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
|
||||
@ResourceDef(name = "Observation", profile = CustomObservationDstu3.PROFILE)
|
||||
public class CustomObservationDstu3 extends Observation {
|
||||
|
||||
public static final String PROFILE = "http://custom_ObservationDstu3";
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Extension(definedLocally = false, isModifier = false, url = "http://eyeColour")
|
||||
@Child(name = "eyeColour")
|
||||
private StringType myEyeColour;
|
||||
|
||||
public StringType getEyeColour() {
|
||||
return myEyeColour;
|
||||
}
|
||||
|
||||
public void setEyeColour(StringType theEyeColour) {
|
||||
myEyeColour = theEyeColour;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
|
||||
@SuppressWarnings({ })
|
||||
public class FhirResourceDaoCustomTypeDstu3Test extends BaseJpaDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCustomTypeDstu3Test.class);
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myFhirCtx.setDefaultTypeForProfile(CustomObservationDstu3.PROFILE, CustomObservationDstu3.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveAndRestore() {
|
||||
CustomObservationDstu3 obs = new CustomObservationDstu3();
|
||||
obs.setEyeColour(new StringType("blue"));
|
||||
|
||||
IIdType id = myObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
|
||||
CustomObservationDstu3 read = (CustomObservationDstu3) myObservationDao.read(id);
|
||||
assertEquals("blue", read.getEyeColour().getValue());
|
||||
|
||||
IBundleProvider found = myObservationDao.search(new SearchParameterMap());
|
||||
assertEquals(1, found.size());
|
||||
CustomObservationDstu3 search = (CustomObservationDstu3) found.getResources(0, 1).get(0);
|
||||
assertEquals("blue", search.getEyeColour().getValue());
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
myFhirCtx.setDefaultTypeForProfile(CustomObservationDstu3.PROFILE, null);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -8,7 +10,6 @@ import org.junit.Test;
|
|||
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class FhirResourceDaoDocumentDstu3Test extends BaseJpaDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDocumentDstu3Test.class);
|
||||
|
@ -21,7 +22,7 @@ public class FhirResourceDaoDocumentDstu3Test extends BaseJpaDstu3Test {
|
|||
|
||||
@Test
|
||||
public void testPostDocument() throws Exception {
|
||||
String input = IOUtils.toString(getClass().getResourceAsStream("/sample-document.xml"));
|
||||
String input = IOUtils.toString(getClass().getResourceAsStream("/sample-document.xml"), StandardCharsets.UTF_8);
|
||||
Bundle inputBundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||
DaoMethodOutcome responseBundle = myBundleDao.create(inputBundle, mySrd);
|
||||
}
|
||||
|
|
|
@ -13,11 +13,14 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
|
||||
|
@ -82,6 +85,18 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
assertEquals(Condition.class, foundResources.get(1).getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* #454
|
||||
*/
|
||||
@Test
|
||||
public void testIndexWithUtf8Chars() throws IOException {
|
||||
String input = IOUtils.toString(getClass().getResourceAsStream("/bug454_utf8.json"), StandardCharsets.UTF_8);
|
||||
|
||||
CodeSystem cs = (CodeSystem) myFhirCtx.newJsonParser().parseResource(input);
|
||||
myCodeSystemDao.create(cs);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCodeSearch() {
|
||||
Subscription subs = new Subscription();
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"resourceType": "CodeSystem",
|
||||
"url": "http://nestvision.com/fhir/myexample-yh",
|
||||
"name": "NestVision Restful Interactions",
|
||||
"status": "active",
|
||||
"publisher": "杨浩",
|
||||
"description": "this is a codesystem example.",
|
||||
"caseSensitive": true,
|
||||
"concept": [
|
||||
{
|
||||
"code": "mygod",
|
||||
"display": "wodetian",
|
||||
"definition": "this is a translate."
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
call SYSCS_UTIL.SYSCS_COMPRESS_TABLE('SA', 'HFJ_SEARCH_RESULT', 1);
|
||||
CALL SYSCS_UTIL.SYSCS_INPLACE_COMPRESS_TABLE( 'SA', 'HFJ_SEARCH_RESULT', 0, 0, 1 );
|
||||
|
||||
|
||||
dd if=/dev/urandom of=/opt/glassfish/tmp.tmp bs=1M count=500
|
||||
|
|
|
@ -102,6 +102,11 @@
|
|||
JAX-RS server was not able to handle the new mime types defined
|
||||
in STU3
|
||||
</action>
|
||||
<action type="fix">
|
||||
JPA server did not handle custom types when being called
|
||||
programatically (I.e. not through HTTP interface). Thanks to
|
||||
Anthony Mei for pointing this out!
|
||||
</action>
|
||||
</release>
|
||||
<release version="2.0" date="2016-08-30">
|
||||
<action type="fix">
|
||||
|
|
Loading…
Reference in New Issue