From ca5927880f5e396a70a5b4259c425af79cce9c07 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Thu, 15 May 2014 08:08:07 -0400 Subject: [PATCH] More work on JPA --- .../uhn/fhir/rest/param/ReferenceParam.java | 27 +- .../ca/uhn/fhir/jpa/dao/FhirResourceDao.java | 552 +++++++++--------- .../ca/uhn/fhir/jpa/entity/ResourceLink.java | 12 + .../uhn/fhir/jpa/dao/FhirResourceDaoTest.java | 94 ++- 4 files changed, 413 insertions(+), 272 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java index be59c28b368..c1400efd2bb 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java @@ -4,11 +4,23 @@ import ca.uhn.fhir.model.api.IQueryParameterType; public class ReferenceParam implements IQueryParameterType { + private String myChain; private String myValue; - @Override - public void setValueAsQueryToken(String theParameter) { - myValue=theParameter; + public ReferenceParam() { + } + + public ReferenceParam(String theValue) { + setValueAsQueryToken(theValue); + } + + public ReferenceParam(String theValue, String theChain) { + setValueAsQueryToken(theValue); + setChain(theChain); + } + + public String getChain() { + return myChain; } @Override @@ -16,4 +28,13 @@ public class ReferenceParam implements IQueryParameterType { return myValue; } + public void setChain(String theChain) { + myChain = theChain; + } + + @Override + public void setValueAsQueryToken(String theParameter) { + myValue=theParameter; + } + } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java index c6d171a63d2..d96d750a6cc 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDao.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.jpa.dao; +import static org.apache.commons.lang3.StringUtils.*; + import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -31,8 +33,10 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; +import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.RuntimeChildResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.jpa.entity.BaseHasResource; @@ -85,8 +89,227 @@ public class FhirResourceDao private List> myResourceDaos; private String myResourceName; private Class myResourceType; - private Class myTableType; private Map, Class>> myResourceTypeToDao; + private Class myTableType; + + @Transactional(propagation = Propagation.REQUIRED, readOnly = true) + @Override + public MethodOutcome create(T theResource) { + + final X entity = toEntity(theResource); + + entity.setPublished(new Date()); + entity.setUpdated(entity.getPublished()); + + final List stringParams = extractSearchParamStrings(entity, theResource); + final List tokenParams = extractSearchParamTokens(entity, theResource); + final List numberParams = extractSearchParamNumber(entity, theResource); + final List dateParams = extractSearchParamDates(entity, theResource); + final List links = extractResourceLinks(entity, theResource); + + ourLog.info("Saving links: {}",links); + + TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); + template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); + template.setReadOnly(false); + template.execute(new TransactionCallback() { + @Override + public X doInTransaction(TransactionStatus theStatus) { + myEntityManager.persist(entity); + for (ResourceIndexedSearchParamString next : stringParams) { + myEntityManager.persist(next); + } + for (ResourceIndexedSearchParamToken next : tokenParams) { + myEntityManager.persist(next); + } + for (ResourceIndexedSearchParamNumber next : numberParams) { + myEntityManager.persist(next); + } + for (ResourceIndexedSearchParamDate next : dateParams) { + myEntityManager.persist(next); + } + for (ResourceLink next : links) { + myEntityManager.persist(next); + } + return entity; + } + }); + + MethodOutcome outcome = toMethodOutcome(entity); + return outcome; + } + + public Class getResourceType() { + return myResourceType; + } + + @Override + public Class getTableType() { + return myTableType; + } + + @Transactional(propagation = Propagation.REQUIRED) + @Override + public List history(IdDt theId) { + ArrayList retVal = new ArrayList(); + + String resourceType = myCtx.getResourceDefinition(myResourceType).getName(); + TypedQuery q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class); + q.setParameter("PID", theId.asLong()); + q.setParameter("RESTYPE", resourceType); + + // TypedQuery query = + // myEntityManager.createQuery(criteriaQuery); + List results = q.getResultList(); + for (ResourceHistoryTable next : results) { + retVal.add(toResource(next)); + } + + try { + retVal.add(read(theId)); + } catch (ResourceNotFoundException e) { + // ignore + } + + if (retVal.isEmpty()) { + throw new ResourceNotFoundException(theId); + } + + return retVal; + } + + @PostConstruct + public void postConstruct() throws Exception { + myResourceType = myTableType.newInstance().getResourceType(); + myCtx = new FhirContext(myResourceType); + myResourceName = myCtx.getResourceDefinition(myResourceType).getName(); + } + + @Transactional(propagation = Propagation.REQUIRED) + @Override + public T read(IdDt theId) { + X entity = readEntity(theId); + + T retVal = toResource(entity); + return retVal; + } + + @Override + public List search(Map theParams) { + Map>> map = new HashMap>>(); + for (Entry nextEntry : theParams.entrySet()) { + map.put(nextEntry.getKey(), new ArrayList>()); + map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue())); + } + return searchWithAndOr(map); + } + + @Override + public List search(String theSpName, IQueryParameterType theValue) { + return search(Collections.singletonMap(theSpName, theValue)); + } + + @Override + public List searchWithAndOr(Map>> theParams) { + Map>> params = theParams; + if (params == null) { + params = Collections.emptyMap(); + } + + RuntimeResourceDefinition resourceDef = myCtx.getResourceDefinition(myResourceType); + + Set pids = new HashSet(); + + for (Entry>> nextParamEntry : params.entrySet()) { + String nextParamName = nextParamEntry.getKey(); + RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName); + if (nextParamDef != null) { + if (nextParamDef.getParamType() == SearchParamTypeEnum.TOKEN) { + for (List nextAnd : nextParamEntry.getValue()) { + pids = addPredicateToken(pids, nextAnd); + if (pids.isEmpty()) { + return new ArrayList(); + } + } + } else if (nextParamDef.getParamType() == SearchParamTypeEnum.STRING) { + for (List nextAnd : nextParamEntry.getValue()) { + pids = addPredicateString(pids, nextAnd); + if (pids.isEmpty()) { + return new ArrayList(); + } + } + } else if (nextParamDef.getParamType() == SearchParamTypeEnum.QUANTITY) { + for (List nextAnd : nextParamEntry.getValue()) { + pids = addPredicateQuantity(pids, nextAnd); + if (pids.isEmpty()) { + return new ArrayList(); + } + } + } else if (nextParamDef.getParamType() == SearchParamTypeEnum.DATE) { + for (List nextAnd : nextParamEntry.getValue()) { + pids = addPredicateDate(pids, nextAnd); + if (pids.isEmpty()) { + return new ArrayList(); + } + } + } else if (nextParamDef.getParamType() == SearchParamTypeEnum.REFERENCE) { + for (List nextAnd : nextParamEntry.getValue()) { + pids = addPredicateReference(nextParamName, pids, nextAnd); + if (pids.isEmpty()) { + return new ArrayList(); + } + } + } else { + throw new IllegalArgumentException("Don't know how to handle parameter of type: " + nextParamDef.getParamType()); + } + } + } + + // Execute the query and make sure we return distinct results + { + CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); + CriteriaQuery cq = builder.createQuery(myTableType); + Root from = cq.from(myTableType); + if (!params.isEmpty()) { + cq.where(from.get("myId").in(pids)); + } + TypedQuery q = myEntityManager.createQuery(cq); + + List retVal = new ArrayList<>(); + for (X next : q.getResultList()) { + T resource = toResource(next); + retVal.add(resource); + } + return retVal; + } + } + + @Required + public void setTableType(Class theTableType) { + myTableType = theTableType; + } + + @Transactional(propagation = Propagation.SUPPORTS) + @Override + public MethodOutcome update(final T theResource, final IdDt theId) { + TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); + X savedEntity = template.execute(new TransactionCallback() { + @Override + public X doInTransaction(TransactionStatus theStatus) { + final X entity = readEntity(theId); + final ResourceHistoryTable existing = entity.toHistory(myCtx); + + populateResourceIntoEntity(theResource, entity); + myEntityManager.persist(existing); + + entity.setUpdated(new Date()); + myEntityManager.persist(entity); + return entity; + } + }); + + return toMethodOutcome(savedEntity); + } private Set addPredicateDate(Set thePids, List theOrParams) { if (theOrParams == null || theOrParams.isEmpty()) { @@ -128,42 +351,6 @@ public class FhirResourceDao TypedQuery q = myEntityManager.createQuery(cq); return new HashSet(q.getResultList()); } - - private Set addPredicateReference(Set thePids, List theOrParams) { - if (theOrParams == null || theOrParams.isEmpty()) { - return thePids; - } - - CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); - CriteriaQuery cq = builder.createQuery(Long.class); - Root from = cq.from(ResourceIndexedSearchParamDate.class); - cq.select(from.get("myResourcePid").as(Long.class)); - - List codePredicates = new ArrayList(); - for (IQueryParameterType nextOr : theOrParams) { - IQueryParameterType params = nextOr; - - if (params instanceof ReferenceParam) { - ReferenceParam id = (ReferenceParam) params; - } else { - throw new IllegalArgumentException("Invalid token type: " + params.getClass()); - } - - } - - Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0])); - - Predicate type = builder.equal(from.get("myResourceType"), myResourceName); - if (thePids.size() > 0) { - Predicate inPids = (from.get("myResourcePid").in(thePids)); - cq.where(builder.and(type, inPids, masterCodePredicate)); - } else { - cq.where(builder.and(type, masterCodePredicate)); - } - - TypedQuery q = myEntityManager.createQuery(cq); - return new HashSet(q.getResultList()); - } private void addPredicateDateFromRange(CriteriaBuilder builder, Root from, List codePredicates, DateRangeParam range) { Predicate singleCode; @@ -182,7 +369,7 @@ public class FhirResourceDao codePredicates.add(singleCode); } - + private Set addPredicateQuantity(Set thePids, List theOrParams) { if (theOrParams == null || theOrParams.isEmpty()) { return thePids; @@ -266,6 +453,61 @@ public class FhirResourceDao TypedQuery q = myEntityManager.createQuery(cq); return new HashSet(q.getResultList()); } +private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDao.class); + + private Set addPredicateReference(String theParamName, Set thePids, List theOrParams) { + assert theParamName.contains(".")==false; + + if (theOrParams == null || theOrParams.isEmpty()) { + return thePids; + } + + CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); + CriteriaQuery cq = builder.createQuery(Long.class); + Root from = cq.from(ResourceLink.class); + cq.select(from.get("mySourceResourcePid").as(Long.class)); + + List codePredicates = new ArrayList(); + + for (IQueryParameterType nextOr : theOrParams) { + IQueryParameterType params = nextOr; + + if (params instanceof ReferenceParam) { + ReferenceParam ref = (ReferenceParam) params; + + if (isBlank(ref.getChain())) { + Long targetPid=Long.valueOf(ref.getValueAsQueryToken()); + ourLog.info("Searching for resource link with target PID: {}", targetPid); + Predicate eq = builder.equal(from.get("myTargetResourcePid"), targetPid); + codePredicates.add(eq); + } else { + // todo: handle chain with resource type + BaseRuntimeChildDefinition def = myCtx.newTerser().getDefinition(myResourceType, ref.getValueAsQueryToken()); + if (!(def instanceof RuntimeChildResourceDefinition)) { + throw new ConfigurationException("Property "+ref.getValueAsQueryToken()+" of type "+myResourceName+" is not a resource"); + } + RuntimeChildResourceDefinition resDef = (RuntimeChildResourceDefinition) def; + } + + } else { + throw new IllegalArgumentException("Invalid token type: " + params.getClass()); + } + + } + + Predicate masterCodePredicate = builder.or(codePredicates.toArray(new Predicate[0])); + + Predicate type = builder.equal(from.get("mySourcePath"), myResourceName+"."+theParamName); + if (thePids.size() > 0) { + Predicate inPids = (from.get("mySourceResourcePid").in(thePids)); + cq.where(builder.and(type, inPids, masterCodePredicate)); + } else { + cq.where(builder.and(type, masterCodePredicate)); + } + + TypedQuery q = myEntityManager.createQuery(cq); + return new HashSet(q.getResultList()); + } private Set addPredicateString(Set thePids, List theOrParams) { if (theOrParams == null || theOrParams.isEmpty()) { @@ -360,51 +602,6 @@ public class FhirResourceDao return new HashSet(q.getResultList()); } - @Transactional(propagation = Propagation.REQUIRED, readOnly=true) - @Override - public MethodOutcome create(T theResource) { - - final X entity = toEntity(theResource); - - entity.setPublished(new Date()); - entity.setUpdated(entity.getPublished()); - - final List stringParams = extractSearchParamStrings(entity, theResource); - final List tokenParams = extractSearchParamTokens(entity, theResource); - final List numberParams = extractSearchParamNumber(entity, theResource); - final List dateParams = extractSearchParamDates(entity, theResource); - final List links = extractResourceLinks(entity, theResource); - - TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); - template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); - template.setReadOnly(false); - template.execute(new TransactionCallback() { - @Override - public X doInTransaction(TransactionStatus theStatus) { - myEntityManager.persist(entity); - for (ResourceIndexedSearchParamString next : stringParams) { - myEntityManager.persist(next); - } - for (ResourceIndexedSearchParamToken next : tokenParams) { - myEntityManager.persist(next); - } - for (ResourceIndexedSearchParamNumber next : numberParams) { - myEntityManager.persist(next); - } - for (ResourceIndexedSearchParamDate next : dateParams) { - myEntityManager.persist(next); - } - for (ResourceLink next : links) { - myEntityManager.persist(next); - } - return entity; - } - }); - - MethodOutcome outcome = toMethodOutcome(entity); - return outcome; - } - private List extractResourceLinks(X theEntity, T theResource) { ArrayList retVal = new ArrayList(); @@ -430,23 +627,23 @@ public class FhirResourceDao if (nextValue.isEmpty()) { continue; } - + Class type = nextValue.getResourceType(); String id = nextValue.getResourceId(); if (StringUtils.isBlank(id)) { continue; } - + if (myResourceTypeToDao == null) { - myResourceTypeToDao=new HashMap<>(); + myResourceTypeToDao = new HashMap<>(); for (IFhirResourceDao next : myResourceDaos) { myResourceTypeToDao.put(next.getResourceType(), next.getTableType()); } } - + Class> tableType = myResourceTypeToDao.get(type); BaseResourceTable target = myEntityManager.find(tableType, Long.valueOf(id)); - + nextEntity = new ResourceLink(nextPath, theEntity, target); } else { if (!multiType) { @@ -464,11 +661,6 @@ public class FhirResourceDao return retVal; } - @Override - public Class getTableType() { - return myTableType; - } - private List extractSearchParamDates(X theEntity, T theResource) { ArrayList retVal = new ArrayList(); @@ -491,7 +683,7 @@ public class FhirResourceDao if (nextObject == null) { continue; } - + ResourceIndexedSearchParamDate nextEntity; if (nextObject instanceof BaseDateTimeDt) { BaseDateTimeDt nextValue = (BaseDateTimeDt) nextObject; @@ -590,7 +782,10 @@ public class FhirResourceDao nextEntity.setResource(theEntity, def.getName()); retVal.add(nextEntity); } else if (nextObject instanceof HumanNameDt) { - for (StringDt nextName : ((HumanNameDt) nextObject).getFamily()) { + ArrayList allNames = new ArrayList<>(); + allNames.addAll(((HumanNameDt) nextObject).getFamily()); + allNames.addAll(((HumanNameDt) nextObject).getGiven()); + for (StringDt nextName : allNames) { if (nextName.isEmpty()) { continue; } @@ -669,36 +864,6 @@ public class FhirResourceDao return retVal; } - @Transactional(propagation = Propagation.REQUIRED) - @Override - public List history(IdDt theId) { - ArrayList retVal = new ArrayList(); - - String resourceType = myCtx.getResourceDefinition(myResourceType).getName(); - TypedQuery q = myEntityManager.createQuery(ResourceHistoryTable.Q_GETALL, ResourceHistoryTable.class); - q.setParameter("PID", theId.asLong()); - q.setParameter("RESTYPE", resourceType); - - // TypedQuery query = - // myEntityManager.createQuery(criteriaQuery); - List results = q.getResultList(); - for (ResourceHistoryTable next : results) { - retVal.add(toResource(next)); - } - - try { - retVal.add(read(theId)); - } catch (ResourceNotFoundException e) { - // ignore - } - - if (retVal.isEmpty()) { - throw new ResourceNotFoundException(theId); - } - - return retVal; - } - private void populateResourceIntoEntity(T theResource, X retVal) { retVal.setResource(myCtx.newJsonParser().encodeResourceToString(theResource)); retVal.setEncoding(EncodingEnum.JSON); @@ -712,26 +877,6 @@ public class FhirResourceDao } - @PostConstruct - public void postConstruct() throws Exception { - myResourceType = myTableType.newInstance().getResourceType(); - myCtx = new FhirContext(myResourceType); - myResourceName = myCtx.getResourceDefinition(myResourceType).getName(); - } - - public Class getResourceType() { - return myResourceType; - } - - @Transactional(propagation = Propagation.REQUIRED) - @Override - public T read(IdDt theId) { - X entity = readEntity(theId); - - T retVal = toResource(entity); - return retVal; - } - private X readEntity(IdDt theId) { X entity = (X) myEntityManager.find(myTableType, theId.asLong()); if (entity == null) { @@ -740,101 +885,6 @@ public class FhirResourceDao return entity; } - @Override - public List search(Map theParams) { - Map>> map = new HashMap>>(); - for (Entry nextEntry : theParams.entrySet()) { - map.put(nextEntry.getKey(), new ArrayList>()); - map.get(nextEntry.getKey()).add(Collections.singletonList(nextEntry.getValue())); - } - return searchWithAndOr(map); - } - - @Override - public List search(String theSpName, IQueryParameterType theValue) { - return search(Collections.singletonMap(theSpName, theValue)); - } - - @Override - public List searchWithAndOr(Map>> theParams) { - Map>> params = theParams; - if (params == null) { - params = Collections.emptyMap(); - } - - RuntimeResourceDefinition resourceDef = myCtx.getResourceDefinition(myResourceType); - - Set pids = new HashSet(); - - for (Entry>> nextParamEntry : params.entrySet()) { - String nextParamName = nextParamEntry.getKey(); - RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName); - if (nextParamDef != null) { - if (nextParamDef.getParamType() == SearchParamTypeEnum.TOKEN) { - for (List nextAnd : nextParamEntry.getValue()) { - pids = addPredicateToken(pids, nextAnd); - if (pids.isEmpty()) { - return new ArrayList(); - } - } - } else if (nextParamDef.getParamType() == SearchParamTypeEnum.STRING) { - for (List nextAnd : nextParamEntry.getValue()) { - pids = addPredicateString(pids, nextAnd); - if (pids.isEmpty()) { - return new ArrayList(); - } - } - } else if (nextParamDef.getParamType() == SearchParamTypeEnum.QUANTITY) { - for (List nextAnd : nextParamEntry.getValue()) { - pids = addPredicateQuantity(pids, nextAnd); - if (pids.isEmpty()) { - return new ArrayList(); - } - } - } else if (nextParamDef.getParamType() == SearchParamTypeEnum.DATE) { - for (List nextAnd : nextParamEntry.getValue()) { - pids = addPredicateDate(pids, nextAnd); - if (pids.isEmpty()) { - return new ArrayList(); - } - } - } else if (nextParamDef.getParamType() == SearchParamTypeEnum.REFERENCE) { - for (List nextAnd : nextParamEntry.getValue()) { - pids = addPredicateReference(pids, nextAnd); - if (pids.isEmpty()) { - return new ArrayList(); - } - } - } else { - throw new IllegalArgumentException("Don't know how to handle parameter of type: " + nextParamDef.getParamType()); - } - } - } - - // Execute the query and make sure we return distinct results - { - CriteriaBuilder builder = myEntityManager.getCriteriaBuilder(); - CriteriaQuery cq = builder.createQuery(myTableType); - Root from = cq.from(myTableType); - if (!params.isEmpty()) { - cq.where(from.get("myId").in(pids)); - } - TypedQuery q = myEntityManager.createQuery(cq); - - List retVal = new ArrayList<>(); - for (X next : q.getResultList()) { - T resource = toResource(next); - retVal.add(resource); - } - return retVal; - } - } - - @Required - public void setTableType(Class theTableType) { - myTableType = theTableType; - } - private X toEntity(T theResource) { X retVal; try { @@ -873,26 +923,4 @@ public class FhirResourceDao return retVal; } - @Transactional(propagation = Propagation.SUPPORTS) - @Override - public MethodOutcome update(final T theResource, final IdDt theId) { - TransactionTemplate template = new TransactionTemplate(myPlatformTransactionManager); - X savedEntity = template.execute(new TransactionCallback() { - @Override - public X doInTransaction(TransactionStatus theStatus) { - final X entity = readEntity(theId); - final ResourceHistoryTable existing = entity.toHistory(myCtx); - - populateResourceIntoEntity(theResource, entity); - myEntityManager.persist(existing); - - entity.setUpdated(new Date()); - myEntityManager.persist(entity); - return entity; - } - }); - - return toMethodOutcome(savedEntity); - } - } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java index 21b16ca43ea..02180b37c8e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceLink.java @@ -43,6 +43,18 @@ public class ResourceLink implements Serializable { //nothing } + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + b.append("ResourceLink["); + b.append("path=").append(mySourcePath); + b.append(", src=").append(mySourceResource.getIdAsLong()); + b.append(", target=").append(myTargetResource.getIdAsLong()); + + b.append("]"); + return b.toString(); + } + public ResourceLink(String theSourcePath, BaseResourceTable theSourceResource, BaseResourceTable theTargetResource) { super(); mySourcePath = theSourcePath; diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java index 5110aee2a05..907b9350a47 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoTest.java @@ -1,10 +1,6 @@ package ca.uhn.fhir.jpa.dao; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Date; @@ -32,6 +28,7 @@ import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.QualifiedDateParam; public class FhirResourceDaoTest { @@ -73,7 +70,7 @@ public class FhirResourceDaoTest { assertTrue(published.before(now)); assertTrue(updated.before(now)); } - + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoTest.class); @Test public void testPersistResourceLink() { @@ -91,10 +88,58 @@ public class FhirResourceDaoTest { IdDt obsId01 = ourObservationDao.create(obs01).getId(); Observation obs02 = new Observation(); + obs02.setApplies(new DateTimeDt(new Date())); + obs02.setSubject(new ResourceReferenceDt(Patient.class, patientId02)); + IdDt obsId02 = ourObservationDao.create(obs02).getId(); + + ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}]",new Object[] {patientId01,patientId02,obsId01,obsId02}); + + List result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getValue())); + assertEquals(1,result.size()); + assertEquals(obsId01,result.get(0).getId()); + + result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId02.getValue())); + assertEquals(1,result.size()); + assertEquals(obsId02,result.get(0).getId()); + + result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("999999999999")); + assertEquals(0,result.size()); + + } + + @Test + public void testSearchResourceLinkWithChain() { + Patient patient = new Patient(); + patient.addIdentifier("urn:system", "testSearchResourceLinkWithChain"); + IdDt patientId01 = ourPatientDao.create(patient).getId(); + + Patient patient02 = new Patient(); + patient02.addIdentifier("urn:system", "testSearchResourceLinkWithChain"); + IdDt patientId02 = ourPatientDao.create(patient02).getId(); + + Observation obs01 = new Observation(); obs01.setApplies(new DateTimeDt(new Date())); obs01.setSubject(new ResourceReferenceDt(Patient.class, patientId01)); - IdDt obsId02 = ourObservationDao.create(obs01).getId(); + IdDt obsId01 = ourObservationDao.create(obs01).getId(); + + Observation obs02 = new Observation(); + obs02.setApplies(new DateTimeDt(new Date())); + obs02.setSubject(new ResourceReferenceDt(Patient.class, patientId02)); + IdDt obsId02 = ourObservationDao.create(obs02).getId(); + ourLog.info("P1[{}] P2[{}] O1[{}] O2[{}]",new Object[] {patientId01,patientId02,obsId01,obsId02}); + + List result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId01.getValue())); + assertEquals(1,result.size()); + assertEquals(obsId01,result.get(0).getId()); + + result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam(patientId02.getValue(), Patient.SP_IDENTIFIER)); + assertEquals(1,result.size()); + assertEquals(obsId02,result.get(0).getId()); + + result = ourObservationDao.search(Observation.SP_SUBJECT, new ReferenceParam("999999999999", Patient.SP_IDENTIFIER)); + assertEquals(0,result.size()); + } @Test @@ -275,6 +320,41 @@ public class FhirResourceDaoTest { } + @Test + public void testSearchNameParam() { + IdDt id1; + { + Patient patient = new Patient(); + patient.addIdentifier("urn:system", "001"); + patient.addName().addFamily("testSearchNameParam01Fam").addGiven("testSearchNameParam01Giv"); + id1=ourPatientDao.create(patient).getId(); + } + { + Patient patient = new Patient(); + patient.addIdentifier("urn:system", "002"); + patient.addName().addFamily("testSearchNameParam02Fam").addGiven("testSearchNameParam02Giv"); + ourPatientDao.create(patient); + } + + Map params = new HashMap<>(); + params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Fam")); + List patients = ourPatientDao.search(params); + assertEquals(1, patients.size()); + assertEquals(id1, patients.get(0).getId()); + + params = new HashMap<>(); + params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Giv")); + patients = ourPatientDao.search(params); + assertEquals(1, patients.size()); + assertEquals(id1, patients.get(0).getId()); + + params = new HashMap<>(); + params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Foo")); + patients = ourPatientDao.search(params); + assertEquals(0, patients.size()); + + } + @Test public void testUpdateAndGetHistoryResource() throws InterruptedException { Patient patient = new Patient();