Add support in JPA for _content and _text for $everything operation

This commit is contained in:
jamesagnew 2015-10-31 17:09:32 -04:00
parent 2cc88d76eb
commit a6d4de1f3e
20 changed files with 855 additions and 500 deletions

View File

@ -238,7 +238,6 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.5.0.Final</version>
</dependency>
<!-- Misc -->

View File

@ -632,7 +632,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
};
}
protected boolean isValidPid(IIdType theId) {
protected static boolean isValidPid(IIdType theId) {
if (theId == null || theId.getIdPart() == null) {
return false;
}
@ -1186,10 +1186,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
protected Long translateForcedIdToPid(IIdType theId) {
return translateForcedIdToPid(theId, myEntityManager);
}
static Long translateForcedIdToPid(IIdType theId, EntityManager entityManager) {
if (isValidPid(theId)) {
return theId.getIdPartAsLong();
} else {
TypedQuery<ForcedId> q = myEntityManager.createNamedQuery("Q_GET_FORCED_ID", ForcedId.class);
TypedQuery<ForcedId> q = entityManager.createNamedQuery("Q_GET_FORCED_ID", ForcedId.class);
q.setParameter("ID", theId.getIdPart());
try {
return q.getSingleResult().getResourcePid();
@ -1426,6 +1430,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
myEntityManager.persist(next);
}
// Store resource links
for (ResourceLink next : resourceLinks) {
myEntityManager.remove(next);
}

View File

@ -33,18 +33,25 @@ import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> {
private IBundleProvider doEverythingOperation(IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
private IBundleProvider doEverythingOperation(IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
}
if (theContent != null) {
paramMap.add(Constants.PARAM_CONTENT, theContent);
}
if (theNarrative != null) {
paramMap.add(Constants.PARAM_TEXT, theNarrative);
}
paramMap.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setEverythingMode(theId != null ? EverythingModeEnum.PATIENT_INSTANCE : EverythingModeEnum.PATIENT_TYPE);
paramMap.setSort(theSort);
@ -59,21 +66,21 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
}
@Override
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
}
@Override
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort) {
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
// Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
return doEverythingOperation(null, theCount, theLastUpdated, theSort);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);
}
}

View File

@ -45,6 +45,8 @@ 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.IQueryParameterType;
import ca.uhn.fhir.model.dstu.resource.BaseResource;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
@ -57,6 +59,10 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
@Transactional()
@Override
public List<Long> search(String theResourceName, SearchParameterMap theParams) {
return doSearch(theResourceName, theParams, null);
}
private List<Long> doSearch(String theResourceName, SearchParameterMap theParams, Long theReferencingPid) {
FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
QueryBuilder qb = em
@ -72,6 +78,10 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
List<List<? extends IQueryParameterType>> textAndTerms = theParams.remove(Constants.PARAM_TEXT);
addTextSearch(qb, bool, textAndTerms, "myNarrativeText");
if (theReferencingPid != null) {
bool.must(qb.keyword().onField("myResourceLinks.myTargetResourcePid").matching(theReferencingPid).createQuery());
}
if (bool.isEmpty()) {
return null;
}
@ -92,7 +102,10 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
ArrayList<Long> retVal = new ArrayList<Long>();
for (Object object : result) {
Object[] nextArray = (Object[]) object;
retVal.add((Long)nextArray[0]);
Long next = (Long)nextArray[0];
if (next != null) {
retVal.add(next);
}
}
return retVal;
@ -118,4 +131,23 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
}
}
@Override
public List<Long> everything(String theResourceName, SearchParameterMap theParams) {
Long pid = null;
if (theParams.get(BaseResource.SP_RES_ID) != null) {
StringParam idParm = (StringParam) theParams.get(BaseResource.SP_RES_ID).get(0).get(0);
pid = BaseHapiFhirDao.translateForcedIdToPid(new IdDt(idParm.getValue()), myEntityManager);
}
Long referencingPid = pid;
List<Long> retVal = doSearch(null, theParams, referencingPid);
if (referencingPid != null) {
retVal.add(referencingPid);
}
return retVal;
}
}

View File

@ -28,12 +28,13 @@ import org.hl7.fhir.instance.model.api.IIdType;
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
public interface IFhirResourceDaoPatient<T extends IBaseResource> extends IFhirResourceDao<T> {
IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdate, SortSpec theSort);
IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, UnsignedIntDt theCount, DateRangeParam theLastUpdate, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative);
IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSortSpec);
IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, UnsignedIntDt theCount, DateRangeParam theLastUpdated, SortSpec theSortSpec, StringAndListParam theContent, StringAndListParam theNarrative);
}

View File

@ -26,4 +26,6 @@ public interface ISearchDao {
List<Long> search(String theResourceName, SearchParameterMap theParams);
List<Long> everything(String theResourceName, SearchParameterMap theParams);
}

View File

