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> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId> <artifactId>hibernate-search-orm</artifactId>
<version>5.5.0.Final</version>
</dependency> </dependency>
<!-- Misc --> <!-- 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) { if (theId == null || theId.getIdPart() == null) {
return false; return false;
} }
@ -1186,10 +1186,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
} }
protected Long translateForcedIdToPid(IIdType theId) { protected Long translateForcedIdToPid(IIdType theId) {
return translateForcedIdToPid(theId, myEntityManager);
}
static Long translateForcedIdToPid(IIdType theId, EntityManager entityManager) {
if (isValidPid(theId)) { if (isValidPid(theId)) {
return theId.getIdPartAsLong(); return theId.getIdPartAsLong();
} else { } 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()); q.setParameter("ID", theId.getIdPart());
try { try {
return q.getSingleResult().getResourcePid(); return q.getSingleResult().getResourcePid();
@ -1356,7 +1360,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
} }
} }
if (theEntity.getId() == null) { if (theEntity.getId() == null) {
myEntityManager.persist(theEntity); myEntityManager.persist(theEntity);
@ -1426,6 +1430,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
myEntityManager.persist(next); myEntityManager.persist(next);
} }
// Store resource links
for (ResourceLink next : resourceLinks) { for (ResourceLink next : resourceLinks) {
myEntityManager.remove(next); 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.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam; 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.param.StringParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>implements IFhirResourceDaoPatient<Patient> { 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(); SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) { if (theCount != null) {
paramMap.setCount(theCount.getValue()); 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.setIncludes(Collections.singleton(IResource.INCLUDE_ALL.asRecursive()));
paramMap.setEverythingMode(theId != null ? EverythingModeEnum.PATIENT_INSTANCE : EverythingModeEnum.PATIENT_TYPE); paramMap.setEverythingMode(theId != null ? EverythingModeEnum.PATIENT_INSTANCE : EverythingModeEnum.PATIENT_TYPE);
paramMap.setSort(theSort); paramMap.setSort(theSort);
@ -59,21 +66,21 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
} }
@Override @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 // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName()); ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort); return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
} }
@Override @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 // Notify interceptors
ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName()); ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails); 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.context.FhirContext;
import ca.uhn.fhir.jpa.entity.ResourceTable; import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.model.api.IQueryParameterType; 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.param.StringParam;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
@ -57,6 +59,10 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
@Transactional() @Transactional()
@Override @Override
public List<Long> search(String theResourceName, SearchParameterMap theParams) { 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); FullTextEntityManager em = org.hibernate.search.jpa.Search.getFullTextEntityManager(myEntityManager);
QueryBuilder qb = em 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); List<List<? extends IQueryParameterType>> textAndTerms = theParams.remove(Constants.PARAM_TEXT);
addTextSearch(qb, bool, textAndTerms, "myNarrativeText"); addTextSearch(qb, bool, textAndTerms, "myNarrativeText");
if (theReferencingPid != null) {
bool.must(qb.keyword().onField("myResourceLinks.myTargetResourcePid").matching(theReferencingPid).createQuery());
}
if (bool.isEmpty()) { if (bool.isEmpty()) {
return null; return null;
} }
@ -92,7 +102,10 @@ public class FhirSearchDao extends BaseHapiFhirDao<IBaseResource> implements ISe
ArrayList<Long> retVal = new ArrayList<Long>(); ArrayList<Long> retVal = new ArrayList<Long>();
for (Object object : result) { for (Object object : result) {
Object[] nextArray = (Object[]) object; Object[] nextArray = (Object[]) object;
retVal.add((Long)nextArray[0]); Long next = (Long)nextArray[0];
if (next != null) {
retVal.add(next);
}
} }
return retVal; 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.model.primitive.UnsignedIntDt;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.IBundleProvider;
public interface IFhirResourceDaoPatient<T extends IBaseResource> extends IFhirResourceDao<T> { 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

@ -25,5 +25,7 @@ import java.util.List;
public interface ISearchDao { public interface ISearchDao {
List<Long> search(String theResourceName, SearchParameterMap theParams); List<Long> search(String theResourceName, SearchParameterMap theParams);
List<Long> everything(String theResourceName, SearchParameterMap theParams);
} }

View File

@ -117,7 +117,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
public class SearchBuilder { public class SearchBuilder {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilder.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilder.class);
private BaseHapiFhirDao<?> myCallingDao; private BaseHapiFhirDao<?> myCallingDao;
private FhirContext myContext; private FhirContext myContext;
private EntityManager myEntityManager; private EntityManager myEntityManager;
@ -135,7 +135,7 @@ public class SearchBuilder {
mySearchResultDao = theSearchResultDao; mySearchResultDao = theSearchResultDao;
myCallingDao = theDao; myCallingDao = theDao;
} }
private Set<Long> addPredicateComposite(RuntimeSearchParam theParamDef, Set<Long> thePids, List<? extends IQueryParameterType> theNextAnd) { private Set<Long> addPredicateComposite(RuntimeSearchParam theParamDef, Set<Long> thePids, List<? extends IQueryParameterType> theNextAnd) {
// TODO: fail if missing is set for a composite query // TODO: fail if missing is set for a composite query
@ -170,7 +170,7 @@ public class SearchBuilder {
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateDate(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) { private Set<Long> addPredicateDate(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
if (theList == null || theList.isEmpty()) { if (theList == null || theList.isEmpty()) {
return thePids; return thePids;
@ -225,7 +225,7 @@ public class SearchBuilder {
predicates.add(builder.equal(from.get("myResourceType"), myResourceName)); predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
predicates.add(from.get("myId").in(thePids)); predicates.add(from.get("myId").in(thePids));
predicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, from)); predicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, from));
cq.where(toArray(predicates)); cq.where(toArray(predicates));
TypedQuery<Long> q = myEntityManager.createQuery(cq); TypedQuery<Long> q = myEntityManager.createQuery(cq);
@ -274,8 +274,8 @@ public class SearchBuilder {
if (retVal.size() > 0) { if (retVal.size() > 0) {
Predicate inPids = (from.get("myId").in(retVal)); Predicate inPids = (from.get("myId").in(retVal));
predicates.add(inPids); predicates.add(inPids);
} }
predicates.add(builder.isNull(from.get("myDeleted"))); predicates.add(builder.isNull(from.get("myDeleted")));
cq.where(toArray(predicates)); cq.where(toArray(predicates));
@ -289,9 +289,8 @@ public class SearchBuilder {
return retVal; return retVal;
} }
private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, private boolean addPredicateMissingFalseIfPresent(CriteriaBuilder theBuilder, String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
IQueryParameterType nextOr) {
boolean missingFalse = false; boolean missingFalse = false;
if (nextOr.getMissing() != null) { if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) { if (nextOr.getMissing().booleanValue() == true) {
@ -305,9 +304,7 @@ public class SearchBuilder {
return missingFalse; 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; boolean missingFalse = false;
if (nextOr.getMissing() != null) { if (nextOr.getMissing() != null) {
if (nextOr.getMissing().booleanValue() == true) { if (nextOr.getMissing().booleanValue() == true) {
@ -395,6 +392,7 @@ public class SearchBuilder {
TypedQuery<Long> q = myEntityManager.createQuery(cq); TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) { private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName, String theParamName, Class<? extends BaseResourceIndexedSearchParam> theParamTable) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class); CriteriaQuery<Long> cq = builder.createQuery(Long.class);
@ -427,7 +425,6 @@ public class SearchBuilder {
return retVal; return retVal;
} }
private Set<Long> addPredicateParamMissingResourceLink(Set<Long> thePids, String joinName, String theParamName) { private Set<Long> addPredicateParamMissingResourceLink(Set<Long> thePids, String joinName, String theParamName) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Long> cq = builder.createQuery(Long.class); CriteriaQuery<Long> cq = builder.createQuery(Long.class);
@ -457,7 +454,7 @@ public class SearchBuilder {
HashSet<Long> retVal = new HashSet<Long>(resultList); HashSet<Long> retVal = new HashSet<Long>(resultList);
return retVal; return retVal;
} }
private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) { private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
if (theList == null || theList.isEmpty()) { if (theList == null || theList.isEmpty()) {
return thePids; return thePids;
@ -572,8 +569,7 @@ public class SearchBuilder {
TypedQuery<Long> q = myEntityManager.createQuery(cq); TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) { private Set<Long> addPredicateReference(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
assert theParamName.contains(".") == false; assert theParamName.contains(".") == false;
@ -766,6 +762,7 @@ public class SearchBuilder {
TypedQuery<Long> q = myEntityManager.createQuery(cq); TypedQuery<Long> q = myEntityManager.createQuery(cq);
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Set<Long> addPredicateTag(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList, String theParamName, DateRangeParam theLastUpdated) { private Set<Long> addPredicateTag(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList, String theParamName, DateRangeParam theLastUpdated) {
Set<Long> pids = thePids; Set<Long> pids = thePids;
if (theList == null || theList.isEmpty()) { if (theList == null || theList.isEmpty()) {
@ -849,7 +846,7 @@ public class SearchBuilder {
if (theLastUpdated != null) { if (theLastUpdated != null) {
andPredicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, defJoin)); andPredicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, defJoin));
} }
Predicate masterCodePredicate = builder.and(toArray(andPredicates)); Predicate masterCodePredicate = builder.and(toArray(andPredicates));
if (pids.size() > 0) { if (pids.size() > 0) {
@ -965,7 +962,6 @@ public class SearchBuilder {
return new HashSet<Long>(q.getResultList()); return new HashSet<Long>(q.getResultList());
} }
private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) { private Predicate createCompositeParamPart(CriteriaBuilder builder, Root<ResourceTable> from, RuntimeSearchParam left, IQueryParameterType leftValue) {
Predicate retVal = null; Predicate retVal = null;
switch (left.getParamType()) { switch (left.getParamType()) {
@ -1072,8 +1068,7 @@ public class SearchBuilder {
} }
} }
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
String rawSearchTerm; String rawSearchTerm;
if (theParameter instanceof TokenParam) { if (theParameter instanceof TokenParam) {
TokenParam id = (TokenParam) theParameter; TokenParam id = (TokenParam) theParameter;
@ -1092,8 +1087,7 @@ public class SearchBuilder {
} }
if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) { if (rawSearchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" throw new InvalidRequestException("Parameter[" + theParamName + "] has length (" + rawSearchTerm.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
+ ResourceIndexedSearchParamString.MAX_LENGTH + "): " + rawSearchTerm);
} }
String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm); String likeExpression = BaseHapiFhirDao.normalizeString(rawSearchTerm);
@ -1107,8 +1101,7 @@ public class SearchBuilder {
return singleCode; return singleCode;
} }
private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, private Predicate createPredicateToken(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
From<ResourceIndexedSearchParamToken, ResourceIndexedSearchParamToken> theFrom) {
String code; String code;
String system; String system;
if (theParameter instanceof TokenParam) { if (theParameter instanceof TokenParam) {
@ -1128,12 +1121,10 @@ public class SearchBuilder {
} }
if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) { if (system != null && system.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException( throw new InvalidRequestException("Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
"Parameter[" + theParamName + "] has system (" + system.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + system);
} }
if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) { if (code != null && code.length() > ResourceIndexedSearchParamToken.MAX_LENGTH) {
throw new InvalidRequestException( throw new InvalidRequestException("Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
"Parameter[" + theParamName + "] has code (" + code.length() + ") that is longer than maximum allowed (" + ResourceIndexedSearchParamToken.MAX_LENGTH + "): " + code);
} }
ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>()); ArrayList<Predicate> singleCodePredicates = (new ArrayList<Predicate>());
@ -1169,11 +1160,11 @@ public class SearchBuilder {
List<Predicate> predicates = new ArrayList<Predicate>(); List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(builder.equal(from.get("myResourceType"), myResourceName)); predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
predicates.add(builder.isNull(from.get("myDeleted"))); predicates.add(builder.isNull(from.get("myDeleted")));
if (theLastUpdated != null) { if (theLastUpdated != null) {
predicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, from)); predicates.addAll(createLastUpdatedPredicates(theLastUpdated, builder, from));
} }
cq.where(toArray(predicates)); cq.where(toArray(predicates));
TypedQuery<Tuple> query = myEntityManager.createQuery(cq); TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
@ -1281,9 +1272,9 @@ public class SearchBuilder {
Root<ResourceTable> from = cq.from(ResourceTable.class); Root<ResourceTable> from = cq.from(ResourceTable.class);
cq.select(from.get("myId").as(Long.class)); cq.select(from.get("myId").as(Long.class));
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from); List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from);
lastUpdatedPredicates.add(0, from.get("myId").in(thePids)); lastUpdatedPredicates.add(0, from.get("myId").in(thePids));
cq.where(SearchBuilder.toArray(lastUpdatedPredicates)); cq.where(SearchBuilder.toArray(lastUpdatedPredicates));
TypedQuery<Long> query = myEntityManager.createQuery(cq); TypedQuery<Long> query = myEntityManager.createQuery(cq);
List<Long> resultList = query.getResultList(); List<Long> resultList = query.getResultList();
@ -1325,10 +1316,11 @@ public class SearchBuilder {
theResourceListToPopulate.set(index, resource); theResourceListToPopulate.set(index, resource);
} }
} }
/** /**
* THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet()) * THIS SHOULD RETURN HASHSET and not jsut Set because we add to it later (so it can't be Collections.emptySet())
* @param theLastUpdated *
* @param theLastUpdated
*/ */
private HashSet<Long> loadReverseIncludes(Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, EverythingModeEnum theEverythingModeEnum, DateRangeParam theLastUpdated) { private HashSet<Long> loadReverseIncludes(Collection<Long> theMatches, Set<Include> theRevIncludes, boolean theReverseMode, EverythingModeEnum theEverythingModeEnum, DateRangeParam theLastUpdated) {
if (theMatches.size() == 0) { if (theMatches.size() == 0) {
@ -1369,11 +1361,12 @@ public class SearchBuilder {
List<ResourceLink> results = q.getResultList(); List<ResourceLink> results = q.getResultList();
for (ResourceLink resourceLink : results) { for (ResourceLink resourceLink : results) {
if (theReverseMode) { if (theReverseMode) {
// if (theEverythingModeEnum.isEncounter()) { // if (theEverythingModeEnum.isEncounter()) {
// if (resourceLink.getSourcePath().equals("Encounter.subject") || resourceLink.getSourcePath().equals("Encounter.patient")) { // if (resourceLink.getSourcePath().equals("Encounter.subject") ||
// nextRoundOmit.add(resourceLink.getSourceResourcePid()); // resourceLink.getSourcePath().equals("Encounter.patient")) {
// } // nextRoundOmit.add(resourceLink.getSourceResourcePid());
// } // }
// }
pidsToInclude.add(resourceLink.getSourceResourcePid()); pidsToInclude.add(resourceLink.getSourceResourcePid());
} else { } else {
pidsToInclude.add(resourceLink.getTargetResourcePid()); pidsToInclude.add(resourceLink.getTargetResourcePid());
@ -1443,10 +1436,9 @@ public class SearchBuilder {
return allAdded; return allAdded;
} }
private List<Long> processSort(final SearchParameterMap theParams, Collection<Long> theLoadPids) { private List<Long> processSort(final SearchParameterMap theParams, Collection<Long> theLoadPids) {
final List<Long> pids; final List<Long> pids;
// Set<Long> loadPids = theLoadPids; // Set<Long> loadPids = theLoadPids;
if (theParams.getSort() != null && isNotBlank(theParams.getSort().getParamName())) { if (theParams.getSort() != null && isNotBlank(theParams.getSort().getParamName())) {
List<Order> orders = new ArrayList<Order>(); List<Order> orders = new ArrayList<Order>();
List<Predicate> predicates = new ArrayList<Predicate>(); List<Predicate> predicates = new ArrayList<Predicate>();
@ -1487,8 +1479,7 @@ public class SearchBuilder {
} }
return pids; return pids;
} }
public IBundleProvider search(final SearchParameterMap theParams) { public IBundleProvider search(final SearchParameterMap theParams) {
StopWatch w = new StopWatch(); StopWatch w = new StopWatch();
final InstantDt now = InstantDt.withCurrentTime(); final InstantDt now = InstantDt.withCurrentTime();
@ -1501,28 +1492,41 @@ public class SearchBuilder {
Collection<Long> loadPids; Collection<Long> loadPids;
if (theParams.getEverythingMode() != null) { if (theParams.getEverythingMode() != null) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); Long pid = null;
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) { if (theParams.get(BaseResource.SP_RES_ID) != null) {
StringParam idParm = (StringParam) theParams.get(BaseResource.SP_RES_ID).get(0).get(0); StringParam idParm = (StringParam) theParams.get(BaseResource.SP_RES_ID).get(0).get(0);
predicates.add(builder.equal(from.get("myId"), idParm.getValue())); pid = BaseHapiFhirDao.translateForcedIdToPid(new IdDt(idParm.getValue()), myEntityManager);
} }
predicates.add(builder.equal(from.get("myResourceType"), myResourceName));
predicates.add(builder.isNull(from.get("myDeleted")));
cq.where(builder.and(SearchBuilder.toArray(predicates)));
Join<Object, Object> join = from.join("myIncomingResourceLinks", JoinType.LEFT);
cq.multiselect(from.get("myId").as(Long.class), join.get("mySourceResourcePid").as(Long.class));
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
loadPids = new HashSet<Long>(); loadPids = new HashSet<Long>();
for (Tuple next : query.getResultList()) { if (theParams.containsKey(Constants.PARAM_CONTENT) || theParams.containsKey(Constants.PARAM_TEXT)) {
loadPids.add(next.get(0, Long.class)); List<Long> pids = mySearchDao.everything(myResourceName, theParams);
Long nextLong = next.get(1, Long.class); // if (pid != null) {
if(nextLong != null) { // loadPids.add(pid);
loadPids.add(nextLong); // }
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 (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")));
cq.where(builder.and(SearchBuilder.toArray(predicates)));
Join<Object, Object> join = from.join("myIncomingResourceLinks", JoinType.LEFT);
cq.multiselect(from.get("myId").as(Long.class), join.get("mySourceResourcePid").as(Long.class));
TypedQuery<Tuple> query = myEntityManager.createQuery(cq);
for (Tuple next : query.getResultList()) {
loadPids.add(next.get(0, Long.class));
Long nextLong = next.get(1, Long.class);
if (nextLong != null) {
loadPids.add(nextLong);
}
} }
} }
@ -1539,7 +1543,7 @@ public class SearchBuilder {
} }
} else { } else {
List<Long> searchResultPids; List<Long> searchResultPids;
if (mySearchDao == null) { if (mySearchDao == null) {
if (theParams.containsKey(Constants.PARAM_TEXT)) { if (theParams.containsKey(Constants.PARAM_TEXT)) {
@ -1565,7 +1569,8 @@ public class SearchBuilder {
// // Load _include and _revinclude before filter and sort in everything mode // // Load _include and _revinclude before filter and sort in everything mode
// if (theParams.getEverythingMode() != null) { // if (theParams.getEverythingMode() != null) {
// if (theParams.getRevIncludes() != null && theParams.getRevIncludes().isEmpty() == false) { // 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())); // loadPids.addAll(loadReverseIncludes(loadPids, theParams.getIncludes(), false, theParams.getEverythingMode()));
// } // }
// } // }
@ -1849,5 +1854,4 @@ public class SearchBuilder {
return thePredicates.toArray(new Predicate[thePredicates.size()]); 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.Validate;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.search.annotations.ContainedIn;
import org.hibernate.search.annotations.Field;
@Entity @Entity
@Table(name = "HFJ_RES_LINK" , indexes= { @Table(name = "HFJ_RES_LINK" , indexes= {
@ -57,6 +59,7 @@ public class ResourceLink implements Serializable {
@ManyToOne(optional = false, fetch=FetchType.LAZY) @ManyToOne(optional = false, fetch=FetchType.LAZY)
@JoinColumn(name = "SRC_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false) @JoinColumn(name = "SRC_RESOURCE_ID", referencedColumnName = "RES_ID", nullable = false)
// @ContainedIn()
private ResourceTable mySourceResource; private ResourceTable mySourceResource;
@Column(name = "SRC_RESOURCE_ID", insertable = false, updatable = false, nullable = false) @Column(name = "SRC_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
@ -67,6 +70,7 @@ public class ResourceLink implements Serializable {
private ResourceTable myTargetResource; private ResourceTable myTargetResource;
@Column(name = "TARGET_RESOURCE_ID", insertable = false, updatable = false, nullable = false) @Column(name = "TARGET_RESOURCE_ID", insertable = false, updatable = false, nullable = false)
@Field()
private Long myTargetResourcePid; private Long myTargetResourcePid;
public ResourceLink() { public ResourceLink() {
@ -77,7 +81,9 @@ public class ResourceLink implements Serializable {
super(); super();
mySourcePath = theSourcePath; mySourcePath = theSourcePath;
mySourceResource = theSourceResource; mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
myTargetResource = theTargetResource; myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
} }
@Override @Override
@ -134,11 +140,13 @@ public class ResourceLink implements Serializable {
public void setSourceResource(ResourceTable theSourceResource) { public void setSourceResource(ResourceTable theSourceResource) {
mySourceResource = theSourceResource; mySourceResource = theSourceResource;
mySourceResourcePid = theSourceResource.getId();
} }
public void setTargetResource(ResourceTable theTargetResource) { public void setTargetResource(ResourceTable theTargetResource) {
Validate.notNull(theTargetResource); Validate.notNull(theTargetResource);
myTargetResource = theTargetResource; myTargetResource = theTargetResource;
myTargetResourcePid = theTargetResource.getId();
} }
@Override @Override

View File

@ -29,6 +29,7 @@ import java.util.Set;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
@ -39,8 +40,11 @@ import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient; 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.Field;
import org.hibernate.search.annotations.Indexed; import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import ca.uhn.fhir.jpa.search.IndexNonDeletedInterceptor; import ca.uhn.fhir.jpa.search.IndexNonDeletedInterceptor;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -65,6 +69,13 @@ public class ResourceTable extends BaseHasResource implements Serializable {
private static final long serialVersionUID = 1L; 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") @Column(name = "SP_HAS_LINKS")
private boolean myHasLinks; private boolean myHasLinks;
@ -85,27 +96,16 @@ public class ResourceTable extends BaseHasResource implements Serializable {
/** /**
* Holds the narrative text only - Used for Fulltext searching but not directly stored in the DB * 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) @Transient()
// @Lob
@Transient
@Field() @Field()
private String myNarrativeText; 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) @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceIndexedSearchParamCoords> myParamsCoords; private Collection<ResourceIndexedSearchParamCoords> myParamsCoords;
@Column(name = "SP_COORDS_PRESENT") @Column(name = "SP_COORDS_PRESENT")
private boolean myParamsCoordsPopulated; private boolean myParamsCoordsPopulated;
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) @OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
private Collection<ResourceIndexedSearchParamDate> myParamsDate; private Collection<ResourceIndexedSearchParamDate> myParamsDate;
@ -146,6 +146,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
private String myProfile; private String myProfile;
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false) @OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
@IndexedEmbedded()
private Collection<ResourceLink> myResourceLinks; private Collection<ResourceLink> myResourceLinks;
@Column(name = "RES_TYPE", length = RESTYPE_LEN) @Column(name = "RES_TYPE", length = RESTYPE_LEN)
@ -303,6 +304,10 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return myParamsUriPopulated; return myParamsUriPopulated;
} }
public void setContentTextParsedIntoWords(String theContentText) {
myContentText = theContentText;
}
public void setHasLinks(boolean theHasLinks) { public void setHasLinks(boolean theHasLinks) {
myHasLinks = theHasLinks; myHasLinks = theHasLinks;
} }
@ -326,10 +331,6 @@ public class ResourceTable extends BaseHasResource implements Serializable {
myNarrativeText = theNarrativeText; myNarrativeText = theNarrativeText;
} }
public void setContentTextParsedIntoWords(String theContentText) {
myContentText = theContentText;
}
public void setParamsCoords(Collection<ResourceIndexedSearchParamCoords> theParamsCoords) { public void setParamsCoords(Collection<ResourceIndexedSearchParamCoords> theParamsCoords) {
if (!isParamsTokenPopulated() && theParamsCoords.isEmpty()) { if (!isParamsTokenPopulated() && theParamsCoords.isEmpty()) {
return; return;
@ -462,4 +463,12 @@ public class ResourceTable extends BaseHasResource implements Serializable {
return retVal; 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; package ca.uhn.fhir.jpa.provider;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.List;
/* /*
* #%L * #%L
* HAPI FHIR JPA Server * 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.jpa.dao.IFhirResourceDaoPatient;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu2.resource.Patient; 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.IdParam;
import ca.uhn.fhir.rest.annotation.Operation; import ca.uhn.fhir.rest.annotation.Operation;
import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.OperationParam;
import ca.uhn.fhir.rest.annotation.Sort; import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.DateRangeParam; 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.Constants;
public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu2<Patient> { public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu2<Patient> {
/** /**
* Patient/123/$everything * Patient/123/$everything
*/ */
@ -53,7 +60,15 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
@Description(shortDefinition="Only return resources which were last updated as specified by the given range") @Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1) @OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated, 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 @Sort
SortSpec theSortSpec SortSpec theSortSpec
) { ) {
@ -61,15 +76,16 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
startRequest(theServletRequest); startRequest(theServletRequest);
try { 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 { } finally {
endRequest(theServletRequest); endRequest(theServletRequest);
}} }
}
/** /**
* /Patient/$everything * /Patient/$everything
*/ */
//@formatter:off //@formatter:off
@Operation(name = "everything", idempotent = true) @Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider patientTypeEverything( public ca.uhn.fhir.rest.server.IBundleProvider patientTypeEverything(
@ -82,19 +98,42 @@ public class BaseJpaResourceProviderPatientDstu2 extends JpaResourceProviderDstu
@Description(shortDefinition="Only return resources which were last updated as specified by the given range") @Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1) @OperationParam(name = Constants.PARAM_LASTUPDATED, min=0, max=1)
DateRangeParam theLastUpdated, 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 @Sort
SortSpec theSortSpec SortSpec theSortSpec
) { ) {
//@formatter:on //@formatter:on
startRequest(theServletRequest); startRequest(theServletRequest);
try { try {
return ((IFhirResourceDaoPatient<Patient>)getDao()).patientTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec); return ((IFhirResourceDaoPatient<Patient>) getDao()).patientTypeEverything(theServletRequest, theCount, theLastUpdated, theSortSpec, toStringAndList(theContent), toStringAndList(theNarrative));
} finally { } finally {
endRequest(theServletRequest); 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 javax.persistence.PersistenceContext;
import org.apache.commons.io.IOUtils; 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.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Before; import org.junit.Before;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -75,7 +77,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired @Autowired
protected ApplicationContext myAppCtx; protected ApplicationContext myAppCtx;
@Autowired @Autowired
@Qualifier("myConceptMapDaoDstu2") @Qualifier("myConceptMapDaoDstu2")
protected IFhirResourceDao<ConceptMap> myConceptMapDao; protected IFhirResourceDao<ConceptMap> myConceptMapDao;
@ -162,6 +164,16 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
myDaoConfig.setInterceptors(myInterceptor); myDaoConfig.setInterceptors(myInterceptor);
} }
@Before
@Transactional
public void beforeFlushFT() {
FullTextEntityManager ftem = Search.getFullTextEntityManager(myEntityManager);
ftem.purgeAll(ResourceTable.class);
ftem.flushToIndexes();
myDaoConfig.setSchedulingDisabled(true);
}
@Before @Before
@Transactional() @Transactional()
public void beforePurgeDatabase() { public void beforePurgeDatabase() {

View File

@ -4,48 +4,40 @@ import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import java.util.List; import java.util.List;
import org.hibernate.search.jpa.FullTextEntityManager; import javax.servlet.http.HttpServletRequest;
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 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.Observation;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt; 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.param.StringParam;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.Constants;
public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test { public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu2SearchFtTest.class); 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 @Test
public void testSearchAndReindex() { public void testSearchAndReindex() {
Patient patient; Patient patient;
SearchParameterMap map; SearchParameterMap map;
patient = new Patient(); patient = new Patient();
patient.getText().setDiv("<div>DIVAAA</div>"); patient.getText().setDiv("<div>DIVAAA</div>");
patient.addName().addGiven("NAMEAAA"); patient.addName().addGiven("NAMEAAA");
IIdType pId1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless(); IIdType pId1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA")); map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
@ -53,11 +45,11 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_TEXT, new StringParam("DIVAAA")); map.add(Constants.PARAM_TEXT, new StringParam("DIVAAA"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
/* /*
* Reindex * Reindex
*/ */
patient = new Patient(); patient = new Patient();
patient.setId(pId1); patient.setId(pId1);
patient.getText().setDiv("<div>DIVBBB</div>"); patient.getText().setDiv("<div>DIVBBB</div>");
@ -79,24 +71,204 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB")); map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); 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 * When processing transactions, we do two passes. Make sure we don't update the lucene index twice since that would
* lucene index twice since that would be inefficient * be inefficient
*/ */
@Test @Test
public void testSearchDontReindexForUpdateWithIndexDisabled() { public void testSearchDontReindexForUpdateWithIndexDisabled() {
Patient patient; Patient patient;
SearchParameterMap map; SearchParameterMap map;
patient = new Patient(); patient = new Patient();
patient.getText().setDiv("<div>DIVAAA</div>"); patient.getText().setDiv("<div>DIVAAA</div>");
patient.addName().addGiven("NAMEAAA"); patient.addName().addGiven("NAMEAAA");
IIdType pId1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless(); IIdType pId1 = myPatientDao.create(patient).getId().toUnqualifiedVersionless();
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA")); map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
@ -104,11 +276,11 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_TEXT, new StringParam("DIVAAA")); map.add(Constants.PARAM_TEXT, new StringParam("DIVAAA"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
/* /*
* Update but don't reindex * Update but don't reindex
*/ */
patient = new Patient(); patient = new Patient();
patient.setId(pId1); patient.setId(pId1);
patient.getText().setDiv("<div>DIVBBB</div>"); patient.getText().setDiv("<div>DIVBBB</div>");
@ -122,8 +294,8 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEBBB")); map.add(Constants.PARAM_CONTENT, new StringParam("NAMEBBB"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), not(contains(pId1))); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), not(contains(pId1)));
myPatientDao.update(patient, null, true); myPatientDao.update(patient, null, true);
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA")); map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty()); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
@ -139,12 +311,9 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
map = new SearchParameterMap(); map = new SearchParameterMap();
map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB")); map.add(Constants.PARAM_TEXT, new StringParam("DIVBBB"));
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1)); assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), contains(pId1));
} }
@Test @Test
public void testSearchWithChainedParams() { public void testSearchWithChainedParams() {
String methodName = "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.hasItems;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -141,14 +142,14 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless(); IIdType moId = myMedicationOrderDao.create(mo).getId().toUnqualifiedVersionless();
HttpServletRequest request = mock(HttpServletRequest.class); 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)); assertThat(toUnqualifiedVersionlessIds(resp), containsInAnyOrder(orgId, medId, patId, moId, patId2));
request = mock(HttpServletRequest.class); 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)); assertThat(toUnqualifiedVersionlessIds(resp), containsInAnyOrder(orgId, medId, patId, moId));
} }
@Test @Test
public void testIndexNoDuplicatesDate() { public void testIndexNoDuplicatesDate() {
DiagnosticOrder order = new DiagnosticOrder(); DiagnosticOrder order = new DiagnosticOrder();

View File

@ -1,7 +1,14 @@
package ca.uhn.fhir.jpa.dao; 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 /*//@formatter:off
* [ERROR] Search parameter action has conflicting types token and reference * [ERROR] Search parameter action has conflicting types token and reference
* [ERROR] Search parameter source has conflicting types token and reference * [ERROR] Search parameter source 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.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List; 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.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.springframework.transaction.TransactionStatus; 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.ResourceTable;
import ca.uhn.fhir.jpa.entity.TagTypeEnum; import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test; 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.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.model.api.TagList;
@ -67,81 +57,61 @@ import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; 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.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider; 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.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; 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 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 @Test
public void testRendexing() { public void testRendexing() {
Patient p = new Patient(); Patient p = new Patient();
p.addName().addFamily("family"); p.addName().addFamily("family");
final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless(); final IIdType id = myPatientDao.create(p).getId().toUnqualifiedVersionless();
ValueSet vs = new ValueSet(); ValueSet vs = new ValueSet();
vs.setUrl("http://foo"); vs.setUrl("http://foo");
myValueSetDao.create(vs); myValueSetDao.create(vs);
ResourceTable entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { ResourceTable entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
public ResourceTable doInTransaction(TransactionStatus theStatus) { public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong()); return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}}); }
});
assertEquals(Long.valueOf(1), entity.getIndexStatus()); assertEquals(Long.valueOf(1), entity.getIndexStatus());
mySystemDao.markAllResourcesForReindexing(); mySystemDao.markAllResourcesForReindexing();
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
public ResourceTable doInTransaction(TransactionStatus theStatus) { public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong()); return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}}); }
});
assertEquals(null, entity.getIndexStatus()); assertEquals(null, entity.getIndexStatus());
mySystemDao.performReindexingPass(null); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
public ResourceTable doInTransaction(TransactionStatus theStatus) { public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong()); return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}}); }
});
assertEquals(Long.valueOf(1), entity.getIndexStatus()); assertEquals(Long.valueOf(1), entity.getIndexStatus());
// Just make sure this doesn't cause a choke // Just make sure this doesn't cause a choke
mySystemDao.performReindexingPass(100000); mySystemDao.performReindexingPass(100000);
// Try making the resource unparseable // Try making the resource unparseable
TransactionTemplate template = new TransactionTemplate(myTxManager); TransactionTemplate template = new TransactionTemplate(myTxManager);
template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
template.execute(new TransactionCallback<ResourceTable>() { template.execute(new TransactionCallback<ResourceTable>() {
@ -157,21 +127,21 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
} }
myEntityManager.merge(table); myEntityManager.merge(table);
return null; return null;
}}); }
});
mySystemDao.performReindexingPass(null); mySystemDao.performReindexingPass(null);
entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() { entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback<ResourceTable>() {
@Override @Override
public ResourceTable doInTransaction(TransactionStatus theStatus) { public ResourceTable doInTransaction(TransactionStatus theStatus) {
return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong()); return myEntityManager.find(ResourceTable.class, id.getIdPartAsLong());
}}); }
});
assertEquals(Long.valueOf(2), entity.getIndexStatus()); assertEquals(Long.valueOf(2), entity.getIndexStatus());
} }
@Test @Test
public void testSystemMetaOperation() { 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 @Test
public void testTransactionCreateMatchUrlWithOneMatch() { public void testTransactionCreateMatchUrlWithOneMatch() {
String methodName = "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 @Test
public void testTransactionCreateMatchUrlWithTwoMatch() { public void testTransactionCreateMatchUrlWithTwoMatch() {
String methodName = "testTransactionCreateMatchUrlWithTwoMatch"; String methodName = "testTransactionCreateMatchUrlWithTwoMatch";
@ -576,8 +411,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertThat(patientId, not(containsString("test"))); assertThat(patientId, not(containsString("test")));
/* /*
* Interceptor should have been called once for the transaction, and once for the * Interceptor should have been called once for the transaction, and once for the embedded operation
* embedded operation
*/ */
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture()); verify(myInterceptor).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
@ -591,7 +425,85 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertNotNull(details.getId()); assertNotNull(details.getId());
assertEquals("Patient", details.getResourceType()); assertEquals("Patient", details.getResourceType());
assertEquals(Patient.class, details.getResource().getClass()); assertEquals(Patient.class, details.getResource().getClass());
}
@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 @Test
@ -721,7 +633,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
@Test @Test
public void testTransactionDeleteMatchUrlWithTwoMatch() { public void testTransactionDeleteMatchUrlWithTwoMatch() {
myDaoConfig.setAllowMultipleDelete(false); myDaoConfig.setAllowMultipleDelete(false);
String methodName = "testTransactionDeleteMatchUrlWithTwoMatch"; String methodName = "testTransactionDeleteMatchUrlWithTwoMatch";
Patient p = new Patient(); Patient p = new Patient();
@ -757,12 +669,12 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
Bundle request = new Bundle(); Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName); request.addEntry().getRequest().setMethod(HTTPVerbEnum.DELETE).setUrl("Patient?identifier=urn%3Asystem%7C" + methodName);
// try { // try {
mySystemDao.transaction(myRequestDetails, request); mySystemDao.transaction(myRequestDetails, request);
// fail(); // fail();
// } catch (ResourceNotFoundException e) { // } catch (ResourceNotFoundException e) {
// assertThat(e.getMessage(), containsString("resource matching URL \"Patient?")); // assertThat(e.getMessage(), containsString("resource matching URL \"Patient?"));
// } // }
} }
@Test @Test
@ -827,6 +739,14 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference().getValue()); 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 @Test
public void testTransactionFromBundleJosh() throws Exception { public void testTransactionFromBundleJosh() throws Exception {
@ -842,59 +762,6 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals("201 Created", resp.getEntry().get(1).getResponse().getStatus()); 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 @Test
public void testTransactionReadAndSearch() { public void testTransactionReadAndSearch() {
String methodName = "testTransactionReadAndSearch"; String methodName = "testTransactionReadAndSearch";
@ -935,10 +802,9 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
assertEquals(Bundle.class, nextEntry.getResource().getClass()); assertEquals(Bundle.class, nextEntry.getResource().getClass());
Bundle respBundle = (Bundle) nextEntry.getResource(); Bundle respBundle = (Bundle) nextEntry.getResource();
assertEquals(1, respBundle.getTotal().intValue()); assertEquals(1, respBundle.getTotal().intValue());
/* /*
* Interceptor should have been called once for the transaction, and once for the * Interceptor should have been called once for the transaction, and once for the embedded operation
* embedded operation
*/ */
ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class); ArgumentCaptor<ActionRequestDetails> detailsCapt = ArgumentCaptor.forClass(ActionRequestDetails.class);
verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture()); verify(myInterceptor, times(1)).incomingRequestPreHandled(eq(RestOperationTypeEnum.TRANSACTION), detailsCapt.capture());
@ -963,7 +829,51 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
details = detailsCapt.getValue(); details = detailsCapt.getValue();
assertEquals("Patient", details.getResourceType()); 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 @Test
@ -1013,48 +923,20 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2Test {
} }
@Test @Test
public void testTransactionReadWithIfNoneMatch() { public void testTransactionSingleEmptyResource() {
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(); Bundle request = new Bundle();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()); request.setType(BundleTypeEnum.SEARCH_RESULTS);
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\""); Patient p = new Patient();
request.addEntry().getRequest().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\""); 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 @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; package ca.uhn.fhir.jpa.provider;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.mockito.Mockito.mock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
@ -18,15 +15,11 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet; 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.dao.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider; import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle; 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.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 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.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.composite.PeriodDt; 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.BaseResource;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry; import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Condition; 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.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest; import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
import ca.uhn.fhir.model.dstu2.resource.DocumentReference; 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.Organization;
import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient; 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.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.Subscription; 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.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; 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.UnsignedIntDt;
import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; 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.api.SummaryEnum;
import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.param.DateRangeParam; 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.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; 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 final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
// private static JpaConformanceProvider ourConfProvider;
@Override @Override
public void before() throws Exception { public void before() throws Exception {
super.before(); super.before();
@ -117,6 +119,67 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode()); 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 @Test
public void testBundleCreate() throws Exception { public void testBundleCreate() throws Exception {
IGenericClient client = ourClient; IGenericClient client = ourClient;

View File

@ -226,8 +226,8 @@
<derby_version>10.12.1.1</derby_version> <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 <!-- 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... --> 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_version>5.0.3.Final</hibernate_version>
<hibernate_validator_version>5.2.1.Final</hibernate_validator_version> <hibernate_validator_version>5.2.2.Final</hibernate_validator_version>
<jetty_version>9.3.4.v20151007</jetty_version> <jetty_version>9.3.4.v20151007</jetty_version>
<maven_assembly_plugin_version>2.5.3</maven_assembly_plugin_version> <maven_assembly_plugin_version>2.5.3</maven_assembly_plugin_version>
<maven_failsafe_plugin_version>2.18.1</maven_failsafe_plugin_version> <maven_failsafe_plugin_version>2.18.1</maven_failsafe_plugin_version>
@ -497,6 +497,11 @@
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
<version>${hibernate_validator_version}</version> <version>${hibernate_validator_version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.5.0.Final</version>
</dependency>
<dependency> <dependency>
<groupId>org.javassist</groupId> <groupId>org.javassist</groupId>
<artifactId>javassist</artifactId> <artifactId>javassist</artifactId>

View File

@ -15,7 +15,7 @@
<li>Commons-lang3 (Core): 3.3.2 -&gt; 3.4</li> <li>Commons-lang3 (Core): 3.3.2 -&gt; 3.4</li>
<li>Logback (Core): 1.1.2 -&gt; 1.1.3</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>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>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>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> <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 the server, and correcltly set the same value in JPA server $everything
results. results.
</action> </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>
<release version="1.2" date="2015-09-18"> <release version="1.2" date="2015-09-18">
<action type="add"> <action type="add">