More JPA work
This commit is contained in:
parent
78d712de25
commit
03bf040ef9
|
@ -20,6 +20,8 @@ package ca.uhn.fhir.model.primitive;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -99,10 +101,11 @@ public class IdDt extends BasePrimitive<String> {
|
|||
* If the value is not a valid BigDecimal
|
||||
*/
|
||||
public BigDecimal asBigDecimal() {
|
||||
if (getValue() == null) {
|
||||
String val = getUnqualifiedId();
|
||||
if (isBlank(val)) {
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(getValueAsString());
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,10 +115,11 @@ public class IdDt extends BasePrimitive<String> {
|
|||
* If the value is not a valid Long
|
||||
*/
|
||||
public Long asLong() {
|
||||
if (getValue() == null) {
|
||||
String val = getUnqualifiedId();
|
||||
if (isBlank(val)) {
|
||||
return null;
|
||||
}
|
||||
return Long.parseLong(getValueAsString());
|
||||
return Long.parseLong(val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,11 +26,16 @@ import java.util.List;
|
|||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
|
||||
public class FhirTerser {
|
||||
|
||||
|
@ -55,7 +60,6 @@ public class FhirTerser {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private BaseRuntimeChildDefinition getDefinition(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, List<String> theSubList) {
|
||||
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));
|
||||
|
||||
|
@ -100,4 +104,87 @@ public class FhirTerser {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all child elements (including the resource itself) which are <b>non-empty</b>
|
||||
* and are either of the exact type specified, or are a subclass of that type.
|
||||
* <p>
|
||||
* For example, specifying a type of {@link StringDt} would return all non-empty string instances within
|
||||
* the message. Specifying a type of {@link IResource} would return the resource itself, as well as any contained resources.
|
||||
* </p>
|
||||
* @param theResourceT The resource instance to search. Must not be null.
|
||||
* @param theType The type to search for. Must not be null.
|
||||
* @return
|
||||
*/
|
||||
public <T extends IElement> List<T> getAllPopulatedChildElementsOfType(IResource theResource, Class<T> theType) {
|
||||
ArrayList<T> retVal = new ArrayList<T>();
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(theResource);
|
||||
getAllChildElementsOfType(theResource, def, theType, retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private <T extends IElement> void getAllChildElementsOfType(IElement theElement, BaseRuntimeElementDefinition<?> theDefinition, Class<T> theType, ArrayList<T> theList) {
|
||||
if (theElement.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
addIfCorrectType(theElement, theType, theList);
|
||||
addUndeclaredExtensions(theElement, theType, theList);
|
||||
|
||||
switch (theDefinition.getChildType()) {
|
||||
case PRIMITIVE_XHTML:
|
||||
case PRIMITIVE_DATATYPE:
|
||||
case RESOURCE_REF:
|
||||
// These are primitive types
|
||||
break;
|
||||
case RESOURCE_BLOCK:
|
||||
case COMPOSITE_DATATYPE:
|
||||
case RESOURCE: {
|
||||
BaseRuntimeElementCompositeDefinition<?> childDef = (BaseRuntimeElementCompositeDefinition<?>) theDefinition;
|
||||
for (BaseRuntimeChildDefinition nextChild : childDef.getChildren()) {
|
||||
List<? extends IElement> values = nextChild.getAccessor().getValues(theElement);
|
||||
if (values != null) {
|
||||
for (IElement nextValue : values) {
|
||||
if (nextValue == null) {
|
||||
continue;
|
||||
}
|
||||
BaseRuntimeElementDefinition<?> childElementDef = nextChild.getChildElementDefinitionByDatatype(nextValue.getClass());
|
||||
getAllChildElementsOfType(nextValue, childElementDef, theType, theList);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONTAINED_RESOURCES: {
|
||||
ContainedDt value = (ContainedDt) theElement;
|
||||
for (IResource next : value.getContainedResources()) {
|
||||
BaseRuntimeElementCompositeDefinition<?> def = myContext.getResourceDefinition(next);
|
||||
getAllChildElementsOfType(next, def, theType, theList);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EXTENSION_DECLARED:
|
||||
case UNDECL_EXT: {
|
||||
throw new IllegalStateException("state should not happen: " + theDefinition.getChildType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends IElement> void addUndeclaredExtensions(IElement theElement, Class<T> theType, ArrayList<T> theList) {
|
||||
if (theElement instanceof ISupportsUndeclaredExtensions) {
|
||||
ISupportsUndeclaredExtensions elem = (ISupportsUndeclaredExtensions) theElement;
|
||||
for (ExtensionDt nextExt : elem.getUndeclaredExtensions()) {
|
||||
addIfCorrectType(nextExt, theType, theList);
|
||||
addIfCorrectType(nextExt.getValue(), theType, theList);
|
||||
addUndeclaredExtensions(nextExt, theType, theList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends IElement> void addIfCorrectType(IElement theElement, Class<T> theType, ArrayList<T> theList) {
|
||||
if (theElement != null && theType.isAssignableFrom(theElement.getClass())) {
|
||||
theList.add((T) theElement);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.test;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirTerserTest {
|
||||
|
||||
@Test
|
||||
public void testGetAllPopulatedChildElementsOfType() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:foo");
|
||||
p.addAddress().addLine("Line1");
|
||||
p.addAddress().addLine("Line2");
|
||||
p.addName().addFamily("Line3");
|
||||
|
||||
FhirTerser t = new FhirContext().newTerser();
|
||||
List<StringDt> strings = t.getAllPopulatedChildElementsOfType(p, StringDt.class);
|
||||
|
||||
assertEquals(3, strings.size());
|
||||
assertThat(strings, containsInAnyOrder(new StringDt("Line1"), new StringDt("Line2"), new StringDt("Line3")));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,431 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.AddressDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContactDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public abstract class BaseFhirDao {
|
||||
private FhirContext myContext=new FhirContext();
|
||||
@PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT")
|
||||
private EntityManager myEntityManager;
|
||||
@Autowired
|
||||
private List<IFhirResourceDao<?>> myResourceDaos;
|
||||
|
||||
private Map<Class<? extends IResource>, IFhirResourceDao<?>> myResourceTypeToDao;
|
||||
|
||||
public FhirContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
public void setContext(FhirContext theContext) {
|
||||
myContext = theContext;
|
||||
}
|
||||
|
||||
protected List<ResourceLink> extractResourceLinks(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceLink> retVal = new ArrayList<ResourceLink>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResourceLink nextEntity;
|
||||
if (nextObject instanceof ResourceReferenceDt) {
|
||||
ResourceReferenceDt nextValue = (ResourceReferenceDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String typeString = nextValue.getResourceId().getResourceType();
|
||||
if (isBlank(typeString)) {
|
||||
continue;
|
||||
}
|
||||
Class<? extends IResource> type = getContext().getResourceDefinition(typeString).getImplementingClass();
|
||||
String id = nextValue.getResourceId().getUnqualifiedId();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IFhirResourceDao<?> dao = getDao(type);
|
||||
if (dao == null) {
|
||||
throw new InvalidRequestException("This server is not able to handle resources of type: " + nextValue.getResourceId().getResourceType());
|
||||
}
|
||||
Long valueOf;
|
||||
try {
|
||||
valueOf = Long.valueOf(id);
|
||||
} catch (Exception e) {
|
||||
String resName = getContext().getResourceDefinition(type).getName();
|
||||
throw new InvalidRequestException("Resource ID " + resName + "/" + id + " is invalid (must be numeric), specified in path: " + nextPath);
|
||||
}
|
||||
ResourceTable target = myEntityManager.find(ResourceTable.class, valueOf);
|
||||
if (target == null) {
|
||||
String resName = getContext().getResourceDefinition(type).getName();
|
||||
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPath);
|
||||
}
|
||||
nextEntity = new ResourceLink(nextPath, theEntity, target);
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setHasLinks(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamDate> retVal = new ArrayList<ResourceIndexedSearchParamDate>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.DATE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResourceIndexedSearchParamDate nextEntity;
|
||||
if (nextObject instanceof BaseDateTimeDt) {
|
||||
BaseDateTimeDt nextValue = (BaseDateTimeDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(), nextValue.getValue(), nextValue.getValue());
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsDatePopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected ArrayList<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamNumber> retVal = new ArrayList<ResourceIndexedSearchParamNumber>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.NUMBER && nextSpDef.getParamType() != SearchParamTypeEnum.QUANTITY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
if (nextObject instanceof QuantityDt) {
|
||||
QuantityDt nextValue = (QuantityDt) nextObject;
|
||||
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(), nextValue.getUnits().getValue());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected List<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamString> retVal = new ArrayList<ResourceIndexedSearchParamString>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.STRING) {
|
||||
continue;
|
||||
}
|
||||
if (nextSpDef.getPath().isEmpty()) {
|
||||
continue; // TODO: implement phoenetic, and any others that have
|
||||
// no path
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
if (nextObject instanceof IPrimitiveDatatype<?>) {
|
||||
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextValue.getValueAsString()), nextValue.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
} else {
|
||||
if (nextObject instanceof HumanNameDt) {
|
||||
ArrayList<StringDt> allNames = new ArrayList<>();
|
||||
HumanNameDt nextHumanName = (HumanNameDt) nextObject;
|
||||
allNames.addAll(nextHumanName.getFamily());
|
||||
allNames.addAll(nextHumanName.getGiven());
|
||||
for (StringDt nextName : allNames) {
|
||||
if (nextName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else if (nextObject instanceof AddressDt) {
|
||||
ArrayList<StringDt> allNames = new ArrayList<>();
|
||||
AddressDt nextAddress = (AddressDt) nextObject;
|
||||
allNames.addAll(nextAddress.getLine());
|
||||
allNames.add(nextAddress.getCity());
|
||||
allNames.add(nextAddress.getState());
|
||||
allNames.add(nextAddress.getCountry());
|
||||
allNames.add(nextAddress.getZip());
|
||||
for (StringDt nextName : allNames) {
|
||||
if (nextName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else if (nextObject instanceof ContactDt) {
|
||||
ContactDt nextContact = (ContactDt) nextObject;
|
||||
if (nextContact.getValue().isEmpty() == false) {
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextContact.getValue().getValueAsString()), nextContact.getValue().getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsStringPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected List<ResourceIndexedSearchParamToken> extractSearchParamTokens(ResourceTable theEntity, IResource theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamToken> retVal = new ArrayList<ResourceIndexedSearchParamToken>();
|
||||
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
FhirTerser t = getContext().newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.TOKEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
if (nextPath.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
ResourceIndexedSearchParamToken nextEntity;
|
||||
if (nextObject instanceof IdentifierDt) {
|
||||
IdentifierDt nextValue = (IdentifierDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), nextValue.getSystem().getValueAsString(), nextValue.getValue().getValue());
|
||||
} else if (nextObject instanceof IPrimitiveDatatype<?>) {
|
||||
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), null, nextValue.getValueAsString());
|
||||
} else if (nextObject instanceof CodeableConceptDt) {
|
||||
CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
|
||||
for (CodingDt nextCoding : nextCC.getCoding()) {
|
||||
if (nextCoding.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), nextCoding.getSystem().getValueAsString(), nextCoding.getCode().getValue());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
nextEntity = null;
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsTokenPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected IFhirResourceDao<? extends IResource> getDao(Class<? extends IResource> theType) {
|
||||
if (myResourceTypeToDao == null) {
|
||||
myResourceTypeToDao = new HashMap<>();
|
||||
for (IFhirResourceDao<?> next : myResourceDaos) {
|
||||
myResourceTypeToDao.put(next.getResourceType(), next);
|
||||
}
|
||||
}
|
||||
|
||||
Map<Class<? extends IResource>, IFhirResourceDao<?>> resourceTypeToDao = myResourceTypeToDao;
|
||||
return resourceTypeToDao.get(theType);
|
||||
}
|
||||
|
||||
protected String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
protected void populateResourceIntoEntity(IResource theResource, ResourceTable theEntity) {
|
||||
theEntity.setResource(getContext().newJsonParser().encodeResourceToString(theResource));
|
||||
theEntity.setEncoding(EncodingEnum.JSON);
|
||||
|
||||
TagList tagList = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (tagList != null) {
|
||||
for (Tag next : tagList) {
|
||||
theEntity.addTag(next.getTerm(), next.getLabel(), next.getScheme());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected ResourceTable toEntity(IResource theResource) {
|
||||
ResourceTable retVal = new ResourceTable();
|
||||
|
||||
populateResourceIntoEntity(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
protected String toResourceName(IResource theResource) {
|
||||
return myContext.getResourceDefinition(theResource).getName();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
@ -24,7 +23,6 @@ import javax.persistence.criteria.Expression;
|
|||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
@ -36,12 +34,10 @@ import org.springframework.transaction.support.TransactionTemplate;
|
|||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
|
@ -49,23 +45,17 @@ import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceLink;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.dstu.composite.AddressDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ContactDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
|
@ -74,26 +64,19 @@ import ca.uhn.fhir.rest.param.DateRangeParam;
|
|||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T> {
|
||||
public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements IFhirResourceDao<T> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDao.class);
|
||||
private FhirContext myCtx;
|
||||
|
||||
@PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT")
|
||||
private EntityManager myEntityManager;
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager myPlatformTransactionManager;
|
||||
@Autowired
|
||||
private List<IFhirResourceDao<?>> myResourceDaos;
|
||||
private String myResourceName;
|
||||
private Class<T> myResourceType;
|
||||
private Map<Class<? extends IResource>, IFhirResourceDao<?>> myResourceTypeToDao;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
|
||||
@Override
|
||||
|
@ -143,22 +126,17 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
return outcome;
|
||||
}
|
||||
|
||||
private String toResourceName(T theResource) {
|
||||
return myCtx.getResourceDefinition(theResource).getName();
|
||||
}
|
||||
|
||||
public Class<T> getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public List<T> history(IdDt theId) {
|
||||
ArrayList<T> retVal = new ArrayList<T>();
|
||||
|
||||
String resourceType = myCtx.getResourceDefinition(myResourceType).getName();
|
||||
String resourceType = getContext().getResourceDefinition(myResourceType).getName();
|
||||
TypedQuery<ResourceHistoryTable> q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class);
|
||||
q.setParameter("PID", theId.asLong());
|
||||
q.setParameter("RESTYPE", resourceType);
|
||||
|
@ -185,8 +163,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
|
||||
@PostConstruct
|
||||
public void postConstruct() throws Exception {
|
||||
myCtx = new FhirContext(myResourceType);
|
||||
myResourceName = myCtx.getResourceDefinition(myResourceType).getName();
|
||||
myResourceName = getContext().getResourceDefinition(myResourceType).getName();
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
|
@ -226,7 +203,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<ResourceTable> cq = builder.createQuery(ResourceTable.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.where(builder.equal(from.get("myResourceType"), myCtx.getResourceDefinition(myResourceType).getName()));
|
||||
cq.where(builder.equal(from.get("myResourceType"), getContext().getResourceDefinition(myResourceType).getName()));
|
||||
if (!theParams.isEmpty()) {
|
||||
cq.where(from.get("myId").in(pids));
|
||||
}
|
||||
|
@ -268,7 +245,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
params = Collections.emptyMap();
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resourceDef = myCtx.getResourceDefinition(myResourceType);
|
||||
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(myResourceType);
|
||||
|
||||
Set<Long> pids = new HashSet<Long>();
|
||||
|
||||
|
@ -338,7 +315,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
final ResourceTable entity = readEntity(theId);
|
||||
entity.setUpdated(entity.getPublished());
|
||||
|
||||
final ResourceHistoryTable historyEntry = entity.toHistory(myCtx);
|
||||
final ResourceHistoryTable historyEntry = entity.toHistory(getContext());
|
||||
|
||||
final List<ResourceIndexedSearchParamString> stringParams = extractSearchParamStrings(entity, theResource);
|
||||
final List<ResourceIndexedSearchParamToken> tokenParams = extractSearchParamTokens(entity, theResource);
|
||||
|
@ -574,8 +551,8 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
Predicate eq = builder.equal(from.get("myTargetResourcePid"), targetPid);
|
||||
codePredicates.add(eq);
|
||||
} else {
|
||||
String chain = myCtx.getResourceDefinition(myResourceType).getSearchParam(theParamName).getPath();
|
||||
BaseRuntimeChildDefinition def = myCtx.newTerser().getDefinition(myResourceType, chain);
|
||||
String chain = getContext().getResourceDefinition(myResourceType).getSearchParam(theParamName).getPath();
|
||||
BaseRuntimeChildDefinition def = getContext().newTerser().getDefinition(myResourceType, chain);
|
||||
if (!(def instanceof RuntimeChildResourceDefinition)) {
|
||||
throw new ConfigurationException("Property " + chain + " of type " + myResourceName + " is not a resource: " + def.getClass());
|
||||
}
|
||||
|
@ -585,17 +562,17 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
resourceTypes = resDef.getResourceTypes();
|
||||
} else {
|
||||
resourceTypes = new ArrayList<>();
|
||||
RuntimeResourceDefinition resDef = myCtx.getResourceDefinition(ref.getResourceType());
|
||||
RuntimeResourceDefinition resDef = getContext().getResourceDefinition(ref.getResourceType());
|
||||
resourceTypes.add(resDef.getImplementingClass());
|
||||
}
|
||||
for (Class<? extends IResource> nextType : resourceTypes) {
|
||||
RuntimeResourceDefinition typeDef = myCtx.getResourceDefinition(nextType);
|
||||
RuntimeResourceDefinition typeDef = getContext().getResourceDefinition(nextType);
|
||||
RuntimeSearchParam param = typeDef.getSearchParam(ref.getChain());
|
||||
if (param == null) {
|
||||
ourLog.debug("Type {} doesn't have search param {}", nextType.getSimpleName(), param);
|
||||
continue;
|
||||
}
|
||||
IFhirResourceDao<?> dao = getResourceTypeToDao().get(nextType);
|
||||
IFhirResourceDao<?> dao = getDao(nextType);
|
||||
if (dao == null) {
|
||||
ourLog.debug("Don't have a DAO for type {}", nextType.getSimpleName(), param);
|
||||
continue;
|
||||
|
@ -621,7 +598,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
|
||||
Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0]));
|
||||
|
||||
RuntimeSearchParam param = myCtx.getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
||||
RuntimeSearchParam param = getContext().getResourceDefinition(getResourceType()).getSearchParam(theParamName);
|
||||
String path = param.getPath();
|
||||
|
||||
Predicate type = builder.equal(from.get("mySourcePath"), path);
|
||||
|
@ -733,360 +710,7 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private List<ResourceLink> extractResourceLinks(ResourceTable theEntity, T theResource) {
|
||||
ArrayList<ResourceLink> retVal = new ArrayList<ResourceLink>();
|
||||
|
||||
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theResource);
|
||||
FhirTerser t = myCtx.newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResourceLink nextEntity;
|
||||
if (nextObject instanceof ResourceReferenceDt) {
|
||||
ResourceReferenceDt nextValue = (ResourceReferenceDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<? extends IResource> type = nextValue.getResourceType();
|
||||
String id = nextValue.getResourceId();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<Class<? extends IResource>, IFhirResourceDao<?>> resourceTypeToDao = getResourceTypeToDao();
|
||||
IFhirResourceDao<?> dao;
|
||||
if (type.equals(myResourceType)) {
|
||||
dao = this;
|
||||
}else {
|
||||
dao = resourceTypeToDao.get(type);
|
||||
}
|
||||
if (dao == null) {
|
||||
throw new InvalidRequestException("This server is not able to handle resources of type: " + nextValue.getResourceType());
|
||||
}
|
||||
Long valueOf;
|
||||
try {
|
||||
valueOf = Long.valueOf(id);
|
||||
} catch (Exception e) {
|
||||
String resName = myCtx.getResourceDefinition(type).getName();
|
||||
throw new InvalidRequestException("Resource ID " + resName + "/" + id + " is invalid (must be numeric), specified in path: " + nextPath);
|
||||
}
|
||||
ResourceTable target = myEntityManager.find(ResourceTable.class, valueOf);
|
||||
if (target == null) {
|
||||
String resName = myCtx.getResourceDefinition(type).getName();
|
||||
throw new InvalidRequestException("Resource " + resName + "/" + id + " not found, specified in path: " + nextPath);
|
||||
}
|
||||
nextEntity = new ResourceLink(nextPath, theEntity, target);
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setHasLinks(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, T theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamDate> retVal = new ArrayList<ResourceIndexedSearchParamDate>();
|
||||
|
||||
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theResource);
|
||||
FhirTerser t = myCtx.newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.DATE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResourceIndexedSearchParamDate nextEntity;
|
||||
if (nextObject instanceof BaseDateTimeDt) {
|
||||
BaseDateTimeDt nextValue = (BaseDateTimeDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamDate(nextSpDef.getName(), nextValue.getValue(), nextValue.getValue());
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsDatePopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private ArrayList<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, T theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamNumber> retVal = new ArrayList<ResourceIndexedSearchParamNumber>();
|
||||
|
||||
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theResource);
|
||||
FhirTerser t = myCtx.newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.NUMBER && nextSpDef.getParamType() != SearchParamTypeEnum.QUANTITY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
if (nextObject instanceof QuantityDt) {
|
||||
QuantityDt nextValue = (QuantityDt) nextObject;
|
||||
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(), nextValue.getUnits().getValue());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsNumberPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private List<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, T theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamString> retVal = new ArrayList<ResourceIndexedSearchParamString>();
|
||||
|
||||
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theResource);
|
||||
FhirTerser t = myCtx.newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.STRING) {
|
||||
continue;
|
||||
}
|
||||
if (nextSpDef.getPath().isEmpty()) {
|
||||
continue; // TODO: implement phoenetic, and any others that have
|
||||
// no path
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = nextSpDef.getName();
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
if (nextObject instanceof IPrimitiveDatatype<?>) {
|
||||
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextValue.getValueAsString()), nextValue.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
} else {
|
||||
if (nextObject instanceof HumanNameDt) {
|
||||
ArrayList<StringDt> allNames = new ArrayList<>();
|
||||
HumanNameDt nextHumanName = (HumanNameDt) nextObject;
|
||||
allNames.addAll(nextHumanName.getFamily());
|
||||
allNames.addAll(nextHumanName.getGiven());
|
||||
for (StringDt nextName : allNames) {
|
||||
if (nextName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else if (nextObject instanceof AddressDt) {
|
||||
ArrayList<StringDt> allNames = new ArrayList<>();
|
||||
AddressDt nextAddress = (AddressDt) nextObject;
|
||||
allNames.addAll(nextAddress.getLine());
|
||||
allNames.add(nextAddress.getCity());
|
||||
allNames.add(nextAddress.getState());
|
||||
allNames.add(nextAddress.getCountry());
|
||||
allNames.add(nextAddress.getZip());
|
||||
for (StringDt nextName : allNames) {
|
||||
if (nextName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else if (nextObject instanceof ContactDt) {
|
||||
ContactDt nextContact = (ContactDt) nextObject;
|
||||
if (nextContact.getValue().isEmpty() == false) {
|
||||
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextContact.getValue().getValueAsString()), nextContact.getValue().getValueAsString());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsStringPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private List<ResourceIndexedSearchParamToken> extractSearchParamTokens(ResourceTable theEntity, T theResource) {
|
||||
ArrayList<ResourceIndexedSearchParamToken> retVal = new ArrayList<ResourceIndexedSearchParamToken>();
|
||||
|
||||
RuntimeResourceDefinition def = myCtx.getResourceDefinition(theResource);
|
||||
FhirTerser t = myCtx.newTerser();
|
||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
||||
if (nextSpDef.getParamType() != SearchParamTypeEnum.TOKEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextPath = nextSpDef.getPath();
|
||||
if (nextPath.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean multiType = false;
|
||||
if (nextPath.endsWith("[x]")) {
|
||||
multiType = true;
|
||||
}
|
||||
|
||||
List<Object> values = t.getValues(theResource, nextPath);
|
||||
for (Object nextObject : values) {
|
||||
ResourceIndexedSearchParamToken nextEntity;
|
||||
if (nextObject instanceof IdentifierDt) {
|
||||
IdentifierDt nextValue = (IdentifierDt) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), nextValue.getSystem().getValueAsString(), nextValue.getValue().getValue());
|
||||
} else if (nextObject instanceof IPrimitiveDatatype<?>) {
|
||||
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
||||
if (nextValue.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), null, nextValue.getValueAsString());
|
||||
} else if (nextObject instanceof CodeableConceptDt) {
|
||||
CodeableConceptDt nextCC = (CodeableConceptDt) nextObject;
|
||||
for (CodingDt nextCoding : nextCC.getCoding()) {
|
||||
if (nextCoding.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nextEntity = new ResourceIndexedSearchParamToken(nextSpDef.getName(), nextCoding.getSystem().getValueAsString(), nextCoding.getCode().getValue());
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
nextEntity = null;
|
||||
} else {
|
||||
if (!multiType) {
|
||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nextEntity != null) {
|
||||
nextEntity.setResource(theEntity);
|
||||
retVal.add(nextEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theEntity.setParamsTokenPopulated(retVal.size() > 0);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private Map<Class<? extends IResource>, IFhirResourceDao<?>> getResourceTypeToDao() {
|
||||
if (myResourceTypeToDao == null) {
|
||||
myResourceTypeToDao = new HashMap<>();
|
||||
for (IFhirResourceDao<?> next : myResourceDaos) {
|
||||
myResourceTypeToDao.put(next.getResourceType(), next);
|
||||
}
|
||||
}
|
||||
|
||||
Map<Class<? extends IResource>, IFhirResourceDao<?>> resourceTypeToDao = myResourceTypeToDao;
|
||||
return resourceTypeToDao;
|
||||
}
|
||||
|
||||
private String normalizeString(String theString) {
|
||||
char[] out = new char[theString.length()];
|
||||
theString = Normalizer.normalize(theString, Normalizer.Form.NFD);
|
||||
int j = 0;
|
||||
for (int i = 0, n = theString.length(); i < n; ++i) {
|
||||
char c = theString.charAt(i);
|
||||
if (c <= '\u007F') {
|
||||
out[j++] = c;
|
||||
}
|
||||
}
|
||||
return new String(out).toUpperCase();
|
||||
}
|
||||
|
||||
private void populateResourceIntoEntity(T theResource, ResourceTable theEntity) {
|
||||
theEntity.setResource(myCtx.newJsonParser().encodeResourceToString(theResource));
|
||||
theEntity.setEncoding(EncodingEnum.JSON);
|
||||
|
||||
TagList tagList = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
|
||||
if (tagList != null) {
|
||||
for (Tag next : tagList) {
|
||||
theEntity.addTag(next.getTerm(), next.getLabel(), next.getScheme());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ResourceTable readEntity(IdDt theId) {
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, theId.asLong());
|
||||
|
@ -1096,17 +720,10 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
return entity;
|
||||
}
|
||||
|
||||
private ResourceTable toEntity(T theResource) {
|
||||
ResourceTable retVal = new ResourceTable();
|
||||
|
||||
populateResourceIntoEntity(theResource, retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private MethodOutcome toMethodOutcome(final ResourceTable entity) {
|
||||
MethodOutcome outcome = new MethodOutcome();
|
||||
outcome.setId(new IdDt(entity.getId()));
|
||||
outcome.setId(new IdDt(entity.getResourceType() + '/' + entity.getId()));
|
||||
outcome.setVersionId(entity.getVersion());
|
||||
return outcome;
|
||||
}
|
||||
|
@ -1138,9 +755,18 @@ public class FhirResourceDao<T extends IResource> implements IFhirResourceDao<T>
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IFhirResourceDao<? extends IResource> getDao(Class<? extends IResource> theType) {
|
||||
if (theType.equals(myResourceType)) {
|
||||
return this;
|
||||
}
|
||||
return super.getDao(theType);
|
||||
}
|
||||
|
||||
|
||||
private T toResource(BaseHasResource theEntity) {
|
||||
String resourceText = theEntity.getResource();
|
||||
IParser parser = theEntity.getEncoding().newParser(myCtx);
|
||||
IParser parser = theEntity.getEncoding().newParser(getContext());
|
||||
T retVal = parser.parseResource(myResourceType, resourceText);
|
||||
retVal.setId(theEntity.getIdDt());
|
||||
retVal.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, theEntity.getVersion());
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
|
||||
public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDao.class);
|
||||
|
||||
@PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT")
|
||||
private EntityManager myEntityManager;
|
||||
|
||||
private FhirContext myContext = new FhirContext();
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@Override
|
||||
public List<IResource> transaction(List<IResource> theResources) {
|
||||
ourLog.info("Beginning transaction with {} resources", theResources.size());
|
||||
|
||||
FhirTerser terser = myContext.newTerser();
|
||||
|
||||
Map<IdDt, IdDt> idConversions = new HashMap<>();
|
||||
List<ResourceTable> persistedResources = new ArrayList<>();
|
||||
for (IResource nextResource : theResources) {
|
||||
IdDt nextId = nextResource.getId();
|
||||
if (isBlank(nextId.getUnqualifiedId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String resourceName = toResourceName(nextResource);
|
||||
|
||||
// IFhirResourceDao<? extends IResource> dao = getDao(nextResource.getClass());
|
||||
// if (dao == null) {
|
||||
// throw new InvalidRequestException("This server is not able to handle resources of type: " +
|
||||
// nextResource.getResourceId().getResourceType());
|
||||
// }
|
||||
|
||||
ResourceTable entity = myEntityManager.find(ResourceTable.class, nextId.asLong());
|
||||
if (entity == null) {
|
||||
entity = toEntity(nextResource);
|
||||
myEntityManager.persist(entity);
|
||||
myEntityManager.flush();
|
||||
}
|
||||
idConversions.put(nextId, new IdDt(resourceName + '/' + entity.getId()));
|
||||
persistedResources.add(entity);
|
||||
|
||||
}
|
||||
|
||||
for (IResource nextResource : theResources) {
|
||||
List<ResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, ResourceReferenceDt.class);
|
||||
for (ResourceReferenceDt nextRef : allRefs) {
|
||||
IdDt nextId = nextRef.getResourceId();
|
||||
if (idConversions.containsKey(nextId)) {
|
||||
IdDt newId = idConversions.get(nextId);
|
||||
ourLog.info(" * Replacing resource ref {} with {}", nextId, newId);
|
||||
nextRef.setResourceId(newId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
public interface IFhirSystemDao {
|
||||
|
||||
List<IResource> transaction(List<IResource> theResources);
|
||||
|
||||
}
|
|
@ -7,8 +7,8 @@ import javax.persistence.Table;
|
|||
|
||||
@Entity
|
||||
@Table(name = "HFJ_SPIDX_TOKEN", indexes = { @Index(name = "IDX_SP_TOKEN", columnList = "SP_SYSTEM,SP_VALUE") })
|
||||
@org.hibernate.annotations.Table(appliesTo="HFJ_SPIDX_TOKEN",indexes= {
|
||||
@org.hibernate.annotations.Index(name="IDX_SP_TOKEN", columnNames= {"SP_SYSTEM","SP_VALUE"})})
|
||||
//@org.hibernate.annotations.Table(appliesTo="HFJ_SPIDX_TOKEN", indexes= {
|
||||
// @org.hibernate.annotations.Index(name="IDX_SP_TOKEN", columnNames= {"SP_SYSTEM","SP_VALUE"})})
|
||||
public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchParam {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
|
@ -7,39 +7,39 @@ public class CustomNamingStrategy extends ImprovedNamingStrategy {
|
|||
private static final long serialVersionUID = 1L;
|
||||
private static final String PREFIX = "FR_";
|
||||
|
||||
@Override
|
||||
public String classToTableName(final String className) {
|
||||
return this.addPrefix(super.classToTableName(className));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String collectionTableName(final String ownerEntity,
|
||||
final String ownerEntityTable, final String associatedEntity,
|
||||
final String associatedEntityTable, final String propertyName) {
|
||||
return this.addPrefix(super.collectionTableName(ownerEntity,
|
||||
ownerEntityTable, associatedEntity, associatedEntityTable,
|
||||
propertyName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String foreignKeyColumnName(String thePropertyName, String thePropertyEntityName, String thePropertyTableName, String theReferencedColumnName) {
|
||||
String foreignKeyColumnName = super.foreignKeyColumnName(thePropertyName, thePropertyEntityName, thePropertyTableName, theReferencedColumnName);
|
||||
return foreignKeyColumnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String logicalCollectionTableName(final String tableName,
|
||||
final String ownerEntityTable, final String associatedEntityTable,
|
||||
final String propertyName) {
|
||||
return this.addPrefix(super.logicalCollectionTableName(tableName,
|
||||
ownerEntityTable, associatedEntityTable, propertyName));
|
||||
}
|
||||
|
||||
private String addPrefix(final String composedTableName) {
|
||||
|
||||
return PREFIX
|
||||
+ composedTableName.toUpperCase().replace("_", "");
|
||||
|
||||
}
|
||||
// @Override
|
||||
// public String classToTableName(final String className) {
|
||||
// return this.addPrefix(super.classToTableName(className));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String collectionTableName(final String ownerEntity,
|
||||
// final String ownerEntityTable, final String associatedEntity,
|
||||
// final String associatedEntityTable, final String propertyName) {
|
||||
// return this.addPrefix(super.collectionTableName(ownerEntity,
|
||||
// ownerEntityTable, associatedEntity, associatedEntityTable,
|
||||
// propertyName));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String foreignKeyColumnName(String thePropertyName, String thePropertyEntityName, String thePropertyTableName, String theReferencedColumnName) {
|
||||
// String foreignKeyColumnName = super.foreignKeyColumnName(thePropertyName, thePropertyEntityName, thePropertyTableName, theReferencedColumnName);
|
||||
// return foreignKeyColumnName;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String logicalCollectionTableName(final String tableName,
|
||||
// final String ownerEntityTable, final String associatedEntityTable,
|
||||
// final String propertyName) {
|
||||
// return this.addPrefix(super.logicalCollectionTableName(tableName,
|
||||
// ownerEntityTable, associatedEntityTable, propertyName));
|
||||
// }
|
||||
//
|
||||
// private String addPrefix(final String composedTableName) {
|
||||
//
|
||||
// return PREFIX
|
||||
// + composedTableName.toUpperCase().replace("_", "");
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
|
@ -84,37 +84,34 @@ public class FhirResourceDaoTest {
|
|||
|
||||
Observation obs01 = new Observation();
|
||||
obs01.setApplies(new DateTimeDt(new Date()));
|
||||
obs01.setSubject(new ResourceReferenceDt(Patient.class, patientId01));
|
||||
obs01.setSubject(new ResourceReferenceDt(patientId01));
|
||||
IdDt obsId01 = ourObservationDao.create(obs01).getId();
|
||||
|
||||
Observation obs02 = new Observation();
|
||||
obs02.setApplies(new DateTimeDt(new Date()));
|
||||
obs02.setSubject(new ResourceReferenceDt(Patient.class, patientId02));
|
||||
obs02.setSubject(new ResourceReferenceDt(patientId02));
|
||||
IdDt obsId02 = ourObservationDao.create(obs02).getId();
|
||||
|
||||
// Create another type, that shouldn't be returned
|
||||
DiagnosticReport dr01 = new DiagnosticReport();
|
||||
dr01.setSubject(new ResourceReferenceDt(Patient.class, patientId01));
|
||||
dr01.setSubject(new ResourceReferenceDt(patientId01));
|
||||
IdDt drId01 = ourDiagnosticReportDao.create(dr01).getId();
|
||||
|
||||
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[] { patientId01, patientId02, obsId01, obsId02, drId01 });
|
||||
|
||||
List<Observation> result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getValue()));
|
||||
List<Observation> result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getUnqualifiedId()));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId01,result.get(0).getId());
|
||||
assertEquals(obsId01.getUnqualifiedId(), result.get(0).getId().getUnqualifiedId());
|
||||
|
||||
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId02.getValue()));
|
||||
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId02.getUnqualifiedId()));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId02,result.get(0).getId());
|
||||
assertEquals(obsId02.getUnqualifiedId(), result.get(0).getId().getUnqualifiedId());
|
||||
|
||||
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("999999999999"));
|
||||
assertEquals(0, result.size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testPersistSearchParamDate() {
|
||||
Patient patient = new Patient();
|
||||
|
@ -126,7 +123,6 @@ public class FhirResourceDaoTest {
|
|||
List<Patient> found = ourPatientDao.search("birthdate", new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN, "2000-01-01"));
|
||||
assertEquals(1, found.size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -209,7 +205,6 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchAll() {
|
||||
{
|
||||
|
@ -250,13 +245,13 @@ public class FhirResourceDaoTest {
|
|||
params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Fam"));
|
||||
List<Patient> patients = ourPatientDao.search(params);
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id1, patients.get(0).getId());
|
||||
assertEquals(id1.getUnqualifiedId(), patients.get(0).getId().getUnqualifiedId());
|
||||
|
||||
params = new HashMap<>();
|
||||
params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Giv"));
|
||||
patients = ourPatientDao.search(params);
|
||||
assertEquals(1, patients.size());
|
||||
assertEquals(id1, patients.get(0).getId());
|
||||
assertEquals(id1.getUnqualifiedId(), patients.get(0).getId().getUnqualifiedId());
|
||||
|
||||
params = new HashMap<>();
|
||||
params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Foo"));
|
||||
|
@ -279,24 +274,24 @@ public class FhirResourceDaoTest {
|
|||
|
||||
Observation obs01 = new Observation();
|
||||
obs01.setApplies(new DateTimeDt(new Date()));
|
||||
obs01.setSubject(new ResourceReferenceDt(Patient.class, patientId01));
|
||||
obs01.setSubject(new ResourceReferenceDt(patientId01));
|
||||
IdDt obsId01 = ourObservationDao.create(obs01).getId();
|
||||
|
||||
Observation obs02 = new Observation();
|
||||
obs02.setApplies(new DateTimeDt(new Date()));
|
||||
obs02.setSubject(new ResourceReferenceDt(Patient.class, patientId02));
|
||||
obs02.setSubject(new ResourceReferenceDt(patientId02));
|
||||
IdDt obsId02 = ourObservationDao.create(obs02).getId();
|
||||
|
||||
// Create another type, that shouldn't be returned
|
||||
DiagnosticReport dr01 = new DiagnosticReport();
|
||||
dr01.setSubject(new ResourceReferenceDt(Patient.class, patientId01));
|
||||
dr01.setSubject(new ResourceReferenceDt(patientId01));
|
||||
IdDt drId01 = ourDiagnosticReportDao.create(dr01).getId();
|
||||
|
||||
ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}] D1[{}]", new Object[] { patientId01, patientId02, obsId01, obsId02, drId01 });
|
||||
|
||||
List<Observation> result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "testSearchResourceLinkWithChain01"));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId01,result.get(0).getId());
|
||||
assertEquals(obsId01.getUnqualifiedId(), result.get(0).getId().getUnqualifiedId());
|
||||
|
||||
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(Patient.SP_IDENTIFIER, "999999999999"));
|
||||
assertEquals(0, result.size());
|
||||
|
@ -306,14 +301,13 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateWithInvalidReferenceFailsGracefully() {
|
||||
Patient patient = new Patient();
|
||||
patient.addName().addFamily("testSearchResourceLinkWithChainWithMultipleTypes01");
|
||||
patient.setManagingOrganization(new ResourceReferenceDt(Organization.class, "99999999"));
|
||||
patient.setManagingOrganization(new ResourceReferenceDt("Patient/99999999"));
|
||||
try {
|
||||
ourPatientDao.create(patient).getId();
|
||||
ourPatientDao.create(patient);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertThat(e.getMessage(), StringContains.containsString("99999 not found"));
|
||||
|
@ -321,7 +315,6 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchResourceLinkWithChainWithMultipleTypes() {
|
||||
Patient patient = new Patient();
|
||||
|
@ -335,12 +328,12 @@ public class FhirResourceDaoTest {
|
|||
|
||||
Observation obs01 = new Observation();
|
||||
obs01.setApplies(new DateTimeDt(new Date()));
|
||||
obs01.setSubject(new ResourceReferenceDt(Patient.class, patientId01));
|
||||
obs01.setSubject(new ResourceReferenceDt(patientId01));
|
||||
IdDt obsId01 = ourObservationDao.create(obs01).getId();
|
||||
|
||||
Observation obs02 = new Observation();
|
||||
obs02.setApplies(new DateTimeDt(new Date()));
|
||||
obs02.setSubject(new ResourceReferenceDt(Location.class, locId01));
|
||||
obs02.setSubject(new ResourceReferenceDt(locId01));
|
||||
IdDt obsId02 = ourObservationDao.create(obs02).getId();
|
||||
|
||||
ourLog.info("P1[{}] L1[{}] Obs1[{}] Obs2[{}]", new Object[] { patientId01, locId01, obsId01, obsId02 });
|
||||
|
@ -356,7 +349,7 @@ public class FhirResourceDaoTest {
|
|||
|
||||
result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("Patient", Patient.SP_NAME, "testSearchResourceLinkWithChainWithMultipleTypes01"));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(obsId01, result.get(0).getId());
|
||||
assertEquals(obsId01.getUnqualifiedId(), result.get(0).getId().getUnqualifiedId());
|
||||
|
||||
}
|
||||
|
||||
|
@ -414,7 +407,6 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTagsWithCreateAndReadAndSearch() {
|
||||
Patient patient = new Patient();
|
||||
|
@ -501,7 +493,6 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateMaintainsSearchParams() throws InterruptedException {
|
||||
Patient p1 = new Patient();
|
||||
|
@ -530,7 +521,6 @@ public class FhirResourceDaoTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
ourCtx.close();
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
<property name="hibernate.cache.use_query_cache" value="false" />
|
||||
<property name="hibernate.cache.use_second_level_cache" value="false" />
|
||||
<property name="hibernate.cache.use_structured_entries" value="false" />
|
||||
<!--
|
||||
<property name="hibernate.ejb.naming_strategy" value="ca.uhn.fhir.jpa.util.CustomNamingStrategy" />
|
||||
-->
|
||||
<!--
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
|
||||
-->
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
<property name="hibernate.cache.use_query_cache" value="false" />
|
||||
<property name="hibernate.cache.use_second_level_cache" value="false" />
|
||||
<property name="hibernate.cache.use_structured_entries" value="false" />
|
||||
<property name="hibernate.ejb.naming_strategy" value="ca.uhn.fhir.jpa.util.CustomNamingStrategy" />
|
||||
<!--
|
||||
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
|
||||
-->
|
||||
|
|
|
@ -395,7 +395,19 @@ public class ${className}
|
|||
return null;
|
||||
}
|
||||
#end
|
||||
#if ( ${className} == "ResourceReferenceDt" )
|
||||
/** TODO: document */
|
||||
@Override
|
||||
public IdDt getResourceId() {
|
||||
return new IdDt(myReference.getValue());
|
||||
}
|
||||
|
||||
/** TODO: document */
|
||||
@Override
|
||||
public void setResourceId(IdDt theResourceId) {
|
||||
myReference = new StringDt(theResourceId.getValue());
|
||||
}
|
||||
#end
|
||||
#childExtensionTypes( $childExtensionTypes )
|
||||
|
||||
}
|
Loading…
Reference in New Issue