@ -290,8 +290,7 @@ public class SearchBuilder {
return retVal;
}
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates,
IQueryParameterType nextOr) {
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
boolean missingFalse = false;
if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) {
@ -305,9 +304,7 @@ public class SearchBuilder {
return missingFalse;
}
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates,
IQueryParameterType nextOr) {
private boolean addPredicateMissingFalseIfPresentForResourceLink(CriteriaBuilder theBuilder, String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
boolean missingFalse = false;
if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) {
@ -395,6 +392,7 @@ public class SearchBuilder {
TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList());
}
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
@ -427,7 +425,6 @@ public class SearchBuilder {
return retVal;
}
private Set<Long> addPredicateParamMissingResourceLink(Set<Long> thePids, String joinName, String theParamName) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
@ -573,7 +570,6 @@ public class SearchBuilder {
return new HashSet<Long>(q.getResultList());
}
private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
assert theParamName.contains(".") == false;
@ -766,6 +762,7 @@ public class SearchBuilder {
TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList());
}
private Set<Long> addPredicateTag(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList, String theParamName, DateRangeParam theLastUpdated) {
Set<Long> pids = thePids;
if (theList == null || theList.isEmpty()) {
@ -965,7 +962,6 @@ public class SearchBuilder {
return new HashSet<Long>(q.getResultList());
}
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
Predicate retVal = null;
switch (left.getParamType()) {
@ -1072,8 +1068,7 @@ public class SearchBuilder {
}
}
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
String rawSearchTerm;
if (theParameter instanceof TokenParam) {
TokenParam id = (TokenParam) theParameter;
@ -1092,8 +1087,7 @@ public class SearchBuilder {
}
if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed ("
+ ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
}
String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm);
@ -1107,8 +1101,7 @@ public class SearchBuilder {
return singleCode;
}
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
String code;
String system;
if (theParameter instanceof TokenParam) {
@ -1128,12 +1121,10 @@ public class SearchBuilder {
}
if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException(
"Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
throw new InvalidRequestException("Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
}
if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException(
"Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
throw new InvalidRequestException("Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
}
ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>());
@ -1328,6 +1319,7 @@ public class SearchBuilder {
/**
* THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet())
*
* @param theLastUpdated
*/
private HashSet<Long> loadReverseIncludes(Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, EverythingModeEnum theEverythingModeEnum, DateRangeParam theLastUpdated) {
@ -1369,11 +1361,12 @@ public class SearchBuilder {
List<ResourceLink> results = q.getResultList();
for (ResourceLink resourceLink : results) {
if (theReverseMode) {
// if (theEverythingModeEnum.isEncounter()) {
// if (resourceLink.getSourcePath().equals("Encounter.subject") || resourceLink.getSourcePath().equals("Encounter.patient")) {
// nextRoundOmit.add(resourceLink.getSourceResourcePid());
// }
// }
// if (theEverythingModeEnum.isEncounter()) {
// if (resourceLink.getSourcePath().equals("Encounter.subject") ||
// resourceLink.getSourcePath().equals("Encounter.patient")) {
// nextRoundOmit.add(resourceLink.getSourceResourcePid());
// }
// }
pidsToInclude.add(resourceLink.getSourceResourcePid());
} else {
pidsToInclude.add(resourceLink.getTargetResourcePid());
@ -1443,10 +1436,9 @@ public class SearchBuilder {
return allAdded;
}
private List<Long> processSort(final SearchParameterMap theParams, Collection<Long> theLoadPids) {
final List<Long> pids;
// Set<Long> loadPids = theLoadPids;
// Set<Long> loadPids = theLoadPids;
if (theParams.getSort() != null && isNotBlank(theParams.getSort().getParamName())) {
List<Order> orders = new ArrayList<Order>();
List<Predicate> predicates = new ArrayList<Predicate>();
@ -1488,7 +1480,6 @@ public class SearchBuilder {
return pids;
}
public IBundleProvider search(final SearchParameterMap theParams) {
StopWatch w = new StopWatch();
final InstantDt now = InstantDt.withCurrentTime();
@ -1501,13 +1492,26 @@ public class SearchBuilder {
Collection<Long> loadPids;
if (theParams.getEverythingMode() != null) {
Long pid = null;
if (theParams.get(BaseResource.SP_RES_ID) != null) {
StringParam idParm = (StringParam) theParams.get(BaseResource.SP_RES_ID).get(0).get(0);
pid = BaseHapiFhirDao.translateForcedIdToPid(new IdDt(idParm.getValue()), myEntityManager);
}
loadPids = new HashSet<Long>();
if (theParams.containsKey(Constants.PARAM_CONTENT) || theParams.containsKey(Constants.PARAM_TEXT)) {
List<Long> pids = mySearchDao.everything(myResourceName, theParams);
// if (pid != null) {
// loadPids.add(pid);
// }
loadPids.addAll(pids);
} else {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
Root<ResourceTable> from = cq.from(ResourceTable.class);
List<Predicate> predicates = new ArrayList<Predicate>();
if (theParams.get(BaseResource.SP_RES_ID) != null) {
StringParam idParm = (StringParam) theParams.get(BaseResource.SP_RES_ID).get(0).get(0);
predicates.add(builder.equal(from.get("myId"), idParm.getValue()));
if (pid != null) {
predicates.add(builder.equal(from.get("myId"), pid));
}
predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
predicates.add(builder.isNull(from.get("myDeleted")));
@ -1517,14 +1521,14 @@ public class SearchBuilder {
cq.multiselect(from.get("myId").as(Long.class), join.get("mySourceResourcePid").as(Long.class));
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
loadPids = new HashSet<Long>();
for (Tuple next : query.getResultList()) {
loadPids.add(next.get(0, Long.class));
Long nextLong = next.get(1, Long.class);
if(nextLong != null) {
if (nextLong != null) {
loadPids.add(nextLong);
}
}
}
} else if (theParams.isEmpty()) {
@ -1565,7 +1569,8 @@ public class SearchBuilder {
// // Load _include and _revinclude before filter and sort in everything mode
// if (theParams.getEverythingMode() != null) {
// if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) {
// loadPids.addAll(loadReverseIncludes(loadPids, theParams.getRevIncludes(), true, theParams.getEverythingMode()));
// loadPids.addAll(loadReverseIncludes(loadPids, theParams.getRevIncludes(), true,
// theParams.getEverythingMode()));
// loadPids.addAll(loadReverseIncludes(loadPids, theParams.getIncludes(), false, theParams.getEverythingMode()));
// }
// }
@ -1849,5 +1854,4 @@ public class SearchBuilder {
return thePredicates.toArray(new Predicate[thePredicates.size()]);
}
}

View File

@ -36,6 +36,8 @@ import javax.persistence.Table;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.search.annotations.ContainedIn;
import org.hibernate.search.annotations.Field;
@Entity
@Table(name = "HFJ_RES_LINK" , indexes= {
@ -57,6 +59,7 @@ public class ResourceLink implements Serializable {
@ManyToOne(optional = false, fetch=FetchType.LAZY)
@JoinColumn(name = "SRC_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false)
// @ContainedIn()
private ResourceTable mySourceResource;
@Column(name = "SRC_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
@ -67,6 +70,7 @@ public class ResourceLink implements Serializable {
private ResourceTable myTargetResource;
@Column(name = "TARGET_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
@Field()
private Long myTargetResourcePid;
public ResourceLink() {
@ -77,7 +81,9 @@ public class ResourceLink implements Serializable {
super();
mySourcePath = theSourcePath;
mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
}
@Override
@ -134,11 +140,13 @@ public class ResourceLink implements Serializable {
public void setSourceResource(ResourceTable theSourceResource) {
mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
}
public void setTargetResource(ResourceTable theTargetResource) {
Validate.notNull(theTargetResource);
myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
}
@Override

View File

@ -29,6 +29,7 @@ import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
@ -39,8 +40,11 @@ import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import ca.uhn.fhir.jpa.search.IndexNonDeletedInterceptor;
import ca.uhn.fhir.model.primitive.IdDt;
@ -65,6 +69,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB
*/
@Transient()
@Field()
private String myContentText;
@Column(name = "SP_HAS_LINKS")
private boolean myHasLinks;
@ -85,21 +96,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
/**
* Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB
*/
// @Column(name = "SP_NARRATIVE_TEXT", length = Integer.MAX_VALUE - 1, nullable=true)
// @Lob
@Transient
@Transient()
@Field()
private String myNarrativeText;
/**
* Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB
*/
// @Column(name = "SP_CONTENT_TEXT", length = Integer.MAX_VALUE - 1, nullable=true)
// @Lob
@Transient
@Field()
private String myContentText;
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceIndexedSearchParamCoords> myParamsCoords;
@ -146,6 +146,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
private String myProfile;
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
@IndexedEmbedded()
private Collection<ResourceLink> myResourceLinks;
@Column(name = "RES_TYPE", length = RESTYPE_LEN)
@ -303,6 +304,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myParamsUriPopulated;
}
public void setContentTextParsedIntoWords(String theContentText) {
myContentText = theContentText;
}
public void setHasLinks(boolean theHasLinks) {
myHasLinks = theHasLinks;
}
@ -326,10 +331,6 @@ public class ResourceTable extends BaseHasResource implements Serializable {
myNarrativeText = theNarrativeText;
}
public void setContentTextParsedIntoWords(String theContentText) {
myContentText = theContentText;
}
public void setParamsCoords(Collection<ResourceIndexedSearchParamCoords> theParamsCoords) {
if (!isParamsTokenPopulated() && theParamsCoords.isEmpty()) {
return;
@ -462,4 +463,12 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return retVal;
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
b.append("resourceType", myResourceType);
b.append("pid", myId);
return b.build();
}
}

View File

@ -1,5 +1,9 @@
package ca.uhn.fhir.jpa.provider;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.List;
/*
* #%L
* HAPI FHIR JPA Server
@ -23,17 +27,20 @@ package ca.uhn.fhir.jpa.provider;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu2<Patient> {
/**
* Patient/123/$everything
*/
@ -54,6 +61,14 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
@Description(shortDefinition="Filter the resources to return only resources matching the given _content filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)")
@OperationParam(name = Constants.PARAM_CONTENT, min=0, max=OperationParam.MAX_UNLIMITED)
List<StringDt> theContent,
@Description(shortDefinition="Filter the resources to return only resources matching the given _text filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)")
@OperationParam(name = Constants.PARAM_TEXT, min=0, max=OperationParam.MAX_UNLIMITED)
List<StringDt> theNarrative,
@Sort
SortSpec theSortSpec
) {
@ -61,10 +76,11 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoPatient<Patient>)getDao()).patientInstanceEverything(theServletRequest, theId, theCount, theLastUpdated, theSortSpec);
return ((IFhirResourceDaoPatient<Patient>) getDao()).patientInstanceEverything(theServletRequest, theId, theCount, theLastUpdated, theSortSpec, toStringAndList(theContent), toStringAndList(theNarrative));
} finally {
endRequest(theServletRequest);
}}
}
}
/**
* /Patient/$everything
@ -83,6 +99,14 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated,
@Description(shortDefinition="Filter the resources to return only resources matching the given _content filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)")
@OperationParam(name = Constants.PARAM_CONTENT, min=0, max=OperationParam.MAX_UNLIMITED)
List<StringDt> theContent,
@Description(shortDefinition="Filter the resources to return only resources matching the given _text filter (note that this filter is applied only to results which link to the given patient, not to the patient itself or to supporting resources linked to by the matched resources)")
@OperationParam(name = Constants.PARAM_TEXT, min=0, max=OperationParam.MAX_UNLIMITED)
List<StringDt> theNarrative,
@Sort
SortSpec theSortSpec
) {
@ -90,11 +114,26 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
startRequest(theServletRequest);
try {
return ((IFhirResourceDaoPatient<Patient>)getDao()).patientTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec);
return ((IFhirResourceDaoPatient<Patient>) getDao()).patientTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec, toStringAndList(theContent), toStringAndList(theNarrative));
} finally {
endRequest(theServletRequest);
}
}
private StringAndListParam toStringAndList(List<StringDt> theNarrative) {
StringAndListParam retVal = new StringAndListParam();
if (theNarrative != null) {
for (StringDt next : theNarrative) {
if (isNotBlank(next.getValue())) {
retVal.addAnd(new StringOrListParam().addOr(new StringParam(next.getValue())));
}
}
}
if (retVal.getValuesAsQueryTokens().isEmpty()) {
return null;
}
return retVal;
}
}

View File

@ -0,0 +1,43 @@
package ca.uhn.fhir.jpa.dao;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import ca.uhn.fhir.jpa.rp.dstu2.PatientResourceProvider;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.RestfulServer;
public abstract class BaseJpaDstu2SystemTest extends BaseJpaDstu2Test {
protected RequestDetails myRequestDetails;
private RestfulServer myServer;
@SuppressWarnings("unchecked")
@Before
public void before() throws ServletException {
myRequestDetails = mock(RequestDetails.class);
if (myServer == null) {
myServer = new RestfulServer(myFhirCtx);
PatientResourceProvider patientRp = new PatientResourceProvider();
patientRp.setDao(myPatientDao);
myServer.setResourceProviders(patientRp);
myServer.init(mock(ServletConfig.class));
}
when(myRequestDetails.getServer()).thenReturn(myServer);
HttpServletRequest servletRequest = mock(HttpServletRequest.class);
when(myRequestDetails.getServletRequest()).thenReturn(servletRequest);
when(servletRequest.getHeaderNames()).thenReturn(mock(Enumeration.class));
when(servletRequest.getRequestURL()).thenReturn(new StringBuffer("/Patient"));
}
}

View File

@ -10,6 +10,8 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Before;
import org.junit.runner.RunWith;
@ -162,6 +164,16 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
myDaoConfig.setInterceptors(myInterceptor);
}
@Before
@Transactional
public void beforeFlushFT() {
FullTextEntityManager ftem = Search.getFullTextEntityManager(myEntityManager);
ftem.purgeAll(ResourceTable.class);
ftem.flushToIndexes();
myDaoConfig.setSchedulingDisabled(true);
}
@Before
@Transactional()
public void beforePurgeDatabase() {

View File

@ -4,38 +4,30 @@ import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import java.util.List;
import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Test;
import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2SearchFtTest.class);
@Before
@Transactional
public void beforeFlushFT() {
FullTextEntityManager ftem = Search.getFullTextEntityManager(myEntityManager);
ftem.purgeAll(ResourceTable.class);
ftem.flushToIndexes();
myDaoConfig.setSchedulingDisabled(true);
}
@Test
public void testSearchAndReindex() {
Patient patient;
@ -80,12 +72,192 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
}
@Test
public void testEverythingInstanceWithContentFilter() {
Patient pt1 = new Patient();
pt1.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
Patient pt2 = new Patient();
pt2.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
Device dev1 = new Device();
dev1.setManufacturer("Some Manufacturer");
IIdType devId1 = myDeviceDao.create(dev1).getId().toUnqualifiedVersionless();
Device dev2 = new Device();
dev2.setManufacturer("Some Manufacturer 2");
myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
Observation obs1 = new Observation();
obs1.getText().setDiv("<div>OBSTEXT1</div>");
obs1.getSubject().setReference(ptId1);
obs1.getCode().addCoding().setCode("CODE1");
obs1.setValue(new StringDt("obsvalue1"));
obs1.getDevice().setReference(devId1);
IIdType obsId1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless();
Observation obs2 = new Observation();
obs2.getSubject().setReference(ptId1);
obs2.getCode().addCoding().setCode("CODE2");
obs2.setValue(new StringDt("obsvalue2"));
IIdType obsId2 = myObservationDao.create(obs2).getId().toUnqualifiedVersionless();
Observation obs3 = new Observation();
obs3.getSubject().setReference(ptId2);
obs3.getCode().addCoding().setCode("CODE3");
obs3.setValue(new StringDt("obsvalue3"));
IIdType obsId3 = myObservationDao.create(obs3).getId().toUnqualifiedVersionless();
HttpServletRequest request;
List<IIdType> actual;
request = mock(HttpServletRequest.class);
StringAndListParam param;
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, devId1));
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obstext1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, param));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, devId1));
request = mock(HttpServletRequest.class);
actual = toUnqualifiedVersionlessIds(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, null, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, obsId2, devId1));
/*
* Add another match
*/
Observation obs4 = new Observation();
obs4.getSubject().setReference(ptId1);
obs4.getCode().addCoding().setCode("CODE1");
obs4.setValue(new StringDt("obsvalue1"));
IIdType obsId4 = myObservationDao.create(obs4).getId().toUnqualifiedVersionless();
assertNotEquals(obsId1.getIdPart(), obsId4.getIdPart(), devId1);
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, obsId4, devId1));
/*
* Make one previous match no longer match
*/
obs1 = new Observation();
obs1.setId(obsId1);
obs1.getSubject().setReference(ptId1);
obs1.getCode().addCoding().setCode("CODE2");
obs1.setValue(new StringDt("obsvalue2"));
myObservationDao.update(obs1);
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientInstanceEverything(request, ptId1, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId4));
}
@Test
public void testEverythingTypeWithContentFilter() {
Patient pt1 = new Patient();
pt1.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
Patient pt2 = new Patient();
pt2.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
Device dev1 = new Device();
dev1.setManufacturer("Some Manufacturer");
IIdType devId1 = myDeviceDao.create(dev1).getId().toUnqualifiedVersionless();
Device dev2 = new Device();
dev2.setManufacturer("Some Manufacturer 2");
IIdType devId2 = myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
Observation obs1 = new Observation();
obs1.getSubject().setReference(ptId1);
obs1.getCode().addCoding().setCode("CODE1");
obs1.setValue(new StringDt("obsvalue1"));
obs1.getDevice().setReference(devId1);
IIdType obsId1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless();
Observation obs2 = new Observation();
obs2.getSubject().setReference(ptId1);
obs2.getCode().addCoding().setCode("CODE2");
obs2.setValue(new StringDt("obsvalue2"));
IIdType obsId2 = myObservationDao.create(obs2).getId().toUnqualifiedVersionless();
Observation obs3 = new Observation();
obs3.getSubject().setReference(ptId2);
obs3.getCode().addCoding().setCode("CODE3");
obs3.setValue(new StringDt("obsvalue3"));
IIdType obsId3 = myObservationDao.create(obs3).getId().toUnqualifiedVersionless();
HttpServletRequest request;
List<IIdType> actual;
request = mock(HttpServletRequest.class);
StringAndListParam param;
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientTypeEverything(request, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, devId1));
request = mock(HttpServletRequest.class);
actual = toUnqualifiedVersionlessIds(myPatientDao.patientTypeEverything(request, null, null, null, null, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, obsId2, devId1, ptId2, obsId3));
/*
* Add another match
*/
Observation obs4 = new Observation();
obs4.getSubject().setReference(ptId1);
obs4.getCode().addCoding().setCode("CODE1");
obs4.setValue(new StringDt("obsvalue1"));
IIdType obsId4 = myObservationDao.create(obs4).getId().toUnqualifiedVersionless();
assertNotEquals(obsId1.getIdPart(), obsId4.getIdPart(), devId1);
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientTypeEverything(request, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId1, obsId4, devId1));
/*
* Make one previous match no longer match
*/
obs1 = new Observation();
obs1.setId(obsId1);
obs1.getSubject().setReference(ptId1);
obs1.getCode().addCoding().setCode("CODE2");
obs1.setValue(new StringDt("obsvalue2"));
myObservationDao.update(obs1);
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
actual = toUnqualifiedVersionlessIds(myPatientDao.patientTypeEverything(request, null, null, null, param, null));
assertThat(actual, containsInAnyOrder(ptId1, obsId4));
}
/**
* When processing transactions, we do two passes. Make sure we don't update the
* lucene index twice since that would be inefficient
* When processing transactions, we do two passes. Make sure we don't update the lucene index twice since that would
* be inefficient
*/
@Test
public void testSearchDontReindexForUpdateWithIndexDisabled() {
@ -140,11 +312,8 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
}
@Test
public void testSearchWithChainedParams() {
String methodName = "testSearchWithChainedParams";

View File

@ -8,6 +8,7 @@ import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -141,11 +142,11 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
HttpServletRequest request = mock(HttpServletRequest.class);
IBundleProvider resp = myPatientDao.patientTypeEverything(request, null, null, null);
IBundleProvider resp = myPatientDao.patientTypeEverything(request, null, null, null, null, null);
assertThat(toUnqualifiedVersionlessIds(resp), containsInAnyOrder(orgId, medId, patId, moId, patId2));
request = mock(HttpServletRequest.class);
resp = myPatientDao.patientInstanceEverything(request, patId, null, null, null);
resp = myPatientDao.patientInstanceEverything(request, patId, null, null, null, null, null);
assertThat(toUnqualifiedVersionlessIds(resp), containsInAnyOrder(orgId, medId, patId, moId));
}

View File

@ -1,6 +1,13 @@
package ca.uhn.fhir.jpa.dao;
public class FhirSystemDaoDstu2SearchTest {
import org.junit.Test;
public class FhirSystemDaoDstu2SearchTest extends BaseJpaDstu2SystemTest {
@Test
public void testSearchByParans() {
// code to come.. just here to prevent a failure
}
/*//@formatter:off
* [ERROR] Search parameter action has conflicting types token and reference

View File

@ -14,25 +14,16 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.transaction.TransactionStatus;
@ -43,7 +34,6 @@ import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.jpa.rp.dstu2.PatientResourceProvider;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList;
@ -67,40 +57,17 @@ import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirSystemDaoDstu2Test.class);
private RequestDetails myRequestDetails;
private RestfulServer myServer;
@Test
public void testTransactionFromBundle6() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
String bundle = IOUtils.toString(bundleRes);
Bundle output = mySystemDao.transaction(myRequestDetails, myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
}
@Test
public void testNestedCount() {
Patient p = new Patient();
p.addName().addFamily("family");
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
}
@Test
public void testRendexing() {
@ -116,7 +83,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
}
});
assertEquals(Long.valueOf(1), entity.getIndexStatus());
mySystemDao.markAllResourcesForReindexing();
@ -125,7 +93,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
}
});
assertEquals(null, entity.getIndexStatus());
mySystemDao.performReindexingPass(null);
@ -134,7 +103,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
}
});
assertEquals(Long.valueOf(1), entity.getIndexStatus());
// Just make sure this doesn't cause a choke
@ -157,7 +127,8 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
myEntityManager.merge(table);
return null;
}});
}
});
mySystemDao.performReindexingPass(null);
@ -165,13 +136,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
@Override
public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}});
}
});
assertEquals(Long.valueOf(2), entity.getIndexStatus());
}
@Test
public void testSystemMetaOperation() {
@ -261,6 +231,53 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionBatchWithFailingRead() {
String methodName = "testTransactionBatchWithFailingRead";
Bundle request = new Bundle();
request.setType(BundleTypeEnum.BATCH);
Patient p = new Patient();
p.addName().addFamily(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient/THIS_ID_DOESNT_EXIST");
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
assertEquals(3, resp.getEntry().size());
assertEquals(BundleTypeEnum.BATCH_RESPONSE, resp.getTypeElement().getValueAsEnum());
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
EntryResponse respEntry;
// Bundle.entry[0] is operation outcome
assertEquals(OperationOutcome.class, resp.getEntry().get(0).getResource().getClass());
assertEquals(IssueSeverityEnum.INFORMATION, ((OperationOutcome) resp.getEntry().get(0).getResource()).getIssue().get(0).getSeverityElement().getValueAsEnum());
assertThat(((OperationOutcome) resp.getEntry().get(0).getResource()).getIssue().get(0).getDiagnostics(), startsWith("Batch completed in "));
// Bundle.entry[1] is create response
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
assertThat(resp.getEntry().get(1).getResponse().getLocation(), startsWith("Patient/"));
// Bundle.entry[2] is failed read response
assertEquals(OperationOutcome.class, resp.getEntry().get(2).getResource().getClass());
assertEquals(IssueSeverityEnum.ERROR, ((OperationOutcome) resp.getEntry().get(2).getResource()).getIssue().get(0).getSeverityElement().getValueAsEnum());
assertEquals("Resource Patient/THIS_ID_DOESNT_EXIST is not known", ((OperationOutcome) resp.getEntry().get(2).getResource()).getIssue().get(0).getDiagnostics());
assertEquals("404 Not Found", resp.getEntry().get(2).getResponse().getStatus());
// Check POST
respEntry = resp.getEntry().get(1).getResponse();
assertEquals("201 Created", respEntry.getStatus());
IdDt createdId = new IdDt(respEntry.getLocation());
assertEquals("Patient", createdId.getResourceType());
myPatientDao.read(createdId); // shouldn't fail
// Check GET
respEntry = resp.getEntry().get(2).getResponse();
assertThat(respEntry.getStatus(), startsWith("404"));
}
@Test
public void testTransactionCreateMatchUrlWithOneMatch() {
String methodName = "testTransactionCreateMatchUrlWithOneMatch";
@ -303,188 +320,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionWithInvalidType() {
Bundle request = new Bundle();
request.setType(BundleTypeEnum.SEARCH_RESULTS);
Patient p = new Patient();
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
}
}
@SuppressWarnings("unchecked")
@Before
public void before() throws ServletException {
myRequestDetails = mock(RequestDetails.class);
if (myServer == null) {
myServer = new RestfulServer(myFhirCtx);
PatientResourceProvider patientRp = new PatientResourceProvider();
patientRp.setDao(myPatientDao);
myServer.setResourceProviders(patientRp);
myServer.init(mock(ServletConfig.class));
}
when(myRequestDetails.getServer()).thenReturn(myServer);
HttpServletRequest servletRequest = mock(HttpServletRequest.class);
when(myRequestDetails.getServletRequest()).thenReturn(servletRequest);
when(servletRequest.getHeaderNames()).thenReturn(mock(Enumeration.class));
when(servletRequest.getRequestURL()).thenReturn(new StringBuffer("/Patient"));
}
@Test
public void testTransactionSingleEmptyResource() {
Bundle request = new Bundle();
request.setType(BundleTypeEnum.SEARCH_RESULTS);
Patient p = new Patient();
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
}
}
@Test
public void testTransactionBatchWithFailingRead() {
String methodName = "testTransactionBatchWithFailingRead";
Bundle request = new Bundle();
request.setType(BundleTypeEnum.BATCH);
Patient p = new Patient();
p.addName().addFamily(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl("Patient/THIS_ID_DOESNT_EXIST");
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
assertEquals(3, resp.getEntry().size());
assertEquals(BundleTypeEnum.BATCH_RESPONSE, resp.getTypeElement().getValueAsEnum());
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resp));
EntryResponse respEntry;
// Bundle.entry[0] is operation outcome
assertEquals(OperationOutcome.class, resp.getEntry().get(0).getResource().getClass());
assertEquals(IssueSeverityEnum.INFORMATION, ((OperationOutcome)resp.getEntry().get(0).getResource()).getIssue().get(0).getSeverityElement().getValueAsEnum());
assertThat(((OperationOutcome)resp.getEntry().get(0).getResource()).getIssue().get(0).getDiagnostics(), startsWith("Batch completed in "));
// Bundle.entry[1] is create response
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
assertThat(resp.getEntry().get(1).getResponse().getLocation(), startsWith("Patient/"));
// Bundle.entry[2] is failed read response
assertEquals(OperationOutcome.class, resp.getEntry().get(2).getResource().getClass());
assertEquals(IssueSeverityEnum.ERROR, ((OperationOutcome)resp.getEntry().get(2).getResource()).getIssue().get(0).getSeverityElement().getValueAsEnum());
assertEquals("Resource Patient/THIS_ID_DOESNT_EXIST is not known", ((OperationOutcome)resp.getEntry().get(2).getResource()).getIssue().get(0).getDiagnostics());
assertEquals("404 Not Found", resp.getEntry().get(2).getResponse().getStatus());
// Check POST
respEntry = resp.getEntry().get(1).getResponse();
assertEquals("201 Created", respEntry.getStatus());
IdDt createdId = new IdDt(respEntry.getLocation());
assertEquals("Patient", createdId.getResourceType());
myPatientDao.read(createdId); // shouldn't fail
// Check GET
respEntry = resp.getEntry().get(2).getResponse();
assertThat(respEntry.getStatus(), startsWith("404"));
}
@Test
public void testTransactionCreateWithDuplicateMatchUrl01() {
String methodName = "testTransactionCreateWithDuplicateMatchUrl01";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(),
"Unable to process Transaction - Request would cause multiple resources to match URL: \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateWithDuplicateMatchUrl01\". Does transaction request contain duplicates?");
}
}
@Test
public void testTransactionCreateWithInvalidMatchUrl() {
String methodName = "testTransactionCreateWithInvalidMatchUrl";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
EntryRequest entry = request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
entry.setIfNoneExist("Patient?identifier identifier" + methodName);
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?identifier identifiertestTransactionCreateWithInvalidMatchUrl] - URL is invalid (must not contain spaces)", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?identifier=");
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Invalid match URL[Patient?identifier=] - URL has no search parameters", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?foo=bar");
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?foo=bar] - Resource type Patient does not have a parameter with name: foo", e.getMessage());
}
}
public void testTransactionCreateWithDuplicateMatchUrl02() {
String methodName = "testTransactionCreateWithDuplicateMatchUrl02";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(),
"Unable to process Transaction - Request would cause multiple resources to match URL: \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateWithDuplicateMatchUrl02\". Does transaction request contain duplicates?");
}
}
@Test
public void testTransactionCreateMatchUrlWithTwoMatch() {
String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
@ -576,8 +411,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertThat(patientId, not(containsString("test")));
/*
* Interceptor should have been called once for the transaction, and once for the
* embedded operation
* Interceptor should have been called once for the transaction, and once for the embedded operation
*/
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
@ -594,6 +428,84 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionCreateWithDuplicateMatchUrl01() {
String methodName = "testTransactionCreateWithDuplicateMatchUrl01";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(), "Unable to process Transaction - Request would cause multiple resources to match URL: \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateWithDuplicateMatchUrl01\". Does transaction request contain duplicates?");
}
}
public void testTransactionCreateWithDuplicateMatchUrl02() {
String methodName = "testTransactionCreateWithDuplicateMatchUrl02";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Patient?identifier=urn%3Asystem%7C" + methodName);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals(e.getMessage(), "Unable to process Transaction - Request would cause multiple resources to match URL: \"Patient?identifier=urn%3Asystem%7CtestTransactionCreateWithDuplicateMatchUrl02\". Does transaction request contain duplicates?");
}
}
@Test
public void testTransactionCreateWithInvalidMatchUrl() {
String methodName = "testTransactionCreateWithInvalidMatchUrl";
Bundle request = new Bundle();
Patient p;
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
EntryRequest entry = request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
entry.setIfNoneExist("Patient?identifier identifier" + methodName);
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?identifier identifiertestTransactionCreateWithInvalidMatchUrl] - URL is invalid (must not contain spaces)", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?identifier=");
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Invalid match URL[Patient?identifier=] - URL has no search parameters", e.getMessage());
}
try {
entry.setIfNoneExist("Patient?foo=bar");
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Failed to parse match URL[Patient?foo=bar] - Resource type Patient does not have a parameter with name: foo", e.getMessage());
}
}
@Test
public void testTransactionCreateWithInvalidReferenceNumeric() {
String methodName = "testTransactionCreateWithInvalidReferenceNumeric";
@ -757,12 +669,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
// try {
// try {
mySystemDao.transaction(myRequestDetails, request);
// fail();
// } catch (ResourceNotFoundException e) {
// assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
// }
// fail();
// } catch (ResourceNotFoundException e) {
// assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
// }
}
@Test
@ -827,6 +739,14 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference().getValue());
}
@Test
public void testTransactionFromBundle6() throws Exception {
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
String bundle = IOUtils.toString(bundleRes);
Bundle output = mySystemDao.transaction(myRequestDetails, myFhirCtx.newXmlParser().parseResource(Bundle.class, bundle));
ourLog.info(myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(output));
}
@Test
public void testTransactionFromBundleJosh() throws Exception {
@ -842,59 +762,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus());
}
@Test
public void testTransactionWithReferenceToCreateIfNoneExist() {
Bundle bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
Medication med = new Medication();
IdDt medId = IdDt.newRandomUuid();
med.setId(medId);
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
MedicationOrder mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
ourLog.info("Request:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
Bundle outcome = mySystemDao.transaction(myRequestDetails, bundle);
ourLog.info("Response:\n"+myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
IdDt medId1 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId1 = new IdDt( outcome.getEntry().get(1).getResponse().getLocation());
/*
* Again!
*/
bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
med = new Medication();
medId = IdDt.newRandomUuid();
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
outcome = mySystemDao.transaction(myRequestDetails, bundle);
IdDt medId2 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId2 = new IdDt(outcome.getEntry().get(1).getResponse().getLocation());
assertTrue(medId1.isIdPartValidLong());
assertTrue(medId2.isIdPartValidLong());
assertTrue(medOrderId1.isIdPartValidLong());
assertTrue(medOrderId2.isIdPartValidLong());
assertEquals(medId1, medId2);
assertNotEquals(medOrderId1, medOrderId2);
}
@Test
public void testTransactionReadAndSearch() {
String methodName = "testTransactionReadAndSearch";
@ -937,8 +804,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals(1, respBundle.getTotal().intValue());
/*
* Interceptor should have been called once for the transaction, and once for the
* embedded operation
* Interceptor should have been called once for the transaction, and once for the embedded operation
*/
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
@ -963,7 +829,51 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
details = detailsCapt.getValue();
assertEquals("Patient", details.getResourceType());
}
@Test
public void testTransactionReadWithIfNoneMatch() {
String methodName = "testTransactionReadWithIfNoneMatch";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType idv1 = myPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Family Name");
p.setId("Patient/" + methodName);
IIdType idv2 = myPatientDao.update(p).getId();
ourLog.info("Updated patient, got id: {}", idv2);
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue());
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\"");
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\"");
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
assertEquals(3, resp.getEntry().size());
Entry nextEntry;
nextEntry = resp.getEntry().get(0);
assertNotNull(nextEntry.getResource());
assertEquals(Patient.class, nextEntry.getResource().getClass());
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
assertEquals("200 OK", nextEntry.getResponse().getStatus());
nextEntry = resp.getEntry().get(1);
assertNotNull(nextEntry.getResource());
assertEquals(Patient.class, nextEntry.getResource().getClass());
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
assertEquals("200 OK", nextEntry.getResponse().getStatus());
nextEntry = resp.getEntry().get(2);
assertEquals("304 Not Modified", nextEntry.getResponse().getStatus());
assertNull(nextEntry.getResource());
}
@Test
@ -1013,48 +923,20 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionReadWithIfNoneMatch() {
String methodName = "testTransactionReadWithIfNoneMatch";
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.setId("Patient/" + methodName);
IIdType idv1 = myPatientDao.update(p).getId();
ourLog.info("Created patient, got id: {}", idv1);
p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
p.addName().addFamily("Family Name");
p.setId("Patient/" + methodName);
IIdType idv2 = myPatientDao.update(p).getId();
ourLog.info("Updated patient, got id: {}", idv2);
public void testTransactionSingleEmptyResource() {
Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue());
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\"");
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\"");
request.setType(BundleTypeEnum.SEARCH_RESULTS);
Patient p = new Patient();
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
Bundle resp = mySystemDao.transaction(myRequestDetails, request);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
}
assertEquals(3, resp.getEntry().size());
Entry nextEntry;
nextEntry = resp.getEntry().get(0);
assertNotNull(nextEntry.getResource());
assertEquals(Patient.class, nextEntry.getResource().getClass());
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
assertEquals("200 OK", nextEntry.getResponse().getStatus());
nextEntry = resp.getEntry().get(1);
assertNotNull(nextEntry.getResource());
assertEquals(Patient.class, nextEntry.getResource().getClass());
assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified());
assertEquals("200 OK", nextEntry.getResponse().getStatus());
nextEntry = resp.getEntry().get(2);
assertEquals("304 Not Modified", nextEntry.getResponse().getStatus());
assertNull(nextEntry.getResource());
}
@Test
@ -1211,6 +1093,75 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testTransactionWithInvalidType() {
Bundle request = new Bundle();
request.setType(BundleTypeEnum.SEARCH_RESULTS);
Patient p = new Patient();
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerbEnum.POST);
try {
mySystemDao.transaction(myRequestDetails, request);
fail();
} catch (InvalidRequestException e) {
assertEquals("Unable to process transaction where incoming Bundle.type = searchset", e.getMessage());
}
}
@Test
public void testTransactionWithReferenceToCreateIfNoneExist() {
Bundle bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
Medication med = new Medication();
IdDt medId = IdDt.newRandomUuid();
med.setId(medId);
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
MedicationOrder mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
ourLog.info("Request:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
Bundle outcome = mySystemDao.transaction(myRequestDetails, bundle);
ourLog.info("Response:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
IdDt medId1 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId1 = new IdDt(outcome.getEntry().get(1).getResponse().getLocation());
/*
* Again!
*/
bundle = new Bundle();
bundle.setType(BundleTypeEnum.TRANSACTION);
med = new Medication();
medId = IdDt.newRandomUuid();
med.getCode().addCoding().setSystem("billscodes").setCode("theCode");
bundle.addEntry().setResource(med).setFullUrl(medId.getValue()).getRequest().setMethod(HTTPVerbEnum.POST).setIfNoneExist("Medication?code=billscodes|theCode");
mo = new MedicationOrder();
mo.setMedication(new ResourceReferenceDt(medId));
bundle.addEntry().setResource(mo).setFullUrl(mo.getId().getValue()).getRequest().setMethod(HTTPVerbEnum.POST);
outcome = mySystemDao.transaction(myRequestDetails, bundle);
IdDt medId2 = new IdDt(outcome.getEntry().get(0).getResponse().getLocation());
IdDt medOrderId2 = new IdDt(outcome.getEntry().get(1).getResponse().getLocation());
assertTrue(medId1.isIdPartValidLong());
assertTrue(medId2.isIdPartValidLong());
assertTrue(medOrderId1.isIdPartValidLong());
assertTrue(medOrderId2.isIdPartValidLong());
assertEquals(medId1, medId2);
assertNotEquals(medOrderId1, medOrderId2);
}
//
//
// /**
@ -1396,5 +1347,4 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
}
}

