Fix #441: Correctly handle search with chains across a field with choice

type
This commit is contained in:
James Agnew 2016-09-30 14:03:20 -04:00
parent 8b80d932da
commit ff4755fbf3
9 changed files with 136 additions and 188 deletions

View File

@ -21,20 +21,10 @@ package ca.uhn.fhir.context;
*/ */
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.instance.model.api.IBaseDatatype;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description; import ca.uhn.fhir.model.api.annotation.Description;
@ -46,6 +36,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
private Map<Class<? extends IBase>, String> myDatatypeToElementName; private Map<Class<? extends IBase>, String> myDatatypeToElementName;
private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myDatatypeToElementDefinition; private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myDatatypeToElementDefinition;
private String myReferenceSuffix; private String myReferenceSuffix;
private List<Class<? extends IBaseResource>> myResourceTypes;
public RuntimeChildChoiceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBase>> theChoiceTypes) { public RuntimeChildChoiceDefinition(Field theField, String theElementName, Child theChildAnnotation, Description theDescriptionAnnotation, List<Class<? extends IBase>> theChoiceTypes) {
super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName); super(theField, theChildAnnotation, theDescriptionAnnotation, theElementName);
@ -86,6 +77,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
myNameToChildDefinition = new HashMap<String, BaseRuntimeElementDefinition<?>>(); myNameToChildDefinition = new HashMap<String, BaseRuntimeElementDefinition<?>>();
myDatatypeToElementName = new HashMap<Class<? extends IBase>, String>(); myDatatypeToElementName = new HashMap<Class<? extends IBase>, String>();
myDatatypeToElementDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>(); myDatatypeToElementDefinition = new HashMap<Class<? extends IBase>, BaseRuntimeElementDefinition<?>>();
myResourceTypes = new ArrayList<Class<? extends IBaseResource>>();
if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) { if (theContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
myReferenceSuffix = "Resource"; myReferenceSuffix = "Resource";
@ -107,6 +99,8 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
myNameToChildDefinition.put(getElementName() + "Reference", nextDef); myNameToChildDefinition.put(getElementName() + "Reference", nextDef);
myNameToChildDefinition.put(getElementName() + "Resource", nextDef); myNameToChildDefinition.put(getElementName() + "Resource", nextDef);
myResourceTypes.add((Class<? extends IBaseResource>) next);
} else { } else {
nextDef = theClassToElementDefinitions.get(next); nextDef = theClassToElementDefinitions.get(next);
BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef; BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef;
@ -166,10 +160,14 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
myNameToChildDefinition = Collections.unmodifiableMap(myNameToChildDefinition); myNameToChildDefinition = Collections.unmodifiableMap(myNameToChildDefinition);
myDatatypeToElementName = Collections.unmodifiableMap(myDatatypeToElementName); myDatatypeToElementName = Collections.unmodifiableMap(myDatatypeToElementName);
myDatatypeToElementDefinition = Collections.unmodifiableMap(myDatatypeToElementDefinition); myDatatypeToElementDefinition = Collections.unmodifiableMap(myDatatypeToElementDefinition);
myResourceTypes = Collections.unmodifiableList(myResourceTypes);
} }
public List<Class<? extends IBaseResource>> getResourceTypes() {
return myResourceTypes;
}
@Override @Override
public String getChildNameByDatatype(Class<? extends IBase> theDatatype) { public String getChildNameByDatatype(Class<? extends IBase> theDatatype) {
String retVal = myDatatypeToElementName.get(theDatatype); String retVal = myDatatypeToElementName.get(theDatatype);

View File

@ -27,34 +27,13 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.Tuple; import javax.persistence.Tuple;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.*;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -70,45 +49,16 @@ import org.springframework.transaction.support.TransactionTemplate;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao; import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao; import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao; import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.entity.BaseHasResource; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.entity.ResourceLink;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.jpa.entity.ResourceTag;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchInclude;
import ca.uhn.fhir.jpa.entity.SearchResult;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.entity.TagDefinition;
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider; import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.util.StopWatch; import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.api.IPrimitiveDatatype; import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.base.composite.BaseQuantityDt; import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
@ -120,19 +70,7 @@ import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.CompositeParam; import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.param.UriParamQualifierEnum;
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.SimpleBundleProvider; import ca.uhn.fhir.rest.server.SimpleBundleProvider;
@ -606,21 +544,31 @@ public class SearchBuilder {
} }
} else { } else {
String paramPath = myContext.getResourceDefinition(myResourceType).getSearchParam(theParamName).getPath();
BaseRuntimeChildDefinition def = myContext.newTerser().getDefinition(myResourceType, paramPath);
if (!(def instanceof RuntimeChildResourceDefinition)) {
throw new ConfigurationException("Property " + paramPath + " of type " + myResourceName + " is not a resource: " + def.getClass());
}
List<Class<? extends IBaseResource>> resourceTypes; List<Class<? extends IBaseResource>> resourceTypes;
String resourceId; String resourceId;
if (!ref.getValue().matches("[a-zA-Z]+\\/.*")) { if (!ref.getValue().matches("[a-zA-Z]+\\/.*")) {
String paramPath = myContext.getResourceDefinition(myResourceType).getSearchParam(theParamName).getPath();
if (paramPath.endsWith(".as(Reference)")) {
paramPath = paramPath.substring(0, paramPath.length() - ".as(Reference)".length()) + "Reference";
}
BaseRuntimeChildDefinition def = myContext.newTerser().getDefinition(myResourceType, paramPath);
if (def instanceof RuntimeChildChoiceDefinition) {
RuntimeChildChoiceDefinition choiceDef = (RuntimeChildChoiceDefinition)def;
resourceTypes = choiceDef.getResourceTypes();
} else if (def instanceof RuntimeChildResourceDefinition) {
RuntimeChildResourceDefinition resDef = (RuntimeChildResourceDefinition) def; RuntimeChildResourceDefinition resDef = (RuntimeChildResourceDefinition) def;
resourceTypes = resDef.getResourceTypes(); resourceTypes = resDef.getResourceTypes();
resourceId = ref.getValue();
} else { } else {
resourceTypes = new ArrayList<Class<? extends IBaseResource>>(); throw new ConfigurationException("Property " + paramPath + " of type " + myResourceName + " is not a resource: " + def.getClass());
}
resourceId = ref.getValue();
} else {
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(ref.getResourceType()); RuntimeResourceDefinition resDef = myContext.getResourceDefinition(ref.getResourceType());
resourceTypes = new ArrayList<Class<? extends IBaseResource>>(1);
resourceTypes.add(resDef.getImplementingClass()); resourceTypes.add(resDef.getImplementingClass());
resourceId = ref.getIdPart(); resourceId = ref.getIdPart();
} }
@ -2011,16 +1959,6 @@ public class SearchBuilder {
myResourceName = theResourceName; myResourceName = theResourceName;
} }
private List<Long> toList(Collection<Long> theLoadPids) {
final List<Long> pids;
if (theLoadPids instanceof List) {
pids = (List<Long>) theLoadPids;
} else {
pids = new ArrayList<Long>(theLoadPids);
}
return pids;
}
private IQueryParameterType toParameterType(RuntimeSearchParam theParam) { private IQueryParameterType toParameterType(RuntimeSearchParam theParam) {
IQueryParameterType qp; IQueryParameterType qp;
switch (theParam.getParamType()) { switch (theParam.getParamType()) {

View File

@ -682,7 +682,10 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
try { try {
String[] nextPathsSplit = SPLIT.split(thePaths); String[] nextPathsSplit = SPLIT.split(thePaths);
for (String nextPath : nextPathsSplit) { for (String nextPath : nextPathsSplit) {
values.addAll(fp.evaluate((Base) theResource, nextPath)); List<Base> allValues = fp.evaluate((Base) theResource, nextPath);
if (allValues.isEmpty() == false) {
values.addAll(allValues);
}
} }
} catch (FHIRException e) { } catch (FHIRException e) {
throw new InternalErrorException(e); throw new InternalErrorException(e);

View File

@ -40,28 +40,7 @@ import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
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.resource.Appointment; import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.ConceptMap;
import ca.uhn.fhir.model.dstu2.resource.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.Immunization;
import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Media;
import ca.uhn.fhir.model.dstu2.resource.Medication;
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.Substance;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.method.MethodUtil; import ca.uhn.fhir.rest.method.MethodUtil;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
@ -120,6 +99,9 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myMedicationDaoDstu2") @Qualifier("myMedicationDaoDstu2")
protected IFhirResourceDao<Medication> myMedicationDao; protected IFhirResourceDao<Medication> myMedicationDao;
@Autowired @Autowired
@Qualifier("myMedicationAdministrationDaoDstu2")
protected IFhirResourceDao<MedicationAdministration> myMedicationAdministrationDao;
@Autowired
@Qualifier("myMedicationOrderDaoDstu2") @Qualifier("myMedicationOrderDaoDstu2")
protected IFhirResourceDao<MedicationOrder> myMedicationOrderDao; protected IFhirResourceDao<MedicationOrder> myMedicationOrderDao;
@Autowired @Autowired

View File

@ -11,41 +11,8 @@ import javax.persistence.EntityManager;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextEntityManager;
import org.hibernate.search.jpa.Search; import org.hibernate.search.jpa.Search;
import org.hl7.fhir.dstu3.hapi.validation.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport; import org.hl7.fhir.dstu3.hapi.validation.IValidationSupport;
import org.hl7.fhir.dstu3.model.AllergyIntolerance; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Appointment;
import org.hl7.fhir.dstu3.model.AuditEvent;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.CarePlan;
import org.hl7.fhir.dstu3.model.CodeSystem;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.CompartmentDefinition;
import org.hl7.fhir.dstu3.model.ConceptMap;
import org.hl7.fhir.dstu3.model.Condition;
import org.hl7.fhir.dstu3.model.Device;
import org.hl7.fhir.dstu3.model.DiagnosticRequest;
import org.hl7.fhir.dstu3.model.DiagnosticReport;
import org.hl7.fhir.dstu3.model.Encounter;
import org.hl7.fhir.dstu3.model.Immunization;
import org.hl7.fhir.dstu3.model.Location;
import org.hl7.fhir.dstu3.model.Media;
import org.hl7.fhir.dstu3.model.Medication;
import org.hl7.fhir.dstu3.model.MedicationOrder;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.dstu3.model.NamingSystem;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.OperationDefinition;
import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Practitioner;
import org.hl7.fhir.dstu3.model.Questionnaire;
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
import org.hl7.fhir.dstu3.model.StructureDefinition;
import org.hl7.fhir.dstu3.model.Subscription;
import org.hl7.fhir.dstu3.model.Substance;
import org.hl7.fhir.dstu3.model.ValueSet;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -63,14 +30,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestDstu3Config; import ca.uhn.fhir.jpa.config.TestDstu3Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest; import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoValueSet;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest; import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString;
@ -160,6 +120,9 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
@Qualifier("myMedicationDaoDstu3") @Qualifier("myMedicationDaoDstu3")
protected IFhirResourceDao<Medication> myMedicationDao; protected IFhirResourceDao<Medication> myMedicationDao;
@Autowired @Autowired
@Qualifier("myMedicationAdministrationDaoDstu3")
protected IFhirResourceDao<MedicationAdministration> myMedicationAdministrationDao;
@Autowired
@Qualifier("myMedicationOrderDaoDstu3") @Qualifier("myMedicationOrderDaoDstu3")
protected IFhirResourceDao<MedicationOrder> myMedicationOrderDao; protected IFhirResourceDao<MedicationOrder> myMedicationOrderDao;
@Autowired @Autowired

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder; import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasItems;
@ -22,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.boot.model.source.spi.IdentifierSourceSimple;
import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem; import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender; import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
@ -42,7 +44,10 @@ import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.entity.*; import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.MedicationPrescription;
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec; import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
@ -96,6 +101,26 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
myCodeSystemDao.create(cs); myCodeSystemDao.create(cs);
} }
/**
* See #441
*/
@Test
public void testChainedMedication() {
Medication medication = new Medication();
medication.getCode().addCoding().setSystem("SYSTEM").setCode("04823543");
IIdType medId = myMedicationDao.create(medication).getId().toUnqualifiedVersionless();
MedicationAdministration ma = new MedicationAdministration();
ma.setMedication(new Reference(medId));
IIdType moId = myMedicationAdministrationDao.create(ma).getId().toUnqualified();
SearchParameterMap map = new SearchParameterMap();
map.add(MedicationAdministration.SP_MEDICATION, new ReferenceAndListParam().addAnd(new ReferenceOrListParam().add(new ReferenceParam("code", "04823543"))));
IBundleProvider results = myMedicationAdministrationDao.search(map);
List<String> ids = toUnqualifiedIdValues(results);
assertThat(ids, contains(moId.getValue()));
}
@Test @Test
public void testCodeSearch() { public void testCodeSearch() {

View File

@ -54,28 +54,8 @@ 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;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.BaseResource; import ca.uhn.fhir.model.dstu2.resource.*;
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.Device;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
import ca.uhn.fhir.model.dstu2.resource.ImagingStudy;
import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Medication;
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Practitioner;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum; import ca.uhn.fhir.model.dstu2.valueset.AnswerFormatEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterClassEnum;
import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum; import ca.uhn.fhir.model.dstu2.valueset.EncounterStateEnum;
@ -131,6 +111,33 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, resp.getStatusLine().getStatusCode()); assertEquals(200, resp.getStatusLine().getStatusCode());
} }
/**
* See #441
*/
@Test
public void testSearchMedicationChain() throws Exception {
Medication medication = new Medication();
medication.getCode().addCoding().setSystem("SYSTEM").setCode("04823543");
IIdType medId = myMedicationDao.create(medication).getId().toUnqualifiedVersionless();
MedicationAdministration ma = new MedicationAdministration();
ma.setMedication(new ResourceReferenceDt(medId));
IIdType moId = myMedicationAdministrationDao.create(ma).getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/MedicationAdministration?medication.code=04823543");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
assertThat(responseString, containsString(moId.getIdPart()));
} finally {
response.close();
}
}
@Test @Test
public void testEverythingInstanceWithContentFilter() { public void testEverythingInstanceWithContentFilter() {
Patient pt1 = new Patient(); Patient pt1 = new Patient();

View File

@ -86,6 +86,31 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
TestUtil.clearAllStaticFieldsForUnitTest(); TestUtil.clearAllStaticFieldsForUnitTest();
} }
/**
* See #441
*/
@Test
public void testSearchMedicationChain() throws Exception {
Medication medication = new Medication();
medication.getCode().addCoding().setSystem("SYSTEM").setCode("04823543");
IIdType medId = myMedicationDao.create(medication).getId().toUnqualifiedVersionless();
MedicationAdministration ma = new MedicationAdministration();
ma.setMedication(new Reference(medId));
IIdType moId = myMedicationAdministrationDao.create(ma).getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/MedicationAdministration?medication.code=04823543");
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String responseString = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
assertThat(responseString, containsString(moId.getIdPart()));
} finally {
response.close();
}
}
@Test @Test
public void testSearchPagingKeepsOldSearches() throws Exception { public void testSearchPagingKeepsOldSearches() throws Exception {
String methodName = "testSearchPagingKeepsOldSearches"; String methodName = "testSearchPagingKeepsOldSearches";

View File

@ -121,6 +121,13 @@
<![CDATA[<code>Resource#equalsDeep()</code>]]>. Thanks to <![CDATA[<code>Resource#equalsDeep()</code>]]>. Thanks to
GitHub user @XcrigX for reporting! GitHub user @XcrigX for reporting!
</action> </action>
<action type="fix" issue="441">
JPA server did not correctly process searches for chained parameters
where the chain passed across a field that was a choice between a
reference and a non-reference type (e.g.
<![CDATA[<code>MedicationAdministration.medication[x]</code>]]>.
Thanks to GitHub user @Crudelus for reporting!
</action>
</release> </release>
<release version="2.0" date="2016-08-30"> <release version="2.0" date="2016-08-30">
<action type="fix"> <action type="fix">