View File

@ -1,14 +1,11 @@
package ca.uhn.fhir.jpa.provider;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
@ -18,15 +15,11 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import ca.uhn.fhir.jpa.config.DispatcherServletConfig;
import ca.uhn.fhir.jpa.config.TestDstu2Config;
import ca.uhn.fhir.jpa.dao.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;

View File

@ -46,8 +46,6 @@ import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.dstu.resource.Device;
import ca.uhn.fhir.model.dstu.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
@ -55,6 +53,7 @@ import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.BaseResource;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Condition;
import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
@ -67,6 +66,7 @@ import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
@ -82,6 +82,7 @@ import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
@ -90,6 +91,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
@ -101,8 +105,6 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
// private static JpaConformanceProvider ourConfProvider;
@Override
public void before() throws Exception {
super.before();
@ -117,6 +119,67 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
@Test
public void testEverythingInstanceWithContentFilter() {
Patient pt1 = new Patient();
pt1.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
Patient pt2 = new Patient();
pt2.addName().addFamily("Everything").addGiven("Arthur");
IIdType ptId2 = myPatientDao.create(pt2).getId().toUnqualifiedVersionless();
Device dev1 = new Device();
dev1.setManufacturer("Some Manufacturer");
IIdType devId1 = myDeviceDao.create(dev1).getId().toUnqualifiedVersionless();
Device dev2 = new Device();
dev2.setManufacturer("Some Manufacturer 2");
myDeviceDao.create(dev2).getId().toUnqualifiedVersionless();
Observation obs1 = new Observation();
obs1.getText().setDiv("<div>OBSTEXT1</div>");
obs1.getSubject().setReference(ptId1);
obs1.getCode().addCoding().setCode("CODE1");
obs1.setValue(new StringDt("obsvalue1"));
obs1.getDevice().setReference(devId1);
IIdType obsId1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless();
Observation obs2 = new Observation();
obs2.getSubject().setReference(ptId1);
obs2.getCode().addCoding().setCode("CODE2");
obs2.setValue(new StringDt("obsvalue2"));
IIdType obsId2 = myObservationDao.create(obs2).getId().toUnqualifiedVersionless();
Observation obs3 = new Observation();
obs3.getSubject().setReference(ptId2);
obs3.getCode().addCoding().setCode("CODE3");
obs3.setValue(new StringDt("obsvalue3"));
IIdType obsId3 = myObservationDao.create(obs3).getId().toUnqualifiedVersionless();
List<IIdType> actual;
StringAndListParam param;
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
//@formatter:off
Parameters response = ourClient
.operation()
.onInstance(ptId1)
.named("everything")
.withParameter(Parameters.class, Constants.PARAM_CONTENT, new StringDt("obsvalue1"))
.execute();
//@formatter:on
actual = toUnqualifiedVersionlessIds((ca.uhn.fhir.model.dstu2.resource.Bundle)response.getParameter().get(0).getResource());
assertThat(actual, containsInAnyOrder(ptId1, obsId1, devId1));
}
@Test
public void testBundleCreate() throws Exception {
IGenericClient client = ourClient;

View File

@ -226,8 +226,8 @@
<derby_version>10.12.1.1</derby_version>
<!-- Note on Hibernate versions: Hibernate 4.3+ uses JPA 2.1, which is too new for a number of platforms including JBoss EAP 6.x and Glassfish 3.0. Upgrade this version with caution! Also note that if
you change this, you may get a failure in hibernate4-maven-plugin. See the note in hapi-fhir-jpaserver-base/pom.xml's configuration for that plugin... -->
<hibernate_version>5.0.2.Final</hibernate_version>
<hibernate_validator_version>5.2.1.Final</hibernate_validator_version>
<hibernate_version>5.0.3.Final</hibernate_version>
<hibernate_validator_version>5.2.2.Final</hibernate_validator_version>
<jetty_version>9.3.4.v20151007</jetty_version>
<maven_assembly_plugin_version>2.5.3</maven_assembly_plugin_version>
<maven_failsafe_plugin_version>2.18.1</maven_failsafe_plugin_version>
@ -497,6 +497,11 @@
<artifactId>hibernate-validator</artifactId>
<version>${hibernate_validator_version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>

View File

@ -15,7 +15,7 @@
<li>Commons-lang3 (Core): 3.3.2 -&gt; 3.4</li>
<li>Logback (Core): 1.1.2 -&gt; 1.1.3</li>
<li>Springframework (JPA, Web Tester): 4.1.5 -&gt; 4.2.2</li>
<li>Hibernate (JPA, Web Tester): 4.2.17 -&gt; 5.0.2</li>
<li>Hibernate (JPA, Web Tester): 4.2.17 -&gt; 5.0.3</li>
<li>Hibernate Validator (JPA, Web Tester): 5.2.1 -&gt; 5.2.2</li>
<li>Derby (JPA, CLI, Public Server): 10.11.1.1 -&gt; 10.12.1.1 </li>
<li>Jetty (JPA, CLI, Public Server): 9.2.6.v20141205 -&gt; 9.3.4.v20151007 </li>
@ -227,6 +227,12 @@
the server, and correcltly set the same value in JPA server $everything
results.
</action>
<action type="add">
JPA $everything operations now support new parameters _content
and _text, which work the same way as the same parameters on a
search. This is experimental, since it is not a part of the core
FHIR specification.
</action>
</release>
<release version="1.2" date="2015-09-18">
<action type="add">